Files
cbsnexora/src/app/clients/kyc-document-renewal.util.spec.ts
T
keshav 7b895a0e2b
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s
feat: add KYC document renewal alerts, Aadhaar/PAN exceptions, and AML recurring alerts UI; remove old journal AML marking
2026-08-11 11:11:18 +05:30

137 lines
5.0 KiB
TypeScript

/**
* 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/.
*/
import {
deriveKycDocumentRenewal,
kycDocumentNeedsAttention,
KYC_DOCUMENT_EXPIRY_WARNING_DAYS,
KYC_DOCUMENT_RENEWAL_YEARS
} from './kyc-document-renewal.util';
const TODAY = new Date(2026, 7, 7); // 07 Aug 2026
const at = (y: number, m: number, d: number) => new Date(y, m - 1, d);
const check = (issueDate: Date | null, expiryDate: Date | null = null, today: Date = TODAY) =>
deriveKycDocumentRenewal({ issueDate, expiryDate, today });
describe('deriveKycDocumentRenewal', () => {
describe('the five-year rule', () => {
it('says nothing about a document with neither date captured', () => {
const result = check(null, null);
expect(result.state).toBe('UNKNOWN');
expect(result.dueOn).toBeNull();
expect(result.daysRemaining).toBeNull();
});
it('leaves a recently issued document alone', () => {
const result = check(at(2025, 1, 15));
expect(result.state).toBe('OK');
expect(result.reason).toBe('AGE');
});
it('falls due exactly five years after issue', () => {
const result = check(at(2021, 8, 7));
expect(result.dueOn).toEqual(at(2026, 8, 7));
expect(result.daysRemaining).toBe(0);
// Due today is not yet past — the branch still has the day to act.
expect(result.state).toBe('OK');
});
it('becomes DUE the day after the fifth anniversary', () => {
const result = check(at(2021, 8, 6));
expect(result.state).toBe('DUE');
expect(result.reason).toBe('AGE');
});
it('is DUE, not EXPIRED, once past five years — the document is still valid, just stale', () => {
const result = check(at(2020, 3, 10));
expect(result.state).toBe('DUE');
expect(result.reason).toBe('AGE');
expect(result.daysRemaining).toBeLessThan(0);
});
it('does not warn ahead of the five-year mark — a document one day short is entirely fine', () => {
// Due tomorrow on age alone, and still OK: only expiry gets an advance warning.
const result = check(at(2021, 8, 8));
expect(result.daysRemaining).toBe(1);
expect(result.state).toBe('OK');
});
});
describe('an explicit expiry date', () => {
it('warns seven days before expiry', () => {
const result = check(at(2025, 6, 1), at(2026, 8, 14));
expect(result.reason).toBe('EXPIRY');
expect(result.daysRemaining).toBe(7);
expect(result.state).toBe('EXPIRING_SOON');
});
it('is still OK eight days out', () => {
expect(check(at(2025, 6, 1), at(2026, 8, 15)).state).toBe('OK');
});
it('warns on the day of expiry itself', () => {
const result = check(at(2025, 6, 1), at(2026, 8, 7));
expect(result.daysRemaining).toBe(0);
expect(result.state).toBe('EXPIRING_SOON');
});
it('marks a passed expiry as EXPIRED — no longer a valid OVD', () => {
const result = check(at(2024, 1, 1), at(2026, 1, 1));
expect(result.state).toBe('EXPIRED');
expect(result.reason).toBe('EXPIRY');
});
it('governs when it falls before the five-year mark', () => {
// Issued last year, so the age clock is years away — expiry is what matters.
const result = check(at(2025, 6, 1), at(2026, 10, 1));
expect(result.reason).toBe('EXPIRY');
expect(result.dueOn).toEqual(at(2026, 10, 1));
});
it('yields to the five-year rule when it falls later', () => {
// A passport issued in 2019 expiring in 2029 is stale long before it expires.
const result = check(at(2019, 5, 20), at(2029, 5, 20));
expect(result.reason).toBe('AGE');
expect(result.dueOn).toEqual(at(2024, 5, 20));
expect(result.state).toBe('DUE');
});
it('is judged on expiry alone when no issue date was captured', () => {
const result = check(null, at(2027, 1, 1));
expect(result.reason).toBe('EXPIRY');
expect(result.state).toBe('OK');
});
});
describe('leap-year issue dates', () => {
it('pins a 29 February issue to 28 February, not 1 March', () => {
// 2020-02-29 + 5 years has no real anniversary; rolling into March would push the
// document into the wrong month.
const result = check(at(2020, 2, 29));
expect(result.dueOn).toEqual(at(2025, 2, 28));
});
});
describe('kycDocumentNeedsAttention', () => {
it('flags only the states staff must act on', () => {
expect(kycDocumentNeedsAttention('UNKNOWN')).toBe(false);
expect(kycDocumentNeedsAttention('OK')).toBe(false);
expect(kycDocumentNeedsAttention('EXPIRING_SOON')).toBe(true);
expect(kycDocumentNeedsAttention('EXPIRED')).toBe(true);
expect(kycDocumentNeedsAttention('DUE')).toBe(true);
});
});
it('uses a five-year age window and a seven-day expiry warning', () => {
expect(KYC_DOCUMENT_RENEWAL_YEARS).toBe(5);
expect(KYC_DOCUMENT_EXPIRY_WARNING_DAYS).toBe(7);
});
});