136 lines
5.4 KiB
HTML
136 lines
5.4 KiB
HTML
<!--
|
|
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/.
|
|
-->
|
|
|
|
<h2 mat-dialog-title class="review-dialog-title" [class.escalate]="!isWhitelist">
|
|
<mat-icon>{{ isWhitelist ? 'verified' : 'report' }}</mat-icon>
|
|
{{ title }}
|
|
</h2>
|
|
|
|
<mat-dialog-content class="review-dialog-content">
|
|
<!-- Restate exactly which transaction is being disposed of -->
|
|
<div class="review-summary">
|
|
<div class="review-summary-row">
|
|
<span class="review-label">Transaction</span>
|
|
<span class="review-value">
|
|
{{ data.alert.transactionType }} <span class="review-mono">#{{ data.alert.transactionId }}</span>
|
|
</span>
|
|
</div>
|
|
<div class="review-summary-row">
|
|
<span class="review-label">Client</span>
|
|
<span class="review-value">
|
|
{{ data.alert.clientDisplayName || '—' }}
|
|
<span *ngIf="data.alert.clientId" class="review-muted">(ID {{ data.alert.clientId }})</span>
|
|
</span>
|
|
</div>
|
|
<div class="review-summary-row">
|
|
<span class="review-label">Amount</span>
|
|
<span class="review-value review-mono">{{ amount() }}</span>
|
|
</div>
|
|
<div class="review-summary-row">
|
|
<span class="review-label">Rule</span>
|
|
<span class="review-value">
|
|
{{ data.alert.ruleCode }}
|
|
<span class="review-muted">— {{ data.alert.ruleDescription }}</span>
|
|
</span>
|
|
</div>
|
|
<div class="review-summary-row">
|
|
<span class="review-label">Raised On</span>
|
|
<span class="review-value">{{ data.alert.raisedOnDate | date: 'dd MMM yyyy, HH:mm:ss' }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Escalation is not a reversible bookkeeping change; say what it sets in motion -->
|
|
<div *ngIf="!isWhitelist" class="review-warning">
|
|
<mat-icon>warning</mat-icon>
|
|
<span>
|
|
This opens an STR case for the Principal Officer and re-rates the client's risk category. The case carries a
|
|
7-working-day FIU filing deadline.
|
|
</span>
|
|
</div>
|
|
|
|
<div *ngIf="isWhitelist" class="review-note">
|
|
<mat-icon>info_outline</mat-icon>
|
|
<span>The alert is closed with no report filed. The reason below is retained as the audit trail.</span>
|
|
</div>
|
|
|
|
<div *ngIf="errorMessage" class="review-error">
|
|
<mat-icon>error_outline</mat-icon>
|
|
<span>{{ errorMessage }}</span>
|
|
</div>
|
|
|
|
<form [formGroup]="reviewForm" autocomplete="off">
|
|
<!-- Evidence classification only applies to clearing an alert -->
|
|
<ng-container *ngIf="isWhitelist">
|
|
<div class="evidence-block" [class.evidence-block-invalid]="evidenceMissing">
|
|
<span class="evidence-legend">Evidence relied on — tick all that apply</span>
|
|
<div formArrayName="evidence" class="evidence-options">
|
|
<mat-checkbox *ngFor="let t of evidenceTypes; let i = index" [formControlName]="i" class="evidence-option">
|
|
{{ t }}
|
|
</mat-checkbox>
|
|
</div>
|
|
<span *ngIf="evidenceMissing" class="evidence-error">Tick at least one form of evidence</span>
|
|
</div>
|
|
|
|
<mat-form-field appearance="outline" class="review-notes-field">
|
|
<mat-label>Document / Reference No.</mat-label>
|
|
<input matInput formControlName="evidenceRef" placeholder="e.g. Invoice INV-4471, Sale deed 12/2026" />
|
|
<mat-hint>Optional — identifies the documents held on file</mat-hint>
|
|
</mat-form-field>
|
|
</ng-container>
|
|
|
|
<mat-form-field appearance="outline" class="review-notes-field">
|
|
<mat-label>{{ notesLabel }}</mat-label>
|
|
<textarea
|
|
matInput
|
|
rows="4"
|
|
formControlName="notes"
|
|
[placeholder]="
|
|
isWhitelist
|
|
? 'What the evidence shows and how it accounts for this transaction'
|
|
: 'The pattern or behaviour that makes this transaction suspicious'
|
|
"
|
|
></textarea>
|
|
<mat-error *ngIf="reviewForm.get('notes')?.hasError('required')">
|
|
Required — this is the audit record for the decision
|
|
</mat-error>
|
|
<mat-error *ngIf="reviewForm.get('notes')?.hasError('maxlength')">
|
|
Keep this under {{ detailMax }} characters
|
|
</mat-error>
|
|
</mat-form-field>
|
|
|
|
<!-- No guessing about what is retained: show the exact string that will be stored. -->
|
|
<div *ngIf="composedNotes" class="review-stored">
|
|
<span class="review-stored-label">Stored on the alert record</span>
|
|
<code class="review-stored-value">{{ composedNotes }}</code>
|
|
<span class="review-stored-hint">
|
|
Saved to <code>m_aml_alert.review_notes</code> against alert #{{ data.alert.id }}, and shown in the NOTES column
|
|
of the FIU‑IND STR register.
|
|
</span>
|
|
</div>
|
|
|
|
<div *ngIf="composedTooLong" class="review-error">
|
|
<mat-icon>error_outline</mat-icon>
|
|
<span>Too long to store — untick some evidence, or shorten the detail or reference.</span>
|
|
</div>
|
|
</form>
|
|
</mat-dialog-content>
|
|
|
|
<mat-dialog-actions align="end" class="review-dialog-actions">
|
|
<button mat-stroked-button type="button" [disabled]="submitting" (click)="cancel()">Cancel</button>
|
|
<button
|
|
mat-flat-button
|
|
type="button"
|
|
[color]="isWhitelist ? 'primary' : 'warn'"
|
|
[disabled]="reviewForm.invalid || composedTooLong || submitting"
|
|
(click)="submit()"
|
|
>
|
|
<mat-spinner *ngIf="submitting" diameter="18" class="review-spinner"></mat-spinner>
|
|
{{ submitting ? 'Saving…' : confirmLabel }}
|
|
</button>
|
|
</mat-dialog-actions>
|