oss file updated, profitl loss as per the day month and also with date select
This commit is contained in:
+273
-26
@@ -71,17 +71,19 @@
|
||||
<div class="fiu-kpi fiu-kpi--amber">
|
||||
<div class="fiu-kpi-ic"><fa-icon icon="exclamation-triangle"></fa-icon></div>
|
||||
<div>
|
||||
<div class="fiu-kpi-n">{{ pendingStr | number }}</div>
|
||||
<div class="fiu-kpi-n">{{ liveStrPending | number }}</div>
|
||||
<div class="fiu-kpi-l">STR Pending</div>
|
||||
<div class="fiu-kpi-sub">draft / PO review</div>
|
||||
<div class="fiu-kpi-sub">
|
||||
{{ liveStrOpen }} to investigate · {{ liveStrAwaitingFiling }} awaiting filing
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiu-kpi fiu-kpi--green">
|
||||
<div class="fiu-kpi-ic"><fa-icon icon="check-circle"></fa-icon></div>
|
||||
<div>
|
||||
<div class="fiu-kpi-n">{{ filedStr | number }}</div>
|
||||
<div class="fiu-kpi-n">{{ liveStrFiled | number }}</div>
|
||||
<div class="fiu-kpi-l">STR Filed</div>
|
||||
<div class="fiu-kpi-sub">acknowledged by FIU</div>
|
||||
<div class="fiu-kpi-sub">{{ liveStrCleared }} concluded clear</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiu-kpi fiu-kpi--purple">
|
||||
@@ -112,7 +114,12 @@
|
||||
</div>
|
||||
<div class="dc-meta">Filing window: <strong>within 7 days of detection</strong></div>
|
||||
<div class="dc-meta">
|
||||
Pending: <strong>{{ pendingStr }}</strong> · Filed: <strong>{{ filedStr }}</strong>
|
||||
To investigate: <strong>{{ liveStrOpen }}</strong> · Awaiting filing:
|
||||
<strong>{{ liveStrAwaitingFiling }}</strong>
|
||||
</div>
|
||||
<div class="dc-meta">
|
||||
Filed: <strong>{{ liveStrFiled }}</strong> · Concluded clear:
|
||||
<strong>{{ liveStrCleared }}</strong>
|
||||
</div>
|
||||
<button class="dc-btn" (click)="showTab('str')"><fa-icon icon="external-link-alt"></fa-icon> Open</button>
|
||||
</div>
|
||||
@@ -129,12 +136,12 @@
|
||||
<!-- CTR -->
|
||||
@if (activeTab === 'ctr') {
|
||||
<div class="fiu-section">
|
||||
<!-- LIVE: cash-related AML alerts awaiting AML Officer review -->
|
||||
<!-- LIVE: cash-related CTR threshold alerts -->
|
||||
<div class="fiu-form-meta">
|
||||
<div class="fiu-form-title">
|
||||
<h3>Live Cash Alerts</h3>
|
||||
<h3>Live CTR Threshold Alerts</h3>
|
||||
<p>
|
||||
Raised by the transaction-monitoring rule engine — review and whitelist or escalate to Principal Officer
|
||||
Mechanical cash transaction threshold breaches — review and whitelist or escalate to Principal Officer
|
||||
</p>
|
||||
</div>
|
||||
<select class="fiu-inp" [(ngModel)]="amlAlertStatusFilter" (ngModelChange)="loadAmlAlerts()">
|
||||
@@ -156,12 +163,13 @@
|
||||
<th class="ta-r">Amount</th>
|
||||
<th>Raised On</th>
|
||||
<th>Status</th>
|
||||
<th class="ta-c">Routes To</th>
|
||||
<th>Notes</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (alert of amlAlerts; track alert.id) {
|
||||
@for (alert of ctrAlerts; track alert.id) {
|
||||
<tr>
|
||||
<td>{{ alert.id }}</td>
|
||||
<td>{{ alert.clientDisplayName }}</td>
|
||||
@@ -172,6 +180,9 @@
|
||||
<td>
|
||||
<span [class]="amlStatusClass(alert.status)">{{ alert.status }}</span>
|
||||
</td>
|
||||
<td class="ta-c">
|
||||
<span [class]="alertRouteClass(alert.status)">{{ alertRouteLabel(alert.status) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
@if (alert.status === 'RAISED' || alert.status === 'UNDER_REVIEW') {
|
||||
<input
|
||||
@@ -195,12 +206,17 @@
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="9" class="fiu-empty">No live alerts.</td>
|
||||
<td colspan="10" class="fiu-empty">No live alerts.</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="fiu-tbl-legend">
|
||||
<span class="report-pill report-pending">Pending</span> awaiting Whitelist/Escalate decision ·
|
||||
<span class="report-pill report-ctr">CTR only</span> whitelisted — cleared, no STR needed ·
|
||||
<span class="report-pill report-str">→ STR</span> escalated to Principal Officer as an STR case
|
||||
</p>
|
||||
|
||||
<!-- LIVE: monthly CTR reports (mechanical, threshold-based) -->
|
||||
<div class="fiu-form-meta">
|
||||
@@ -295,6 +311,8 @@
|
||||
<th>Instrument</th>
|
||||
<th>Branch</th>
|
||||
<th class="ta-c">Relationship</th>
|
||||
<th class="ta-c">Filed Under</th>
|
||||
<th>Compliance Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -327,21 +345,131 @@
|
||||
t.relationshipFlag
|
||||
}}</span>
|
||||
</td>
|
||||
<td class="ta-c">
|
||||
<span class="report-pill report-ctr" title="Always included in the monthly CTR / TC2 file">CTR</span>
|
||||
@if (t.complianceStatus === 'SUSPICIOUS') {
|
||||
<span class="report-pill report-str" title="Also escalated to an STR case for Principal Officer review">+ STR</span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (!t.complianceStatus || t.complianceStatus === 'PENDING') {
|
||||
<div class="fiu-action-group" style="gap: 4px;">
|
||||
<button class="fiu-btn" style="padding: 4px 8px; font-size: 11px; color: var(--f-green); border-color: var(--f-green); background: var(--f-green-l);" (click)="whitelistCtrTxn(t)">
|
||||
Whitelist
|
||||
</button>
|
||||
<button class="fiu-btn" style="padding: 4px 8px; font-size: 11px; color: var(--f-red); border-color: var(--f-red); background: var(--f-red-l);" (click)="flagCtrTxnSuspicious(t)">
|
||||
Flag STR
|
||||
</button>
|
||||
</div>
|
||||
} @else {
|
||||
<span [class]="t.complianceStatus === 'WHITELISTED' ? 'status-pill status-whitelisted' : 'status-pill status-escalated'">
|
||||
{{ t.complianceStatus }}
|
||||
</span>
|
||||
@if (t.complianceStatus === 'WHITELISTED') {
|
||||
<div class="muted" style="margin-top: 3px;">Stays in CTR only</div>
|
||||
} @else {
|
||||
<button class="fiu-link-btn" (click)="openStrCase(t)">View in STR tab →</button>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="9" class="fiu-empty">No transactions match the filters.</td>
|
||||
<td colspan="11" class="fiu-empty">No transactions match the filters.</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="fiu-tbl-legend">
|
||||
<span class="report-pill report-ctr">CTR</span> every cash txn ≥ threshold stays in the monthly CTR / TC2
|
||||
file ·
|
||||
<span class="report-pill report-str">+ STR</span> also flagged as suspicious and escalated to a separate STR
|
||||
case (see the STR tab)
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- STR -->
|
||||
@if (activeTab === 'str') {
|
||||
<div class="fiu-section">
|
||||
<!-- LIVE: suspicious AML alerts awaiting AML Officer review (Structuring, PEP, etc.) -->
|
||||
<div class="fiu-form-meta">
|
||||
<div class="fiu-form-title">
|
||||
<h3>Live AML Alerts (Awaiting Triage)</h3>
|
||||
<p>
|
||||
Flagged by the monitoring engine for suspicious behavioral patterns — triage and whitelist or escalate
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiu-tbl-wrap">
|
||||
<table class="fiu-tbl">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Client</th>
|
||||
<th>Type</th>
|
||||
<th>Rule</th>
|
||||
<th class="ta-r">Amount</th>
|
||||
<th>Raised On</th>
|
||||
<th>Status</th>
|
||||
<th class="ta-c">Routes To</th>
|
||||
<th>Notes</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (alert of amlSuspiciousAlerts; track alert.id) {
|
||||
<tr>
|
||||
<td>{{ alert.id }}</td>
|
||||
<td>{{ alert.clientDisplayName }}</td>
|
||||
<td>{{ alert.transactionType }}</td>
|
||||
<td>{{ alert.ruleCode }} — {{ alert.ruleDescription }}</td>
|
||||
<td class="ta-r mono">₹{{ alert.amount | number: '1.0-0' }}</td>
|
||||
<td>{{ alert.raisedOn | date: 'medium' }}</td>
|
||||
<td>
|
||||
<span [class]="amlStatusClass(alert.status)">{{ alert.status }}</span>
|
||||
</td>
|
||||
<td class="ta-c">
|
||||
<span [class]="alertRouteClass(alert.status, false)">{{ alertRouteLabel(alert.status, false) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
@if (alert.status === 'RAISED' || alert.status === 'UNDER_REVIEW') {
|
||||
<input
|
||||
type="text"
|
||||
class="fiu-inp"
|
||||
placeholder="Review notes"
|
||||
[(ngModel)]="amlReviewNotes[alert.id]"
|
||||
/>
|
||||
} @else {
|
||||
<span class="muted">{{ alert.reviewNotes }}</span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (alert.status === 'RAISED' || alert.status === 'UNDER_REVIEW') {
|
||||
<div class="fiu-action-group" *mifosxHasPermission="'REVIEW_AML_ALERT'">
|
||||
<button class="fiu-btn fiu-btn-g" (click)="whitelistAlert(alert)">Whitelist</button>
|
||||
<button class="fiu-btn fiu-btn-xml" (click)="escalateAlert(alert)">Escalate</button>
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="10" class="fiu-empty">No suspicious behavioral alerts.</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="fiu-tbl-legend">
|
||||
<span class="report-pill report-pending">Pending</span> awaiting Whitelist/Escalate decision ·
|
||||
<span class="report-pill report-cleared">Cleared</span> whitelisted — no report filed ·
|
||||
<span class="report-pill report-str">→ STR</span> escalated to Principal Officer as an STR case
|
||||
</p>
|
||||
|
||||
<hr style="border: 0; border-top: 1px solid var(--f-g200); margin: 8px 0;" />
|
||||
|
||||
<!-- LIVE: STR cases with full Principal Officer actions -->
|
||||
<div class="fiu-form-meta">
|
||||
<div class="fiu-form-title">
|
||||
@@ -407,6 +535,17 @@
|
||||
<button class="fiu-btn fiu-btn-g" (click)="closeStrCaseDetail()">Close</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="case-outcome"
|
||||
[class.case-outcome--clear]="selectedStrCase.status === 'CONCLUDED_CLEAR'"
|
||||
[class.case-outcome--suspicious]="
|
||||
selectedStrCase.status === 'CONCLUDED_SUSPICIOUS' || selectedStrCase.status === 'FILED'
|
||||
"
|
||||
>
|
||||
<span [class]="amlStatusClass(selectedStrCase.status)">{{ selectedStrCase.status }}</span>
|
||||
<span>{{ strCaseOutcome(selectedStrCase) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="case-form" *mifosxHasPermission="'CONCLUDE_AML_STR'">
|
||||
<div class="form-row">
|
||||
<label for="fiuInvestigationNotes">Investigation notes (source-of-transaction history reviewed)</label>
|
||||
@@ -416,17 +555,96 @@
|
||||
<label for="fiuSourceOfFundsNotes">Source-of-funds notes</label>
|
||||
<textarea id="fiuSourceOfFundsNotes" rows="2" [(ngModel)]="concludeSourceOfFundsNotes"></textarea>
|
||||
</div>
|
||||
<div class="form-row conclusion-row">
|
||||
<label>
|
||||
<input type="radio" name="fiuConclusion" value="NOT_SUSPICIOUS" [(ngModel)]="concludeConclusion" />
|
||||
Not suspicious (whitelist)
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="fiuConclusion" value="SUSPICIOUS" [(ngModel)]="concludeConclusion" />
|
||||
Suspicious (file STR)
|
||||
</label>
|
||||
<!-- Verification checklist — the verdict is derived, not chosen. -->
|
||||
<div class="checklist">
|
||||
<div class="checklist-head">
|
||||
<span>Principal Officer verification — mark each point as found</span>
|
||||
<span class="checklist-progress" [class.done]="allAnswered">
|
||||
{{ answeredCount }} / {{ strChecklist.length }} answered
|
||||
</span>
|
||||
</div>
|
||||
<table class="checklist-tbl">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Verification point</th>
|
||||
<th class="ta-c col-yes">Genuine</th>
|
||||
<th class="ta-c col-no">Not satisfied</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (item of strChecklist; track item.key) {
|
||||
<tr
|
||||
[class.row-yes]="strFindings[item.key] === true"
|
||||
[class.row-no]="strFindings[item.key] === false"
|
||||
[class.row-pending]="strFindings[item.key] === null"
|
||||
>
|
||||
<td>
|
||||
<div class="chk-label">{{ item.label }}</div>
|
||||
<div class="chk-hint">{{ item.hint }}</div>
|
||||
</td>
|
||||
<td class="ta-c">
|
||||
<button
|
||||
type="button"
|
||||
class="chk-box chk-box--yes"
|
||||
[class.on]="strFindings[item.key] === true"
|
||||
[attr.aria-pressed]="strFindings[item.key] === true"
|
||||
[attr.aria-label]="'Mark ' + item.label + ' as genuine'"
|
||||
(click)="setFinding(item.key, true)"
|
||||
>
|
||||
<fa-icon icon="check-circle"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
<td class="ta-c">
|
||||
<button
|
||||
type="button"
|
||||
class="chk-box chk-box--no"
|
||||
[class.on]="strFindings[item.key] === false"
|
||||
[attr.aria-pressed]="strFindings[item.key] === false"
|
||||
[attr.aria-label]="'Mark ' + item.label + ' as not satisfied'"
|
||||
(click)="setFinding(item.key, false)"
|
||||
>
|
||||
<fa-icon icon="exclamation-triangle"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button class="fiu-btn fiu-btn-xml" (click)="concludeStrCase()">Conclude</button>
|
||||
|
||||
<!-- Derived verdict -->
|
||||
<div
|
||||
class="verdict"
|
||||
[class.verdict--clear]="allAnswered && derivedConclusion === 'NOT_SUSPICIOUS'"
|
||||
[class.verdict--suspicious]="allAnswered && derivedConclusion === 'SUSPICIOUS'"
|
||||
>
|
||||
@if (!allAnswered) {
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
Answer every verification point to determine the outcome —
|
||||
{{ strChecklist.length - answeredCount }} still pending.
|
||||
</span>
|
||||
} @else if (derivedConclusion === 'NOT_SUSPICIOUS') {
|
||||
<fa-icon icon="check-circle"></fa-icon>
|
||||
<span>
|
||||
<strong>Not suspicious.</strong> All {{ strChecklist.length }} points found genuine — the case will
|
||||
be closed and nothing filed with FIU-IND.
|
||||
</span>
|
||||
} @else {
|
||||
<fa-icon icon="exclamation-triangle"></fa-icon>
|
||||
<span>
|
||||
<strong>Suspicious — STR must be filed.</strong>
|
||||
{{ failedFindings.length }} of {{ strChecklist.length }} points not satisfied:
|
||||
{{ failedFindings[0].label }}@if (failedFindings.length > 1) {
|
||||
<span> and {{ failedFindings.length - 1 }} more</span>
|
||||
}.
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button class="fiu-btn fiu-btn-xml" [disabled]="!allAnswered" (click)="concludeStrCase()">
|
||||
Conclude as {{ allAnswered ? (derivedConclusion === 'SUSPICIOUS' ? 'Suspicious' : 'Not Suspicious') : '…' }}
|
||||
</button>
|
||||
|
||||
@if (selectedStrCase.status === 'CONCLUDED_SUSPICIOUS') {
|
||||
<div class="file-str-row">
|
||||
@@ -478,7 +696,12 @@
|
||||
|
||||
<div class="fiu-str-list">
|
||||
@for (s of filteredStr; track s.reportRefNo) {
|
||||
<div class="str-card" [class.str-card--filed]="s.status === 'filed'">
|
||||
<div
|
||||
class="str-card"
|
||||
[id]="'str-card-' + s.reportRefNo"
|
||||
[class.str-card--filed]="s.status === 'filed'"
|
||||
[class.str-card--highlight]="highlightedStrRef === s.reportRefNo"
|
||||
>
|
||||
<div class="str-card-h">
|
||||
<div class="str-card-id">
|
||||
<span class="str-ref">STR-{{ s.reportRefNo }}</span>
|
||||
@@ -521,6 +744,27 @@
|
||||
<p>{{ s.poRemarks }}</p>
|
||||
</div>
|
||||
}
|
||||
@if (s.poFinding) {
|
||||
<div class="str-finding" [class.str-finding--suspicious]="s.poFinding === 'SUSPICIOUS'">
|
||||
<label>
|
||||
<fa-icon [icon]="s.poFinding === 'CLEAN' ? 'check-circle' : 'exclamation-triangle'"></fa-icon>
|
||||
Principal Officer Finding
|
||||
</label>
|
||||
<p>{{ poFindingLabel(s.poFinding) }}</p>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="str-po-action" *mifosxHasPermission="'CONCLUDE_AML_STR'">
|
||||
<label>Principal Officer investigation — is the source of funds legitimate?</label>
|
||||
<div class="fiu-action-group">
|
||||
<button class="fiu-btn fiu-btn-clean" (click)="concludeLocalStr(s, 'CLEAN')">
|
||||
Clean — close case
|
||||
</button>
|
||||
<button class="fiu-btn fiu-btn-xml" (click)="concludeLocalStr(s, 'SUSPICIOUS')">
|
||||
Suspicious — file STR with FIU-IND
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
} @empty {
|
||||
@@ -626,10 +870,13 @@
|
||||
<div class="fiu-form-meta">
|
||||
<div class="fiu-form-title">
|
||||
<h3>FINnet 2.0 Submission Files</h3>
|
||||
<p>6 CSV files in FIU-IND prescribed schema, plus STR XML</p>
|
||||
<p>
|
||||
6 CSV files in FIU-IND prescribed schema, plus STR XML. Counts reflect any filters set on the CTR and
|
||||
STR tabs, so every file in the bundle covers the same transactions.
|
||||
</p>
|
||||
</div>
|
||||
<button class="fiu-btn fiu-btn-xls" (click)="exportAll()">
|
||||
<fa-icon icon="file-csv"></fa-icon> Download All
|
||||
<fa-icon icon="file-csv"></fa-icon> Download All 7
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -641,7 +888,7 @@
|
||||
</div>
|
||||
<div class="file-card">
|
||||
<div class="file-card-h"><fa-icon icon="file-csv"></fa-icon>TC2.csv</div>
|
||||
<p>Branch / cash transactions ({{ ctrTxns.length }} rows)</p>
|
||||
<p>Branch / cash transactions ({{ filteredCtr.length }} rows)</p>
|
||||
<button class="fiu-btn fiu-btn-csv" (click)="exportTc2()">
|
||||
<fa-icon icon="file-csv"></fa-icon> Download
|
||||
</button>
|
||||
@@ -676,7 +923,7 @@
|
||||
</div>
|
||||
<div class="file-card file-card--xml">
|
||||
<div class="file-card-h"><fa-icon icon="file-alt"></fa-icon>STR.xml</div>
|
||||
<p>Suspicious Transaction Report ({{ filedStr + pendingStr }} suspects)</p>
|
||||
<p>Suspicious Transaction Report ({{ strSuspects.length }} suspects — cases concluded clean are excluded)</p>
|
||||
<button class="fiu-btn fiu-btn-xml" (click)="exportStrXml()">
|
||||
<fa-icon icon="file-alt"></fa-icon> Download XML
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user