BANAL version 0.10
Chapter 5: Recurring and Memorized Transactions
A recurrence entry allows you to periodically create entries in
an existing database (including the recurrence database itself).
There are two types of recurrence entries:
- Recurring
-
These entries will be run periodically. You can also specify
that a recurring entry be run once, afterwards it will be
changed to a memorized entry.
- Memorized
-
A memorized entry may only be run by explicitly requesting it
on the command line. It is never run automatically.
5.1: Adding a Recurrence Entry
Adding a recurrence entry is identical to adding an entry for any
other database (eg. Expense). However, being the most complicated
database, it deserves special attention.
The fields and their meanings are:
- Recurrence
-
This, like other databases, is the unique identifier for this entry.
- Description
-
Optional description of the recurrence entry.
- TableName
-
This field specifies the database for which you are creating an entry.
Values for this field include
Expense, Invoice and Charge (plus all of
the others and any that you have created).
- Template
-
Similar to the
-t option to all edit commands, this option allows
you to specify an existing (at the time of the recurrence entry running)
entry in the database named in the TableName field. You will not be able
to overwrite the templated entry, so if you have not changed the new
entry's unique ID in the Commands field then it will revert to 'new'.
- NextDate
-
This field states when the entry should be processed for the first time.
Leave this field empty if you want a memorized entry. If you specify a
date in the past then the entry will be processed on that date and for
every valid date (based on the Interval) thereafter.
- Interval
-
Uses this field to define how often BANAL will process you entry.
Use 'none' for a memorized entry. Other valid values are
once,
day, week, month and year.
- Commands
-
This field is the most critical. You may specify any valid perl command
and you will have access to two important functions: makeDate and incrDate.
Also you may assign the field values for the created entry in TableName
directly (eg. Invoice = 'Someinvoice';), however, when using the field
names you must have them completely surrounded by whitespace. See the
section on commands (5.2) for more information.
5.2: Commands in a Recurrence Entry
The basics of the Commands field in a recurrence entry are simple.
Let's look at creating an invoice as an example. Use bk invoices -F
to obtain the field names. A basic set of commands to make an invoice
every month would look like:
Invoice = makeDate("CLI-%y-%m");
Client = 'someclient';
$tmp = 'Services invoice. Pay up by ';
Date = makeDate("%Y.%m%d");
Description = $tmp . incrDate( Date , 90);
From = makeDate("%Y.%m01");
To = makeDate("%Y.%m%l");
You can use the makeDate function to create dates based on the running
date (which may or may not be the same as the current date). See the
section on makeDate (5.2.1) for details.
There are some important caveats:
- Do not embedded Perl style comment in the commands. The only
current exception is if they are placed after all valid command
statements.
- Do keep whitespace (spaces, tabs, newlines) around all use
of field names. Otherwise they will not be recognized as such.
- The only legal field names are the ones in the database entry.
5.2.1: makeDate
The makeDate function take a string with embedded directives that
will be parsed and substituted as appropriate. You would use it
in a statement similar to:
$value = makeDate("some string %d with directives");
Directive are always in the format '%c', where c is any character.
The directives are:
- %%
-
a literal %
- %b
-
abbreviated month name (Jan..Dec)
- %d
-
day of month (01..31)
- %j
-
day of year (001..366)
- %l
-
last day of the month (28..31)
- %m
-
month (01..12)
- %U
-
week number of year with Sunday as first day of week (00..53)
- %w
-
day of the week (0..6)
- %y
-
last two digits of year (00..99)
- %Y
-
year (1970...)
An example (run on February 10, 1997):
makeDate("%j: Happy b-day mom, %Y.%m%d")
would give:
41: Happy b-day mom, 1997.0210
5.2.2: incrDate
The incrDate function take a date in the normail format (YYYY.MMDD)
and increases/decreases it based on the intervals specified. The
incrments are days, months and years (in that order). You would
use it in a statement similar to:
$value = incrDate("1997.0901", 1, 2, 3);
This would increase the supplied date (Sept. 1, 1997) by 1 day,
2 months and 3 years.
You may also use negative values.
5.2.3: existsSetting
The existsSetting function take a string in the normal format
and returns a boolean value (0 or 1) depending on whether or not the
setting exists. You could use it in a statement similar to:
$value = existsSetting("/My/Toy/Setting") ? 1 : 2;
This would set the $value variable to 1 if the setting "/My/Toy/Setting"
exists and to 2 if it does not.
5.2.4: getSetting
The getSetting function take a string in the normal Setting format
and returns the value (or undef) depending on whether or not the
setting exists. You could use it in a statement similar to:
$value = getSetting("/My/Toy/Setting") || 1.0;
This would set the $value variable to whatever the setting is or to 1.0
if the setting doesn't exist or has a 0/""/undef value.
Because 0 or empty strings are sometimes a legitimate value, it is usually
better to do something more complicated to ensure that you get the right
values.
$value = existsSetting("/Setting") ? getSetting("/Setting") : 1.0;
This will use the value of "/Setting" no matter what it is, if it exists.
Otherwise, it will use 1.0.
5.2.5: Extra Commands on the command line
When using the runbatch (2.7) command you may wish to specify
additional argument on the command line. These commands are run before
any memorized or recurring transactions' commands are processed (and they
are redone for each transaction).
A useful example would be for creating an invoice and overriding
the Client name. You could specify: Client = 'SGI' (with appropriate
shell quoting, of course). And then have a line in the Commands field (note
the space between Client and ';') such as:
Client = 'Bruce' if not Client ;
You may also wish to use temporary variables on the command line and in
the commands section. Do this by specifying the variable on the command
line like:
bk runbatch '$myvar = "some string or value";'
Then have a line in you Commands field of the recurrence which makes
use of it. Like:
Description = $myvar;