DDS: Agent settlement (Agent Tran), Close Party account UI, reports UI, Party-Savings link field

This commit is contained in:
tarunmalviya
2026-08-25 10:56:03 +05:30
parent 7ef75c902d
commit 57a61b3057
78 changed files with 12711 additions and 2 deletions
@@ -0,0 +1,355 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="am-container">
<div class="am-header">
<button mat-stroked-button [routerLink]="['../']" class="am-back">
<i class="fas fa-arrow-left"></i> {{ 'labels.heading.Organization' | translate }}
</button>
<h2 class="am-header__title">Agent Master Entry</h2>
</div>
<div class="am-card">
<form [formGroup]="agentForm">
<div class="am-section">
<div class="am-section__header">
<i class="fas fa-id-card"></i>
<h3>Agent Details</h3>
</div>
<div class="am-grid">
<mat-form-field appearance="outline" class="am-field">
<mat-label>Client ID</mat-label>
<input matInput required formControlName="clientId" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Code</mat-label>
<input matInput formControlName="agentCode" placeholder="Auto-generated" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field am-field--wide">
<mat-label>Agent Name ID</mat-label>
<input matInput required formControlName="agentNameId" placeholder="Person or institution name" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field am-field--wide">
<mat-label>Agent Address (Line 1)</mat-label>
<input matInput required formControlName="agentAddress1" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field am-field--wide">
<mat-label>Agent Address (Line 2)</mat-label>
<input matInput formControlName="agentAddress2" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent City</mat-label>
<input matInput required formControlName="agentCity" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent PinCode</mat-label>
<input matInput required formControlName="agentPinCode" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Telephone</mat-label>
<input matInput formControlName="agentTelephone" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Home Branch</mat-label>
<input matInput required formControlName="homeBranch" />
</mat-form-field>
</div>
</div>
<div class="am-section">
<div class="am-section__header">
<i class="fas fa-percent"></i>
<h3>Collection &amp; Commission Settings</h3>
</div>
<div class="am-grid">
<mat-form-field appearance="outline" class="am-field">
<mat-label>Com. Calculation</mat-label>
<mat-select required formControlName="commissionCalculation">
<mat-option value="Yes">Yes</mat-option>
<mat-option value="No">No</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>TDS</mat-label>
<mat-select required formControlName="tdsApplicable">
<mat-option value="Yes">Yes</mat-option>
<mat-option value="No">No</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>TDS %</mat-label>
<input matInput type="number" formControlName="tdsPercent" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Cur.TDS</mat-label>
<input matInput formControlName="currentTds" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>TDS Amt</mat-label>
<input matInput formControlName="tdsAmount" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Limit</mat-label>
<input matInput type="number" formControlName="limit" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Machine Rent</mat-label>
<input matInput type="number" formControlName="machineRent" />
</mat-form-field>
</div>
</div>
<div class="am-section">
<div class="am-section__header">
<i class="fas fa-piggy-bank"></i>
<h3>Settlement &amp; Security Accounts</h3>
</div>
<div class="am-grid">
<mat-form-field appearance="outline" class="am-field">
<mat-label>Saving Branch</mat-label>
<input matInput required formControlName="savingBranch" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Saving A/C Type</mat-label>
<mat-select required formControlName="agentSavingAccountType">
@for (accountType of agentSavingAccountTypes; track accountType) {
<mat-option [value]="accountType">{{ accountType }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Saving A/C No</mat-label>
<input matInput required formControlName="agentSavingAccountNo" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Trf Branch</mat-label>
<input matInput formControlName="transferBranch" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Trf.Amt A/C Type</mat-label>
<input matInput formControlName="transferAmountAccountType" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Trf.Amt A/C No</mat-label>
<input matInput formControlName="transferAccountNo" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Security Branch</mat-label>
<input matInput formControlName="agentSecurityBranch" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Security A/C Type</mat-label>
<mat-select formControlName="agentSecurityAccountType">
@for (accountType of agentSavingAccountTypes; track accountType) {
<mat-option [value]="accountType">{{ accountType }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Security A/C No</mat-label>
<input matInput formControlName="agentSecurityAccountNo" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Opening Date</mat-label>
<input matInput required [matDatepicker]="openingDatePicker" formControlName="agentOpeningDate" />
<mat-datepicker-toggle matIconSuffix [for]="openingDatePicker"></mat-datepicker-toggle>
<mat-datepicker #openingDatePicker></mat-datepicker>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Birth Date</mat-label>
<input
matInput
required
[max]="maxDate"
[matDatepicker]="birthDatePicker"
formControlName="agentBirthDate"
/>
<mat-datepicker-toggle matIconSuffix [for]="birthDatePicker"></mat-datepicker-toggle>
<mat-datepicker #birthDatePicker></mat-datepicker>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Current Balance</mat-label>
<input matInput formControlName="agentCurrentBalance" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Agent Opening Balance</mat-label>
<input matInput formControlName="agentOpeningBalance" />
</mat-form-field>
</div>
</div>
<div class="am-section">
<div class="am-section__header">
<i class="fas fa-clock"></i>
<h3>Collection Limit History</h3>
<button mat-stroked-button type="button" class="am-add-guarantor" (click)="addLimit()">
<i class="fas fa-plus"></i> Add Limit
</button>
</div>
@if (limits.length === 0) {
<p class="am-empty-guarantors">No limit periods added yet.</p>
}
@for (limitRow of limits.controls; track limitRow; let i = $index) {
<div class="am-limit-row" [formGroup]="$any(limitRow)">
<mat-form-field appearance="outline" class="am-field">
<mat-label>From Date</mat-label>
<input matInput required [matDatepicker]="fromPicker" formControlName="fromDate" />
<mat-datepicker-toggle matIconSuffix [for]="fromPicker"></mat-datepicker-toggle>
<mat-datepicker #fromPicker></mat-datepicker>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>To Date</mat-label>
<input matInput required [matDatepicker]="toPicker" formControlName="toDate" />
<mat-datepicker-toggle matIconSuffix [for]="toPicker"></mat-datepicker-toggle>
<mat-datepicker #toPicker></mat-datepicker>
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Limit</mat-label>
<input matInput required type="number" formControlName="limit" />
</mat-form-field>
<button
mat-icon-button
type="button"
class="am-remove-guarantor"
(click)="removeLimit(i)"
matTooltip="Remove limit period"
>
<i class="fas fa-trash"></i>
</button>
</div>
}
</div>
<div class="am-section">
<div class="am-section__header">
<i class="fas fa-user-shield"></i>
<h3>Guarantor's Detail</h3>
<button mat-stroked-button type="button" class="am-add-guarantor" (click)="addGuarantor()">
<i class="fas fa-plus"></i> Add Guarantor
</button>
</div>
@if (guarantors.length === 0) {
<p class="am-empty-guarantors">No guarantors added yet.</p>
}
@for (guarantor of guarantors.controls; track guarantor; let i = $index) {
<div class="am-guarantor-row" [formGroup]="$any(guarantor)">
<mat-form-field appearance="outline" class="am-field">
<mat-label>Client ID</mat-label>
<input matInput required formControlName="clientId" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Guarantor Name</mat-label>
<input matInput required formControlName="guarantorName" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Address 1</mat-label>
<input matInput required formControlName="address1" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Address 2</mat-label>
<input matInput formControlName="address2" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>City</mat-label>
<input matInput required formControlName="city" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Pin Code</mat-label>
<input matInput required formControlName="pinCode" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Telephone</mat-label>
<input matInput formControlName="telephone" />
</mat-form-field>
<button
mat-icon-button
type="button"
class="am-remove-guarantor"
(click)="removeGuarantor(i)"
matTooltip="Remove guarantor"
>
<i class="fas fa-trash"></i>
</button>
</div>
}
</div>
<div class="am-section">
<div class="am-section__header">
<i class="fas fa-wallet"></i>
<h3>Deductions &amp; Deposits</h3>
</div>
<div class="am-grid">
<mat-form-field appearance="outline" class="am-field">
<mat-label>Comm</mat-label>
<input matInput formControlName="commission" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Other Comm</mat-label>
<input matInput type="number" formControlName="otherCommission" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Ag.Deposit</mat-label>
<input matInput type="number" formControlName="agentDeposit" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Adv.Festival</mat-label>
<input matInput type="number" formControlName="festivalAdvance" />
</mat-form-field>
<mat-form-field appearance="outline" class="am-field">
<mat-label>Other Deduction</mat-label>
<input matInput type="number" formControlName="otherDeduction" />
</mat-form-field>
</div>
</div>
<div class="am-action-bar">
<button mat-raised-button type="button" (click)="exit()">Exit</button>
<button mat-stroked-button type="button" (click)="cancel()">Cancel</button>
<button mat-stroked-button type="button" (click)="retrieve()">Retrieve</button>
<button mat-raised-button color="primary" type="button" [disabled]="agentForm.invalid" (click)="save()">
Save
</button>
</div>
</form>
</div>
</div>
@@ -0,0 +1,141 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
$primary: #0f766e;
.am-container {
max-width: 1040px;
margin: 0 auto;
padding: 24px 16px;
}
.am-header {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 20px;
&__title {
margin: 0;
font-size: 22px;
font-weight: 500;
}
}
.am-back {
color: $primary;
}
.am-card {
background: var(--md-sys-color-surface, #fff);
border-radius: 8px;
box-shadow: 0 2px 8px rgb(0 0 0 / 8%);
padding: 8px 24px 24px;
}
.am-section {
padding: 20px 0;
border-bottom: 1px solid rgb(0 0 0 / 8%);
&:last-of-type {
border-bottom: none;
}
&__header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 16px;
i {
color: $primary;
}
h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
flex: 1;
}
}
}
.am-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px 16px;
}
.am-field {
width: 100%;
&--wide {
grid-column: span 2;
}
}
.am-add-guarantor {
color: $primary;
}
.am-empty-guarantors {
color: rgb(0 0 0 / 50%);
font-size: 14px;
margin: 0 0 8px;
}
.am-guarantor-row {
display: grid;
grid-template-columns: repeat(7, 1fr) auto;
gap: 8px 12px;
align-items: start;
padding: 10px 0;
border-top: 1px dashed rgb(0 0 0 / 10%);
&:first-of-type {
border-top: none;
}
}
.am-limit-row {
display: grid;
grid-template-columns: repeat(3, 1fr) auto;
gap: 8px 12px;
align-items: start;
padding: 10px 0;
border-top: 1px dashed rgb(0 0 0 / 10%);
&:first-of-type {
border-top: none;
}
}
.am-remove-guarantor {
color: #b91c1c;
margin-top: 8px;
}
.am-action-bar {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 20px;
padding-top: 16px;
flex-wrap: wrap;
}
@media (width <= 900px) {
.am-grid {
grid-template-columns: repeat(2, 1fr);
}
.am-guarantor-row,
.am-limit-row {
grid-template-columns: repeat(2, 1fr);
}
}
@@ -0,0 +1,381 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Component, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, UntypedFormArray, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
/** Custom Services */
import { OrganizationService } from 'app/organization/organization.service';
import { SettingsService } from 'app/settings/settings.service';
import { Dates } from 'app/core/utils/dates';
/**
* Agent Master Entry component.
*
* A DDS collection agent — either a person or an institution — registered
* with its own settlement savings account and one or more guarantors. As of
* 2026-08-24 the Agent also does the daily collection work directly (the
* SubAgent tier was removed): it carries the collection-limit history,
* TDS/commission settings and security account SubAgent used to own.
*
* Backed by its own DDS Agent API (`/dds/agents`) - independent of Staff/
* Client CRUD, per the DDS agent/commission hierarchy being genuinely new
* feature work.
*/
@Component({
selector: 'mifosx-agent-master',
templateUrl: './agent-master.component.html',
styleUrls: ['./agent-master.component.scss'],
imports: [...STANDALONE_SHARED_IMPORTS]
})
export class AgentMasterComponent {
private formBuilder = inject(UntypedFormBuilder);
private router = inject(Router);
private organizationService = inject(OrganizationService);
private settingsService = inject(SettingsService);
private dateUtils = inject(Dates);
maxDate = new Date();
agentId: number | null = null;
agentSavingAccountTypes = [
'Savings Deposit Individual A/C',
'Savings Deposit Joint A/C',
'Current Account'
];
agentForm: UntypedFormGroup = this.formBuilder.group({
clientId: [
'',
Validators.required
],
agentCode: [
{
value: '',
disabled: true
}
],
agentNameId: [
'',
Validators.required
],
agentAddress1: [
'',
Validators.required
],
agentAddress2: [''],
agentCity: [
'',
Validators.required
],
agentPinCode: [
'',
Validators.required
],
agentTelephone: [''],
agentSavingAccountType: [
'',
Validators.required
],
agentSavingAccountNo: [
'',
Validators.required
],
agentOpeningDate: [
'',
Validators.required
],
agentBirthDate: [
'',
Validators.required
],
agentCurrentBalance: [
{
value: 0,
disabled: true
}
],
agentOpeningBalance: [
{
value: 0,
disabled: true
}
],
homeBranch: [
'',
Validators.required
],
tdsApplicable: [
'No',
Validators.required
],
tdsPercent: [0],
currentTds: [
{
value: 0,
disabled: true
}
],
tdsAmount: [
{
value: 0,
disabled: true
}
],
savingBranch: [
'',
Validators.required
],
transferBranch: [''],
transferAmountAccountType: [''],
transferAccountNo: [''],
commissionCalculation: [
'Yes',
Validators.required
],
limit: [0],
machineRent: [0],
agentSecurityBranch: [''],
agentSecurityAccountType: [''],
agentSecurityAccountNo: [''],
commission: [
{
value: 0,
disabled: true
}
],
otherCommission: [0],
agentDeposit: [0],
festivalAdvance: [0],
otherDeduction: [0],
limits: this.formBuilder.array([]),
guarantors: this.formBuilder.array([])
});
get limits(): UntypedFormArray {
return this.agentForm.get('limits') as UntypedFormArray;
}
get guarantors(): UntypedFormArray {
return this.agentForm.get('guarantors') as UntypedFormArray;
}
private buildLimitGroup(): UntypedFormGroup {
return this.formBuilder.group({
fromDate: [
'',
Validators.required
],
toDate: [
'',
Validators.required
],
limit: [
0,
Validators.required
]
});
}
private buildGuarantorGroup(): UntypedFormGroup {
return this.formBuilder.group({
clientId: [
'',
Validators.required
],
guarantorName: [
'',
Validators.required
],
address1: [
'',
Validators.required
],
address2: [''],
city: [
'',
Validators.required
],
pinCode: [
'',
Validators.required
],
telephone: ['']
});
}
addLimit(): void {
this.limits.push(this.buildLimitGroup());
}
removeLimit(index: number): void {
this.limits.removeAt(index);
}
addGuarantor(): void {
this.guarantors.push(this.buildGuarantorGroup());
}
removeGuarantor(index: number): void {
this.guarantors.removeAt(index);
}
retrieve(): void {
const clientId = this.agentForm.get('clientId')?.value;
if (!clientId) {
return;
}
this.organizationService.getAgents().subscribe((agents: any[]) => {
const match = (agents || []).find((agent) => String(agent.clientId) === String(clientId));
if (match) {
this.patchFormFromAgent(match);
}
});
}
cancel(): void {
this.agentId = null;
this.agentForm.reset();
this.agentForm.patchValue({
agentCurrentBalance: 0,
agentOpeningBalance: 0,
tdsApplicable: 'No',
commissionCalculation: 'Yes',
currentTds: 0,
tdsAmount: 0,
commission: 0
});
this.limits.clear();
this.guarantors.clear();
}
exit(): void {
this.router.navigate(['/organization']);
}
save(): void {
const raw = this.agentForm.getRawValue();
const dateFormat = this.settingsService.dateFormat;
const locale = this.settingsService.language.code;
const payload: any = {
clientId: Number(raw.clientId),
agentNameId: raw.agentNameId,
agentAddress1: raw.agentAddress1,
agentAddress2: raw.agentAddress2 || undefined,
agentCity: raw.agentCity,
agentPinCode: raw.agentPinCode,
agentTelephone: raw.agentTelephone || undefined,
agentSavingAccountType: raw.agentSavingAccountType,
agentSavingAccountNo: raw.agentSavingAccountNo,
agentOpeningDate: this.dateUtils.formatDate(raw.agentOpeningDate, dateFormat),
agentBirthDate: this.dateUtils.formatDate(raw.agentBirthDate, dateFormat),
agentOpeningBalance: raw.agentOpeningBalance || 0,
homeBranch: raw.homeBranch,
tdsApplicable: raw.tdsApplicable === 'Yes',
tdsPercent: raw.tdsPercent || undefined,
savingBranch: raw.savingBranch,
transferBranch: raw.transferBranch || undefined,
transferAmountAccountType: raw.transferAmountAccountType || undefined,
transferAccountNo: raw.transferAccountNo || undefined,
commissionCalculation: raw.commissionCalculation === 'Yes',
limit: raw.limit || undefined,
machineRent: raw.machineRent || undefined,
agentSecurityBranch: raw.agentSecurityBranch || undefined,
agentSecurityAccountType: raw.agentSecurityAccountType || undefined,
agentSecurityAccountNo: raw.agentSecurityAccountNo || undefined,
otherCommission: raw.otherCommission || undefined,
agentDeposit: raw.agentDeposit || undefined,
festivalAdvance: raw.festivalAdvance || undefined,
otherDeduction: raw.otherDeduction || undefined,
dateFormat,
locale,
limits: (raw.limits || []).map((limit: any) => ({
fromDate: this.dateUtils.getDate(limit.fromDate),
toDate: this.dateUtils.getDate(limit.toDate),
limit: limit.limit
})),
guarantors: (raw.guarantors || []).map((guarantor: any) => ({
clientId: Number(guarantor.clientId),
guarantorName: guarantor.guarantorName,
address1: guarantor.address1,
address2: guarantor.address2 || undefined,
city: guarantor.city,
pinCode: guarantor.pinCode,
telephone: guarantor.telephone || undefined
}))
};
if (this.agentId) {
this.organizationService.updateAgent(this.agentId, payload).subscribe(() => this.exit());
} else {
this.organizationService.createAgent(payload).subscribe(() => this.exit());
}
}
private patchFormFromAgent(agent: any): void {
this.agentId = agent.id;
this.agentForm.patchValue({
clientId: agent.clientId,
agentCode: agent.agentCode,
agentNameId: agent.agentNameId,
agentAddress1: agent.agentAddress1,
agentAddress2: agent.agentAddress2,
agentCity: agent.agentCity,
agentPinCode: agent.agentPinCode,
agentTelephone: agent.agentTelephone,
agentSavingAccountType: agent.agentSavingAccountType,
agentSavingAccountNo: agent.agentSavingAccountNo,
agentOpeningDate: agent.agentOpeningDate ? new Date(agent.agentOpeningDate) : null,
agentBirthDate: agent.agentBirthDate ? new Date(agent.agentBirthDate) : null,
agentCurrentBalance: agent.agentCurrentBalance,
agentOpeningBalance: agent.agentOpeningBalance,
homeBranch: agent.homeBranch,
tdsApplicable: agent.tdsApplicable ? 'Yes' : 'No',
tdsPercent: agent.tdsPercent,
currentTds: agent.currentTds,
tdsAmount: agent.tdsAmount,
savingBranch: agent.savingBranch,
transferBranch: agent.transferBranch,
transferAmountAccountType: agent.transferAmountAccountType,
transferAccountNo: agent.transferAccountNo,
commissionCalculation: agent.commissionCalculation ? 'Yes' : 'No',
limit: agent.limit,
machineRent: agent.machineRent,
agentSecurityBranch: agent.agentSecurityBranch,
agentSecurityAccountType: agent.agentSecurityAccountType,
agentSecurityAccountNo: agent.agentSecurityAccountNo,
commission: agent.commission,
otherCommission: agent.otherCommission,
agentDeposit: agent.agentDeposit,
festivalAdvance: agent.festivalAdvance,
otherDeduction: agent.otherDeduction
});
this.limits.clear();
(agent.limits || []).forEach((limit: any) => {
const group = this.buildLimitGroup();
group.patchValue({
fromDate: limit.fromDate ? new Date(limit.fromDate) : null,
toDate: limit.toDate ? new Date(limit.toDate) : null,
limit: limit.limit
});
this.limits.push(group);
});
this.guarantors.clear();
(agent.guarantors || []).forEach((guarantor: any) => {
const group = this.buildGuarantorGroup();
group.patchValue(guarantor);
this.guarantors.push(group);
});
}
}