diff --git a/src/app/cashier/cashier-routing.module.ts b/src/app/cashier/cashier-routing.module.ts
index c9e818ee7..86568fc2a 100644
--- a/src/app/cashier/cashier-routing.module.ts
+++ b/src/app/cashier/cashier-routing.module.ts
@@ -70,6 +70,18 @@ const routes: Routes = [
),
data: { title: 'Account Facilities', breadcrumb: 'Account Facilities' }
},
+ {
+ path: 'account-facilities/cheque-book',
+ loadComponent: () =>
+ import('../clerk/cheque-book/cheque-book.component').then((m) => m.ClerkChequeBookComponent),
+ data: { title: 'Cheque Book', breadcrumb: 'Cheque Book' }
+ },
+ {
+ path: 'account-facilities/cheque-book/:id',
+ loadComponent: () =>
+ import('../clerk/cheque-book/cheque-book-detail.component').then((m) => m.ClerkChequeBookDetailComponent),
+ data: { title: 'Cheque Book Detail', breadcrumb: 'Cheque Book Detail' }
+ },
{
path: 'photo-signature',
loadComponent: () =>
diff --git a/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.html b/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.html
index 0afd956de..cf657e658 100644
--- a/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.html
+++ b/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.html
@@ -73,6 +73,9 @@
+
}
@@ -130,7 +133,9 @@
? 'warn'
: l.status === 'LOST'
? 'bad'
- : 'neutral'
+ : l.status === 'RETURNED'
+ ? 'returned'
+ : 'neutral'
"
(click)="selectLeaf(l)"
>
diff --git a/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.scss b/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.scss
index a994d762f..0334282b6 100644
--- a/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.scss
+++ b/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.scss
@@ -118,6 +118,10 @@ mat-form-field {
&.neutral {
color: #757575;
}
+
+ &.returned {
+ color: #9333ea;
+ }
}
.empty-state {
diff --git a/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.ts b/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.ts
index db69eb49f..2a95702db 100644
--- a/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.ts
+++ b/src/app/chequebook/cheque-book-detail/cheque-book-detail.component.ts
@@ -21,13 +21,14 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { ChequeBookService } from '../chequebook.service';
import { LeafDetailDialogComponent } from './leaf-detail-dialog/leaf-detail-dialog.component';
-type LeafAction = 'stoppayment' | 'revokestoppayment' | 'reportlost' | 'cancelleaf' | 'markused';
+type LeafAction = 'stoppayment' | 'revokestoppayment' | 'reportlost' | 'cancelleaf' | 'markused' | 'return';
/**
- * One issued cheque book: its leaf register, and the five leaf-range actions (stop-payment, revoke,
- * report-lost, cancel-leaf, mark-used) — each defaults to the whole book when no range is given.
+ * One issued cheque book: its leaf register, and the six leaf-range actions (stop-payment, revoke,
+ * report-lost, cancel-leaf, mark-used, return) — each defaults to the whole book when no range is given.
* "Mark as used" is a manual record (this CBS has no clearing/presentment integration to detect it itself)
- * — a branch sets it once it sees a leaf clear on the bank/clearing statement.
+ * — a branch sets it once it sees a leaf clear on the bank/clearing statement. "Return" flags a leaf as
+ * presented-and-dishonoured (insufficient funds, signature mismatch, etc.) — terminal, like report-lost.
*/
@Component({
selector: 'mifosx-cheque-book-detail',
@@ -112,7 +113,8 @@ export class ChequeBookDetailComponent implements OnInit {
revokestoppayment: (id, p) => this.chequeBookService.revokeStopPayment(id, p),
reportlost: (id, p) => this.chequeBookService.reportBookLost(id, p),
cancelleaf: (id, p) => this.chequeBookService.cancelLeaf(id, p),
- markused: (id, p) => this.chequeBookService.markUsed(id, p)
+ markused: (id, p) => this.chequeBookService.markUsed(id, p),
+ return: (id, p) => this.chequeBookService.returnBook(id, p)
};
const call = actionCalls[this.activeAction](this.bookId, payload);
diff --git a/src/app/chequebook/cheque-book-detail/leaf-detail-dialog/leaf-detail-dialog.component.html b/src/app/chequebook/cheque-book-detail/leaf-detail-dialog/leaf-detail-dialog.component.html
index 0712eb0e1..2a1470c61 100644
--- a/src/app/chequebook/cheque-book-detail/leaf-detail-dialog/leaf-detail-dialog.component.html
+++ b/src/app/chequebook/cheque-book-detail/leaf-detail-dialog/leaf-detail-dialog.component.html
@@ -18,7 +18,9 @@
? 'warn'
: data.status === 'LOST'
? 'bad'
- : 'neutral'
+ : data.status === 'RETURNED'
+ ? 'returned'
+ : 'neutral'
"
>{{ data.leafSerialNo }}
@@ -57,6 +59,12 @@
>{{ data.usedReason }}
}
+ @if (data.returnReason) {
+
+ {{ 'labels.inputs.Return Reason' | translate }}{{ data.returnReason }}
+
+ }
diff --git a/src/app/chequebook/chequebook.service.ts b/src/app/chequebook/chequebook.service.ts
index c18fa2db0..371362194 100644
--- a/src/app/chequebook/chequebook.service.ts
+++ b/src/app/chequebook/chequebook.service.ts
@@ -166,6 +166,11 @@ export class ChequeBookService {
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) -----
/**
diff --git a/src/app/chequebook/leaf-lookup/leaf-lookup.component.html b/src/app/chequebook/leaf-lookup/leaf-lookup.component.html
index 9f3b775b2..280ce6243 100644
--- a/src/app/chequebook/leaf-lookup/leaf-lookup.component.html
+++ b/src/app/chequebook/leaf-lookup/leaf-lookup.component.html
@@ -53,7 +53,9 @@
? 'warn'
: result.status === 'LOST'
? 'bad'
- : 'neutral'
+ : result.status === 'RETURNED'
+ ? 'returned'
+ : 'neutral'
"
>{{ result.status }}
@@ -117,6 +119,12 @@
>{{ result.usedReason }}
}
+ @if (result.status === 'RETURNED') {
+
+ {{ 'labels.inputs.Return Reason' | translate }}{{ result.returnReason }}
+
+ }
diff --git a/src/app/chequebook/leaf-lookup/leaf-lookup.component.scss b/src/app/chequebook/leaf-lookup/leaf-lookup.component.scss
index 35b4d10b8..822668cad 100644
--- a/src/app/chequebook/leaf-lookup/leaf-lookup.component.scss
+++ b/src/app/chequebook/leaf-lookup/leaf-lookup.component.scss
@@ -116,6 +116,11 @@
background: #e0e0e0;
color: #757575;
}
+
+ &.returned {
+ background: #f3e8fd;
+ color: #9333ea;
+ }
}
.empty-state {
diff --git a/src/app/clerk/account-facilities/account-facilities.component.scss b/src/app/clerk/account-facilities/account-facilities.component.scss
index 020d40e68..125be056f 100644
--- a/src/app/clerk/account-facilities/account-facilities.component.scss
+++ b/src/app/clerk/account-facilities/account-facilities.component.scss
@@ -11,116 +11,79 @@
}
.af-page {
+ background: #f8fafc;
min-height: calc(100vh - 68px);
- background: #f0f4f8;
- padding: 24px 28px;
display: flex;
flex-direction: column;
- gap: 20px;
+ gap: 12px;
}
-// ── Hero ──────────────────────────────────────────────────────────────────────
+// ── Header ──────────────────────────────────────────────────────────────────────
-.af-hero {
+.af-header {
display: flex;
align-items: center;
- gap: 18px;
- background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 40%, #2563eb 100%);
- border-radius: 16px;
- padding: 22px 28px;
- color: #fff;
- box-shadow: 0 8px 32px rgb(37 99 235 / 35%);
- position: relative;
- overflow: hidden;
+ justify-content: space-between;
+ padding: 12px 20px;
+ background: #fff;
+ border-bottom: 1px solid #e2e8f0;
- &::before {
- content: '';
- position: absolute;
- top: -40px;
- right: -40px;
- width: 200px;
- height: 200px;
- background: rgb(255 255 255 / 5%);
- border-radius: 50%;
- }
-
- &__icon-wrap {
- width: 56px;
- height: 56px;
- background: rgb(255 255 255 / 15%);
- border: 1px solid rgb(255 255 255 / 25%);
- border-radius: 14px;
+ &__left {
display: flex;
align-items: center;
- justify-content: center;
- flex-shrink: 0;
- backdrop-filter: blur(8px);
+ gap: 10px;
}
- &__text {
- flex: 1;
+ &__icon {
+ color: #0f4f3c;
+ flex-shrink: 0;
}
&__title {
- font-size: 22px;
- font-weight: 800;
- letter-spacing: -0.01em;
- margin: 0 0 5px;
+ font-size: 15px;
+ font-weight: 700;
+ color: #0d1b2a;
}
- &__stats {
- display: flex;
- gap: 14px;
- align-items: center;
+ &__sub {
+ font-size: 12px;
+ color: #64748b;
+ margin-top: 1px;
}
&__stat {
- display: flex;
- align-items: center;
- gap: 5px;
- font-size: 12.5px;
- color: rgb(255 255 255 / 75%);
+ font-weight: 700;
- strong {
- color: #fff;
- font-weight: 700;
+ &--green {
+ color: #16a34a;
}
- &--green strong {
- color: #86efac;
+ &--red {
+ color: #dc2626;
}
-
- &--red strong {
- color: #fca5a5;
- }
- }
-
- &__sep {
- width: 1px;
- height: 14px;
- background: rgb(255 255 255 / 25%);
}
}
-.af-back-btn {
+.af-btn {
display: inline-flex;
align-items: center;
- gap: 7px;
- padding: 10px 20px;
- background: rgb(255 255 255 / 12%);
- border: 1px solid rgb(255 255 255 / 25%);
- border-radius: 10px;
- color: #fff;
- font-size: 12.5px;
+ gap: 6px;
+ border-radius: 7px;
+ font-family: inherit;
font-weight: 600;
cursor: pointer;
- transition: all 0.2s;
- white-space: nowrap;
- backdrop-filter: blur(8px);
+ border: 1px solid #e2e8f0;
+ transition: background 0.15s;
+ height: 30px;
+ padding: 0 12px;
+ font-size: 12.5px;
+ background: #fff;
+ color: #0d1b2a;
&:hover {
- background: rgb(255 255 255 / 22%);
- transform: translateX(-2px);
+ background: #f0fdf4;
+ border-color: #0f4f3c;
+ color: #0f4f3c;
}
}
@@ -132,12 +95,12 @@
flex-direction: column;
align-items: center;
justify-content: center;
- gap: 14px;
- padding: 60px 20px;
+ gap: 10px;
+ padding: 40px 20px;
&__icon {
- width: 88px;
- height: 88px;
+ width: 64px;
+ height: 64px;
background: #e2e8f0;
border: 1px solid #cbd5e1;
border-radius: 50%;
@@ -147,80 +110,87 @@
}
&__title {
- font-size: 18px;
+ font-size: 15px;
font-weight: 700;
color: #1e293b;
- margin: 6px 0 0;
+ margin: 4px 0 0;
}
&__sub {
- font-size: 13.5px;
+ font-size: 12.5px;
color: #64748b;
text-align: center;
margin: 0;
}
&__btn {
- margin-top: 10px;
- padding: 10px 24px;
- background: #2563eb;
+ margin-top: 6px;
+ padding: 8px 20px;
+ background: #0f4f3c;
border: none;
- border-radius: 10px;
+ border-radius: 8px;
color: #fff;
- font-size: 13px;
+ font-size: 12.5px;
font-weight: 600;
cursor: pointer;
transition: background 0.15s;
&:hover {
- background: #1d4ed8;
+ background: #0a3d2e;
}
}
}
+// ── Body ────────────────────────────────────────────────────────────────────────
+
+.af-body {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ padding: 0 20px 16px;
+}
+
// ── Progress card ──────────────────────────────────────────────────────────────
.af-progress-card {
background: #fff;
border: 1px solid #e2e8f0;
- border-radius: 14px;
- padding: 18px 22px;
- box-shadow: 0 1px 4px rgb(0 0 0 / 6%);
+ border-radius: 10px;
+ padding: 12px 16px;
&__top {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 12px;
+ margin-bottom: 8px;
}
&__label {
- font-size: 11.5px;
- font-weight: 600;
+ font-size: 11px;
+ font-weight: 700;
color: #64748b;
text-transform: uppercase;
- letter-spacing: 0.08em;
+ letter-spacing: 0.06em;
}
&__fraction {
- font-size: 13px;
+ font-size: 12.5px;
font-weight: 700;
- color: #16a34a;
+ color: #0f4f3c;
}
}
.af-progress-bar {
- height: 10px;
+ height: 7px;
background: #e2e8f0;
border-radius: 999px;
overflow: hidden;
&__fill {
height: 100%;
- background: linear-gradient(90deg, #16a34a, #22c55e);
+ background: #16a34a;
border-radius: 999px;
- transition: width 0.5s ease;
- box-shadow: 0 0 8px rgb(34 197 94 / 35%);
+ transition: width 0.4s ease;
}
}
@@ -229,65 +199,53 @@
.af-fac-card {
background: #fff;
border: 1px solid #e2e8f0;
- border-radius: 14px;
+ border-radius: 10px;
overflow: hidden;
- box-shadow: 0 1px 4px rgb(0 0 0 / 6%);
&__header {
- display: flex;
- align-items: center;
- gap: 9px;
- padding: 12px 22px;
- background: #1e293b;
- color: #94a3b8;
- font-size: 11.5px;
+ padding: 9px 16px;
+ background: #f8fafc;
+ border-bottom: 1px solid #e2e8f0;
+ color: #64748b;
+ font-size: 11px;
font-weight: 700;
text-transform: uppercase;
- letter-spacing: 0.08em;
+ letter-spacing: 0.06em;
}
}
.af-pills {
display: flex;
flex-wrap: wrap;
- gap: 10px;
- padding: 20px 22px;
+ gap: 7px;
+ padding: 12px 16px;
}
.af-pill {
display: inline-flex;
align-items: center;
- gap: 6px;
- padding: 7px 15px;
+ gap: 5px;
+ padding: 4px 11px;
border-radius: 999px;
- font-size: 13px;
+ font-size: 12px;
font-weight: 600;
- border: 1.5px solid;
- transition:
- transform 0.15s,
- box-shadow 0.15s;
+ border: 1px solid;
cursor: default;
&__dot {
- width: 7px;
- height: 7px;
+ width: 6px;
+ height: 6px;
border-radius: 50%;
flex-shrink: 0;
}
&--on {
background: #f0fdf4;
- border-color: #22c55e;
- color: #15803d;
+ border-color: #86efac;
+ color: #166534;
.af-pill__dot {
background: #22c55e;
- box-shadow: 0 0 5px rgb(34 197 94 / 50%);
- }
-
- &:hover {
- transform: translateY(-1px);
- box-shadow: 0 4px 12px rgb(34 197 94 / 20%);
}
}
@@ -307,63 +265,46 @@
.af-stats-row {
display: grid;
grid-template-columns: 1fr 1fr;
- gap: 14px;
+ gap: 10px;
}
.af-stat-card {
- border-radius: 14px;
- padding: 20px 24px;
+ border-radius: 10px;
+ padding: 10px 14px;
display: flex;
- align-items: center;
- gap: 16px;
+ align-items: baseline;
+ gap: 7px;
border: 1px solid;
- box-shadow: 0 1px 4px rgb(0 0 0 / 6%);
+ font-size: 12px;
&__icon {
- width: 44px;
- height: 44px;
- border-radius: 12px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- font-size: 20px;
+ font-size: 12px;
+ font-weight: 700;
}
&__num {
- font-size: 30px;
+ font-size: 17px;
font-weight: 800;
line-height: 1;
- display: block;
}
&__label {
- font-size: 12px;
+ font-size: 11px;
font-weight: 600;
text-transform: uppercase;
- letter-spacing: 0.08em;
- display: block;
- margin-top: 3px;
+ letter-spacing: 0.05em;
opacity: 0.75;
}
&--green {
- background: linear-gradient(135deg, #f0fdf4, #dcfce7);
+ background: #f0fdf4;
border-color: #86efac;
- color: #15803d;
-
- .af-stat-card__icon {
- background: #bbf7d0;
- }
+ color: #166534;
}
&--red {
- background: linear-gradient(135deg, #f8fafc, #f1f5f9);
- border-color: #cbd5e1;
- color: #475569;
-
- .af-stat-card__icon {
- background: #e2e8f0;
- }
+ background: #f8fafc;
+ border-color: #e2e8f0;
+ color: #64748b;
}
}
diff --git a/src/app/clerk/account-facilities/account-facilities.component.ts b/src/app/clerk/account-facilities/account-facilities.component.ts
index 6f887f97b..9457ef896 100644
--- a/src/app/clerk/account-facilities/account-facilities.component.ts
+++ b/src/app/clerk/account-facilities/account-facilities.component.ts
@@ -18,34 +18,37 @@ import { ClerkUiStateService } from '../../cashier/clerk-ui-state.service';
styleUrl: './account-facilities.component.scss',
template: `