fix(dds): approval of a calculation run shows the entries its posting will book
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Waiting to run
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Waiting to run
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Waiting to run
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Waiting to run
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Waiting to run
Fineract Documentation build / build (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Waiting to run
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Waiting to run
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Waiting to run
Fineract Liquibase Only mode - PostgreSQL / test (push) Waiting to run
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Waiting to run
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Waiting to run
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Waiting to run
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Waiting to run
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Waiting to run
Fineract Documentation build / build (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Waiting to run
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Waiting to run
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Waiting to run
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Waiting to run
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Waiting to run
Fineract Liquibase Only mode - PostgreSQL / test (push) Waiting to run
- A calculation run books nothing on the ledger, yet its approval preview was built as a posting and showed "Agent Commission Expense not set on the DDS product". The preview now projects the entries the matching Posting run will make, marked projected - A commission calculation's split over product Commission Expense GLs is taken from the agent's collections no run has counted yet, up to the run's end date Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
+22
@@ -508,6 +508,28 @@ public class DdsLedger {
|
|||||||
if (basis.isEmpty()) {
|
if (basis.isEmpty()) {
|
||||||
basis = this.jdbcTemplate.queryForList(String.format(COMMISSION_BASIS_SQL, ""), agentId, payingRunId); // NOSONAR
|
basis = this.jdbcTemplate.queryForList(String.format(COMMISSION_BASIS_SQL, ""), agentId, payingRunId); // NOSONAR
|
||||||
}
|
}
|
||||||
|
return shareOut(basis, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The collections a commission run would count if it were posted now: not counted by any run yet, up to a date. */
|
||||||
|
private static final String COMMISSION_PENDING_SQL = "select upper(trim(p.sub_type)) as \"product\", t.commission_expense_gl_id as \"glId\", "
|
||||||
|
+ "sum(pt.amount) as \"volume\" from m_dds_party_transaction pt join m_dds_party p on p.id = pt.party_id "
|
||||||
|
+ "left join m_dds_account_type t on t.account_type_code = upper(trim(p.sub_type)) "
|
||||||
|
+ "where pt.agent_id = ? and pt.transaction_type = 'PARTY_TRAN' and pt.direction = 'CREDIT' "
|
||||||
|
+ "and pt.commission_batch_run_id is null and pt.transaction_date <= ? group by upper(trim(p.sub_type)), "
|
||||||
|
+ "t.commission_expense_gl_id order by upper(trim(p.sub_type))";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where an agent's commission will be booked once it is posted - for a calculation run, which books
|
||||||
|
* nothing itself but whose approval should say which commission accounts the Posting run will debit.
|
||||||
|
* The split is over the collections the calculation counts (none counted yet, up to its end date).
|
||||||
|
*/
|
||||||
|
public Map<GLAccount, BigDecimal> projectedCommissionSplit(final Long agentId, final BigDecimal amount, final LocalDate through) {
|
||||||
|
return shareOut(this.jdbcTemplate.queryForList(COMMISSION_PENDING_SQL, agentId, java.sql.Date.valueOf(through)), amount); // NOSONAR
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Shares an amount over the commission accounts of the products collected for, by volume; the last takes the rounding. */
|
||||||
|
private Map<GLAccount, BigDecimal> shareOut(final List<Map<String, Object>> basis, final BigDecimal amount) {
|
||||||
if (basis.isEmpty()) {
|
if (basis.isEmpty()) {
|
||||||
throw new DdsLedgerNotConfiguredException("a collection by this agent to tell which DDS product's Agent Commission Expense "
|
throw new DdsLedgerNotConfiguredException("a collection by this agent to tell which DDS product's Agent Commission Expense "
|
||||||
+ "account the commission belongs to");
|
+ "account the commission belongs to");
|
||||||
|
|||||||
+15
-2
@@ -582,13 +582,22 @@ public class DdsApprovalReadService {
|
|||||||
// customer's product's interest account, commission shared over the commission accounts
|
// customer's product's interest account, commission shared over the commission accounts
|
||||||
// of the products each agent collected for, as the posting itself will book it.
|
// of the products each agent collected for, as the posting itself will book it.
|
||||||
final String jobType = first("select job_type from m_dds_batch_run where id = ?", resourceId);
|
final String jobType = first("select job_type from m_dds_batch_run where id = ?", resourceId);
|
||||||
|
// A calculation books nothing itself; its lines are what the matching Posting run will
|
||||||
|
// book, shown so the checker sees which accounts and ledger accounts the figures belong to.
|
||||||
|
final boolean projected = jobType != null && jobType.endsWith("_CALCULATION");
|
||||||
if (jobType != null && jobType.startsWith("COMMISSION")) {
|
if (jobType != null && jobType.startsWith("COMMISSION")) {
|
||||||
final Map<String, BigDecimal> byAccount = new LinkedHashMap<>();
|
final Map<String, BigDecimal> byAccount = new LinkedHashMap<>();
|
||||||
final Map<String, String> names = new LinkedHashMap<>();
|
final Map<String, String> names = new LinkedHashMap<>();
|
||||||
for (final Map<String, Object> runRow : this.jdbcTemplate.queryForList( // NOSONAR
|
for (final Map<String, Object> runRow : this.jdbcTemplate.queryForList( // NOSONAR
|
||||||
"select agent_id, amount from m_dds_batch_run_row where batch_run_id = ? and amount > 0 order by id", resourceId)) {
|
"select agent_id, amount, to_date from m_dds_batch_run_row where batch_run_id = ? and amount > 0 order by id",
|
||||||
|
resourceId)) {
|
||||||
try {
|
try {
|
||||||
this.ddsLedger.commissionSplit(((Number) runRow.get("agent_id")).longValue(), (BigDecimal) runRow.get("amount"), resourceId)
|
final long agentOfRow = ((Number) runRow.get("agent_id")).longValue();
|
||||||
|
final BigDecimal amountOfRow = (BigDecimal) runRow.get("amount");
|
||||||
|
(projected && runRow.get("to_date") != null
|
||||||
|
? this.ddsLedger.projectedCommissionSplit(agentOfRow, amountOfRow,
|
||||||
|
((java.sql.Date) runRow.get("to_date")).toLocalDate())
|
||||||
|
: this.ddsLedger.commissionSplit(agentOfRow, amountOfRow, resourceId))
|
||||||
.forEach((account, share) -> {
|
.forEach((account, share) -> {
|
||||||
byAccount.merge(account.getGlCode(), share, BigDecimal::add);
|
byAccount.merge(account.getGlCode(), share, BigDecimal::add);
|
||||||
names.put(account.getGlCode(), account.getName());
|
names.put(account.getGlCode(), account.getName());
|
||||||
@@ -622,6 +631,10 @@ public class DdsApprovalReadService {
|
|||||||
lines.add(line("CR", (String) credited.get("accountNo"), (String) credited.get("accountName"),
|
lines.add(line("CR", (String) credited.get("accountNo"), (String) credited.get("accountName"),
|
||||||
(String) credited.get("type"), (BigDecimal) credited.get("amount")));
|
(String) credited.get("type"), (BigDecimal) credited.get("amount")));
|
||||||
}
|
}
|
||||||
|
if (projected) {
|
||||||
|
// Marked, so the review says these entries are made by the Posting run, not on approval.
|
||||||
|
lines.forEach(each -> each.put("projected", true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default -> {
|
default -> {
|
||||||
// A change to a party, agent or scheme moves no money and has no sides.
|
// A change to a party, agent or scheme moves no money and has no sides.
|
||||||
|
|||||||
Reference in New Issue
Block a user