You can add one or more posting modules, each containing any number of posting rules, to an existing chart of accounts (CoA).
Note the order in which posting rules are specified in a module is significant. For each journal entry line, LUSID uses the first matching posting rule found to post the debit or credit amount to a particular general ledger account.
Methods
Call the CreatePostingModule API, for example:
curl -X POST 'https://<your-domain>.lusid.com/api/api/chartofaccounts/CoAs/DailyCoA/postingmodules'
-H 'Content-Type: application/json-patch+json'
-H 'Authorization: Bearer <your-API-access-token>'
-d '{
"code": "DailyPM",
"displayName": "Daily NAV posting module",
"description": "This is a posting module for daily NAV",
"rules": [
{
"ruleId": "rule_0001",
"account": "Other-Investments",
"ruleFilter": "EconomicBucket startswith 'NA' and HoldType neq 'P'"
},
{
"ruleId": "rule_0002",
"account": "Cash",
"ruleFilter": "EconomicBucket startswith 'NA' and HoldType eq 'B'"
},
{
"ruleId": "rule_0003",
"account": "Commitments",
"ruleFilter": "EconomicBucket eq 'NA_Cost' and HoldType eq 'C'"
}
]
}'
Navigate to Fund Accounting > Chart of Accounts, open the Posting Modules tab, select the parent CoA and click the Create posting module button.
You can either add posting rules to the module using the Add button in this dialog, or alternatively navigate to the Posting Rules tab.
Write a Luminesce SQL query using the Lusid.PostingModule.Writer provider to create a posting module and the Lusid.PostingModule.Rule.Writer provider to set posting rules, and execute it using a tool such as the LUSID web app, for example:
Data fields
This section supplements the API documentation and on-screen help text in the LUSID web app.
A posting module is identified by a code
that must be unique within the parent CoA.
You can specify any number of posting rules. Note the order is significant. Each posting rule consists of:
A
ruleId
that uniquely identifies the posting rule in the posting module.The code of an
account
to post the credit or debit amount to. Note you can use Mustache template syntax to parameterise the codes of similar accounts, potentially reducing the number of posting rules.A
ruleFilter
specifying a rule. Syntax and allowed values.
Subsequent updates
Once created, you can edit an existing posting module as follows:
To change the
displayName
ordescription
of the module, call the SetPostingModuleDetails API. You cannot change thecode
.To change the order of existing rules in the module, call the SetPostingModuleRules API. Note you must specify all the rules again, this time in the required order; any omitted from the request are removed.
To insert one or more new posting rules at a specific order, call the PatchPostingModule API. For example, the following request adds a new rule as the second in the list (the index starts at 0):
curl -X PATCH 'https://<your-domain>.lusid.com/api/api/chartofaccounts/CoAs/DailyCoA/postingmodules/DailyPM' -H 'Content-Type: application/json-patch+json' -H 'Authorization: Bearer <your-API-access-token>' -d '[ { "value": { "ruleId": "rule_0001a", "generalLedgerAccountCode": "Error", "ruleFilter": "EconomicBucket eq 'PL_Other'" }, "path": "/rules/1", "op": "add" } ]'
To add a new rule as the first in the list, specify a
path
of/rules/0
. To add a new rule last, specify/rules/-
. LUSID automatically moves the index position of other rules.To delete a posting module, call the DeletePostingModule API.
Note it may be easier to change the order of posting rules in the LUSID web app using the ‘grab handles’ (in yellow) or up/down arrows (in red):
Parameterising account codes to reduce posting rules
You can use Mustache template syntax in the general ledger account field of a posting rule to derive account codes from data attributes of journal entry lines, potentially reducing the number of posting rules.
For example, imagine you have four general ledger accounts in your CoA that share the same purpose but with codes that distinguish between portfolio currency and strategy:
1101-GBP-Growth
1101-USD-Growth
1101-GBP-Income
1101-USD-Income
The following posting rule examines each journal entry line matching the ruleFilter
expression and posts the amount to an appropriate account:
"rules": [
{
"ruleId": "NA-Subscriptions",
"account": "1101-{{Portfolio.BaseCurrency}}-{{Properties[Transaction/SHKs/Strategy]}}",
"ruleFilter": "MovementName eq 'Subscriptions'"
}
]
This might replace the following four posting rules with more complicated ruleFilter
expressions:
"rules": [
{
"ruleId": "NA-Subscriptions-01",
"account": "1101-GBP-Growth",
"ruleFilter": "MovementName eq 'Subscriptions' and Portfolio.BaseCurrency eq 'GBP' and Properties[Transaction/SHKs/Strategy] eq 'Growth'"
},
{
"ruleId": "NA-Subscriptions-02",
"account": "1101-USD-Growth",
"ruleFilter": "MovementName eq 'Subscriptions' and Portfolio.BaseCurrency eq 'USD' and Properties[Transaction/SHKs/Strategy] eq 'Growth'"
},
{
"ruleId": "NA-Subscriptions-03",
"account": "1101-GBP-Income",
"ruleFilter": "MovementName eq 'Subscriptions' and Portfolio.BaseCurrency eq 'GBP' and Properties[Transaction/SHKs/Strategy] eq 'Income'"
},
{
"ruleId": "NA-Subscriptions-04",
"account": "1101-USD-Income",
"ruleFilter": "MovementName eq 'Subscriptions' and Portfolio.BaseCurrency eq 'USD' and Properties[Transaction/SHKs/Strategy] eq 'Income'"
}
]
Syntax of a posting rule
A posting rule consists of:
A
ruleId
that uniquely identifies the posting rule in the posting module.An
account
that is the code of an account in the parent chart of accounts (CoA).A
ruleFilter
expression that describes criteria for matching journal entry lines to the account.
The syntax of a ruleFilter
expression is:
<attribute> <operator> <value>
...where:
<attribute>
and<value>
are explained in the table below.<operator>
is one of the LUSID filter operators.
Note the following:
A
ruleFilter
expression is case-insensitive.A string
value
must be enclosed in single straight quote marks (the%27
UTF-8 encoding).You can concatenate expressions using the
and
andor
operators, for example:MovementName eq 'Side1' and subholdingkeys[Transaction/Ibor/Strategy] eq 'Income'
If you use both, standard boolean operator precedence applies:
InstrumentScope startswith 'Custom' or (LocalAmount lte 1000 and HoldType eq 'P')
| Data type | Example expression | Explanation/origin of | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| String |
| Either | ||||||||||||
| DateTime |
| For a transaction, this is the trade date. For a valuation, this is the date of the latest detected change to market data. | ||||||||||||
| String |
| LUSID automatically categorises every journal entry line into a broad economic bucket. Some economic buckets are further categorised into components and variants. More information. | ||||||||||||
| String |
| For a transaction, this is the unique identifier in the portfolio ( | ||||||||||||
| String |
| For a transaction, if the underlying instrument is a currency and the trade is settled (holding type of | ||||||||||||
| Decimal |
| The amount in the transaction currency. | ||||||||||||
| Decimal |
| The amount in the portfolio base currency. | ||||||||||||
| String |
| The currency of the underlying instrument, if specified. | ||||||||||||
| String |
| The instrument scope in which the underlying instrument is mastered. | ||||||||||||
| String |
| The LUID (globally unique ID) of the underlying instrument. | ||||||||||||
| String |
| One of the LUSID holding type codes. | ||||||||||||
| String |
| For a transaction, this is the name of the movement in the transaction type to which the transaction belongs. If the movement does not have a name (and note its For a valuation, this is always | ||||||||||||
| String |
| Either | ||||||||||||
| String |
| Either
| ||||||||||||
A sub-holding key on the portfolio | User-defined |
| Under-the-hood, a SHK is defined as a custom property with a 3-stage key in the | ||||||||||||
A portfolio field | System-defined |
| This can be any of the stored fields for a portfolio except the | ||||||||||||
A portfolio property | User-defined |
| This can be any property with a 3-stage key in the Portfolio domain. | ||||||||||||
An instrument field (see also a transaction instrument field, below) | System-defined |
| This can be any of the stored fields for an instrument except the | ||||||||||||
An instrument property (see also a transaction instrument property, below) | User-defined |
| This can be any property with a 3-stage key in the | ||||||||||||
A transaction field | System-defined |
| This can be any of the stored fields for a transaction, prefixed by | ||||||||||||
A transaction property | User-defined |
| This can be any property with a 3-stage key in the | ||||||||||||
An instrument field on a transaction | System-defined |
| If a journal entry line is generated in response to a currency movement, then the instrument of the line itself is a currency. The instrument of the original transaction, however, may be (for example) an equity. This gives you access to the instrument fields and properties of the equity. The available fields and properties are the same as those for the instrument of the line itself, above. | ||||||||||||
An instrument property on a transaction | User-defined |
| |||||||||||||
An account field | System-defined |
| This can be any of the stored fields for an account, prefixed by | ||||||||||||
An account property | User-defined |
| This can be any property with a 3-stage key in the | ||||||||||||
A fund property | User-defined |
| This can be any property with a 3-stage key in the | ||||||||||||
An ABOR property (V1 funds only) | User-defined |
| This can be any property with a 3-stage key in the |