Account Hierarchy Template

From GnuCash
Revision as of 16:54, 1 March 2018 by Fell (talk | contribs) (Testing: Syntax Check & Testing in Gnucash)
Jump to: navigation, search

Creating localized Account Hierarchy Templates

Motivation and Overview

Sometimes the standard GnuCash account hierarchy template needs a bigger rework before it fits the requirements of your government - especially for business purposes. In this case it might be better to start creating a new hierarchy template from scratch.

Depending on your experience and resources there are different approachs:

and do some Copy&Paste #Changing the Header #... and the Footer with your preferred text editor.

In all cases you want to run the #Syntax Check before sharing your file.

An almost normal Start

Usually you will start with an empty file, but it is also possible to strip down the copy of a working gnucash file.

Start with an new empty gnucash file

Create the account hierarchy, which is according your needs.

  • Usually you should mark accounts which have subaccounts as Placeholder.

Before you save to file in xml format, uncheck Edit->Preferences->General->Files:Compress Files to get an uncompressed xml file.

FIXME: I am not quite sure whether "Save file" or "Export hierarchy" is the better choice currently. One obvious difference: export saves no transactions, but also other parts will be ignored. (E.g. what will happen with taxtables, but it seems only accounts can be created.)

Strip data from an existing, uncompressed gnucash xml file

You have a nice working GnuCash file and somebody asks for a copy of your template. So you want to remove all your personal data. But you surely want to keep the accounts and in business templates the tax table.

Open the copy of the file with a text editor, preferential with syntax highlighting for xml. Remove unwanted sections:

<book:slots> ... </book:slots>
<gnc:count-data ...>        <!-- give you an overview, and should be adjusted at the end -->
<gnc:commodity version="2.0.0">...</gnc:commodity>   <!-- remove only foreign currencies -->
<gnc:transaction version="2.0.0">...</gnc:transaction>
<gnc:budget version="2.0.0">...</gnc:budget>
<gnc:GncCustomer version="2.0.0">...</gnc:GncCustomer>
<gnc:GncEntry version="2.0.0">...</gnc:GncEntry>
<gnc:GncInvoice version="2.0.0">...</gnc:GncInvoice>
<gnc:GncVendor version="2.0.0">...</gnc:GncVendor>
<!-- feel free to add that which I missed like employee, price, order... -->

Now run a #Syntax Check.

Changing the Header

After you saved your template, you must manually adjust the first lines (the "header") of your new created file as follows. Otherwise the "New File Wizard" would not know how to handle your template. The file name itself does not matter (it will not be shown anywhere), but the first lines of the file must contain the following information:

<?xml version="1.0" encoding="utf-8" ?>
<gnc-account-example 
  xmlns="http://www.gnucash.org/XML/"
  xmlns:act="http://www.gnucash.org/XML/act"
  xmlns:addr="http://www.gnucash.org/XML/addr"
  xmlns:bgt="http://www.gnucash.org/XML/bgt"
  xmlns:billterm="http://www.gnucash.org/XML/billterm"
  xmlns:book="http://www.gnucash.org/XML/book"
  xmlns:bt-days="http://www.gnucash.org/XML/bt-days"
  xmlns:bt-prox="http://www.gnucash.org/XML/bt-prox"
  xmlns:cd="http://www.gnucash.org/XML/cd"
  xmlns:cmdty="http://www.gnucash.org/XML/cmdty"
  xmlns:cust="http://www.gnucash.org/XML/cust"
  xmlns:employee="http://www.gnucash.org/XML/employee"
  xmlns:entry="http://www.gnucash.org/XML/entry"
  xmlns:fs="http://www.gnucash.org/XML/fs"
  xmlns:gnc="http://www.gnucash.org/XML/gnc"
  xmlns:gnc-act="http://www.gnucash.org/XML/gnc-act"
  xmlns:invoice="http://www.gnucash.org/XML/invoice"
  xmlns:job="http://www.gnucash.org/XML/job"
  xmlns:lot="http://www.gnucash.org/XML/lot"
  xmlns:order="http://www.gnucash.org/XML/order"
  xmlns:owner="http://www.gnucash.org/XML/owner"
  xmlns:price="http://www.gnucash.org/XML/price"
  xmlns:recurrence="http://www.gnucash.org/XML/recurrence"
  xmlns:slot="http://www.gnucash.org/XML/slot"
  xmlns:split="http://www.gnucash.org/XML/split"
  xmlns:sx="http://www.gnucash.org/XML/sx"
  xmlns:taxtable="http://www.gnucash.org/XML/taxtable"
  xmlns:trn="http://www.gnucash.org/XML/trn"
  xmlns:ts="http://www.gnucash.org/XML/ts"
  xmlns:tte="http://www.gnucash.org/XML/tte"
  xmlns:vendor="http://www.gnucash.org/XML/vendor">
