148 lines
5.7 KiB
HTML
148 lines
5.7 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="rule-dialog-title">
|
|
<mat-icon>add_moderator</mat-icon>
|
|
Add AML Rule
|
|
</h2>
|
|
|
|
<mat-dialog-content class="rule-dialog-content">
|
|
<form [formGroup]="ruleForm" class="rule-form" autocomplete="off">
|
|
<div *ngIf="errorMessage" class="rule-form-error">
|
|
<mat-icon>error_outline</mat-icon>
|
|
<span>{{ errorMessage }}</span>
|
|
</div>
|
|
|
|
<mat-form-field appearance="outline" class="rule-field-full">
|
|
<mat-label>Rule Description</mat-label>
|
|
<textarea
|
|
matInput
|
|
rows="2"
|
|
formControlName="ruleName"
|
|
placeholder="e.g. Cash deposits exceeding the monthly threshold"
|
|
></textarea>
|
|
<mat-error *ngIf="ruleForm.get('ruleName')?.hasError('required')">Rule description is required</mat-error>
|
|
<mat-error *ngIf="ruleForm.get('ruleName')?.hasError('maxlength')">Keep this under 100 characters</mat-error>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline" class="rule-field-full">
|
|
<mat-label>Rule Reason / Criteria</mat-label>
|
|
<textarea
|
|
matInput
|
|
rows="3"
|
|
formControlName="reason"
|
|
placeholder="Why the rule exists and what it looks for"
|
|
></textarea>
|
|
<mat-error *ngIf="ruleForm.get('reason')?.hasError('required')">Reason is required</mat-error>
|
|
<mat-error *ngIf="ruleForm.get('reason')?.hasError('maxlength')">Keep this under 500 characters</mat-error>
|
|
</mat-form-field>
|
|
|
|
<div class="rule-grid">
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Risk Category</mat-label>
|
|
<mat-select formControlName="riskCategory">
|
|
<mat-option *ngFor="let r of riskCategories" [value]="r.value">{{ r.label }}</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Applies Over</mat-label>
|
|
<mat-select formControlName="txnWindowDays">
|
|
<mat-option *ngFor="let w of windowOptions" [value]="w.value">{{ w.label }}</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Minimum Limit</mat-label>
|
|
<span matPrefix class="rule-field-prefix">₹</span>
|
|
<input matInput type="number" min="0" formControlName="txnMinLimitAmount" />
|
|
<mat-hint>Leave blank for a non-amount rule</mat-hint>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Maximum Limit</mat-label>
|
|
<span matPrefix class="rule-field-prefix">₹</span>
|
|
<input matInput type="number" min="0" formControlName="txnMaxLimitAmount" />
|
|
<mat-hint>Blank means no upper limit</mat-hint>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Rule Type</mat-label>
|
|
<mat-select formControlName="txnRuleType">
|
|
<mat-option *ngFor="let t of ruleTypes" [value]="t">{{ t }}</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Account Type</mat-label>
|
|
<mat-select formControlName="txnAppliesTo">
|
|
<mat-option *ngFor="let a of accountTypes" [value]="a.value">{{ a.label }}</mat-option>
|
|
</mat-select>
|
|
<mat-hint>Which accounts the rule watches</mat-hint>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Direction</mat-label>
|
|
<mat-select formControlName="txnDirection">
|
|
<mat-option *ngFor="let d of directionOptions" [value]="d.value">{{ d.label }}</mat-option>
|
|
</mat-select>
|
|
<mat-hint>Credit = paisa aaya, Debit = paisa gaya</mat-hint>
|
|
</mat-form-field>
|
|
|
|
<div class="rule-cash-only">
|
|
<mat-checkbox formControlName="txnCashOnly">Cash transactions only</mat-checkbox>
|
|
</div>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>AML Check Status</mat-label>
|
|
<mat-select formControlName="amlCheckStatus">
|
|
<mat-option *ngFor="let s of amlCheckStatuses" [value]="s">{{ s }}</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Banned Entity Match</mat-label>
|
|
<mat-select formControlName="bannedEntityMatch">
|
|
<mat-option *ngFor="let y of yesNo" [value]="y">{{ y }}</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
|
|
<div *ngIf="bandInverted" class="rule-form-error">
|
|
<mat-icon>error_outline</mat-icon>
|
|
<span>Maximum limit cannot be lower than the minimum — the rule would never match.</span>
|
|
</div>
|
|
|
|
<div *ngIf="isCcRule" class="rule-form-info">
|
|
<mat-icon>info_outline</mat-icon>
|
|
<span>
|
|
This rule will be listed under the CC chip. It does not fire on live transactions yet: the engine is not yet fed
|
|
current-account transactions.
|
|
</span>
|
|
</div>
|
|
|
|
<p class="rule-form-note">
|
|
Amount or window details also create the matching live-transaction rule. Leave them blank for a profile-only rule.
|
|
</p>
|
|
</form>
|
|
</mat-dialog-content>
|
|
|
|
<mat-dialog-actions align="end" class="rule-dialog-actions">
|
|
<button mat-stroked-button type="button" [disabled]="submitting" (click)="cancel()">Cancel</button>
|
|
<button
|
|
mat-flat-button
|
|
color="primary"
|
|
type="button"
|
|
[disabled]="ruleForm.invalid || bandInverted || submitting"
|
|
(click)="submit()"
|
|
>
|
|
<mat-spinner *ngIf="submitting" diameter="18" class="rule-submit-spinner"></mat-spinner>
|
|
{{ submitting ? 'Saving…' : 'Add Rule' }}
|
|
</button>
|
|
</mat-dialog-actions>
|