diff --git a/src/app/deposits/dds-accounts/dds-account-view/dds-account-view.component.ts b/src/app/deposits/dds-accounts/dds-account-view/dds-account-view.component.ts
index 8f9e097ba..e27d63091 100644
--- a/src/app/deposits/dds-accounts/dds-account-view/dds-account-view.component.ts
+++ b/src/app/deposits/dds-accounts/dds-account-view/dds-account-view.component.ts
@@ -666,7 +666,8 @@ export class DdsAccountViewComponent implements OnInit {
id: account.id,
agentId: account.agentId,
interestCalc: account.interestCalc,
- collectedToDate: account.collectedToDate
+ collectedToDate: account.collectedToDate,
+ openingBalance: account.openingBalance
},
width: '960px',
maxWidth: '96vw',
diff --git a/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.html b/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.html
index cff4b29bb..c675c3c3f 100644
--- a/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.html
+++ b/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.html
@@ -62,16 +62,6 @@
}
- @if (pendingInterest > 0) {
-
@@ -131,7 +121,8 @@
Either way, {{ data.agentCode }} is charged
{{ scheme.prematureAgentCommissionPenalty | number: '1.0-2' }}%
- of the commission owed to them — the round was not kept going.
}
@@ -258,7 +249,12 @@
₹{{ deposits | number: '1.2-2' }}
- Interest credited so far
+ Interest credited so far
+ @if (creditedThrough) {
+ till {{ creditedThrough | dateFormat }}
+ }
+
@if (interestCredited === null) {
…
@@ -267,18 +263,107 @@
}
+
+ @if (interestDue > 0) {
+
+ Interest still to credit
+ @if (interestThrough) {
+ till {{ interestThrough | dateFormat }} — added at closing
+ }
+
+ + ₹{{ interestDue | number: '1.2-2' }}
+
+ } @else if (interestThrough) {
+
+ Interest is up to date
+ credited till {{ interestThrough | dateFormat }}
+
+ }
+
+
+ Total interest earned
+ @if (interestThrough) {
+ {{ data.openingDate | dateFormat }} to {{ interestThrough | dateFormat }}
+ }
+
+ ₹{{ totalInterest | number: '1.2-2' }}
+
- Current balance
+ Balance on closing day
+ {{ businessDate | dateFormat }} — this day earns no interest, the money leaves today
₹{{ balance | number: '1.2-2' }}
+
+ @if (interestDays.length > 0) {
+
+
+ {{ showDays ? 'Hide' : 'Show' }} day-by-day interest ({{ interestDays.length }}
+ {{ interestDays.length === 1 ? 'day' : 'days' }})
+
+ @if (showDays) {
+
+
+
+
+ Date
+ Balance
+ Interest
+
+
+
+
+ @for (day of interestDays; track day.date.getTime()) {
+
+ {{ day.date | dateFormat }}
+ ₹{{ day.balance | number: '1.2-2' }}
+ ₹{{ day.interest | number: '1.4-4' }}
+
+ {{
+ day.credited ? 'Credited' : 'To credit'
+ }}
+
+
+ }
+
+
+
+ Credited so far
+ ₹{{ interestCredited ?? 0 | number: '1.2-2' }}
+
+ @if (interestDue > 0) {
+
+ Added at closing
+ + ₹{{ interestDue | number: '1.2-2' }}
+
+ }
+
+ Total interest
+ ₹{{ totalInterest | number: '1.2-2' }}
+
+
+
+
+ Balance × {{ data.interestRate | number: '1.0-2' }}% ÷ 365 for each day. Each run's total is rounded to
+ paise, so the totals can differ from the day figures by a paisa. {{ businessDate | dateFormat }}, the
+ closing day, earns nothing.
+
+
+ }
+ }
+
@if (borneBy === 'CUSTOMER') {
Interest taken back
₹{{ interestCredited ?? 0 | number: '1.2-2' }} ×
- {{ data.interestRate - reducedRate | number: '1.0-2' }}% ÷
+ >₹{{ totalInterest | number: '1.2-2' }} × {{ data.interestRate - reducedRate | number: '1.0-2' }}% ÷
{{ data.interestRate | number: '1.0-2' }}%
@@ -319,13 +404,19 @@
Commission penalty
- @if (scheme?.prematureAgentCommissionPenalty > 0) {
+ @if (agentPenalty && (agentPenalty.penaltyRate ?? 0) > 0) {
{{ scheme.prematureAgentCommissionPenalty | number: '1.0-2' }}% of ₹{{
- agentCommission ?? 0 | number: '1.2-2'
- }}
- owed ₹{{ agentPenalty.collection ?? 0 | number: '1.2-2' }} collected on this account ×
+ {{ agentPenalty.penaltyRate | number: '1.0-2' }}%
+ @if (agentPenalty.commissionEarned !== null && agentPenalty.commissionEarned !== undefined) {
+ {{ penaltyCapped ? 'Capped at' : 'Never more than' }} ₹{{
+ agentPenalty.commissionEarned | number: '1.2-2'
+ }}
+ this account earned them ({{ agentPenalty.commissionRate | number: '1.0-2' }}% commission)
+ }
}
₹{{ commissionPenalty | number: '1.2-2' }}
diff --git a/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.scss b/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.scss
index 1044fbddf..ee0803ede 100644
--- a/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.scss
+++ b/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.scss
@@ -449,6 +449,23 @@
font-variant-numeric: tabular-nums;
}
+ &--ok {
+ color: #15803d;
+ }
+
+ &--interest {
+ margin: 4px 0;
+ padding: 8px 10px;
+ border-radius: 8px;
+ background: #f0fdf4;
+ color: #15803d;
+ font-weight: 600;
+
+ b {
+ font-size: 0.95rem;
+ }
+ }
+
&--sum {
margin-top: 2px;
border-top: 1px dashed #cbd5e1;
@@ -526,6 +543,102 @@
}
}
+/* The interest day by day, opened from the calculation panel */
+.pcd-days {
+ max-height: 260px;
+ margin: 2px 0 6px;
+ overflow: auto;
+ border: 1px solid #e2e8f0;
+ border-radius: 8px;
+ background: #fff;
+
+ &__toggle {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ margin: 4px 0 6px;
+ padding: 0;
+ border: none;
+ background: none;
+ color: #4338ca;
+ font: inherit;
+ font-size: 0.78rem;
+ font-weight: 600;
+ cursor: pointer;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+
+ table {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.76rem;
+ }
+
+ th,
+ td {
+ padding: 5px 8px;
+ border-bottom: 1px solid #f1f5f9;
+ text-align: left;
+ white-space: nowrap;
+ }
+
+ th {
+ position: sticky;
+ top: 0;
+ background: #f8fafc;
+ font-size: 0.68rem;
+ font-weight: 700;
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+ color: #64748b;
+ }
+
+ .num {
+ text-align: right;
+ font-variant-numeric: tabular-nums;
+ }
+
+ tfoot td {
+ font-weight: 600;
+ color: #334155;
+ }
+
+ &__due td {
+ color: #15803d;
+ }
+
+ &__sum td {
+ border-top: 1px solid #cbd5e1;
+ color: #0f172a;
+ }
+
+ &__tag {
+ padding: 1px 7px;
+ border-radius: 999px;
+ background: #f1f5f9;
+ font-size: 0.68rem;
+ font-weight: 600;
+ color: #475569;
+
+ &--due {
+ background: #dcfce7;
+ color: #15803d;
+ }
+ }
+
+ &__note {
+ margin: 0;
+ padding: 6px 8px 8px;
+ font-size: 0.7rem;
+ line-height: 1.5;
+ color: #94a3b8;
+ white-space: normal;
+ }
+}
+
@media (width <= 760px) {
.pcd-grid {
grid-template-columns: minmax(0, 1fr);
diff --git a/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.ts b/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.ts
index 69d895c57..31d2be321 100644
--- a/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.ts
+++ b/src/app/deposits/party-master/premature-close-dialog/premature-close-dialog.component.ts
@@ -23,6 +23,7 @@ import { FaIconComponent } from '@fortawesome/angular-fontawesome';
/** Custom Services */
import { OrganizationService } from 'app/organization/organization.service';
import { ProductsService } from 'app/products/products.service';
+import { SettingsService } from 'app/settings/settings.service';
/** Custom Pipes */
import { DateFormatPipe } from 'app/pipes/date-format.pipe';
@@ -66,6 +67,7 @@ import { DateFormatPipe } from 'app/pipes/date-format.pipe';
export class PrematureCloseDialogComponent implements OnInit {
private organizationService = inject(OrganizationService);
private productsService = inject(ProductsService);
+ private settingsService = inject(SettingsService);
private dialogRef = inject(MatDialogRef
);
data = inject(MAT_DIALOG_DATA);
@@ -183,6 +185,7 @@ export class PrematureCloseDialogComponent implements OnInit {
this.organizationService.getPartyTransactionsOfParty(this.data.id).subscribe({
next: (txns: any) => {
const list: any[] = Array.isArray(txns) ? txns : txns?.pageItems || [];
+ this.transactions = list;
this.interestCredited = list
.filter((t) => PrematureCloseDialogComponent.INTEREST_TYPES.includes(t.transactionType))
.reduce((sum, t) => sum + (t.direction === 'DEBIT' ? -1 : 1) * Number(t.amount || 0), 0);
@@ -190,11 +193,18 @@ export class PrematureCloseDialogComponent implements OnInit {
error: () => (this.interestCredited = null)
});
}
- // The commission the agent is owed now, which the scheme's penalty is a share of.
- if (this.data.agentId) {
- this.organizationService.getAgent(this.data.agentId).subscribe({
- next: (agent: any) => (this.agentCommission = Number(agent?.commission || 0)),
- error: () => (this.agentCommission = null)
+ // Interest earned through yesterday but not yet credited. The closure credits it first, so the
+ // figures below start from it rather than from a balance that is a few days behind.
+ if (this.data.id) {
+ this.organizationService.getPartyInterestDue(this.data.id).subscribe({
+ next: (due: any) => {
+ this.interestDue = Number(due?.interestDue || 0);
+ this.interestThrough = due?.through ?? null;
+ this.creditedThrough = due?.creditedThrough ?? null;
+ // The agent's penalty as the server works it out: on this account's collection alone.
+ this.agentPenalty = due?.agentPenalty ?? null;
+ },
+ error: () => (this.interestDue = 0)
});
}
}
@@ -207,33 +217,113 @@ export class PrematureCloseDialogComponent implements OnInit {
/** Interest credited to the account so far; null until read (or if it could not be). */
interestCredited: number | null = null;
- /** What the agent is owed in commission today; null until read. */
- agentCommission: number | null = null;
+ /** Interest earned through the day before closing but not yet credited - credited by the closure itself. */
+ interestDue = 0;
+ /** The last day that earns (the day before the business date), and the day interest is credited through now. */
+ interestThrough: string | null = null;
+ creditedThrough: string | null = null;
+
+ /** Everything posted to the account, for the day-by-day interest table. */
+ private transactions: any[] = [];
+
+ /** Whether the day-by-day interest table is open. */
+ showDays = false;
+
+ private static dayKey(date: Date): string {
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
+ }
+
+ /**
+ * Each earning day from opening to the day before closing: the balance at the end of that day - every
+ * movement up to it, interest postings included, as the server's daily product counts it - and the
+ * interest it earns (balance × rate ÷ 365). Days up to the last credited day are marked credited; the
+ * rest are what the closure credits first. The server rounds each run's total, not each day, so the
+ * per-day figures are shown to four places and the totals come from the server.
+ */
+ get interestDays(): { date: Date; balance: number; interest: number; credited: boolean }[] {
+ const opened = PrematureCloseDialogComponent.toDate(this.data.openingDate);
+ const rate = Number(this.data.interestRate || 0);
+ if (!opened || rate <= 0) {
+ return [];
+ }
+ const last = new Date(this.businessDate);
+ last.setDate(last.getDate() - 1);
+ const creditedTo = this.creditedThrough ? PrematureCloseDialogComponent.toDate(this.creditedThrough) : null;
+ const byDay = new Map();
+ for (const t of this.transactions) {
+ const on = PrematureCloseDialogComponent.toDate(t.transactionDate);
+ if (on) {
+ const key = PrematureCloseDialogComponent.dayKey(on);
+ byDay.set(key, (byDay.get(key) || 0) + (t.direction === 'DEBIT' ? -1 : 1) * Number(t.amount || 0));
+ }
+ }
+ const rows: { date: Date; balance: number; interest: number; credited: boolean }[] = [];
+ let balance = Number(this.data.openingBalance || 0);
+ for (
+ let day = new Date(opened);
+ day.getTime() <= last.getTime() && rows.length < 400;
+ day.setDate(day.getDate() + 1)
+ ) {
+ balance += byDay.get(PrematureCloseDialogComponent.dayKey(day)) || 0;
+ rows.push({
+ date: new Date(day),
+ balance,
+ interest: (balance * rate) / 36500,
+ credited: !!creditedTo && day.getTime() <= creditedTo.getTime()
+ });
+ }
+ return rows;
+ }
+
+ /**
+ * The agent's penalty on this account, from the server: its collection, the scheme's penalty rate,
+ * the agent's commission rate and what the account earned them (the cap), and the penalty itself.
+ */
+ agentPenalty: {
+ collection?: number;
+ penaltyRate?: number;
+ commissionRate?: number | null;
+ commissionEarned?: number | null;
+ penalty?: number;
+ } | null = null;
private static round2(value: number): number {
return Math.round((value + Number.EPSILON) * 100) / 100;
}
- get balance(): number {
+ /** The balance today, before the interest still owed is credited. */
+ get currentBalance(): number {
return Number(this.data.currentBalance || 0);
}
- /** Interest calculated but not posted - the server refuses to close until it is posted. */
- get pendingInterest(): number {
- return Number(this.data.interestCalc || 0);
+ /** The balance on the closing day, once the interest owed through yesterday is credited. */
+ get balance(): number {
+ return PrematureCloseDialogComponent.round2(this.currentBalance + this.interestDue);
+ }
+
+ /** All interest the account will have earned by closing - credited so far plus what is still owed. */
+ get totalInterest(): number {
+ return PrematureCloseDialogComponent.round2((this.interestCredited ?? 0) + this.interestDue);
+ }
+
+ /** The bank's working day, which the server closes on - not the computer's clock. */
+ get businessDate(): Date {
+ const date = new Date(this.settingsService.businessDate || new Date());
+ date.setHours(0, 0, 0, 0);
+ return date;
}
/** What the customer paid in: the balance less the interest credited on it. */
get deposits(): number {
const collected = Number(this.data.collectedToDate || 0);
- return collected > 0 ? collected : Math.max(0, this.balance - (this.interestCredited ?? 0));
+ return collected > 0 ? collected : Math.max(0, this.currentBalance - (this.interestCredited ?? 0));
}
/** Customer bears it: credited interest scaled by the share of the rate given up. */
get customerRecovery(): number {
const rate = Number(this.data.interestRate || 0);
const reduction = Number(this.scheme?.prematureInterestReduction || 0);
- const credited = this.interestCredited ?? 0;
+ const credited = this.totalInterest;
if (rate <= 0 || reduction <= 0 || credited <= 0) {
return 0;
}
@@ -244,9 +334,9 @@ export class PrematureCloseDialogComponent implements OnInit {
return PrematureCloseDialogComponent.round2(this.balance - this.customerRecovery);
}
- /** Days from today to the month's end, today counted - the days the agent funds. */
+ /** Days from the closing day to the month's end, the closing day counted - the days the agent funds. */
get agentTopUpDays(): number {
- const today = new Date();
+ const today = this.businessDate;
const lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate();
return lastDay - today.getDate() + 1;
}
@@ -264,13 +354,16 @@ export class PrematureCloseDialogComponent implements OnInit {
return PrematureCloseDialogComponent.round2(this.balance + this.agentTopUp);
}
- /** The share of the agent's commission taken whichever way it is settled. */
+ /** The agent's penalty on this account, taken whichever way it is settled. */
get commissionPenalty(): number {
- const rate = Number(this.scheme?.prematureAgentCommissionPenalty || 0);
- if (rate <= 0 || !this.agentCommission) {
- return 0;
- }
- return PrematureCloseDialogComponent.round2((this.agentCommission * rate) / 100);
+ return Number(this.agentPenalty?.penalty || 0);
+ }
+
+ /** Whether the penalty was cut down to what the account earned the agent. */
+ get penaltyCapped(): boolean {
+ const earned = this.agentPenalty?.commissionEarned;
+ const uncapped = (Number(this.agentPenalty?.collection || 0) * Number(this.agentPenalty?.penaltyRate || 0)) / 100;
+ return earned !== null && earned !== undefined && uncapped > Number(earned);
}
/** What the customer receives on the option picked, or null before one is picked. */
@@ -294,13 +387,21 @@ export class PrematureCloseDialogComponent implements OnInit {
/** The API sends dates as [year, month, day]; month is 1-based there and 0-based in Date. */
private static toDate(value: any): Date | null {
- const date =
- Array.isArray(value) && value.length >= 3
- ? new Date(value[0], value[1] - 1, value[2])
- : value
- ? new Date(value)
- : null;
- return date && !isNaN(date.getTime()) ? date : null;
+ if (Array.isArray(value) && value.length >= 3) {
+ return new Date(value[0], value[1] - 1, value[2]);
+ }
+ // A bare 'yyyy-MM-dd' is a calendar day: read in local time, not as UTC midnight - which in India is
+ // 05:30 the same day and would push every day-by-day comparison off by one.
+ const day = typeof value === 'string' ? /^(\d{4})-(\d{2})-(\d{2})$/.exec(value) : null;
+ if (day) {
+ return new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3]));
+ }
+ const date = value ? new Date(value) : null;
+ if (!date || isNaN(date.getTime())) {
+ return null;
+ }
+ date.setHours(0, 0, 0, 0);
+ return date;
}
private static readonly DAY_MS = 24 * 60 * 60 * 1000;
@@ -320,8 +421,7 @@ export class PrematureCloseDialogComponent implements OnInit {
if (!opened) {
return 0;
}
- const today = new Date();
- today.setHours(0, 0, 0, 0);
+ const today = this.businessDate;
const run = Math.round((today.getTime() - opened.getTime()) / PrematureCloseDialogComponent.DAY_MS) + 1;
return Math.min(this.termDays, Math.max(0, run));
}
diff --git a/src/app/organization/organization.service.ts b/src/app/organization/organization.service.ts
index 2e861671f..92f281ea7 100644
--- a/src/app/organization/organization.service.ts
+++ b/src/app/organization/organization.service.ts
@@ -490,6 +490,14 @@ export class OrganizationService {
* @param {string | number} partyId DDS account (party) id.
* @returns {Observable} Everything posted to that DDS account, most recent first.
*/
+ /**
+ * Interest a DDS account has earned through the day before the business date but not yet been
+ * credited - what an early closure today credits before it settles.
+ */
+ getPartyInterestDue(partyId: string | number): Observable {
+ return this.http.get(`/dds/parties/${partyId}/interestdue`);
+ }
+
getPartyTransactionsOfParty(partyId: string | number): Observable {
return this.http.get('/dds/partytransactions', {
params: new HttpParams().set('partyId', String(partyId))
diff --git a/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.html b/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.html
index bb58777ab..a4522dc3b 100644
--- a/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.html
+++ b/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.html
@@ -165,7 +165,7 @@
- Agent: commission reduced by (%)
+ Agent penalty (% of this account's collection)
- Charged whoever bears the interest — the round was not kept going.
+ Taken off the agent's next commission, whoever bears the interest - never more than the commission the
+ account earned them.
diff --git a/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.scss b/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.scss
index fe521eece..651fe48b2 100644
--- a/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.scss
+++ b/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.scss
@@ -285,6 +285,11 @@ $text-soft: #94a3b8;
background: #fef3c7;
color: #92400e;
}
+
+ &--green {
+ background: #dcfce7;
+ color: #166534;
+ }
}
// ── Footer ───────────────────────────────────────────────────────────────────────────────────────────
diff --git a/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.ts b/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.ts
index 17cb0a873..fc3be0c26 100644
--- a/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.ts
+++ b/src/app/products/dds-account-types/create-dds-account-type/create-dds-account-type.component.ts
@@ -24,8 +24,9 @@ import { SettingsService } from 'app/settings/settings.service';
import { AccountingService } from 'app/accounting/accounting.service';
import { announceHeldForApproval, heldForApproval } from 'app/deposits/dds-approvals/dds-approval-notice';
-/** acc_gl_account classification: 2 liability, 5 expense. */
+/** acc_gl_account classification: 2 liability, 4 income, 5 expense. */
const GL_LIABILITY = 2;
+const GL_INCOME = 4;
const GL_EXPENSE = 5;
/** One ledger account the product names, as a row on the Accounting tab. */
@@ -34,7 +35,7 @@ interface AccountingRow {
label: string;
inputLabel: string;
hint: string;
- pill: 'blue' | 'amber';
+ pill: 'blue' | 'amber' | 'green';
pillLabel: string;
required: boolean;
options: GLAccount[];
@@ -93,7 +94,9 @@ export class CreateDdsAccountTypeComponent implements OnInit {
readonly accountingControls = [
'depositLiabilityGlId',
'interestExpenseGlId',
- 'commissionExpenseGlId'
+ 'commissionExpenseGlId',
+ 'prematureIncomeGlId',
+ 'tdsPayableGlId'
];
/** The Accounting tab's rows, grouped by kind as the savings product's are. */
@@ -196,6 +199,16 @@ export class CreateDdsAccountTypeComponent implements OnInit {
commissionExpenseGlId: [
null,
Validators.required
+ ],
+ /** What an early closure earns the bank: the customer's interest given back and the agent's penalty. */
+ prematureIncomeGlId: [
+ null,
+ Validators.required
+ ],
+ /** Where TDS withheld from the agents' commission (Section 194H) is owed until it is paid over. */
+ tdsPayableGlId: [
+ null,
+ Validators.required
]
});
@@ -226,7 +239,9 @@ export class CreateDdsAccountTypeComponent implements OnInit {
prematureAgentCommissionPenalty: accountType.prematureAgentCommissionPenalty ?? 1,
depositLiabilityGlId: accountType.depositLiabilityGlId ?? null,
interestExpenseGlId: accountType.interestExpenseGlId ?? null,
- commissionExpenseGlId: accountType.commissionExpenseGlId ?? null
+ commissionExpenseGlId: accountType.commissionExpenseGlId ?? null,
+ prematureIncomeGlId: accountType.prematureIncomeGlId ?? null,
+ tdsPayableGlId: accountType.tdsPayableGlId ?? null
});
});
}
@@ -258,16 +273,16 @@ export class CreateDdsAccountTypeComponent implements OnInit {
(a: any) => a.usage?.id === 1 && !a.disabled
);
const ofType = (...types: number[]) => rows.filter((a: any) => types.includes(a.type?.id));
- this.buildAccountingSections(ofType(GL_LIABILITY), ofType(GL_EXPENSE));
+ this.buildAccountingSections(ofType(GL_LIABILITY), ofType(GL_EXPENSE), ofType(GL_INCOME));
},
error: () => {
this.glLoadFailed = true;
- this.buildAccountingSections([], []);
+ this.buildAccountingSections([], [], []);
}
});
}
- private buildAccountingSections(liabilities: GLAccount[], expenses: GLAccount[]): void {
+ private buildAccountingSections(liabilities: GLAccount[], expenses: GLAccount[], incomes: GLAccount[]): void {
this.accountingSections = [
{
key: 'liabilities',
@@ -282,6 +297,16 @@ export class CreateDdsAccountTypeComponent implements OnInit {
pillLabel: 'Liability',
required: true,
options: liabilities
+ },
+ {
+ controlName: 'tdsPayableGlId',
+ label: 'TDS Payable (194H)',
+ inputLabel: 'TDS payable account',
+ hint: "TDS withheld from the agents' commission on this product - credited when the commission is paid, until it is paid over to the tax department.",
+ pill: 'blue',
+ pillLabel: 'Liability',
+ required: true,
+ options: liabilities
}
]
},
@@ -310,6 +335,22 @@ export class CreateDdsAccountTypeComponent implements OnInit {
options: expenses
}
]
+ },
+ {
+ key: 'income',
+ title: 'Income',
+ rows: [
+ {
+ controlName: 'prematureIncomeGlId',
+ label: 'Premature Closure Income',
+ inputLabel: 'Premature closure income account',
+ hint: 'What closing early earns the bank: the interest a customer gives back (Premature Closure tab), on the day of closing. The agent penalty is not booked here - it comes off their commission, which reverses that much commission expense.',
+ pill: 'green',
+ pillLabel: 'Income',
+ required: true,
+ options: incomes
+ }
+ ]
}
];
}