<gnc-act:title>
  IGAS-2099
</gnc-act:title>
<gnc-act:short-description>
  Inter Galactical Accounting Standard, Stardate 2099
</gnc-act:short-description>
<gnc-act:long-description>
  This is the Base Module of the Inter Galactical Accounting Standard as transmitted on stardate 2099-01-01. You might also need the module "starfleet" or "klingon". ~Cpt. Picard
</gnc-act:long-description>
<gnc-act:exclude-from-select-all>1</gnc-act:exclude-from-select-all>
<gnc:account version="2.0.0">
  <act:name>Root Account</act:name>
  <act:id type="new">e24772da4864456b196be5a6301c6756</act:id>
  <act:type>ROOT</act:type>
  <act:commodity-scu>0</act:commodity-scu>
</gnc:account>

Annotations:

  • Line 1: encoding
You must save your file in the appropriate character encoding and note the used character encoding here! For possible values refer Locale Settings.
  • Line 2ff: Namespace
The parser in GC 2.2.x makes no use of it, but future versions might change.
Some details can be found in [1] or in gnucash-v2.rnc. Defining the namespace has the benefit, you can check the syntax of your file later with xmllint.
  • gnc-act:title
Enter a short, unique Name, which is shown in the table in the "New File Wizard" so that the user can choose this template. This name is usually also part of the filename, but the file name itself does not matter and is never shown to the user. This name is restricted to ONE line.
  • gnc-act:short-description
A one-line description shown in the table in the "New File Wizard"
  • gnc-act:long-description
A somewhat longer description which is shown in a text box in the "New File Wizard" if the user chooses this template. This should explain the content and the efficient usage of the template to the user.
  • gnc-act:exclude-from-select-all
Whether this template should be selected if the user clicks the button "Select All". The business-related templates are probably rather special and should not be mixed with a general home-user account structure, so you should probably enable this flag by writing a "1" in here.
  • Root Account
Only the base module should have exactly one.
The accounts in the optional modules linked over <act:parent type="new">...</act:parent>

If you decide to copy&paste this template, please replace the root guid by a self generated with

  • either:
