This commit is contained in:
2026-09-23 15:51:10 +05:30
parent cda7c52d11
commit 08a427467a
123 changed files with 20687 additions and 4156 deletions
@@ -68,18 +68,70 @@
<tr>
<th class="ta-left">Voucher / Receipt</th>
<th class="ta-left">Date</th>
<th class="ta-left">Description</th>
<th class="ta-left">Collected by</th>
<th class="ta-right">Amount</th>
<th class="ta-center">Detail</th>
</tr>
</thead>
<tbody>
@for (v of detail.vouchers; track v.id) {
<tr>
<tr class="sard-voucher-row" (click)="toggleVoucherGlEntries(v.id)">
<td class="ta-left mono">{{ v.voucherNo || v.receiptNo }}</td>
<td class="ta-left">{{ v.collectionDate }}</td>
<td class="ta-left sard-desc-cell" [title]="v.note">{{ v.note || '—' }}</td>
<td class="ta-left">{{ v.collectedByName || '—' }}</td>
<td class="ta-right amount-cell">{{ v.amount | number: '1.2-2' }}</td>
<td class="ta-center">
<button
type="button"
mat-icon-button
class="sard-detail-btn"
(click)="$event.stopPropagation(); toggleVoucherGlEntries(v.id)"
title="View this receipt's actual GL posting"
>
<mat-icon>visibility</mat-icon>
</button>
</td>
</tr>
@if (expandedVoucherId === v.id) {
<tr class="sard-gl-row">
<td colspan="6">
@if (loadingGlEntriesId === v.id) {
<div class="sard-gl-loading">Loading GL entry…</div>
} @else if (!glEntriesByVoucherId[v.id]?.length) {
<div class="sard-gl-empty">No GL posting recorded for this receipt.</div>
} @else {
<table class="sard-gl-table">
<thead>
<tr>
<th class="ta-left">GL Account</th>
<th class="ta-center">Dr / Cr</th>
<th class="ta-right">Amount</th>
</tr>
</thead>
<tbody>
@for (leg of glEntriesByVoucherId[v.id]; track leg.glCode + leg.drCr) {
<tr>
<td class="ta-left mono">{{ leg.glCode }} — {{ leg.accountName }}</td>
<td class="ta-center">
<span
class="sard-drcr-pill"
[class.sard-drcr-pill--dr]="leg.drCr === 'Dr'"
[class.sard-drcr-pill--cr]="leg.drCr === 'Cr'"
>
{{ leg.drCr }}
</span>
</td>
<td class="ta-right amount-cell">{{ leg.amount | number: '1.2-2' }}</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
}
}
</tbody>
</table>
@@ -121,3 +121,93 @@ $danger: #b3261e;
font-size: 13px;
margin-top: 12px;
}
.ta-center {
text-align: center;
}
.sard-voucher-row {
cursor: pointer;
&:hover {
background: #f4f7fb;
}
}
.sard-desc-cell {
max-width: 160px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sard-detail-btn {
width: 30px;
height: 30px;
line-height: 30px;
mat-icon {
font-size: 18px;
width: 18px;
height: 18px;
color: $primary;
}
}
.sard-gl-row td {
background: #fbfcfe;
border-top: none;
padding: 4px 8px 10px;
}
.sard-gl-loading,
.sard-gl-empty {
font-size: 12px;
color: $muted;
padding: 4px 0;
}
.sard-gl-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
background: #fff;
border: 1px solid $border;
border-radius: 6px;
overflow: hidden;
th {
color: $muted;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.4px;
padding: 5px 8px;
background: #f4f7fb;
border-bottom: 1px solid $border;
}
td {
padding: 5px 8px;
border-top: 1px solid #eceff4;
}
}
.sard-drcr-pill {
display: inline-block;
padding: 1px 8px;
border-radius: 999px;
font-size: 10px;
font-weight: 700;
&.sard-drcr-pill--dr {
background: #fef2f2;
color: #dc2626;
border: 1px solid #fecaca;
}
&.sard-drcr-pill--cr {
background: #ecfdf5;
color: #059669;
border: 1px solid #a7f3d0;
}
}
@@ -50,6 +50,12 @@ export class ShareAdditionRequestDetailDialogComponent implements OnInit {
actioning = false;
detail: any = null;
/** Which voucher's row is currently expanded to show its real Dr/Cr GL legs, or null if none. */
expandedVoucherId: number | null = null;
loadingGlEntriesId: number | null = null;
/** Fetched once per voucher and kept — a checker toggling the same row twice shouldn't re-fetch. */
glEntriesByVoucherId: { [id: number]: { glCode: string; accountName: string; drCr: string; amount: number }[] } = {};
public dialogRef = inject(MatDialogRef<ShareAdditionRequestDetailDialogComponent>);
public data = inject<{ transactionId: number }>(MAT_DIALOG_DATA);
@@ -76,6 +82,26 @@ export class ShareAdditionRequestDetailDialogComponent implements OnInit {
return this.detail?.vouchers?.length || 0;
}
/** Shows or hides a voucher's real GL posting, fetching it the first time it is opened. */
toggleVoucherGlEntries(voucherId: number): void {
if (this.expandedVoucherId === voucherId) {
this.expandedVoucherId = null;
return;
}
this.expandedVoucherId = voucherId;
if (this.glEntriesByVoucherId[voucherId]) {
return;
}
this.loadingGlEntriesId = voucherId;
this.cashierService
.getShareAdvanceGlEntries(voucherId)
.pipe(catchError(() => of(null)))
.subscribe((res: any) => {
this.glEntriesByVoucherId[voucherId] = res?.entries || [];
this.loadingGlEntriesId = null;
});
}
approve(): void {
this.act('approveadditionalshares');
}
@@ -232,6 +232,12 @@
<fa-icon icon="ban" class="ac-tab__ic"></fa-icon>
<span>DD Revoke Requests</span>
</a>
<!-- Raised from the Risk Review Report. Approving moves the customer's KYC rating and their
re-KYC due date together, so it belongs with the other maker-checker queues. -->
<a class="ac-tab" routerLink="./risk-change-approvals" routerLinkActive="ac-tab--active">
<fa-icon icon="shield-alt" class="ac-tab__ic"></fa-icon>
<span>Risk Category Changes</span>
</a>
</nav>
<div class="ac-tab-panel">
+6
View File
@@ -243,6 +243,12 @@ const routes: Routes = [
(m) => m.DdRevokeApprovalsComponent
),
data: { title: 'DD Revoke Approvals' }
},
{
path: 'risk-change-approvals',
loadComponent: () =>
import('../risk-review/risk-change-approvals.component').then((m) => m.RiskChangeApprovalsComponent),
data: { title: 'Risk Category Approvals' }
}
]
},