feat(dds): DDS product accounting tab; DDS posts only through product GLs
- DDS product names its own Customer Deposits, Interest Expense and Agent Commission Expense GLs (validated by kind), shown on the product view and in the approval review with old -> new on edits - DdsLedger posts every DDS movement through the party's product GLs; commission is shared over the products an agent collected for - dds-* settings removed from Global Configurations (0620); scheme accounts recognised by the DDS party linked to them, not a product id - 0621 drops the agent cash, matured payable and current control GL columns, which nothing posts to - Approval preview of interest/commission runs shows the product GLs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+10
@@ -55,6 +55,16 @@ public final class DdsAccountTypeData implements Serializable {
|
||||
/** The scheme's annual interest rate, which an account opened on it takes. */
|
||||
private final BigDecimal interestRate;
|
||||
private final Boolean active;
|
||||
/** The product's own ledger accounts (see DdsAccountType), each with its code and name to show it by. */
|
||||
private final Long depositLiabilityGlId;
|
||||
private final String depositLiabilityGlCode;
|
||||
private final String depositLiabilityGlName;
|
||||
private final Long interestExpenseGlId;
|
||||
private final String interestExpenseGlCode;
|
||||
private final String interestExpenseGlName;
|
||||
private final Long commissionExpenseGlId;
|
||||
private final String commissionExpenseGlCode;
|
||||
private final String commissionExpenseGlName;
|
||||
private final LocalDateTime createdDate;
|
||||
private final LocalDateTime lastModifiedDate;
|
||||
}
|
||||
|
||||
+38
@@ -115,6 +115,24 @@ public class DdsAccountType extends AbstractAuditableCustom {
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean active;
|
||||
|
||||
/**
|
||||
* The ledger accounts this product posts through, chosen on its Accounting tab the way a savings
|
||||
* product chooses its own. DDS posts through these alone - there is no bank-wide account to fall
|
||||
* back on - so a product missing one stops its postings with a message naming what to set.
|
||||
*
|
||||
* What the bank owes this product's customers - DDS Customer Deposits, or the product's own.
|
||||
*/
|
||||
@Column(name = "deposit_liability_gl_id")
|
||||
private Long depositLiabilityGlId;
|
||||
|
||||
/** What interest paid to this product's customers costs the bank. */
|
||||
@Column(name = "interest_expense_gl_id")
|
||||
private Long interestExpenseGlId;
|
||||
|
||||
/** What the agents' commission on collecting for this product costs the bank. */
|
||||
@Column(name = "commission_expense_gl_id")
|
||||
private Long commissionExpenseGlId;
|
||||
|
||||
protected DdsAccountType() {
|
||||
//
|
||||
}
|
||||
@@ -131,6 +149,9 @@ public class DdsAccountType extends AbstractAuditableCustom {
|
||||
this.prematureInterestReduction = valueOr(command, "prematureInterestReduction", DEFAULT_INTEREST_REDUCTION);
|
||||
this.prematureAgentCommissionPenalty = valueOr(command, "prematureAgentCommissionPenalty", DEFAULT_AGENT_PENALTY);
|
||||
this.interestRate = command.bigDecimalValueOfParameterNamed("interestRate");
|
||||
this.depositLiabilityGlId = command.longValueOfParameterNamed("depositLiabilityGlId");
|
||||
this.interestExpenseGlId = command.longValueOfParameterNamed("interestExpenseGlId");
|
||||
this.commissionExpenseGlId = command.longValueOfParameterNamed("commissionExpenseGlId");
|
||||
// A newly created account type is available for use straight away.
|
||||
this.active = !command.parameterExists("active") || command.booleanPrimitiveValueOfParameterNamed("active");
|
||||
}
|
||||
@@ -238,6 +259,23 @@ public class DdsAccountType extends AbstractAuditableCustom {
|
||||
this.interestRate = newValue;
|
||||
}
|
||||
|
||||
// The product's ledger accounts. All three are required; the deserializer refuses a null.
|
||||
if (command.parameterExists("depositLiabilityGlId")
|
||||
&& command.isChangeInLongParameterNamed("depositLiabilityGlId", this.depositLiabilityGlId)) {
|
||||
this.depositLiabilityGlId = command.longValueOfParameterNamed("depositLiabilityGlId");
|
||||
actualChanges.put("depositLiabilityGlId", this.depositLiabilityGlId);
|
||||
}
|
||||
if (command.parameterExists("interestExpenseGlId")
|
||||
&& command.isChangeInLongParameterNamed("interestExpenseGlId", this.interestExpenseGlId)) {
|
||||
this.interestExpenseGlId = command.longValueOfParameterNamed("interestExpenseGlId");
|
||||
actualChanges.put("interestExpenseGlId", this.interestExpenseGlId);
|
||||
}
|
||||
if (command.parameterExists("commissionExpenseGlId")
|
||||
&& command.isChangeInLongParameterNamed("commissionExpenseGlId", this.commissionExpenseGlId)) {
|
||||
this.commissionExpenseGlId = command.longValueOfParameterNamed("commissionExpenseGlId");
|
||||
actualChanges.put("commissionExpenseGlId", this.commissionExpenseGlId);
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed("active", this.active)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed("active");
|
||||
actualChanges.put("active", newValue);
|
||||
|
||||
Reference in New Issue
Block a user