/** * 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 { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Observable } from 'rxjs'; /** * Cheque Book Inventory — stationery master, a unified stock ledger (HO receipt / branch transfer-in share * one drawdown-cursor concept), account issuance with per-leaf serial tracking, stop-payment and * lost/stolen hotlisting (both issued and unissued stock). */ @Injectable({ providedIn: 'root' }) export class ChequeBookService { private http = inject(HttpClient); // ----- Series ----- /** status: 'ACTIVE' | 'INACTIVE'. Server-side paginated — always returns { pageItems, totalFilteredRecords }. */ getSeries(status?: string, offset = 0, limit = 20): Observable { let params = new HttpParams().set('offset', offset).set('limit', limit); if (status) params = params.set('status', status); return this.http.get('/chequeseries', { params }); } createSeries(payload: any): Observable { return this.http.post('/chequeseries', payload); } updateSeries(id: string | number, payload: any): Observable { return this.http.put(`/chequeseries/${id}`, payload); } deactivateSeries(id: string | number): Observable { return this.http.delete(`/chequeseries/${id}`); } // ----- Stock lots ----- /** Server-side paginated — always returns { pageItems, totalFilteredRecords }. */ getStockLots( officeId?: string | number, seriesId?: string | number, status?: string, offset = 0, limit = 20 ): Observable { let params = new HttpParams().set('offset', offset).set('limit', limit); if (officeId) params = params.set('officeId', officeId); if (seriesId) params = params.set('seriesId', seriesId); if (status) params = params.set('status', status); return this.http.get('/chequestocklots', { params }); } receiveStock(payload: any): Observable { return this.http.post('/chequestocklots', payload); } reportStockLotLost(lotId: string | number, payload: any): Observable { return this.http.post(`/chequestocklots/${lotId}`, payload, { params: new HttpParams().set('command', 'reportlost') }); } // ----- Stock transfers ----- /** Server-side paginated — always returns { pageItems, totalFilteredRecords }. */ getStockTransfers(status?: string, offset = 0, limit = 20): Observable { let params = new HttpParams().set('offset', offset).set('limit', limit); if (status) params = params.set('status', status); return this.http.get('/chequestocktransfers', { params }); } dispatchStockTransfer(payload: any): Observable { return this.http.post('/chequestocktransfers', payload); } receiveStockTransfer(transferId: string | number): Observable { return this.http.post( `/chequestocktransfers/${transferId}`, {}, { params: new HttpParams().set('command', 'receive') } ); } rejectStockTransfer(transferId: string | number): Observable { return this.http.post( `/chequestocktransfers/${transferId}`, {}, { params: new HttpParams().set('command', 'reject') } ); } // ----- Cheque books ----- getBooks( accountType?: string, accountId?: string | number, officeId?: string | number, status?: string, offset = 0, limit = 20 ): Observable { let params = new HttpParams().set('offset', offset).set('limit', limit); if (accountType) params = params.set('accountType', accountType); if (accountId) params = params.set('accountId', accountId); if (officeId) params = params.set('officeId', officeId); if (status) params = params.set('status', status); return this.http.get('/chequebooks', { params }); } getBook(id: string | number): Observable { return this.http.get(`/chequebooks/${id}`); } getLeaves(bookId: string | number): Observable { return this.http.get(`/chequebooks/${bookId}/leaves`); } requestBook(payload: any): Observable { return this.http.post('/chequebooks', payload); } issueBook(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'issue') }); } rejectBook(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'reject') }); } withdrawBook(bookId: string | number): Observable { return this.http.post(`/chequebooks/${bookId}`, {}, { params: new HttpParams().set('command', 'withdraw') }); } stopPayment(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'stoppayment') }); } revokeStopPayment(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'revokestoppayment') }); } reportBookLost(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'reportlost') }); } cancelLeaf(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'cancelleaf') }); } /** Manually record that leaves cleared, once the branch sees them on the bank/clearing statement. */ markUsed(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'markused') }); } /** Flag leaves as returned/dishonoured (insufficient funds, signature mismatch, etc.) — terminal, like reportlost. */ returnBook(bookId: string | number, payload: any): Observable { return this.http.post(`/chequebooks/${bookId}`, payload, { params: new HttpParams().set('command', 'return') }); } // ----- Pending requests (bespoke maker-checker for series/stock/book creation) ----- /** * A different user than the maker must approve/reject — enforced server-side, not just in this UI. * Server-side paginated and date-filtered, matching the clerk disbursement/withdrawal request queues. */ getPendingRequests(status?: string, fromDate?: string, toDate?: string, offset = 0, limit = 20): Observable { let params = new HttpParams().set('offset', offset).set('limit', 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('/chequebook/pending-requests', { params }); } getPendingRequest(id: string | number): Observable { return this.http.get(`/chequebook/pending-requests/${id}`); } approvePendingRequest(id: string | number): Observable { return this.http.post( `/chequebook/pending-requests/${id}`, {}, { params: new HttpParams().set('command', 'approve') } ); } rejectPendingRequest(id: string | number, payload: any): Observable { return this.http.post(`/chequebook/pending-requests/${id}`, payload, { params: new HttpParams().set('command', 'reject') }); } // ----- Leaf lookup ----- lookupLeaf(serialNo: string | number): Observable { return this.http.get('/chequeleaves/lookup', { params: new HttpParams().set('serialNo', serialNo) }); } // ----- Account lookup (by account number) ----- /** Search a Savings or Current account by its account number; returns a paginated list to match against. */ searchAccountByNo(accountType: string, accountNo: string): Observable { const base = accountType === 'CURRENT' ? '/currentaccounts' : '/savingsaccounts'; const params = new HttpParams().set('accountNo', accountNo).set('offset', '0').set('limit', '20'); return this.http.get(base, { params }); } // ----- Shared template data ----- getOffices(): Observable { return this.http.get('/offices'); } }