feat: standing instructions UI - view redesign, edit pre-fill fix, current account tab improvements

- Redesign view-standing-instructions with sectioned layout (General Info, From Account,
  To Account, Transfer Settings, Recurrence) using info-grid/info-row CSS pattern with
  color-coded status badge
- Fix edit-standing-instructions: remove buggy recurrenceOnMonthDay.push() crash that
  caused all form fields to be empty; add parseISODate() and parseMonthDay() helpers
  handling both ISO string and array formats; add null safety with ?. guards on all fields
- Fix edit form patchValue: fromAccount and toAccount show as 'productName - accountNo'
- Improve current account standing-instructions-tab HTML with ?. null guards
- Add missing i18n keys: General Information, From Account, To Account, Transfer Settings,
  Recurrence Settings, Valid From, Valid Till

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-05-26 10:53:52 +05:30
co-authored by Claude Sonnet 4.6
parent 1779591b7a
commit ae414c620e
10 changed files with 379 additions and 168 deletions
@@ -41,6 +41,9 @@ export class StandingInstructionsTemplateResolver {
case 'fromsavings':
this.accountTypeId = '2';
break;
case 'fromcurrentaccount':
this.accountTypeId = '3';
break;
default:
this.accountTypeId = '0';
}
@@ -114,6 +114,9 @@ export class CreateStandingInstructionsComponent implements OnInit {
case 'fromsavings':
this.accountTypeId = '2';
break;
case 'fromcurrentaccount':
this.accountTypeId = '3';
break;
default:
this.accountTypeId = '0';
}
@@ -84,37 +84,76 @@ export class EditStandingInstructionsComponent implements OnInit {
*/
ngOnInit() {
this.createEditStandingInstructionsForm();
const presentDate = new Date();
const n = presentDate.getFullYear();
if (this.standingInstructionsData.recurrenceOnMonthDay) {
this.standingInstructionsData.recurrenceOnMonthDay.push(n);
}
const d = this.standingInstructionsData;
this.editStandingInstructionsForm.patchValue({
name: this.standingInstructionsData.name,
applicant: this.standingInstructionsData.fromClient.displayName,
type: this.standingInstructionsData.transferType.value,
priority: this.standingInstructionsData.priority.id,
status: this.standingInstructionsData.status.id,
fromAccountType: this.standingInstructionsData.fromAccountType.value,
fromAccount: this.standingInstructionsData.fromAccount.productName,
name: d.name,
applicant: d.fromClient?.displayName,
type: d.transferType?.value,
priority: d.priority?.id,
status: d.status?.id,
fromAccountType: d.fromAccountType?.value,
fromAccount: d.fromAccount?.productName
? `${d.fromAccount.productName} - ${d.fromAccount.accountNo}`
: d.fromAccount?.accountNo,
destination: this.allowclientedit ? 'Within Bank' : 'Own Account',
toOffice: this.standingInstructionsData.toOffice.name,
toClientId: this.standingInstructionsData.toClient.displayName,
toAccountType: this.standingInstructionsData.toAccountType.value,
toAccount: this.standingInstructionsData.toAccount.productName,
instructionType: this.standingInstructionsData.instructionType.id,
amount: this.standingInstructionsData.amount,
validFrom: this.standingInstructionsData.validFrom && new Date(this.standingInstructionsData.validFrom),
validTill: this.standingInstructionsData.validTill && new Date(this.standingInstructionsData.validTill),
recurrenceType: this.standingInstructionsData.recurrenceType.id,
recurrenceInterval: this.standingInstructionsData.recurrenceInterval,
recurrenceFrequency: this.standingInstructionsData.recurrenceFrequency.id,
recurrenceOnMonthDay:
this.standingInstructionsData.recurrenceOnMonthDay &&
new Date(this.standingInstructionsData.recurrenceOnMonthDay)
toOffice: d.toOffice?.name,
toClientId: d.toClient?.displayName,
toAccountType: d.toAccountType?.value,
toAccount: d.toAccount?.productName
? `${d.toAccount.productName} - ${d.toAccount.accountNo}`
: d.toAccount?.accountNo,
instructionType: d.instructionType?.id,
amount: d.amount,
validFrom: this.parseISODate(d.validFrom),
validTill: this.parseISODate(d.validTill),
recurrenceType: d.recurrenceType?.id,
recurrenceInterval: d.recurrenceInterval,
recurrenceFrequency: d.recurrenceFrequency?.id,
recurrenceOnMonthDay: this.parseMonthDay(d.recurrenceOnMonthDay)
});
}
/**
* Parses an ISO date string "YYYY-MM-DD" or array [year, month, day]
* into a local-timezone Date (avoids UTC-offset off-by-one day issues).
*/
private parseISODate(value: any): Date | null {
if (!value) return null;
if (typeof value === 'string') {
const parts = value.split('-');
if (parts.length === 3) {
return new Date(+parts[0], +parts[1] - 1, +parts[2]);
}
return new Date(value);
}
if (Array.isArray(value) && value.length >= 3) {
// Array format [year, month, day] — month is 1-indexed in Java
return new Date(value[0], value[1] - 1, value[2]);
}
return null;
}
/**
* Parses a MonthDay value from the API into a Date for the current year.
* Handles ISO MonthDay string "--MM-DD" (Jackson default) and
* legacy array format [month, day].
*/
private parseMonthDay(value: any): Date | null {
if (!value) return null;
const currentYear = new Date().getFullYear();
if (typeof value === 'string') {
// ISO MonthDay: "--MM-DD"
const match = value.match(/^--(\d{2})-(\d{2})$/);
if (match) {
return new Date(currentYear, +match[1] - 1, +match[2]);
}
} else if (Array.isArray(value) && value.length >= 2) {
// Legacy array [month, day] — month is 1-indexed
return new Date(currentYear, value[0] - 1, value[1]);
}
return null;
}
/**
* Creates the standing instructions form.
*/
@@ -46,7 +46,7 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
<mat-select [formControl]="transferType">
@for (transferTypeData of transferTypeDatas; track transferTypeData) {
@for (transferTypeData of transferTypeDatas; track transferTypeData.id) {
<mat-option [value]="transferTypeData.id">
{{ transferTypeData.value }}
</mat-option>
@@ -118,12 +118,12 @@ export class ListStandingInstructionsComponent {
constructor() {
this.route.data.subscribe((data: { standingIntructionsTemplate: any }) => {
this.standingIntructionsTemplateData = data.standingIntructionsTemplate;
this.setParams();
this.transferTypeDatas = this.standingIntructionsTemplateData.transferTypeOptions;
if (data.standingIntructionsTemplate.fromClient) {
this.clientName = this.standingIntructionsTemplateData.fromClient.displayName;
this.getStandingInstructions();
}
this.setParams();
this.transferTypeDatas = this.standingIntructionsTemplateData.transferTypeOptions;
});
}
@@ -136,6 +136,9 @@ export class ListStandingInstructionsComponent {
case 'fromsavings':
this.accountTypeId = '2';
break;
case 'fromcurrentaccount':
this.accountTypeId = '3';
break;
default:
this.accountTypeId = '0';
}
@@ -6,134 +6,193 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="layout-row align-end gap-2px responsive-column container m-b-20">
<button mat-raised-button color="primary" [routerLink]="['../', 'edit']">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Edit' | translate }}
</button>
<button
mat-raised-button
color="primary"
[routerLink]="['../', 'list-account-transactions']"
*mifosxHasPermission="'READ_ACCOUNTTRANSFER'"
>
{{ 'labels.buttons.View Transactions History' | translate }}
</button>
</div>
<div class="container">
<!-- Action Buttons -->
<div class="action-buttons m-b-20">
<button mat-raised-button color="primary" [routerLink]="['../', 'edit']">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Edit' | translate }}
</button>
<button
mat-raised-button
color="primary"
[routerLink]="['../', 'list-account-transactions']"
*mifosxHasPermission="'READ_ACCOUNTTRANSFER'"
>
{{ 'labels.buttons.View Transactions History' | translate }}
</button>
</div>
<mat-card>
<mat-card-content>
<div class="layout-row-wrap responsive-column">
<h2 class="mat-h2 flex-fill">{{ standingInstructionsData.name }}</h2>
<mat-divider [inset]="true"></mat-divider>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Applicant' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.fromClient.displayName }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Type' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.transferType.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Priority' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.priority.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Status' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.status.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.From Account Type' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.fromAccountType.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.From Account' | translate }}:</span>
<span class="flex-60"
>{{ standingInstructionsData.fromAccount.productName }} -
{{ standingInstructionsData.fromAccount.accountNo }}</span
>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Destination' | translate }}:</span>
<span class="flex-60">
@if (allowclientedit) {
<span> {{ 'labels.inputs.Within Bank' | translate }} </span>
}
@if (!allowclientedit) {
<span> {{ 'labels.inputs.Own Account' | translate }} </span>
}
<div class="si-container">
<!-- Instruction Name Header -->
<div class="si-header">
<h2>{{ standingInstructionsData?.name }}</h2>
<span class="status-badge" [class]="'status-' + standingInstructionsData?.status?.value?.toLowerCase()">
{{ standingInstructionsData?.status?.value }}
</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.To Office' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.toOffice.name }}</span>
</div>
<mat-divider></mat-divider>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Beneficiary' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.toClient.displayName }}</span>
</div>
<!-- Section 1: General Information -->
<section class="si-section">
<h3 class="section-title">{{ 'labels.heading.General Information' | translate }}</h3>
<mat-divider></mat-divider>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.To Account Type' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.toAccountType.value }}</span>
</div>
<div class="info-grid">
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Applicant' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.fromClient?.displayName }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.To Account' | translate }}:</span>
<span class="flex-60"
>{{ standingInstructionsData.toAccount.productName }} -
{{ standingInstructionsData.toAccount.accountNo }}</span
>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Type' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.transferType?.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Standing Instruction Type' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.instructionType.value }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Priority' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.priority?.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Amount' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.amount }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Standing Instruction Type' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.instructionType?.value }}</span>
</div>
</div>
</section>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Validity' | translate }}:</span>
<span class="flex-60"
>{{ standingInstructionsData.validFrom | dateFormat }} -
{{ standingInstructionsData.validTill | dateFormat }}</span
>
</div>
<!-- Section 2: From Account -->
<section class="si-section">
<h3 class="section-title">{{ 'labels.heading.From Account' | translate }}</h3>
<mat-divider></mat-divider>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Recurrence Type' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.recurrenceType.value }}</span>
</div>
<div class="info-grid">
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Office' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.fromOffice?.name }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Interval' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.recurrenceInterval }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Client' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.fromClient?.displayName }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Recurrence Frequency' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.recurrenceFrequency.value }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Account Type' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.fromAccountType?.value }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.On Month Day' | translate }}:</span>
<span class="flex-60">{{ standingInstructionsData.recurrenceOnMonthDay | dateFormat }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Account' | translate }}:</span>
<span class="info-value">
@if (standingInstructionsData?.fromAccount?.productName) {
{{ standingInstructionsData.fromAccount.productName }} —
}
{{ standingInstructionsData?.fromAccount?.accountNo }}
</span>
</div>
</div>
</section>
<!-- Section 3: To Account -->
<section class="si-section">
<h3 class="section-title">{{ 'labels.heading.To Account' | translate }}</h3>
<mat-divider></mat-divider>
<div class="info-grid">
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Destination' | translate }}:</span>
<span class="info-value">
@if (allowclientedit) {
{{ 'labels.inputs.Within Bank' | translate }}
} @else {
{{ 'labels.inputs.Own Account' | translate }}
}
</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Office' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.toOffice?.name }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Beneficiary' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.toClient?.displayName }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Account Type' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.toAccountType?.value }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Account' | translate }}:</span>
<span class="info-value">
@if (standingInstructionsData?.toAccount?.productName) {
{{ standingInstructionsData.toAccount.productName }} —
}
{{ standingInstructionsData?.toAccount?.accountNo }}
</span>
</div>
</div>
</section>
<!-- Section 4: Transfer Settings -->
<section class="si-section">
<h3 class="section-title">{{ 'labels.heading.Transfer Settings' | translate }}</h3>
<mat-divider></mat-divider>
<div class="info-grid">
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Amount' | translate }}:</span>
<span class="info-value amount-value">{{ standingInstructionsData?.amount | number: '1.2-2' }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Valid From' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.validFrom | dateFormat }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Valid Till' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.validTill | dateFormat }}</span>
</div>
</div>
</section>
<!-- Section 5: Recurrence Settings -->
<section class="si-section">
<h3 class="section-title">{{ 'labels.heading.Recurrence Settings' | translate }}</h3>
<mat-divider></mat-divider>
<div class="info-grid">
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Recurrence Type' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.recurrenceType?.value }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Interval' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.recurrenceInterval }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.Recurrence Frequency' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.recurrenceFrequency?.value }}</span>
</div>
@if (standingInstructionsData?.recurrenceOnMonthDay) {
<div class="info-row">
<span class="info-label">{{ 'labels.inputs.On Month Day' | translate }}:</span>
<span class="info-value">{{ standingInstructionsData?.recurrenceOnMonthDay | dateFormat }}</span>
</div>
}
</div>
</section>
</div>
</mat-card-content>
</mat-card>
@@ -6,25 +6,113 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.mat-elevation-z1 {
margin: 1em 0 1.5em;
.action-buttons {
display: flex;
gap: 0.75rem;
justify-content: flex-end;
flex-wrap: wrap;
}
h2,
h3,
h4 {
.si-container {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.si-header {
display: flex;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
h2 {
margin: 0;
font-size: 1.4rem;
font-weight: 500;
flex: 1;
}
}
.status-badge {
display: inline-block;
padding: 0.2rem 0.75rem;
border-radius: 12px;
font-size: 0.8rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
background-color: #e0e0e0;
color: #555;
&.status-active {
background-color: #e8f5e9;
color: #2e7d32;
}
&.status-disabled {
background-color: #fff3e0;
color: #e65100;
}
&.status-deleted {
background-color: #f5f5f5;
color: #9e9e9e;
}
}
.si-section {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.section-title {
margin: 0;
font-weight: 500;
}
span {
margin: 0.5em 0;
}
.margin-t {
margin-top: 1em;
font-size: 1rem;
font-weight: 600;
color: var(--mdc-theme-primary, #3f51b5);
text-transform: uppercase;
letter-spacing: 0.5px;
}
mat-divider {
margin: 0 0 1em;
margin-bottom: 0.25rem;
}
.info-grid {
display: grid;
gap: 0.6rem;
}
.info-row {
display: grid;
grid-template-columns: minmax(160px, 220px) 1fr;
gap: 1rem;
align-items: start;
@media (width <= 768px) {
grid-template-columns: 1fr;
gap: 0.2rem;
}
}
.info-label {
font-weight: 500;
color: rgb(0 0 0 / 60%);
@media (width <= 768px) {
font-size: 0.8rem;
color: rgb(0 0 0 / 45%);
}
}
.info-value {
word-break: break-word;
color: rgb(0 0 0 / 87%);
&.amount-value {
font-size: 1.1rem;
font-weight: 600;
color: var(--mdc-theme-primary, #3f51b5);
}
}
@@ -16,32 +16,43 @@
<ng-container matColumnDef="client">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Client' | translate }}</th>
<td mat-cell *matCellDef="let instruction">
{{ instruction.fromClient.displayName }}-{{ instruction.fromClient.id }}
{{ instruction.fromClient?.displayName }}-{{ instruction.fromClient?.id }}
</td>
</ng-container>
<ng-container matColumnDef="fromAccount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.From Account' | translate }}</th>
<td mat-cell *matCellDef="let instruction">
{{ instruction.fromAccount.accountNo }} ({{ instruction.fromAccountType.value }})
{{ instruction.fromAccount?.accountNo }}
@if (instruction.fromAccountType?.value) {
({{ instruction.fromAccountType.value }})
}
</td>
</ng-container>
<ng-container matColumnDef="beneficiary">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Beneficiary' | translate }}</th>
<td mat-cell *matCellDef="let instruction">{{ instruction.toClient.displayName }}</td>
<td mat-cell *matCellDef="let instruction">{{ instruction.toClient?.displayName }}</td>
</ng-container>
<ng-container matColumnDef="toAccount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.To Account' | translate }}</th>
<td mat-cell *matCellDef="let instruction">
{{ instruction.toAccount.accountNo }} ({{ instruction.toAccountType.value }})
{{ instruction.toAccount?.accountNo }}
@if (instruction.toAccountType?.value) {
({{ instruction.toAccountType.value }})
}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let instruction">{{ instruction.instructionType.value }}/{{ instruction.amount }}</td>
<td mat-cell *matCellDef="let instruction">
@if (instruction.instructionType?.value) {
{{ instruction.instructionType.value }}/
}
{{ instruction.amount }}
</td>
</ng-container>
<ng-container matColumnDef="validity">
@@ -55,7 +66,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let instruction">
@if (instruction.status.value !== 'Deleted') {
@if (instruction.status?.value !== 'Deleted') {
<span>
<button
class="account-action-button"
@@ -68,7 +79,7 @@
</button>
</span>
}
@if (instruction.status.value !== 'Deleted') {
@if (instruction.status?.value !== 'Deleted') {
<span>
<button
class="account-action-button"
@@ -101,7 +101,7 @@ export class CurrentAccountsService {
.set('clientId', clientId)
.set('clientName', clientName)
.set('fromAccountId', fromAccountId)
.set('fromAccountType', '2')
.set('fromAccountType', '3')
.set('locale', locale)
.set('dateFormat', dateFormat);
return this.http.get(`/standinginstructions`, { params: httpParams });
+9 -4
View File
@@ -430,7 +430,6 @@
"Create Hook": "Create Hook",
"Create Interest Refund": "Create Interest Refund",
"Create Current Product": "Create Current Product",
"Create Fixed Deposit Product": "Create Fixed Deposit Product",
"Create Journal Entries": "Create Journal Entries",
"Create Loan Product": "Create Loan Product",
"Create Office": "Create Office",
@@ -1078,7 +1077,6 @@
"Create Fixed Deposit Product": "Create Fixed Deposit Product",
"Create Loan Product": "Create Loan Product",
"Create Recurring Deposit Product": "Create Recurring Deposit Product",
"Create Share Product": "Create Share Product",
"Create Tax Group": "Create Tax Group",
"Create fixed deposit product": "Create fixed deposit product",
"Create loan product": "Create loan product",
@@ -1454,7 +1452,12 @@
"You have created": "You have created",
"identifier id": "identifier id",
"savings-transaction-datatable-tab works": "savings-transaction-datatable-tab works",
"successfully select option": "successfully. Please select from the options below to proceed further."
"successfully select option": "successfully. Please select from the options below to proceed further.",
"From Account": "From Account",
"General Information": "General Information",
"Recurrence Settings": "Recurrence Settings",
"To Account": "To Account",
"Transfer Settings": "Transfer Settings"
},
"inputs": {
"# Remittance": "# Remittance",
@@ -3013,7 +3016,9 @@
"s3_secret_key": "s3_secret_key",
"task-management component": "task-management component",
"to": "to",
"valid": "valid"
"valid": "valid",
"Valid From": "Valid From",
"Valid Till": "Valid Till"
},
"links": {
"Community": "Community",