TOTAL FACE VALUE
diff --git a/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.scss b/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.scss
index ddfd4101c..97e7362ac 100644
--- a/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.scss
+++ b/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.scss
@@ -206,6 +206,13 @@
}
/* Certificate Data Table */
+
+/* The details grid and the allotment schedule read as one block, so the gap that used to sit under
+ the details table now sits under whichever table comes last. */
+.certificate-details-table:not(:last-of-type) {
+ margin-bottom: 0;
+}
+
.certificate-details-table {
width: 100%;
border-collapse: collapse;
@@ -250,6 +257,47 @@
}
}
+/* The allotment schedule — one row per block of shares allotted, in the same paper-and-ink palette
+ as the details grid so it reads as part of the certificate rather than a report pasted into it. */
+.allotment-table {
+ position: relative;
+ z-index: 2; /* Above the watermark, like the other certificate content. */
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 40px;
+
+ th {
+ padding: 8px 12px;
+ border: 1px solid #ede8db;
+ background-color: #f7f5ee;
+ font-size: 11px;
+ font-weight: bold;
+ color: #7b6f63;
+ text-transform: uppercase;
+ letter-spacing: 0.6px;
+ }
+
+ td {
+ padding: 9px 12px;
+ border: 1px solid #ede8db;
+ font-size: 13px;
+ color: #322f2b;
+ }
+
+ .allotment-meeting {
+ color: #7b6f63;
+ font-size: 12px;
+ }
+
+ .ta-left {
+ text-align: left;
+ }
+
+ .ta-right {
+ text-align: right;
+ }
+}
+
/* Certificate Footer Seal / Signatures */
.cert-footer {
display: flex;
diff --git a/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.ts b/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.ts
index 1f5ea5703..2b4c517b9 100644
--- a/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.ts
+++ b/src/app/shares/shares-account-view/share-certificate-dialog/share-certificate-dialog.component.ts
@@ -61,6 +61,27 @@ export class ShareCertificateDialogComponent implements OnInit {
issueDate: Date = new Date();
todayDate: Date = new Date();
+ /**
+ * One row per approved purchase, oldest first — the allotments this certificate covers.
+ *
+ * A member's holding is built up over time: the opening subscription, then each further tranche,
+ * every one authorised by its own board resolution on its own date. Collapsing that into a single
+ * total and one "Date of Issue" loses exactly what a share certificate exists to record — when
+ * each block of shares was allotted, under which resolution, and which share numbers it covers.
+ * The running range is what lets a member's 20 shares be read as 10 allotted in August and 10 in
+ * September rather than as one undated block.
+ */
+ allotments: {
+ date: any;
+ shares: number;
+ unitPrice: number;
+ faceValue: number;
+ resolutionNumber: string;
+ meetingDate: any;
+ shareNumbersFrom: number;
+ shareNumbersTo: number;
+ }[] = [];
+
ngOnInit() {
this.sharesAccountData = this.data.sharesAccountData;
this.clientId = String(this.data.clientId);
@@ -82,6 +103,18 @@ export class ShareCertificateDialogComponent implements OnInit {
const endNum = startNum + approvedShares - 1;
this.shareNumbersRange = approvedShares > 0 ? `${startNum.toLocaleString()} – ${endNum.toLocaleString()}` : 'None';
+ this.buildAllotments(startNum);
+
+ // The certificate is issued as of the most recent allotment, not the account's activation: a
+ // certificate reprinted after a further tranche covers those shares too, and dating it from
+ // activation would say the later shares were issued before they existed.
+ if (this.allotments.length > 0) {
+ const latest = this.allotments[this.allotments.length - 1];
+ if (latest.date) {
+ this.issueDate = new Date(latest.date);
+ }
+ }
+
// Calculate cumulative dividends
if (this.sharesAccountData.dividends) {
this.cumulativeDividend = this.sharesAccountData.dividends.reduce(
@@ -124,6 +157,48 @@ export class ShareCertificateDialogComponent implements OnInit {
});
}
+ /**
+ * Builds the allotment rows from the account's approved purchases.
+ *
+ * Only approved purchases count. A pending tranche has not been allotted — the board has not
+ * approved it and, on the cash and savings routes alike, the money is still sitting in Share
+ * Sundry — so putting it on a certificate would certify shares the member does not yet hold.
+ * Rejected ones and charge payments are not allotments at all.
+ *
+ * Share numbers run consecutively in purchase order, so each row's range picks up where the last
+ * left off and the ranges together reconcile to the account's total holding.
+ *
+ * @param startNum the first share number of the account's holding.
+ */
+ private buildAllotments(startNum: number): void {
+ const purchases = (this.sharesAccountData.purchasedShares || [])
+ .filter(
+ (txn: any) => txn?.type?.value === 'Purchase' && txn?.status?.code === 'purchasedSharesStatusType.approved'
+ )
+ .slice()
+ .sort((a: any, b: any) => new Date(a.purchasedDate).getTime() - new Date(b.purchasedDate).getTime());
+
+ let nextShareNumber = startNum;
+ this.allotments = purchases.map((txn: any) => {
+ const shares = Number(txn.numberOfShares) || 0;
+ const unitPrice = Number(txn.purchasedPrice) || 0;
+ const from = nextShareNumber;
+ nextShareNumber += shares;
+ return {
+ date: txn.purchasedDate,
+ shares,
+ unitPrice,
+ faceValue: shares * unitPrice,
+ // The account's own resolution stands in for the opening subscription, which carries none of
+ // its own; each additional tranche has the resolution captured when it was applied for.
+ resolutionNumber: txn.resolutionNumber || this.sharesAccountData.resolutionNumber || '',
+ meetingDate: txn.meetingDate || this.sharesAccountData.resolutionDate || null,
+ shareNumbersFrom: from,
+ shareNumbersTo: from + shares - 1
+ };
+ });
+ }
+
formatAddress(addr: any): string {
if (!addr) return '';
return [
diff --git a/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.html b/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.html
index cb819bf7e..8b133df93 100644
--- a/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.html
+++ b/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.html
@@ -62,14 +62,16 @@
Resolution No. / Meeting Date
- @if (transaction.type.value === 'Redeem') {
- {{ transaction.resolutionNumber || '—' }}
+
+ @if (transaction.resolutionNumber) {
+ {{ transaction.resolutionNumber }}
@if (transaction.meetingDate) {
({{ transaction.meetingDate | dateFormat }})
}
} @else {
-
{{ shareAccountData.resolutionNumber || '—' }}
@if (shareAccountData.resolutionDate) {
({{ shareAccountData.resolutionDate | dateFormat }})
diff --git a/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.ts b/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.ts
index 46a7e3db0..3a6fb578d 100644
--- a/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.ts
+++ b/src/app/shares/shares-account-view/transactions-tab/transactions-tab.component.ts
@@ -24,6 +24,7 @@ import {
import { ActivatedRoute } from '@angular/router';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
+import { isSettledShareTransaction } from 'app/shares/share-transactions.util';
/**
* Transactions Tab Component.
@@ -78,7 +79,7 @@ export class TransactionsTabComponent implements OnInit {
this.route.parent.data.subscribe((data: { sharesAccountData: any }) => {
this.shareAccountData = data.sharesAccountData;
this.transactionsData = this.shareAccountData.purchasedShares
- .filter((transaction: any) => transaction.type.value !== 'Charge Payment')
+ .filter(isSettledShareTransaction)
.slice()
.sort((a: any, b: any) => new Date(a.purchasedDate).getTime() - new Date(b.purchasedDate).getTime());
diff --git a/src/app/shares/shares.service.ts b/src/app/shares/shares.service.ts
index 956093a20..0bf0f7d71 100644
--- a/src/app/shares/shares.service.ts
+++ b/src/app/shares/shares.service.ts
@@ -122,6 +122,21 @@ export class SharesService {
return this.http.post(`/accounts/share/${accountId}`, data, { params: httpParams });
}
+ /**
+ * Whether a new additional-share tranche can be funded from the member's linked savings.
+ *
+ * Tranche-scoped, unlike `/sharesavingsdebit/eligibility`: that one values an account's first
+ * application by summing every purchase on the account, which for a further tranche would quote
+ * the member's whole holding history and call an already-settled account ineligible.
+ *
+ * @returns {Observable} `{ eligible, reason, requestedShares, unitPrice, amount,
+ * savingsAccountNo, savingsBalance }`.
+ */
+ getAdditionalSharesSavingsEligibility(accountId: string, requestedShares: number): Observable {
+ const httpParams = new HttpParams().set('requestedShares', String(requestedShares));
+ return this.http.get(`/shareaccounts/${accountId}/additionalshares/savings-eligibility`, { params: httpParams });
+ }
+
/**
* @param {string} accountId Shares Account Id.
* @param {any} data Details edit payload.
@@ -146,6 +161,19 @@ export class SharesService {
return this.http.get(`/shareaccounts/edit/pending`);
}
+ /**
+ * Share accounts submitted and awaiting a checker's approval.
+ *
+ * Its own endpoint rather than `/accounts/share`, which only lists ACTIVE accounts and returns the
+ * whole account graph per row; this returns just the member, product, requested shares and value a
+ * checker decides on.
+ *
+ * @returns {Observable} One row per pending account.
+ */
+ getPendingShareAccounts(): Observable {
+ return this.http.get('/shareaccounts/pending');
+ }
+
/**
* @param {string} accountId Shares Account Id.
* @returns {Observable}
diff --git a/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.html b/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.html
new file mode 100644
index 000000000..6e15d8f66
--- /dev/null
+++ b/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.html
@@ -0,0 +1,107 @@
+
+
+
+ @if (showData) {
+
+
+ search
+
+
+
+
+
+
+
+ Account No.
+ {{ account.accountNo }}
+
+
+
+ Member
+
+ {{ account.clientName }}
+ @if (account.officeName) {
+ {{ account.officeName }}
+ }
+
+
+
+
+ Product
+ {{ account.productName }}
+
+
+
+ Shares
+ {{ account.requestedShares }}
+
+
+
+ Amount
+
+ {{ account.requestedAmount | number: '1.2-2' }}
+
+
+
+
+
+ Resolution
+
+ {{ account.resolutionNumber || '—' }}
+ @if (account.resolutionDate) {
+ {{ formatDate(account.resolutionDate) }}
+ }
+
+
+
+
+ Submitted
+
+ {{ formatDate(account.submittedDate) }}
+ @if (account.submittedByUsername) {
+ by {{ account.submittedByUsername }}
+ }
+
+
+
+
+ Actions
+
+
+ View
+
+
+ Approve
+
+
+ Reject
+
+
+
+
+
+
+
+
+ }
+
+ @if (!showData) {
+
+
+
No pending share accounts
+
There are no share accounts awaiting approval at this time.
+
+ }
+
diff --git a/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.scss b/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.scss
new file mode 100644
index 000000000..3e8e2c212
--- /dev/null
+++ b/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.scss
@@ -0,0 +1,128 @@
+/**
+ * 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/.
+ */
+
+$border: #e2e8f0;
+$text-muted: #64748b;
+
+.psa-tab-content {
+ padding: 16px 0;
+}
+
+.psa-action-bar {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 16px;
+ flex-wrap: wrap;
+}
+
+.psa-search-field {
+ flex: 1;
+ min-width: 200px;
+ max-width: 340px;
+}
+
+.psa-btn {
+ font-size: 11.5px;
+ font-weight: 600;
+ border-radius: 8px !important;
+ height: 32px;
+ padding: 0 10px;
+ margin-right: 6px;
+
+ fa-icon {
+ margin-right: 4px;
+ font-size: 11px;
+ }
+}
+
+.psa-btn-view {
+ border-color: #2563eb;
+ color: #2563eb;
+
+ &:hover {
+ background: #eff6ff;
+ }
+}
+
+.psa-btn-approve {
+ border-color: #16a34a;
+ color: #16a34a;
+
+ &:hover {
+ background: #f0fdf4;
+ }
+}
+
+.psa-btn-reject {
+ border-color: #dc2626;
+ color: #dc2626;
+
+ &:hover {
+ background: #fef2f2;
+ }
+}
+
+.psa-mono {
+ font-family: 'Courier New', monospace;
+}
+
+/* Tabular figures so share counts and amounts line up digit for digit down their columns — a queue
+ is scanned, and two subscriptions of very different sizes should look different at a glance. */
+.psa-num {
+ font-variant-numeric: tabular-nums;
+ font-weight: 500;
+ white-space: nowrap;
+}
+
+/* The second line in a cell — branch under the member, meeting date under the resolution number,
+ who submitted it under the date. Kept with the value it qualifies rather than given a column of
+ its own, which would make an already wide table wider for something read together anyway. */
+.psa-sub {
+ font-size: 11px;
+ color: $text-muted;
+ margin-top: 2px;
+}
+
+.ta-right {
+ text-align: right;
+}
+
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 60px 24px;
+ background: #fff;
+ border: 1px dashed $border;
+ border-radius: 14px;
+ text-align: center;
+ margin: 16px 0;
+
+ .empty-icon {
+ font-size: 42px;
+ color: #cbd5e1;
+ margin-bottom: 14px;
+ }
+
+ .empty-title {
+ margin: 0 0 4px;
+ font-size: 15px;
+ font-weight: 700;
+ color: #0d1b2a;
+ }
+
+ .empty-text {
+ margin: 0;
+ font-size: 12.5px;
+ color: $text-muted;
+ max-width: 380px;
+ line-height: 1.5;
+ }
+}
diff --git a/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.ts b/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.ts
new file mode 100644
index 000000000..03cf94472
--- /dev/null
+++ b/src/app/tasks/checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component.ts
@@ -0,0 +1,192 @@
+/**
+ * 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/.
+ */
+
+import { Component, inject } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { DecimalPipe } from '@angular/common';
+import {
+ MatTableDataSource,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCellDef,
+ MatHeaderCell,
+ MatCellDef,
+ MatCell,
+ MatHeaderRowDef,
+ MatHeaderRow,
+ MatRowDef,
+ MatRow
+} from '@angular/material/table';
+import { MatDialog } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { FaIconComponent } from '@fortawesome/angular-fontawesome';
+
+import { SharesService } from 'app/shares/shares.service';
+import { SettingsService } from 'app/settings/settings.service';
+import { Dates } from 'app/core/utils/dates';
+import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
+import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
+import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
+import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
+import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
+
+/**
+ * Checker-facing list of share accounts submitted and awaiting approval.
+ *
+ * Mirrors PendingShareAccountEditsComponent's list + approve/reject pattern, but for whole accounts
+ * rather than edits to one. Shows what the decision turns on — the member, the product, how many
+ * shares they have subscribed for and what that comes to, and the board resolution behind it — so a
+ * checker can act from the list instead of opening every account to find out what it is.
+ */
+@Component({
+ selector: 'mifosx-pending-share-accounts',
+ templateUrl: './pending-share-accounts.component.html',
+ styleUrls: ['./pending-share-accounts.component.scss'],
+ imports: [
+ ...STANDALONE_SHARED_IMPORTS,
+ FaIconComponent,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCellDef,
+ MatHeaderCell,
+ MatCellDef,
+ MatCell,
+ MatHeaderRowDef,
+ MatHeaderRow,
+ MatRowDef,
+ MatRow,
+ MatIcon,
+ DecimalPipe
+ ]
+})
+export class PendingShareAccountsComponent {
+ private route = inject(ActivatedRoute);
+ private router = inject(Router);
+ private dialog = inject(MatDialog);
+ private sharesService = inject(SharesService);
+ private settingsService = inject(SettingsService);
+ private dateUtils = inject(Dates);
+
+ dataSource: MatTableDataSource;
+ showData = false;
+
+ displayedColumns: string[] = [
+ 'accountNo',
+ 'clientName',
+ 'productName',
+ 'requestedShares',
+ 'requestedAmount',
+ 'resolution',
+ 'submittedDate',
+ 'actions'
+ ];
+
+ constructor() {
+ this.route.data.subscribe((data: { pendingShareAccountsData: any }) => {
+ const items = data.pendingShareAccountsData || [];
+ this.showData = items.length > 0;
+ this.dataSource = new MatTableDataSource(items);
+ });
+ }
+
+ applyFilter(filterValue: string = '') {
+ this.dataSource.filter = filterValue.trim().toLowerCase();
+ }
+
+ /**
+ * A date from the API rendered readably, whether it arrives as a string or as Fineract's
+ * {@code [yyyy, m, d]} array.
+ */
+ formatDate(date: any): string {
+ if (!date) {
+ return '';
+ }
+ const d = Array.isArray(date) ? new Date(date[0], date[1] - 1, date[2]) : new Date(date);
+ return isNaN(d.getTime()) ? String(date) : d.toLocaleDateString('en-IN');
+ }
+
+ /** Opens the account itself, for a checker who wants more than the row shows. */
+ viewAccount(account: any): void {
+ this.router.navigate([
+ '/clients',
+ account.clientId,
+ 'shares-accounts',
+ account.shareAccountId
+ ]);
+ }
+
+ approve(account: any): void {
+ const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
+ data: {
+ heading: 'Approve Share Account',
+ dialogContext:
+ `Approve share account "${account.accountNo}" for ${account.clientName} — ` +
+ `${account.requestedShares} shares at ${account.requestedAmount}?`,
+ type: 'basic'
+ }
+ });
+ dialogRef.afterClosed().subscribe((response: any) => {
+ if (response?.confirm) {
+ // The approval date is the business date rather than the checker's choice: this queue is for
+ // clearing a submission, and a date field per row would be four extra clicks to type what
+ // the system already knows.
+ const data = {
+ approvedDate: this.dateUtils.formatDate(this.settingsService.businessDate, this.settingsService.dateFormat),
+ dateFormat: this.settingsService.dateFormat,
+ locale: this.settingsService.language.code
+ };
+ this.sharesService
+ .executeSharesAccountCommand(account.shareAccountId, 'approve', data)
+ .subscribe(() => this.reload());
+ }
+ });
+ }
+
+ reject(account: any): void {
+ const formfields: FormfieldBase[] = [
+ new InputBase({
+ controlName: 'rejectReason',
+ label: 'Reason for rejection',
+ value: '',
+ type: 'text',
+ required: false
+ })
+ ];
+ const dialogRef = this.dialog.open(FormDialogComponent, {
+ data: {
+ title: `Reject Share Account ${account.accountNo}`,
+ formfields
+ }
+ });
+ dialogRef.afterClosed().subscribe((response: any) => {
+ if (response?.data) {
+ // The reason is recorded as a note rather than dropped: a rejected subscription is the one a
+ // member is most likely to come back and ask about.
+ const data: any = {
+ rejectedDate: this.dateUtils.formatDate(this.settingsService.businessDate, this.settingsService.dateFormat),
+ dateFormat: this.settingsService.dateFormat,
+ locale: this.settingsService.language.code
+ };
+ const reason = response.data.value?.rejectReason?.trim();
+ if (reason) {
+ data.note = reason;
+ }
+ this.sharesService
+ .executeSharesAccountCommand(account.shareAccountId, 'reject', data)
+ .subscribe(() => this.reload());
+ }
+ });
+ }
+
+ reload(): void {
+ const url = this.router.url;
+ this.router
+ .navigateByUrl('/checker-inbox-and-tasks', { skipLocationChange: true })
+ .then(() => this.router.navigate([url]));
+ }
+}
diff --git a/src/app/tasks/checker-inbox-and-tasks/checker-inbox-and-tasks.component.html b/src/app/tasks/checker-inbox-and-tasks/checker-inbox-and-tasks.component.html
index ffcc701fa..8e5a2f0af 100644
--- a/src/app/tasks/checker-inbox-and-tasks/checker-inbox-and-tasks.component.html
+++ b/src/app/tasks/checker-inbox-and-tasks/checker-inbox-and-tasks.component.html
@@ -90,6 +90,17 @@
Pending Account Edits
+
+
+
+ Pending Share Accounts
+
{
+ private sharesService = inject(SharesService);
+
+ resolve(): Observable {
+ return this.sharesService.getPendingShareAccounts().pipe(catchError(() => of([])));
+ }
+}
diff --git a/src/app/tasks/tasks-routing.module.ts b/src/app/tasks/tasks-routing.module.ts
index 416cf3017..7b8701aa4 100644
--- a/src/app/tasks/tasks-routing.module.ts
+++ b/src/app/tasks/tasks-routing.module.ts
@@ -33,6 +33,7 @@ import { PendingSavingsProductsComponent } from './checker-inbox-and-tasks-tabs/
import { ChequebookRequestsComponent } from './checker-inbox-and-tasks-tabs/chequebook-requests/chequebook-requests.component';
import { PendingSavingsAccountEditsComponent } from './checker-inbox-and-tasks-tabs/pending-savings-account-edits/pending-savings-account-edits.component';
import { PendingShareAccountEditsComponent } from './checker-inbox-and-tasks-tabs/pending-share-account-edits/pending-share-account-edits.component';
+import { PendingShareAccountsComponent } from './checker-inbox-and-tasks-tabs/pending-share-accounts/pending-share-accounts.component';
import { PendingClientEditsComponent } from './checker-inbox-and-tasks-tabs/pending-client-edits/pending-client-edits.component';
import { ViewCheckerInboxComponent } from './view-checker-inbox/view-checker-inbox.component';
@@ -51,6 +52,7 @@ import { GetPendingSavingsProducts } from './common-resolvers/getPendingSavingsP
import { GetPendingSavingsAccountEdits } from './common-resolvers/getPendingSavingsAccountEdits.resolver';
import { GetPendingCurrentAccountEdits } from './common-resolvers/getPendingCurrentAccountEdits.resolver';
import { GetPendingShareAccountEdits } from './common-resolvers/getPendingShareAccountEdits.resolver';
+import { GetPendingShareAccounts } from './common-resolvers/getPendingShareAccounts.resolver';
/** Tasks Routes */
const routes: Routes = [
@@ -144,6 +146,14 @@ const routes: Routes = [
path: 'pending-current-account-edits',
redirectTo: 'pending-savings-account-edits'
},
+ {
+ path: 'pending-share-accounts',
+ component: PendingShareAccountsComponent,
+ data: { title: 'Pending Share Accounts' },
+ resolve: {
+ pendingShareAccountsData: GetPendingShareAccounts
+ }
+ },
{
path: 'pending-share-account-edits',
component: PendingShareAccountEditsComponent,
@@ -264,7 +274,8 @@ const routes: Routes = [
GetPendingSavingsProducts,
GetPendingSavingsAccountEdits,
GetPendingCurrentAccountEdits,
- GetPendingShareAccountEdits
+ GetPendingShareAccountEdits,
+ GetPendingShareAccounts
]
})
export class TasksRoutingModule {}
diff --git a/src/assets/translations/en-US.json b/src/assets/translations/en-US.json
index 46110091b..9160611c2 100644
--- a/src/assets/translations/en-US.json
+++ b/src/assets/translations/en-US.json
@@ -2598,6 +2598,7 @@
"Payment Allocation Rule": "Payment Allocation Rule",
"Payment Details": "Payment Details",
"Payment Due At": "Payment Due At",
+ "Payment Option": "Payment Option",
"Payment Type": "Payment Type",
"Payment Type Id": "Payment Type Id",
"Payment due as of": "Payment due as of",
diff --git a/src/environments/.env.ts b/src/environments/.env.ts
index 6c6244804..3e9cc6755 100644
--- a/src/environments/.env.ts
+++ b/src/environments/.env.ts
@@ -9,8 +9,8 @@
/* tslint:disable */
export default {
'mifos_x': {
- 'version': '260825',
- 'hash': '7ef75c90'
+ 'version': '260827',
+ 'hash': '1273bdbe'
},
'allow_switching_backend_instance': true
};