saving , current and RD account code update
This commit is contained in:
+4
-4
@@ -1,4 +1,4 @@
|
||||
<!--
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -61,14 +61,14 @@
|
||||
@if (CurrentProduct.effectiveTo) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective To:</span>
|
||||
<span class="flex-60">{{ CurrentProduct.effectiveTo }}</span>
|
||||
<span class="flex-60">{{ CurrentProduct.effectiveTo | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (CurrentProduct.endDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">End Date:</span>
|
||||
<span class="flex-60">{{ CurrentProduct.endDate }}</span>
|
||||
<span class="flex-60">{{ CurrentProduct.endDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
@if (CurrentProduct.lastInterestDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Last Interest Date:</span>
|
||||
<span class="flex-60">{{ CurrentProduct.lastInterestDate }}</span>
|
||||
<span class="flex-60">{{ CurrentProduct.lastInterestDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from '@angular/material/table';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
import { YesnoPipe } from '../../../../pipes/yesno.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -47,6 +48,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatRow,
|
||||
FaIconComponent,
|
||||
FindPipe,
|
||||
DateFormatPipe,
|
||||
FormatNumberPipe,
|
||||
YesnoPipe
|
||||
]
|
||||
|
||||
-5
@@ -100,11 +100,6 @@
|
||||
<span>Account Closed with Zero Balance in Day Closing</span>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="sps-toggle sps-toggle--inline">
|
||||
<mat-checkbox formControlName="withHoldTax">
|
||||
<span>Withhold Tax is Applicable</span>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+2
-2
@@ -54,7 +54,6 @@ export class CurrentProductSettingsStepComponent implements OnInit {
|
||||
withdrawalFeeForTransfers: this.CurrentProductsTemplate.withdrawalFeeForTransfers,
|
||||
enforceMinRequiredBalance: this.CurrentProductsTemplate.enforceMinRequiredBalance,
|
||||
minRequiredBalance: this.CurrentProductsTemplate.minRequiredBalance,
|
||||
withHoldTax: this.CurrentProductsTemplate.withHoldTax ?? false,
|
||||
balanceFrequency: isEditing ? this.CurrentProductsTemplate.balanceFrequency || defaultPeriod : defaultPeriod,
|
||||
enableLockinPeriod: !!(
|
||||
this.CurrentProductsTemplate.lockinPeriodFrequency && this.CurrentProductsTemplate.lockinPeriodFrequency > 0
|
||||
@@ -107,7 +106,6 @@ export class CurrentProductSettingsStepComponent implements OnInit {
|
||||
'',
|
||||
[Validators.min(0)]
|
||||
],
|
||||
withHoldTax: [false],
|
||||
balanceFrequency: ['Monthly'],
|
||||
enableLockinPeriod: [false],
|
||||
lockinPeriodFrequency: [''],
|
||||
@@ -159,6 +157,8 @@ export class CurrentProductSettingsStepComponent implements OnInit {
|
||||
get CurrentProductSettings() {
|
||||
const formValue = { ...this.CurrentProductSettingsForm.value };
|
||||
|
||||
delete formValue.withHoldTax;
|
||||
|
||||
if (!formValue.allowOverdraft) {
|
||||
delete formValue.overdraftLimit;
|
||||
delete formValue.nominalAnnualInterestRateOverdraft;
|
||||
|
||||
+4
-4
@@ -75,21 +75,21 @@
|
||||
@if (currentProduct.effectiveDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective Date:</span>
|
||||
<span class="flex-60">{{ currentProduct.effectiveDate }}</span>
|
||||
<span class="flex-60">{{ currentProduct.effectiveDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (currentProduct.effectiveTo) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective To:</span>
|
||||
<span class="flex-60">{{ currentProduct.effectiveTo }}</span>
|
||||
<span class="flex-60">{{ currentProduct.effectiveTo | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (currentProduct.endDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">End Date:</span>
|
||||
<span class="flex-60">{{ currentProduct.endDate }}</span>
|
||||
<span class="flex-60">{{ currentProduct.endDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
@if (currentProduct.lastInterestDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Last Interest Date:</span>
|
||||
<span class="flex-60">{{ currentProduct.lastInterestDate }}</span>
|
||||
<span class="flex-60">{{ currentProduct.lastInterestDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -23,6 +23,7 @@ import {
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { ViewSavingsAccountingDetailsComponent } from '../../../../shared/accounting/view-savings-accounting-details/view-savings-accounting-details.component';
|
||||
import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
import { YesnoPipe } from '../../../../pipes/yesno.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -46,6 +47,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
ViewSavingsAccountingDetailsComponent,
|
||||
DateFormatPipe,
|
||||
FormatNumberPipe,
|
||||
YesnoPipe
|
||||
]
|
||||
|
||||
+5
-5
@@ -150,11 +150,11 @@ export class EditRecurringDepositProductComponent {
|
||||
this.recurringDepositProductTermsForm.valid &&
|
||||
this.recurringDepositProductSettingsForm.valid &&
|
||||
this.recurringDepositProductAccountingForm.valid &&
|
||||
(this.recurringDepositProductDetailsForm.pristine ||
|
||||
this.recurringDepositProductCurrencyForm.pristine ||
|
||||
this.recurringDepositProductTermsForm.pristine ||
|
||||
this.recurringDepositProductSettingsForm.pristine ||
|
||||
this.recurringDepositProductAccountingForm.pristine)
|
||||
(!this.recurringDepositProductDetailsForm.pristine ||
|
||||
!this.recurringDepositProductCurrencyForm.pristine ||
|
||||
!this.recurringDepositProductTermsForm.pristine ||
|
||||
!this.recurringDepositProductSettingsForm.pristine ||
|
||||
!this.recurringDepositProductAccountingForm.pristine)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+26
-15
@@ -1,4 +1,4 @@
|
||||
<!--
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -7,10 +7,10 @@
|
||||
-->
|
||||
|
||||
<div class="responsive-column">
|
||||
<!-- ── Product Name ── -->
|
||||
<!-- ── Product Name ── -->
|
||||
<h2 class="mat-h2 flex-100">{{ recurringDepositProduct.name }}</h2>
|
||||
|
||||
<!-- ── Details ── -->
|
||||
<!-- ── Details ── -->
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Details' | translate }}</h3>
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
@@ -27,7 +27,7 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── Product Classification ── -->
|
||||
<!-- ── Product Classification ── -->
|
||||
@if (
|
||||
recurringDepositProduct.accountType ||
|
||||
recurringDepositProduct.customerSegment ||
|
||||
@@ -63,14 +63,14 @@
|
||||
@if (recurringDepositProduct.effectiveTo) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective To:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.effectiveTo }}</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.effectiveTo | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (recurringDepositProduct.endDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">End Date:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.endDate }}</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.endDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
<!-- ── Currency ── -->
|
||||
<!-- ── Currency ── -->
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Currency' | translate }}</h3>
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── Terms ── -->
|
||||
<!-- ── Terms ── -->
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Terms' | translate }}</h3>
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
|
||||
@@ -169,11 +169,22 @@
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@if (recurringDepositProduct.interestCalculateSelector) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculation Type' | translate }}:</span>
|
||||
<span class="flex-60">{{
|
||||
recurringDepositProduct.interestCalculateSelector
|
||||
| find: recurringDepositProductsTemplate.interestCalculationTypeOption : 'id' : 'value'
|
||||
}}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculated using' | translate }}:</span>
|
||||
<span class="flex-60">{{
|
||||
recurringDepositProduct.interestCalculationType
|
||||
| find: recurringDepositProductsTemplate.interestCalculationTypeOptions : 'id' : 'value'
|
||||
| translateKey: 'catalogs'
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@@ -188,7 +199,7 @@
|
||||
@if (recurringDepositProduct.effectiveDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective Date:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.effectiveDate }}</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.effectiveDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -218,11 +229,11 @@
|
||||
@if (recurringDepositProduct.lastInterestDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Last Interest Date:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.lastInterestDate }}</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.lastInterestDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── Settings ── -->
|
||||
<!-- ── Settings ── -->
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Settings' | translate }}</h3>
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
|
||||
@@ -313,7 +324,7 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── Interest Rate Slabs ── -->
|
||||
<!-- ── Interest Rate Slabs ── -->
|
||||
@if (recurringDepositProduct.rdSlabs?.length) {
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Interest Rate Charts' | translate }}</h3>
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
@@ -334,7 +345,7 @@
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="toPeriod">
|
||||
<th mat-header-cell *matHeaderCellDef>To</th>
|
||||
<td mat-cell *matCellDef="let slab">{{ slab.toPeriod ?? '—' }}</td>
|
||||
<td mat-cell *matCellDef="let slab">{{ slab.toPeriod ?? '—' }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="periodTypeLabel">
|
||||
<th mat-header-cell *matHeaderCellDef>Period</th>
|
||||
@@ -352,7 +363,7 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── Charges ── -->
|
||||
<!-- ── Charges ── -->
|
||||
@if (recurringDepositProduct.charges?.length) {
|
||||
<div class="layout-row-wrap responsive-column flex-100">
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Charges' | translate }}</h3>
|
||||
@@ -380,7 +391,7 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── Accounting ── -->
|
||||
<!-- ── Accounting ── -->
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Accounting' | translate }}</h3>
|
||||
<mat-divider class="flex-100"></mat-divider>
|
||||
|
||||
|
||||
+16
-19
@@ -54,14 +54,22 @@
|
||||
<mat-form-field appearance="outline" class="rdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Interest Calculation Type' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCalculationType"
|
||||
formControlName="interestCalculateSelector"
|
||||
matTooltip="{{ 'tooltips.The method used to calculate interest' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestCalculationType of interestCalculationTypeOptionData; track interestCalculationType.id) {
|
||||
<mat-option [value]="interestCalculationType.id">
|
||||
{{ interestCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
@for (opt of interestCalculationTypeOptionData; track opt.id) {
|
||||
<mat-option [value]="opt.id">{{ opt.value }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="rdpt-grid rdpt-grid--three">
|
||||
<mat-form-field appearance="outline" class="rdpt-field">
|
||||
<mat-label>Interest Calculate</mat-label>
|
||||
<mat-select formControlName="interestCalculationType" required>
|
||||
@for (mode of interestCalculationTypeData; track mode.id) {
|
||||
<mat-option [value]="mode.id">{{ mode.value | translateKey: 'catalogs' }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
@@ -69,19 +77,8 @@
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="rdpt-grid rdpt-grid--three">
|
||||
<mat-form-field appearance="outline" class="rdpt-field">
|
||||
<mat-label>Interest Calculate</mat-label>
|
||||
<mat-select formControlName="interestCalculateSelector" required>
|
||||
@for (mode of interestCalculationTypeData; track mode.id) {
|
||||
<mat-option [value]="mode.id">{{ mode.value }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
@if (recurringDepositProductTermsForm.value.interestCalculateSelector === 2) {
|
||||
@if (recurringDepositProductTermsForm.value.interestCalculationType === 2) {
|
||||
<mat-form-field appearance="outline" class="rdpt-field">
|
||||
<mat-label>Average Period</mat-label>
|
||||
<mat-select formControlName="averagePeriod">
|
||||
@@ -142,7 +139,7 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@if (recurringDepositProductTermsForm.value.interestCalculateSelector === 1) {
|
||||
@if (recurringDepositProductTermsForm.value.interestCalculationType === 1) {
|
||||
<div class="rdpt-note">
|
||||
<span>⚠️</span>
|
||||
<span
|
||||
|
||||
+15
-23
@@ -49,10 +49,10 @@ export class RecurringDepositProductTermsStepComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.interestCompoundingPeriodTypeData = this.recurringDepositProductsTemplate.interestCompoundingPeriodTypeOptions;
|
||||
this.interestPostingPeriodTypeData = this.recurringDepositProductsTemplate.interestPostingPeriodTypeOptions;
|
||||
// Standard enum (1=Daily, 2=Average) → "Interest Calculate" dropdown → interestCalculationType form control
|
||||
this.interestCalculationTypeData = this.recurringDepositProductsTemplate.interestCalculationTypeOptions;
|
||||
this.interestCalculationTypeOptionData =
|
||||
this.recurringDepositProductsTemplate.interestCalculationTypeOption ||
|
||||
this.recurringDepositProductsTemplate.interestCalculationTypeOptions;
|
||||
// CBS code values → "Interest Calculation Type" dropdown → interestCalculateSelector form control
|
||||
this.interestCalculationTypeOptionData = this.recurringDepositProductsTemplate.interestCalculationTypeOption || [];
|
||||
this.interestCalculationDaysInYearTypeData =
|
||||
this.recurringDepositProductsTemplate.interestCalculationDaysInYearTypeOptions;
|
||||
this.periodFrequencyData = this.recurringDepositProductsTemplate.periodFrequencyOptions || [];
|
||||
@@ -60,37 +60,33 @@ export class RecurringDepositProductTermsStepComponent implements OnInit {
|
||||
|
||||
const isEditing = !!this.recurringDepositProductsTemplate.id;
|
||||
const defaultPeriod = this.periodFrequencyData[0]?.value || 'Monthly';
|
||||
const savedEnumTypeId =
|
||||
this.recurringDepositProductsTemplate.interestCalculationType?.id ||
|
||||
this.interestCalculationTypeData?.[0]?.id ||
|
||||
1;
|
||||
const savedSelectorId = isEditing
|
||||
? (this.recurringDepositProductsTemplate.interestCalculateSelector ??
|
||||
this.interestCalculationTypeOptionData?.[0]?.id ??
|
||||
null)
|
||||
: (this.interestCalculationTypeOptionData?.[0]?.id ?? null);
|
||||
|
||||
this.recurringDepositProductTermsForm.patchValue({
|
||||
nominalAnnualInterestRate: this.recurringDepositProductsTemplate.nominalAnnualInterestRate ?? 0,
|
||||
interestCompoundingPeriodType: this.recurringDepositProductsTemplate.interestCompoundingPeriodType?.id,
|
||||
interestPostingPeriodType: this.recurringDepositProductsTemplate.interestPostingPeriodType?.id,
|
||||
interestCalculationType: isEditing
|
||||
? this.recurringDepositProductsTemplate.interestCalculationTypeOption?.id ||
|
||||
this.interestCalculationTypeOptionData?.[0]?.id ||
|
||||
1
|
||||
: this.interestCalculationTypeOptionData?.[0]?.id || 1,
|
||||
interestCalculationType: savedEnumTypeId,
|
||||
interestCalculationDaysInYearType: this.recurringDepositProductsTemplate.interestCalculationDaysInYearType?.id,
|
||||
effectiveDate: this.recurringDepositProductsTemplate.effectiveDate
|
||||
? this.parseDate(this.recurringDepositProductsTemplate.effectiveDate)
|
||||
: '',
|
||||
interestCalculateSelector: isEditing
|
||||
? this.recurringDepositProductsTemplate.interestCalculateSelector || 1
|
||||
: this.recurringDepositProductsTemplate.interestCalculationType?.id ||
|
||||
this.interestCalculationTypeData?.[0]?.id ||
|
||||
1,
|
||||
interestCalculateSelector: savedSelectorId,
|
||||
averagePeriod: isEditing ? this.recurringDepositProductsTemplate.averagePeriod || defaultPeriod : defaultPeriod,
|
||||
autoPost: isEditing ? (this.recurringDepositProductsTemplate.autoPost ?? true) : true,
|
||||
frequencyFixDay: isEditing ? this.recurringDepositProductsTemplate.frequencyFixDay || 30 : 30,
|
||||
frequencyFixDay: isEditing ? (this.recurringDepositProductsTemplate.frequencyFixDay ?? 30) : 30,
|
||||
lastInterestDate: this.recurringDepositProductsTemplate.lastInterestDate
|
||||
? this.parseDate(this.recurringDepositProductsTemplate.lastInterestDate)
|
||||
: ''
|
||||
});
|
||||
|
||||
const currentInterestCalcType = this.recurringDepositProductTermsForm.get('interestCalculationType').value;
|
||||
if (currentInterestCalcType && currentInterestCalcType > 2) {
|
||||
this.recurringDepositProductTermsForm.patchValue({ interestCalculationType: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
private parseDate(dateValue: any): Date | null {
|
||||
@@ -163,10 +159,6 @@ export class RecurringDepositProductTermsStepComponent implements OnInit {
|
||||
if (formValue.lastInterestDate instanceof Date) {
|
||||
formValue.lastInterestDate = this.dateUtils.formatDate(formValue.lastInterestDate, dateFormat) || '';
|
||||
}
|
||||
if (formValue.interestCalculationType && formValue.interestCalculationType > 2) {
|
||||
formValue.interestCalculationType = 1;
|
||||
}
|
||||
|
||||
for (const key in formValue) {
|
||||
if (formValue[key] === '') {
|
||||
delete formValue[key];
|
||||
|
||||
+7
-7
@@ -141,16 +141,16 @@
|
||||
<span class="flex-60">{{ recurringDepositProduct.effectiveDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculation Type' | translate }}:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.interestCalculationType.value }}</span>
|
||||
</div>
|
||||
@if (recurringDepositProduct.interestCalculateSelector !== undefined) {
|
||||
@if (recurringDepositProduct.interestCalculationTypeName) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Interest Calculate:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.interestCalculateSelector }}</span>
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculation Type' | translate }}:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.interestCalculationTypeName }}</span>
|
||||
</div>
|
||||
}
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Interest Calculate:</span>
|
||||
<span class="flex-60">{{ recurringDepositProduct.interestCalculationType?.value }}</span>
|
||||
</div>
|
||||
@if (recurringDepositProduct.averagePeriod) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Average Period:</span>
|
||||
|
||||
+8
-9
@@ -1,4 +1,4 @@
|
||||
<!--
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -61,14 +61,14 @@
|
||||
@if (savingProduct.effectiveTo) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective To:</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveTo }}</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveTo | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (savingProduct.endDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">End Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.endDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.endDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -158,9 +158,7 @@
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculation Type' | translate }}:</span>
|
||||
<span class="flex-60">{{
|
||||
savingProduct.interestCalculationType
|
||||
| find: interestCalculationTypeOptionData : 'id' : 'value'
|
||||
| translateKey: 'catalogs'
|
||||
savingProduct.interestCalculateSelector | find: interestCalculationTypeOptionData : 'id' : 'value'
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@@ -176,15 +174,16 @@
|
||||
@if (savingProduct.effectiveDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Interest Calculate:</span>
|
||||
<span class="flex-60">{{
|
||||
savingProduct.interestCalculateSelector
|
||||
savingProduct.interestCalculationType
|
||||
| find: savingProductsTemplate?.interestCalculationTypeOptions : 'id' : 'value'
|
||||
| translateKey: 'catalogs'
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@@ -214,7 +213,7 @@
|
||||
@if (savingProduct.lastInterestDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Last Interest Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.lastInterestDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.lastInterestDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from '@angular/material/table';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
import { YesnoPipe } from '../../../../pipes/yesno.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -47,6 +48,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatRow,
|
||||
FaIconComponent,
|
||||
FindPipe,
|
||||
DateFormatPipe,
|
||||
FormatNumberPipe,
|
||||
YesnoPipe
|
||||
]
|
||||
|
||||
+7
-3
@@ -82,11 +82,15 @@ export class SavingProductSettingsStepComponent implements OnInit {
|
||||
this.savingProductsTemplate.lockinPeriodFrequency &&
|
||||
this.savingProductsTemplate.lockinPeriodFrequency > 0
|
||||
) {
|
||||
// Backend returns lockinPeriodFrequencyType.id as integer (0=DAYS,1=WEEKS,2=MONTHS,3=YEARS)
|
||||
// but the form dropdown uses string IDs, so reverse-map the number back to string
|
||||
const reverseFrequencyTypeMap: { [key: number]: string } = { 0: 'DAYS', 1: 'WEEKS', 2: 'MONTHS', 3: 'YEARS' };
|
||||
const freqTypeId = this.savingProductsTemplate.lockinPeriodFrequencyType?.id;
|
||||
const freqTypeString = reverseFrequencyTypeMap[freqTypeId] ?? '';
|
||||
|
||||
this.savingProductSettingsForm.patchValue({
|
||||
lockinPeriodFrequency: this.savingProductsTemplate.lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType:
|
||||
this.savingProductsTemplate.lockinPeriodFrequencyType &&
|
||||
this.savingProductsTemplate.lockinPeriodFrequencyType.id
|
||||
lockinPeriodFrequencyType: freqTypeString
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+16
-19
@@ -54,14 +54,22 @@
|
||||
<mat-form-field appearance="outline" class="spt-field">
|
||||
<mat-label>{{ 'labels.inputs.Interest Calculation Type' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCalculationType"
|
||||
formControlName="interestCalculateSelector"
|
||||
matTooltip="{{ 'tooltips.The method used to calculate interest' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestCalculationType of interestCalculationTypeOptionData; track interestCalculationType.id) {
|
||||
<mat-option [value]="interestCalculationType.id">
|
||||
{{ interestCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
@for (opt of interestCalculationTypeOptionData; track opt.id) {
|
||||
<mat-option [value]="opt.id">{{ opt.value }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="spt-grid spt-grid--three">
|
||||
<mat-form-field appearance="outline" class="spt-field">
|
||||
<mat-label>Interest Calculate</mat-label>
|
||||
<mat-select formControlName="interestCalculationType" required>
|
||||
@for (mode of interestCalculationTypeData; track mode.id) {
|
||||
<mat-option [value]="mode.id">{{ mode.value | translateKey: 'catalogs' }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
@@ -69,19 +77,8 @@
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="spt-grid spt-grid--three">
|
||||
<mat-form-field appearance="outline" class="spt-field">
|
||||
<mat-label>Interest Calculate</mat-label>
|
||||
<mat-select formControlName="interestCalculateSelector" required>
|
||||
@for (mode of interestCalculationTypeData; track mode.id) {
|
||||
<mat-option [value]="mode.id">{{ mode.value }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
@if (savingProductTermsForm.value.interestCalculateSelector === 2) {
|
||||
@if (savingProductTermsForm.value.interestCalculationType === 2) {
|
||||
<mat-form-field appearance="outline" class="spt-field">
|
||||
<mat-label>Average Period</mat-label>
|
||||
<mat-select formControlName="averagePeriod">
|
||||
@@ -142,7 +139,7 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@if (savingProductTermsForm.value.interestCalculateSelector === 1) {
|
||||
@if (savingProductTermsForm.value.interestCalculationType === 1) {
|
||||
<div class="spt-note">
|
||||
<span>⚠️</span>
|
||||
<span
|
||||
|
||||
+19
-41
@@ -59,59 +59,43 @@ export class SavingProductTermsStepComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.interestCompoundingPeriodTypeData = this.savingProductsTemplate.interestCompoundingPeriodTypeOptions;
|
||||
this.interestPostingPeriodTypeData = this.savingProductsTemplate.interestPostingPeriodTypeOptions;
|
||||
// interestCalculationTypeData = standard enum (1=Daily, 2=Average) → "Interest Calculate" dropdown → interestCalculationType form control
|
||||
this.interestCalculationTypeData = this.savingProductsTemplate.interestCalculationTypeOptions;
|
||||
this.interestCalculationTypeOptionData =
|
||||
this.savingProductsTemplate.interestCalculationTypeOption ||
|
||||
this.savingProductsTemplate.interestCalculationTypeOptions;
|
||||
// interestCalculationTypeOptionData = CBS code values from DB → "Interest Calculation Type" dropdown → interestCalculateSelector form control
|
||||
this.interestCalculationTypeOptionData = this.savingProductsTemplate.interestCalculationTypeOption || [];
|
||||
this.interestCalculationDaysInYearTypeData = this.savingProductsTemplate.interestCalculationDaysInYearTypeOptions;
|
||||
this.periodFrequencyData = this.savingProductsTemplate.periodFrequencyOptions || [];
|
||||
this.setYesNoOptions(this.savingProductsTemplate?.yesNoOptions);
|
||||
|
||||
const isEditing = !!this.savingProductsTemplate.id;
|
||||
const defaultPeriod = this.periodFrequencyData[0]?.value || 'Monthly';
|
||||
// interestCalculationType = standard enum id (1=Daily Balance, 2=Average Daily Balance)
|
||||
const savedEnumTypeId =
|
||||
this.savingProductsTemplate.interestCalculationType?.id || this.interestCalculationTypeData?.[0]?.id || 1;
|
||||
// interestCalculateSelector = CBS code value id from interestCalculationTypeOption
|
||||
const savedSelectorId = isEditing
|
||||
? (this.savingProductsTemplate.interestCalculateSelector ??
|
||||
this.interestCalculationTypeOptionData?.[0]?.id ??
|
||||
null)
|
||||
: (this.interestCalculationTypeOptionData?.[0]?.id ?? null);
|
||||
|
||||
this.savingProductTermsForm.patchValue({
|
||||
nominalAnnualInterestRate: isEditing
|
||||
? this.savingProductsTemplate.nominalAnnualInterestRate
|
||||
: this.savingProductsTemplate.nominalAnnualInterestRate,
|
||||
interestCompoundingPeriodType: isEditing
|
||||
? this.savingProductsTemplate.interestCompoundingPeriodType?.id
|
||||
: this.savingProductsTemplate.interestCompoundingPeriodType?.id,
|
||||
interestPostingPeriodType: isEditing
|
||||
? this.savingProductsTemplate.interestPostingPeriodType?.id
|
||||
: this.savingProductsTemplate.interestPostingPeriodType?.id,
|
||||
interestCalculationType: isEditing
|
||||
? this.savingProductsTemplate.interestCalculationTypeOption?.id ||
|
||||
this.interestCalculationTypeOptionData?.[0]?.id ||
|
||||
1
|
||||
: this.interestCalculationTypeOptionData?.[0]?.id || 1,
|
||||
interestCalculationDaysInYearType: isEditing
|
||||
? this.savingProductsTemplate.interestCalculationDaysInYearType?.id
|
||||
: this.savingProductsTemplate.interestCalculationDaysInYearType?.id,
|
||||
nominalAnnualInterestRate: this.savingProductsTemplate.nominalAnnualInterestRate,
|
||||
interestCompoundingPeriodType: this.savingProductsTemplate.interestCompoundingPeriodType?.id,
|
||||
interestPostingPeriodType: this.savingProductsTemplate.interestPostingPeriodType?.id,
|
||||
interestCalculationType: savedEnumTypeId,
|
||||
interestCalculationDaysInYearType: this.savingProductsTemplate.interestCalculationDaysInYearType?.id,
|
||||
effectiveDate: this.savingProductsTemplate.effectiveDate
|
||||
? new Date(this.savingProductsTemplate.effectiveDate)
|
||||
: '',
|
||||
interestCalculateSelector: isEditing
|
||||
? this.savingProductsTemplate.interestCalculateSelector || 1
|
||||
: this.savingProductsTemplate.interestCalculationType?.id || this.interestCalculationTypeData?.[0]?.id || 1,
|
||||
interestCalculateSelector: savedSelectorId,
|
||||
averagePeriod: isEditing ? this.savingProductsTemplate.averagePeriod || defaultPeriod : defaultPeriod,
|
||||
autoPost: isEditing ? (this.savingProductsTemplate.autoPost ?? true) : true,
|
||||
frequencyFixDay: isEditing ? this.savingProductsTemplate.frequencyFixDay || 30 : 30,
|
||||
frequencyFixDay: isEditing ? (this.savingProductsTemplate.frequencyFixDay ?? 30) : 30,
|
||||
lastInterestDate: this.savingProductsTemplate.lastInterestDate
|
||||
? new Date(this.savingProductsTemplate.lastInterestDate)
|
||||
: ''
|
||||
});
|
||||
|
||||
// Map code value IDs to backend enum values for interestCalculationType
|
||||
// Backend expects: 1=Daily Balance, 2=Average Daily Balance
|
||||
const currentInterestCalcType = this.savingProductTermsForm.get('interestCalculationType').value;
|
||||
if (currentInterestCalcType && currentInterestCalcType > 2) {
|
||||
// If it's a code value ID (like 340, 341), map it to backend enum
|
||||
// Default to 1 (Daily Balance) for custom code values
|
||||
this.savingProductTermsForm.patchValue({
|
||||
interestCalculationType: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private setYesNoOptions(options: any[]) {
|
||||
@@ -198,12 +182,6 @@ export class SavingProductTermsStepComponent implements OnInit {
|
||||
formValue.lastInterestDate = this.dateUtils.formatDate(prevLastInterestDate, dateFormat) || '';
|
||||
}
|
||||
|
||||
// Convert interestCalculationType from code value ID to backend enum value
|
||||
// Backend expects: 1=Daily Balance, 2=Average Daily Balance
|
||||
if (formValue.interestCalculationType && formValue.interestCalculationType > 2) {
|
||||
formValue.interestCalculationType = 1; // Default to Daily Balance
|
||||
}
|
||||
|
||||
return {
|
||||
...formValue
|
||||
};
|
||||
|
||||
+14
-7
@@ -1,4 +1,4 @@
|
||||
<!--
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -75,21 +75,21 @@
|
||||
@if (savingProduct.effectiveDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (savingProduct.effectiveTo) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective To:</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveTo }}</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveTo | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (savingProduct.endDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">End Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.endDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.endDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -164,6 +164,13 @@
|
||||
<span class="flex-60">{{ savingProduct.interestPostingPeriodType.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
|
||||
@if (savingProduct.interestCalculationTypeName) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculation Type' | translate }}:</span>
|
||||
<span class="flex-60">{{ savingProduct.interestCalculationTypeName }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">{{ 'labels.inputs.Interest Calculated using' | translate }}:</span>
|
||||
<span class="flex-60">{{ savingProduct.interestCalculationType.value | translateKey: 'catalogs' }}</span>
|
||||
@@ -177,13 +184,13 @@
|
||||
@if (savingProduct.effectiveDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Effective Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.effectiveDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Interest Calculate:</span>
|
||||
<span class="flex-60">{{ savingProduct.interestCalculateSelector }}</span>
|
||||
<span class="flex-60">{{ savingProduct.interestCalculationType?.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
|
||||
@if (savingProduct.averagePeriod) {
|
||||
@@ -208,7 +215,7 @@
|
||||
@if (savingProduct.lastInterestDate) {
|
||||
<div class="flex-100 layout-row">
|
||||
<span class="flex-40">Last Interest Date:</span>
|
||||
<span class="flex-60">{{ savingProduct.lastInterestDate }}</span>
|
||||
<span class="flex-60">{{ savingProduct.lastInterestDate | dateFormat }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { ViewSavingsAccountingDetailsComponent } from '../../../../shared/accounting/view-savings-accounting-details/view-savings-accounting-details.component';
|
||||
import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
import { YesnoPipe } from '../../../../pipes/yesno.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -48,6 +49,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatRow,
|
||||
ViewSavingsAccountingDetailsComponent,
|
||||
FormatNumberPipe,
|
||||
DateFormatPipe,
|
||||
YesnoPipe
|
||||
]
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user