Send One Account's Ledger Lines in Local Currency at Rate 1
This Groovy script changes the ledger lines of one chosen account just before a document sends its accounting request: a line entered in a foreign currency is rewritten as its local amount, in local currency, at rate 1. Every other account on the document keeps its foreign currency and rate.
Recommended pattern
This script is not tied to any customer's setup. You can paste it as it is and control it entirely through its parameters.
| Class name | EASetTransCurrencyToLocalCurrencyAndRateOne |
| Script | EASetTransCurrencyToLocalCurrencyAndRateOne.groovy |
| Runs on | Any document that has an accounting effect, at the moment it sends its accounting request. |
| Uses | Parameter 2. Leave Parameter 1 empty. |
| Shipped as | Source to paste. It is not built into the system. |
When to use it
Each ledger line remembers the currency it was entered in. When a document is entered in US dollars at a rate of 50, every one of its lines carries 100 USD at 50, even on an account the company only ever follows in Egyptian pounds. Statements and reports that work in the transaction currency then show dollar amounts on an account where nobody expects them.
This script lets one such account be posted in local currency only. Suppose the expense account 53010202 (maintenance) should always read in pounds. A journal entry in dollars debits it with 100 USD at 50 and credits another account with the same amount. With the script set to 53010202, the maintenance line is sent as 5,000 EGP at rate 1. The other line stays 100 USD at 50. The local amounts, and so the balances in local currency, do not change at all.
How it works
- It waits for the accounting request. The script does something only at the moment a document sends its accounting request (Pre Send Business Request). At every other moment it returns at once, and it ignores the document's inventory requests.
- It finds the account's lines. It goes through the request's lines and picks those whose account code is the one in Parameter 2.
- It rewrites each foreign amount. For a debit or credit whose rate is not 1, the amount becomes the line's local amount, the currency becomes the account's currency, and the rate becomes 1. A line that is already at rate 1, or that has no amount, is left alone.
- It combines matching lines. If anything changed, lines that now match each other are combined into one, as the system does when it shortens a ledger.
The document itself is not changed. Only the accounting effect it creates is.
Only for an account kept in local currency
The script takes the currency from the account: the account's own Currency, or the ledger's main currency when the account has Use Transaction Local Currency ticked. On an account kept in a foreign currency, the line would get the local amount labelled with the foreign currency, which is wrong. Use it only for accounts whose currency is the local one.
Setting it up
- Open Administration → Display Customization → Entity Flow and create a new flow. Set Target Type to the document whose accounting effect should change, for example Journal Entry. Use an Entity Type List to cover several documents with one flow.
- Add a line to the Details grid. Paste the whole script from the file above into Groovy Script, and leave Class Name empty: it is filled in when you save.
- Fill in the parameters:
| Parameter | Title shown after saving | What to enter |
|---|---|---|
| Parameter 1 | Not used - leave empty | Nothing. |
| Parameter 2 | Account Code | The code of the account to send in local currency, for example 53010202. |
- Save the flow. Class Name shows the script's class name, the description appears in Description, and the line's Target Action becomes Automatic whatever you chose. That is expected: the script asks the system to call it at every moment and checks for itself that the accounting request is being sent.
Example
A journal entry dated today, in US dollars at a rate of 50:
| Account | Debit | Credit |
|---|---|---|
53010202 Maintenance and repair | 100 USD | |
42010202 Other revenues | 100 USD |
With the script set to 53010202, the ledger lines the entry creates are:
| Account | Transaction amount | Currency | Rate | Local amount |
|---|---|---|---|---|
53010202 | 5,000 | EGP | 1 | 5,000 |
42010202 | 100 | USD | 50 | 5,000 |
Without the script, both lines would read 100 USD at 50.
The script
package com.namasoft.modules.accounting.domain.utils.actions
import com.namasoft.common.utilities.ObjectChecker
import com.namasoft.infra.domainbase.common.valueobjects.TransactionMoney
import com.namasoft.infra.domainbase.datafields.DecimalDF
import com.namasoft.infra.domainbase.datafields.EntityCodeDF
import com.namasoft.infra.domainbase.datafields.LongTextDF
import com.namasoft.infra.domainbase.entity.base.DocumentFile
import com.namasoft.infra.domainbase.entity.base.EntityAction
import com.namasoft.infra.domainbase.modules.basic.LegalEntity
import com.namasoft.infra.domainbase.util.Result
import com.namasoft.modules.accounting.domain.entities.Account
import com.namasoft.modules.basic.domain.primitives.EntityTargetAction
import com.namasoft.modules.basic.domain.requests.BusinessRequest
import com.namasoft.modules.basic.domain.requests.LedgerTransReq
class EASetTransCurrencyToLocalCurrencyAndRateOne implements EntityAction<DocumentFile> {
@Override
Result doAction(EntityTargetAction action, DocumentFile object, LongTextDF... parameters) {
if (ObjectChecker.areNotEqual(action, EntityTargetAction.PreSendRequest()))
return Result.createSuccessResult()
Result result = Result.createAccumulatingResult()
BusinessRequest request = object.fetchCurrentlySendingRequest()
if (!(request instanceof LedgerTransReq))
return Result.createSuccessResult()
LedgerTransReq ltr = request
EntityCodeDF c = EntityCodeDF.fromDataField(parameters[1])
boolean updateHappened = false;
for (final def l in ltr.getLinesList().getLines()) {
if (l.getAccount() == null)
continue
Account acc = l.getAccount().toReal()
if (acc == null)
continue
if (ObjectChecker.areNotEqual(acc.getCode(), c))
continue
updateHappened = updateMoney(l.getDebit(), acc, object.getLegalEntity()) || updateHappened
updateHappened = updateMoney(l.getCredit(), acc, object.getLegalEntity()) || updateHappened
}
if (updateHappened)
ltr.shortenLines()
return result
}
@Override
String describe() {
return "Runs just before a document sends its accounting request (Pre Send Business Request); the line's target action is forced to Automatic. " +
"On every ledger line whose account code is in parameter 2, a debit or credit whose rate is not 1 is rewritten as its local amount, " +
"in the account's currency, at rate 1. Matching lines are then combined into one. Use it only for an account kept in the local currency. " +
"Parameter 1 is not used."
}
@Override
List<String> columnNames() {
return Arrays.asList("Not used - leave empty", "Account Code")
}
static boolean updateMoney(TransactionMoney m, Account acc, LegalEntity le) {
if (m == null || m.getValue() == null || DecimalDF.isEmptyOrZero(m.getValue().getAmount()))
return false
def currency = acc.fetchCurrency(le)
if (ObjectChecker.areEqual(m.getRate(), DecimalDF.one()))
return false;
m.getValue().setAmount(m.getLocalAmount())
m.getValue().setCurrency(currency)
m.setRate(DecimalDF.one())
return true;
}
@Override
public boolean isAutomaticForced() {
return true
}
}Related
- EAGroovyAction: how Groovy scripts are attached to entity flows and task schedules.
- Introduction to Entity Flows: the Pre Send Business Request moment.
- Accounts