uuidgen | sed -e 's/-//g'
(Dependencies: uuidgen is part of util-linux and sed has it's own package)
  • or use an online uuid generator like this one (any other one will do as well). Be sure to untick "Hyphens" to generate gnucash compatible guids. If you forget or the site you use doesn't offer that option, simply remove the hyphens yourself.

.

... and the Footer

Close to the end of the file, you should replace

</gnc-v2>

by

</gnc-account-example>

.

Testing

From time to time you should check the syntax and finally by using your file in GnuCash.

Syntax Check

Finally you should run

xmllint --noout <mytemplate>

to verify the syntactical correctnes of your file.

If xmllint is missing on your computer see Translation#Prerequisite.

Commiters can use in the respective directory:

for i in *-xea; do xmllint --noout $i; done

Testing in Gnucash

  • If you are using Git (after adding it to the repo and make) do an normal make && make install.
  • Otherwise locate the template directory on your system - it might be /usr/share/gnucash/accounts/<yourlocale> or similar. As administrator copy it there in. Warning: This is a dirty hack which your distibutor will discourage.

Now start Gnucash, select New file..., select your template and try every possible and impossible operation.

A sample script for big templates

If the template is really big - as the german - and you have it as text file, it might be less work to adjust the following script from [2] to create the gnucash template. There exist tools in the internet and probably on your computer to convert often used formats like PDF to plain text files e.g. pdf2txt.

#! /bin/bash

# This applications takes an text input file $FILE
# and converts it into a gnucash account scheme with a random name.
# The input file is read line by line where each line
# should be formatted as
#  number name (no leading spaces)
# or
#  category name (one leading space)
# .
# Empty lines are not allowed, number is expected to have 4 digits.
# The output is a two layer structure
# of all accounts. Whenever the first
# digit of number changes, a new source group is created.
# Whenever a new category line is passed, all following
# accounts are put below.
#
# Example:
# input:
#   1234 A
#   2000 B
#    Type B1
#   2001 B1a
#   2002 B1b
#    Type B2
#   2010 B2a
#   2011 B2b
# output:
#   Class 0
#   Class 1
#    \- 1234 A
#   Class 2
#    \- 2000 B
#    \- Type B1
#       \- 2001 B1a
#       \- 2002 B1b
#    \- Type B2
#       \- 2010 B2a
#       \- 2011 B2b
#
# (C) 2009, Michael Braun, michael-developer@fami-braun.de
# Distributed under GPL v3.0 or newer.
# see http://www.gnu.org/licenses/gpl.html for details

echo "start"

FILE="<source>.txt"

if [ ! -f "$FILE" ]; then 
 echo "no such file $FILE"
 exit 1;
fi

getuid()
{
 dd if=/dev/urandom bs=1 count=32  2>/dev/null | md5sum | awk -F' ' '{print $1}';
}

OUT="$(getuid).gnucash"

ROOT=$(getuid);
NUM=$(cat $FILE | wc -l)
NUM=$(expr $NUM + 1);
ID=0

echo -n > $OUT;

cat >> "$OUT" <<EOF
<?xml version="1.0" encoding="utf-8" ?>
<gnc-v2
     xmlns:gnc="http://www.gnucash.org/XML/gnc"
     xmlns:gnc-act="http://www.gnucash.org/XML/gnc-act"
     xmlns:act="http://www.gnucash.org/XML/act"
     xmlns:book="http://www.gnucash.org/XML/book"
     xmlns:cd="http://www.gnucash.org/XML/cd"
     xmlns:cmdty="http://www.gnucash.org/XML/cmdty"
     xmlns:price="http://www.gnucash.org/XML/price"
     xmlns:slot="http://www.gnucash.org/XML/slot"
     xmlns:split="http://www.gnucash.org/XML/split"
     xmlns:sx="http://www.gnucash.org/XML/sx"
     xmlns:trn="http://www.gnucash.org/XML/trn"
     xmlns:ts="http://www.gnucash.org/XML/ts"
     xmlns:fs="http://www.gnucash.org/XML/fs"
     xmlns:bgt="http://www.gnucash.org/XML/bgt"
     xmlns:recurrence="http://www.gnucash.org/XML/recurrence"
     xmlns:lot="http://www.gnucash.org/XML/lot"
     xmlns:cust="http://www.gnucash.org/XML/cust"
     xmlns:job="http://www.gnucash.org/XML/job"
     xmlns:addr="http://www.gnucash.org/XML/addr"
     xmlns:owner="http://www.gnucash.org/XML/owner"
     xmlns:taxtable="http://www.gnucash.org/XML/taxtable"
     xmlns:tte="http://www.gnucash.org/XML/tte"
     xmlns:employee="http://www.gnucash.org/XML/employee"
     xmlns:order="http://www.gnucash.org/XML/order"
     xmlns:billterm="http://www.gnucash.org/XML/billterm"
     xmlns:bt-days="http://www.gnucash.org/XML/bt-days"
     xmlns:bt-prox="http://www.gnucash.org/XML/bt-prox"
     xmlns:invoice="http://www.gnucash.org/XML/invoice"
     xmlns:entry="http://www.gnucash.org/XML/entry"
     xmlns:vendor="http://www.gnucash.org/XML/vendor">
<gnc:count-data cd:type="account">$NUM</gnc:count-data>
<gnc:account version="2.0.0">
  <act:name>Root Account</act:name>
  <act:id type="new">$ROOT</act:id>
  <act:type>ROOT</act:type>
  <act:commodity-scu>0</act:commodity-scu>
</gnc:account>
EOF
LAST=0
CURR=$(getuid);
CURRSUB=$CURR;

addkontenklasse() {
echo
echo -n "add kontenklasse $LAST";
cat >>"$OUT" <<EOF
<gnc:account version="2.0.0">
  <act:name>Kontenklasse $LAST</act:name>
  <act:id type="new">$CURR</act:id>
  <act:type>ASSET</act:type>
  <act:commodity>
    <cmdty:space>ISO4217</cmdty:space>
    <cmdty:id>EUR</cmdty:id>
  </act:commodity>
  <act:commodity-scu>100</act:commodity-scu>
  <act:description>Erträge</act:description>
  <act:slots>
    <slot>
      <slot:key>placeholder</slot:key>
      <slot:value type="string">true</slot:value>
    </slot>
  </act:slots>
  <act:parent type="new">$ROOT</act:parent>
</gnc:account>
EOF
echo " done";
}

addkontenklasse;

addkontengruppe() {
echo
echo -n "add kontengruppe $1";
cat >>"$OUT" <<EOF
<gnc:account version="2.0.0">
  <act:name>$ID $1</act:name>
  <act:id type="new">$CURRSUB</act:id>
  <act:type>ASSET</act:type>
  <act:commodity>
    <cmdty:space>ISO4217</cmdty:space>
    <cmdty:id>EUR</cmdty:id>
  </act:commodity>
  <act:commodity-scu>100</act:commodity-scu>
  <act:description>$1</act:description>
  <act:slots>
    <slot>
      <slot:key>placeholder</slot:key>
      <slot:value type="string">true</slot:value>
    </slot>
  </act:slots>
  <act:parent type="new">$CURR</act:parent>
</gnc:account>
EOF
echo " done";
}

addkonto() {
cat >>"$OUT" <<EOF
<gnc:account version="2.0.0">
  <act:name>$1 $2</act:name>
  <act:id type="new">$(getuid)</act:id>
  <act:type>ASSET</act:type>
  <act:commodity>
    <cmdty:space>ISO4217</cmdty:space>
    <cmdty:id>EUR</cmdty:id>
  </act:commodity>
  <act:commodity-scu>100</act:commodity-scu>
  <act:description>$2</act:description>
  <act:code>$1</act:code>
  <act:parent type="new">$CURRSUB</act:parent>
</gnc:account>
EOF
}

while (true); do
 LL=$REPLY
 read
 if [ "x$REPLY" = "x" ]; then
   echo
   echo "end of file after $LL";
   break;
 fi
 REPLY=$(echo "$REPLY" | sed 's/\s\+/ /g');
 KTOID=$(echo "$REPLY" | sed 's/ .*//');
 NAME=$(echo "$REPLY" | sed 's/^[0-9]\+ \+//');
 if [ -z "$NAME" ]; then
   NAME="dummy";
 fi
 #echo "$REPLY => $KTOID | $NAME";
 echo -n "$KTOID "
 if [ -z "$KTOID" ]; then
   CURRSUB=$(getuid);
   ID=$(expr $ID + 1);
   addkontengruppe "$NAME";
 else 
  if [ $KTOID -gt "$LAST"999 ]; then
   # new cat
   LAST=$(echo $KTOID | sed 's/\(.\).*/\1/');
   CURR=$(getuid);
   CURRSUB=$CURR;
   ID=0
   addkontenklasse;
  fi
  addkonto "$KTOID" "$NAME"; 
 fi
done < "$FILE"

echo "</gnc-account-example>" >> "$OUT";
echo "done: written to $OUT"

Annotations

There are a few terms in the script, you might wish to adjust or at least understand:

  • Kontenklasse: account class, first level in the account hierarchy.
  • kontengruppe: account group, lower node in the tree, but no leave.
Both above are placeholders.
  • Konto: account.
  • Erträge: earnings.
  • <cmdty:id>: 3-letter ISO-currency symbol.
  • <act:commodity-scu>: smallest currency unit, in most cases 100 {C/S}en[t]*|P[f]en* or whatever.

Eventually you wish the account code $1 only in <act:code> and not in <act:name>.

Exporting an existing account hierarchy

You can create an account hierarchy template using this method.

  • You already have a account hierarchy in a gnucash file, but you want to export a subset
  • Go to file > export > export the xml
  • Select the subset you want from the xml as a starting point
  • Change the file xml structure according to the rules defined in this article
  • Take care when you change the xml file: ids and other information may conflict with your current account hierarchy
  • Put the xml file you edit on /usr/share/gnucash/your_language/yourfilename.gnucash-xea
  • Restart Gnucash
  • Use the New Account Hierarchy wizard to import your new account hierarchy

Back to Translation