From efb01d54419ec49936d69ebd3c5c6f13ac1aa9fb Mon Sep 17 00:00:00 2001 From: Jaanu423 Date: Tue, 16 Jun 2026 10:43:29 +0530 Subject: [PATCH] feat(clerk): add GL disbursement maker-checker flow - Add ClerkDisbursementService for submit/approve/reject HTTP calls - Add DisbursementRequestsComponent (manager inbox tab under checker tasks) - Add DisbursementReviewComponent (manager approve/reject detail page) - Add MyDisbursementRequestsComponent (clerk's own disbursement history) - Add 'My Disbursements' nav tab to clerk shell navigation header - Wire routes in cashier-routing and tasks-routing modules - Add 'My Disbursements' button to transaction-entry clerk footer - Include accountName in creditEntries payload for manager review display Co-Authored-By: Claude Sonnet 4.6 --- src/app/cashier/cashier-routing.module.ts | 8 + src/app/cashier/clerk-disbursement.service.ts | 48 +++ .../transaction-entry.component.html | 59 ++- .../transaction-entry.component.ts | 195 ++++++++- .../disbursement-review.component.html | 210 ++++++++++ .../disbursement-review.component.scss | 374 +++++++++++++++++ .../disbursement-review.component.ts | 147 +++++++ .../my-disbursement-requests.component.html | 161 +++++++ .../my-disbursement-requests.component.scss | 389 +++++++++++++++++ .../my-disbursement-requests.component.ts | 209 ++++++++++ src/app/core/shell/shell.component.html | 11 + src/app/core/shell/shell.component.ts | 3 +- .../disbursement-requests.component.html | 162 +++++++ .../disbursement-requests.component.scss | 394 ++++++++++++++++++ .../disbursement-requests.component.ts | 216 ++++++++++ .../checker-inbox-and-tasks.component.html | 12 + src/app/tasks/tasks-routing.module.ts | 19 + src/environments/.env.ts | 4 +- 18 files changed, 2594 insertions(+), 27 deletions(-) create mode 100644 src/app/cashier/clerk-disbursement.service.ts create mode 100644 src/app/clerk/disbursement-review/disbursement-review.component.html create mode 100644 src/app/clerk/disbursement-review/disbursement-review.component.scss create mode 100644 src/app/clerk/disbursement-review/disbursement-review.component.ts create mode 100644 src/app/clerk/my-disbursement-requests/my-disbursement-requests.component.html create mode 100644 src/app/clerk/my-disbursement-requests/my-disbursement-requests.component.scss create mode 100644 src/app/clerk/my-disbursement-requests/my-disbursement-requests.component.ts create mode 100644 src/app/tasks/checker-inbox-and-tasks-tabs/disbursement-requests/disbursement-requests.component.html create mode 100644 src/app/tasks/checker-inbox-and-tasks-tabs/disbursement-requests/disbursement-requests.component.scss create mode 100644 src/app/tasks/checker-inbox-and-tasks-tabs/disbursement-requests/disbursement-requests.component.ts diff --git a/src/app/cashier/cashier-routing.module.ts b/src/app/cashier/cashier-routing.module.ts index 136dc71a2..c9e818ee7 100644 --- a/src/app/cashier/cashier-routing.module.ts +++ b/src/app/cashier/cashier-routing.module.ts @@ -54,6 +54,14 @@ const routes: Routes = [ loadComponent: () => import('../clerk/my-requests/my-requests.component').then((m) => m.MyRequestsComponent), data: { title: 'My Withdrawal Requests', breadcrumb: 'My Withdrawal Requests' } }, + { + path: 'my-disbursement-requests', + loadComponent: () => + import('../clerk/my-disbursement-requests/my-disbursement-requests.component').then( + (m) => m.MyDisbursementRequestsComponent + ), + data: { title: 'My Disbursement Requests', breadcrumb: 'My Disbursement Requests' } + }, { path: 'account-facilities', loadComponent: () => diff --git a/src/app/cashier/clerk-disbursement.service.ts b/src/app/cashier/clerk-disbursement.service.ts new file mode 100644 index 000000000..79e3b4649 --- /dev/null +++ b/src/app/cashier/clerk-disbursement.service.ts @@ -0,0 +1,48 @@ +/** + * 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 { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +/** HTTP service for Clerk Disbursement Request maker-checker workflow. */ +@Injectable({ providedIn: 'root' }) +export class ClerkDisbursementService { + private http = inject(HttpClient); + + submit(data: any): Observable { + return this.http.post('/clerk/disbursement-requests', data); + } + + getMyRequests(status?: string, offset = 0, limit = 20, fromDate?: string, toDate?: string): Observable { + let params = new HttpParams().set('offset', String(offset)).set('limit', String(limit)); + if (status) params = params.set('status', status); + if (fromDate) params = params.set('fromDate', fromDate); + if (toDate) params = params.set('toDate', toDate); + return this.http.get('/clerk/disbursement-requests/my', { params }); + } + + getPendingRequests(status = 'PENDING', offset = 0, limit = 20, fromDate?: string, toDate?: string): Observable { + let params = new HttpParams().set('status', status).set('offset', String(offset)).set('limit', String(limit)); + if (fromDate) params = params.set('fromDate', fromDate); + if (toDate) params = params.set('toDate', toDate); + return this.http.get('/clerk/disbursement-requests', { params }); + } + + getById(id: number): Observable { + return this.http.get(`/clerk/disbursement-requests/${id}`); + } + + approve(id: number): Observable { + return this.http.post(`/clerk/disbursement-requests/${id}/approve`, {}); + } + + reject(id: number, reason: string): Observable { + return this.http.post(`/clerk/disbursement-requests/${id}/reject`, { reason }); + } +} diff --git a/src/app/cashier/transaction-entry/transaction-entry.component.html b/src/app/cashier/transaction-entry/transaction-entry.component.html index a3e257193..0f00f9fd3 100644 --- a/src/app/cashier/transaction-entry/transaction-entry.component.html +++ b/src/app/cashier/transaction-entry/transaction-entry.component.html @@ -107,7 +107,12 @@
- @@ -145,7 +150,7 @@ class="ws-f__ctl" [(ngModel)]="row.acTyp" (click)="$event.stopPropagation()" - (change)="row.acTyp === 'GL' && (row.dbCr = 'Cr')" + (change)="row.acTyp === 'GL' && row.typ !== 'Disbursement' && (row.dbCr = 'Cr')" > @for (a of acTypOptions; track a) { @@ -187,7 +192,7 @@ type="button" class="ws-seg__btn ws-seg__btn--dr" [class.ws-seg__btn--active-dr]="row.dbCr === 'Dr'" - [disabled]="row.acTyp === 'GL'" + [disabled]="row.acTyp === 'GL' && row.typ !== 'Disbursement'" (click)="row.dbCr = 'Dr'" > DR @@ -236,24 +241,26 @@ />
-
- - -
-
- - -
+ @if (row.typ !== 'Withdrawal Slip') { +
+ + +
+
+ + +
+ }
@for (a of acTypOptions; track a) { @@ -1393,6 +1400,14 @@ Add + }