ofcoop-shared-core 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/dist/OfcoopCore.d.ts +60 -0
- package/dist/OfcoopCore.js +273 -0
- package/dist/contracts/MemberContract.d.ts +52 -0
- package/dist/contracts/MemberContract.js +2 -0
- package/dist/contracts/MemberNumberPolicyContract.d.ts +44 -0
- package/dist/contracts/MemberNumberPolicyContract.js +2 -0
- package/dist/contracts/SavingComplianceSnapshotContract.d.ts +34 -0
- package/dist/contracts/SavingComplianceSnapshotContract.js +2 -0
- package/dist/contracts/SavingLedgerContract.d.ts +49 -0
- package/dist/contracts/SavingLedgerContract.js +2 -0
- package/dist/contracts/SavingPolicyContract.d.ts +63 -0
- package/dist/contracts/SavingPolicyContract.js +2 -0
- package/dist/contracts/ShuConfigContract.d.ts +39 -0
- package/dist/contracts/ShuConfigContract.js +2 -0
- package/dist/contracts/ShuContract.d.ts +58 -0
- package/dist/contracts/ShuContract.js +2 -0
- package/dist/contracts/crossDomainPrimitives.d.ts +5 -0
- package/dist/contracts/crossDomainPrimitives.js +2 -0
- package/dist/data/applyPendingMigrations.d.ts +2 -0
- package/dist/data/applyPendingMigrations.js +30 -0
- package/dist/data/migrations.d.ts +2 -0
- package/dist/data/migrations.js +20 -0
- package/dist/data/repositories.d.ts +114 -0
- package/dist/data/repositories.js +324 -0
- package/dist/data/schemas.d.ts +14 -0
- package/dist/data/schemas.js +179 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +54 -0
- package/dist/services/AuditTrailQueryService.d.ts +35 -0
- package/dist/services/AuditTrailQueryService.js +62 -0
- package/dist/services/CoopOrchestrationService.d.ts +35 -0
- package/dist/services/CoopOrchestrationService.js +71 -0
- package/dist/services/DailyOpsService.d.ts +2 -0
- package/dist/services/DailyOpsService.js +7 -0
- package/dist/services/DashboardSummaryService.d.ts +180 -0
- package/dist/services/DashboardSummaryService.js +211 -0
- package/dist/services/DashboardViewModelService.d.ts +42 -0
- package/dist/services/DashboardViewModelService.js +193 -0
- package/dist/services/Member360Service.d.ts +75 -0
- package/dist/services/Member360Service.js +79 -0
- package/dist/services/Member360ViewModelService.d.ts +33 -0
- package/dist/services/Member360ViewModelService.js +66 -0
- package/dist/services/MemberNumberPolicyService.d.ts +4 -0
- package/dist/services/MemberNumberPolicyService.js +18 -0
- package/dist/services/MemberService.d.ts +4 -0
- package/dist/services/MemberService.js +18 -0
- package/dist/services/ReportSummaryService.d.ts +81 -0
- package/dist/services/ReportSummaryService.js +160 -0
- package/dist/services/ReportViewModelService.d.ts +24 -0
- package/dist/services/ReportViewModelService.js +90 -0
- package/dist/services/SavingComplianceSnapshotService.d.ts +4 -0
- package/dist/services/SavingComplianceSnapshotService.js +10 -0
- package/dist/services/SavingLedgerService.d.ts +4 -0
- package/dist/services/SavingLedgerService.js +13 -0
- package/dist/services/SavingPolicyService.d.ts +5 -0
- package/dist/services/SavingPolicyService.js +20 -0
- package/dist/services/ShuConfigService.d.ts +4 -0
- package/dist/services/ShuConfigService.js +16 -0
- package/dist/services/ShuService.d.ts +4 -0
- package/dist/services/ShuService.js +14 -0
- package/dist/services/createActivityAuditTrailProvider.d.ts +22 -0
- package/dist/services/createActivityAuditTrailProvider.js +73 -0
- package/dist/services/createAuditTrailCompositionProvider.d.ts +13 -0
- package/dist/services/createAuditTrailCompositionProvider.js +21 -0
- package/dist/services/createDbAdapterOfcoopServices.d.ts +20 -0
- package/dist/services/createDbAdapterOfcoopServices.js +23 -0
- package/dist/services/createMember360CompositionProviders.d.ts +6 -0
- package/dist/services/createMember360CompositionProviders.js +43 -0
- package/dist/services/createOfauthCompositionProviders.d.ts +39 -0
- package/dist/services/createOfauthCompositionProviders.js +80 -0
- package/dist/services/createOfcoopCreditCompositionProviders.d.ts +59 -0
- package/dist/services/createOfcoopCreditCompositionProviders.js +233 -0
- package/dist/services/createOfcoopDashboardCompositionProviders.d.ts +18 -0
- package/dist/services/createOfcoopDashboardCompositionProviders.js +228 -0
- package/dist/services/createOfcoopDomainAuditCompositionProviders.d.ts +36 -0
- package/dist/services/createOfcoopDomainAuditCompositionProviders.js +117 -0
- package/dist/services/createOfcoopReportCompositionProviders.d.ts +10 -0
- package/dist/services/createOfcoopReportCompositionProviders.js +30 -0
- package/dist/services/errors.d.ts +8 -0
- package/dist/services/errors.js +23 -0
- package/dist/services/impl/DbAdapterMemberNumberPolicyService.d.ts +9 -0
- package/dist/services/impl/DbAdapterMemberNumberPolicyService.js +37 -0
- package/dist/services/impl/DbAdapterMemberService.d.ts +21 -0
- package/dist/services/impl/DbAdapterMemberService.js +142 -0
- package/dist/services/impl/DbAdapterSavingComplianceSnapshotService.d.ts +9 -0
- package/dist/services/impl/DbAdapterSavingComplianceSnapshotService.js +74 -0
- package/dist/services/impl/DbAdapterSavingLedgerService.d.ts +18 -0
- package/dist/services/impl/DbAdapterSavingLedgerService.js +115 -0
- package/dist/services/impl/DbAdapterSavingPolicyService.d.ts +14 -0
- package/dist/services/impl/DbAdapterSavingPolicyService.js +139 -0
- package/dist/services/impl/DbAdapterShuConfigService.d.ts +12 -0
- package/dist/services/impl/DbAdapterShuConfigService.js +62 -0
- package/dist/services/impl/DbAdapterShuService.d.ts +26 -0
- package/dist/services/impl/DbAdapterShuService.js +376 -0
- package/dist/services/impl/runtimeSupport.d.ts +18 -0
- package/dist/services/impl/runtimeSupport.js +29 -0
- package/package.json +41 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveSavingComplianceStatus = deriveSavingComplianceStatus;
|
|
4
|
+
function deriveSavingComplianceStatus(monthlyWajibNominalIdr, wajibNetTotalIdr, hasPolicy) {
|
|
5
|
+
if (!hasPolicy)
|
|
6
|
+
return 'no-policy';
|
|
7
|
+
if (wajibNetTotalIdr >= monthlyWajibNominalIdr)
|
|
8
|
+
return 'compliant';
|
|
9
|
+
return 'underpaid';
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidSavingEntryInput = assertValidSavingEntryInput;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
function assertValidSavingEntryInput(input) {
|
|
6
|
+
if (!input.memberId?.trim())
|
|
7
|
+
throw (0, errors_1.invalidState)('memberId is required');
|
|
8
|
+
if (!input.transactionDate?.trim())
|
|
9
|
+
throw (0, errors_1.invalidState)('transactionDate is required');
|
|
10
|
+
if (Number.isNaN(Number(input.amount)) || Number(input.amount) <= 0) {
|
|
11
|
+
throw (0, errors_1.invalidState)('amount must be > 0');
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SavingPolicyServiceContract, UpsertSavingPolicyInput } from '../contracts/SavingPolicyContract';
|
|
2
|
+
export interface SavingPolicyService extends SavingPolicyServiceContract {
|
|
3
|
+
}
|
|
4
|
+
export declare function assertValidSavingPolicyInput(input: UpsertSavingPolicyInput): void;
|
|
5
|
+
export declare function calculateWajibNetTotal(wajibCreditTotal: number, wajibDebitTotal: number): number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidSavingPolicyInput = assertValidSavingPolicyInput;
|
|
4
|
+
exports.calculateWajibNetTotal = calculateWajibNetTotal;
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
function assertValidSavingPolicyInput(input) {
|
|
7
|
+
if (!input.koperasiId?.trim())
|
|
8
|
+
throw (0, errors_1.invalidState)('koperasiId is required');
|
|
9
|
+
if (!input.tenantId?.trim())
|
|
10
|
+
throw (0, errors_1.invalidState)('tenantId is required');
|
|
11
|
+
if (!input.effectiveDate?.trim())
|
|
12
|
+
throw (0, errors_1.invalidState)('effectiveDate is required');
|
|
13
|
+
if (input.simpananPokokNominalIdr < 0)
|
|
14
|
+
throw (0, errors_1.invalidState)('simpananPokokNominalIdr must be >= 0');
|
|
15
|
+
if (input.monthlyWajibNominalIdr < 0)
|
|
16
|
+
throw (0, errors_1.invalidState)('monthlyWajibNominalIdr must be >= 0');
|
|
17
|
+
}
|
|
18
|
+
function calculateWajibNetTotal(wajibCreditTotal, wajibDebitTotal) {
|
|
19
|
+
return wajibCreditTotal - wajibDebitTotal;
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidShuConfigInput = assertValidShuConfigInput;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
function assertValidShuConfigInput(input) {
|
|
6
|
+
if (!input.koperasiId?.trim())
|
|
7
|
+
throw (0, errors_1.invalidState)('koperasiId is required');
|
|
8
|
+
if (!input.tenantId?.trim())
|
|
9
|
+
throw (0, errors_1.invalidState)('tenantId is required');
|
|
10
|
+
if (!input.effectiveDate?.trim())
|
|
11
|
+
throw (0, errors_1.invalidState)('effectiveDate is required');
|
|
12
|
+
const totalPercent = input.cadanganPercent + input.jasaUsahaPercent + input.jasaModalPercent;
|
|
13
|
+
if (totalPercent !== 100) {
|
|
14
|
+
throw (0, errors_1.invalidState)(`SHU config percent total must be exactly 100, got ${totalPercent}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidCreateShuPeriodInput = assertValidCreateShuPeriodInput;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
function assertValidCreateShuPeriodInput(input) {
|
|
6
|
+
if (!input.periodCode?.trim())
|
|
7
|
+
throw (0, errors_1.invalidState)('periodCode is required');
|
|
8
|
+
if (!input.startDate?.trim())
|
|
9
|
+
throw (0, errors_1.invalidState)('startDate is required');
|
|
10
|
+
if (!input.endDate?.trim())
|
|
11
|
+
throw (0, errors_1.invalidState)('endDate is required');
|
|
12
|
+
if (!input.tenantId?.trim())
|
|
13
|
+
throw (0, errors_1.invalidState)('tenantId is required');
|
|
14
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ActivityRecord } from 'ofcore';
|
|
2
|
+
import type { AuditTrailEvent, AuditTrailQueryInput } from './AuditTrailQueryService';
|
|
3
|
+
export interface ActivityRecordQuery {
|
|
4
|
+
fromTimestamp?: string;
|
|
5
|
+
toTimestamp?: string;
|
|
6
|
+
tenantId?: string | null;
|
|
7
|
+
branchId?: string | null;
|
|
8
|
+
limit?: number;
|
|
9
|
+
activityTypes?: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface ActivityRecordSource {
|
|
12
|
+
listActivityRecords(query: ActivityRecordQuery): Promise<ActivityRecord[]>;
|
|
13
|
+
}
|
|
14
|
+
export interface CreateActivityAuditTrailProviderOptions {
|
|
15
|
+
eventCatalog?: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function createActivityAuditTrailProvider(source: ActivityRecordSource, options?: CreateActivityAuditTrailProviderOptions): {
|
|
18
|
+
auditTrailProvider: {
|
|
19
|
+
listEvents: (query: AuditTrailQueryInput) => Promise<AuditTrailEvent[]>;
|
|
20
|
+
};
|
|
21
|
+
eventCatalog: string[];
|
|
22
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createActivityAuditTrailProvider = createActivityAuditTrailProvider;
|
|
4
|
+
const createOfauthCompositionProviders_1 = require("./createOfauthCompositionProviders");
|
|
5
|
+
const createOfcoopDomainAuditCompositionProviders_1 = require("./createOfcoopDomainAuditCompositionProviders");
|
|
6
|
+
function unique(values) {
|
|
7
|
+
return [...new Set(values)];
|
|
8
|
+
}
|
|
9
|
+
function toDomain(activityType) {
|
|
10
|
+
if (activityType.startsWith('ofcoop.'))
|
|
11
|
+
return 'ofcoop';
|
|
12
|
+
if (activityType.startsWith('ofcoop-credit.'))
|
|
13
|
+
return 'ofcoop-credit';
|
|
14
|
+
if (activityType.startsWith('ofauth.'))
|
|
15
|
+
return 'ofauth';
|
|
16
|
+
return 'external';
|
|
17
|
+
}
|
|
18
|
+
function toEventType(activityType) {
|
|
19
|
+
if (activityType.startsWith('ofcoop.'))
|
|
20
|
+
return activityType.slice('ofcoop.'.length);
|
|
21
|
+
if (activityType.startsWith('ofcoop-credit.'))
|
|
22
|
+
return activityType.slice('ofcoop-credit.'.length);
|
|
23
|
+
if (activityType.startsWith('ofauth.'))
|
|
24
|
+
return activityType.slice('ofauth.'.length).toUpperCase();
|
|
25
|
+
return activityType;
|
|
26
|
+
}
|
|
27
|
+
function toActivityTypes(eventTypes) {
|
|
28
|
+
if (!eventTypes || eventTypes.length === 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
const out = eventTypes.flatMap((eventType) => [
|
|
31
|
+
`ofcoop.${eventType}`,
|
|
32
|
+
`ofcoop-credit.${eventType}`,
|
|
33
|
+
`ofauth.${eventType.toLowerCase()}`,
|
|
34
|
+
]);
|
|
35
|
+
return unique(out);
|
|
36
|
+
}
|
|
37
|
+
function createActivityAuditTrailProvider(source, options = {}) {
|
|
38
|
+
const eventCatalog = unique(options.eventCatalog ??
|
|
39
|
+
[...createOfcoopDomainAuditCompositionProviders_1.OFCOOP_AUDIT_EVENT_CATALOG, ...createOfcoopDomainAuditCompositionProviders_1.OFCOOP_CREDIT_AUDIT_EVENT_CATALOG, ...createOfauthCompositionProviders_1.OFAUTH_AUDIT_EVENT_CATALOG]);
|
|
40
|
+
return {
|
|
41
|
+
eventCatalog,
|
|
42
|
+
auditTrailProvider: {
|
|
43
|
+
async listEvents(query) {
|
|
44
|
+
const rows = await source.listActivityRecords({
|
|
45
|
+
fromTimestamp: query.fromTimestamp,
|
|
46
|
+
toTimestamp: query.toTimestamp,
|
|
47
|
+
tenantId: query.scope?.tenantId,
|
|
48
|
+
branchId: query.scope?.branchId,
|
|
49
|
+
limit: query.limit,
|
|
50
|
+
activityTypes: toActivityTypes(query.eventTypes),
|
|
51
|
+
});
|
|
52
|
+
return rows
|
|
53
|
+
.map((row) => {
|
|
54
|
+
const payloadMemberId = typeof row.payload?.memberId === 'string' ? row.payload.memberId : null;
|
|
55
|
+
const domain = toDomain(row.activityType);
|
|
56
|
+
return {
|
|
57
|
+
eventId: row.activityId,
|
|
58
|
+
sourceDomain: domain,
|
|
59
|
+
eventType: toEventType(row.activityType),
|
|
60
|
+
occurredAt: row.occurredAt,
|
|
61
|
+
memberId: payloadMemberId ?? query.memberId ?? undefined,
|
|
62
|
+
tenantId: row.scopeRef?.tenantId,
|
|
63
|
+
branchId: row.scopeRef?.branchId,
|
|
64
|
+
summary: typeof row.payload?.entityId === 'string' && row.payload.entityId
|
|
65
|
+
? `entity:${row.payload.entityId}`
|
|
66
|
+
: row.activityType,
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
.sort((a, b) => b.occurredAt.localeCompare(a.occurredAt));
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuditTrailEvent, AuditTrailQueryInput } from './AuditTrailQueryService';
|
|
2
|
+
interface AuditTrailProviderRef {
|
|
3
|
+
listEvents: (query: AuditTrailQueryInput) => Promise<AuditTrailEvent[]>;
|
|
4
|
+
}
|
|
5
|
+
interface AuditTrailProviderSourceRef {
|
|
6
|
+
provider: AuditTrailProviderRef;
|
|
7
|
+
eventCatalog?: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function createAuditTrailCompositionProvider(sources: AuditTrailProviderSourceRef[]): {
|
|
10
|
+
auditTrailProvider: AuditTrailProviderRef;
|
|
11
|
+
eventCatalog: string[];
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuditTrailCompositionProvider = createAuditTrailCompositionProvider;
|
|
4
|
+
function uniqueCatalog(input) {
|
|
5
|
+
return [...new Set(input)];
|
|
6
|
+
}
|
|
7
|
+
function createAuditTrailCompositionProvider(sources) {
|
|
8
|
+
const eventCatalog = uniqueCatalog(sources.flatMap((source) => source.eventCatalog ?? []));
|
|
9
|
+
return {
|
|
10
|
+
eventCatalog,
|
|
11
|
+
auditTrailProvider: {
|
|
12
|
+
async listEvents(query) {
|
|
13
|
+
const batches = await Promise.all(sources.map((source) => source.provider.listEvents(query)));
|
|
14
|
+
return batches
|
|
15
|
+
.flat()
|
|
16
|
+
.sort((a, b) => b.occurredAt.localeCompare(a.occurredAt))
|
|
17
|
+
.slice(0, query.limit && query.limit > 0 ? query.limit : 100);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DbAdapter } from 'ofcore';
|
|
2
|
+
import type { MemberServiceContract } from '../contracts/MemberContract';
|
|
3
|
+
import type { MemberNumberPolicyServiceContract } from '../contracts/MemberNumberPolicyContract';
|
|
4
|
+
import type { SavingLedgerServiceContract } from '../contracts/SavingLedgerContract';
|
|
5
|
+
import type { SavingPolicyServiceContract } from '../contracts/SavingPolicyContract';
|
|
6
|
+
import type { SavingComplianceSnapshotServiceContract } from '../contracts/SavingComplianceSnapshotContract';
|
|
7
|
+
import type { ShuConfigServiceContract } from '../contracts/ShuConfigContract';
|
|
8
|
+
import type { ShuServiceContract } from '../contracts/ShuContract';
|
|
9
|
+
import type { ServiceRuntimeOptions } from './impl/runtimeSupport';
|
|
10
|
+
export type { OfcoopDomainEvent, OfcoopDomainEventName, ServiceRuntimeOptions } from './impl/runtimeSupport';
|
|
11
|
+
export interface OfcoopDomainServices {
|
|
12
|
+
memberService: MemberServiceContract;
|
|
13
|
+
memberNumberPolicyService: MemberNumberPolicyServiceContract;
|
|
14
|
+
savingLedgerService: SavingLedgerServiceContract;
|
|
15
|
+
savingPolicyService: SavingPolicyServiceContract;
|
|
16
|
+
savingComplianceSnapshotService: SavingComplianceSnapshotServiceContract;
|
|
17
|
+
shuConfigService: ShuConfigServiceContract;
|
|
18
|
+
shuService: ShuServiceContract;
|
|
19
|
+
}
|
|
20
|
+
export declare function createDbAdapterOfcoopServices(dbAdapter: DbAdapter, options?: ServiceRuntimeOptions): Promise<OfcoopDomainServices>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDbAdapterOfcoopServices = createDbAdapterOfcoopServices;
|
|
4
|
+
const repositories_1 = require("../data/repositories");
|
|
5
|
+
const DbAdapterMemberNumberPolicyService_1 = require("./impl/DbAdapterMemberNumberPolicyService");
|
|
6
|
+
const DbAdapterMemberService_1 = require("./impl/DbAdapterMemberService");
|
|
7
|
+
const DbAdapterSavingComplianceSnapshotService_1 = require("./impl/DbAdapterSavingComplianceSnapshotService");
|
|
8
|
+
const DbAdapterSavingLedgerService_1 = require("./impl/DbAdapterSavingLedgerService");
|
|
9
|
+
const DbAdapterSavingPolicyService_1 = require("./impl/DbAdapterSavingPolicyService");
|
|
10
|
+
const DbAdapterShuConfigService_1 = require("./impl/DbAdapterShuConfigService");
|
|
11
|
+
const DbAdapterShuService_1 = require("./impl/DbAdapterShuService");
|
|
12
|
+
async function createDbAdapterOfcoopServices(dbAdapter, options = {}) {
|
|
13
|
+
const repositories = (0, repositories_1.createOfcoopRepositories)(dbAdapter);
|
|
14
|
+
return {
|
|
15
|
+
memberService: new DbAdapterMemberService_1.DbAdapterMemberService(dbAdapter, repositories, options),
|
|
16
|
+
memberNumberPolicyService: new DbAdapterMemberNumberPolicyService_1.DbAdapterMemberNumberPolicyService(repositories),
|
|
17
|
+
savingLedgerService: new DbAdapterSavingLedgerService_1.DbAdapterSavingLedgerService(dbAdapter, repositories, options),
|
|
18
|
+
savingPolicyService: new DbAdapterSavingPolicyService_1.DbAdapterSavingPolicyService(repositories, options),
|
|
19
|
+
savingComplianceSnapshotService: new DbAdapterSavingComplianceSnapshotService_1.DbAdapterSavingComplianceSnapshotService(repositories),
|
|
20
|
+
shuConfigService: new DbAdapterShuConfigService_1.DbAdapterShuConfigService(repositories, options),
|
|
21
|
+
shuService: new DbAdapterShuService_1.DbAdapterShuService(dbAdapter, repositories, options),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Member360Providers } from './Member360Service';
|
|
2
|
+
interface Member360ProviderSourceRef {
|
|
3
|
+
provider: Pick<Member360Providers, 'getCreditByMember' | 'getAuditByMember' | 'getSettlementSummaryByMember'>;
|
|
4
|
+
}
|
|
5
|
+
export declare function createMember360CompositionProviders(sources: Member360ProviderSourceRef[]): Pick<Member360Providers, 'getCreditByMember' | 'getAuditByMember' | 'getSettlementSummaryByMember'>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMember360CompositionProviders = createMember360CompositionProviders;
|
|
4
|
+
function sortAuditDesc(rows) {
|
|
5
|
+
return [...rows].sort((a, b) => b.occurredAt.localeCompare(a.occurredAt));
|
|
6
|
+
}
|
|
7
|
+
async function resolveFirstCredit(sources, memberId, scope) {
|
|
8
|
+
for (const source of sources) {
|
|
9
|
+
if (!source.provider.getCreditByMember)
|
|
10
|
+
continue;
|
|
11
|
+
const result = await source.provider.getCreditByMember(memberId, scope);
|
|
12
|
+
if (result)
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
async function resolveMergedAudit(sources, memberId, scope) {
|
|
18
|
+
const batches = await Promise.all(sources.map((source) => source.provider.getAuditByMember?.(memberId, scope) ?? Promise.resolve([])));
|
|
19
|
+
return sortAuditDesc(batches.flat()).slice(0, 100);
|
|
20
|
+
}
|
|
21
|
+
async function resolveFirstSettlement(sources, memberId, scope) {
|
|
22
|
+
for (const source of sources) {
|
|
23
|
+
if (!source.provider.getSettlementSummaryByMember)
|
|
24
|
+
continue;
|
|
25
|
+
const result = await source.provider.getSettlementSummaryByMember(memberId, scope);
|
|
26
|
+
if (result)
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function createMember360CompositionProviders(sources) {
|
|
32
|
+
return {
|
|
33
|
+
async getCreditByMember(memberId, scope) {
|
|
34
|
+
return resolveFirstCredit(sources, memberId, scope);
|
|
35
|
+
},
|
|
36
|
+
async getAuditByMember(memberId, scope) {
|
|
37
|
+
return resolveMergedAudit(sources, memberId, scope);
|
|
38
|
+
},
|
|
39
|
+
async getSettlementSummaryByMember(memberId, scope) {
|
|
40
|
+
return resolveFirstSettlement(sources, memberId, scope);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AuditTrailEvent, AuditTrailQueryInput } from './AuditTrailQueryService';
|
|
2
|
+
import type { Member360Providers } from './Member360Service';
|
|
3
|
+
export declare const OFAUTH_AUDIT_EVENT_CATALOG: readonly ["LOGIN_SUCCESS", "LOGIN_FAILED", "LOCKOUT_TRIGGERED", "SESSION_REVOKED", "CONTEXT_SWITCHED", "STEP_UP_CHALLENGED", "STEP_UP_PASSED", "STEP_UP_FAILED"];
|
|
4
|
+
type OfauthAuditEventType = (typeof OFAUTH_AUDIT_EVENT_CATALOG)[number];
|
|
5
|
+
interface OfauthAuditEventRef {
|
|
6
|
+
eventId: string;
|
|
7
|
+
eventType: OfauthAuditEventType;
|
|
8
|
+
identityId?: string;
|
|
9
|
+
sessionId?: string;
|
|
10
|
+
scopeRef?: {
|
|
11
|
+
tenantId?: string;
|
|
12
|
+
branchId?: string;
|
|
13
|
+
attributes?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
result: 'success' | 'failed';
|
|
16
|
+
reasonCode?: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
}
|
|
19
|
+
interface OfauthAuditServiceRef {
|
|
20
|
+
queryEvents: (query: {
|
|
21
|
+
identityId?: string;
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
eventTypes?: OfauthAuditEventType[];
|
|
24
|
+
fromTimestamp?: string;
|
|
25
|
+
toTimestamp?: string;
|
|
26
|
+
}) => Promise<OfauthAuditEventRef[]>;
|
|
27
|
+
}
|
|
28
|
+
interface OfauthIdentityLinkResolver {
|
|
29
|
+
resolveIdentityIdsByMemberId: (memberId: string) => Promise<string[]>;
|
|
30
|
+
resolveMemberIdByIdentityId?: (identityId: string) => Promise<string | null>;
|
|
31
|
+
}
|
|
32
|
+
export declare function createOfauthCompositionProviders(authAuditService: OfauthAuditServiceRef, resolver: OfauthIdentityLinkResolver): {
|
|
33
|
+
member360: Pick<Member360Providers, 'getAuditByMember'>;
|
|
34
|
+
auditTrailProvider: {
|
|
35
|
+
listEvents: (query: AuditTrailQueryInput) => Promise<AuditTrailEvent[]>;
|
|
36
|
+
};
|
|
37
|
+
eventCatalog: string[];
|
|
38
|
+
};
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OFAUTH_AUDIT_EVENT_CATALOG = void 0;
|
|
4
|
+
exports.createOfauthCompositionProviders = createOfauthCompositionProviders;
|
|
5
|
+
exports.OFAUTH_AUDIT_EVENT_CATALOG = [
|
|
6
|
+
'LOGIN_SUCCESS',
|
|
7
|
+
'LOGIN_FAILED',
|
|
8
|
+
'LOCKOUT_TRIGGERED',
|
|
9
|
+
'SESSION_REVOKED',
|
|
10
|
+
'CONTEXT_SWITCHED',
|
|
11
|
+
'STEP_UP_CHALLENGED',
|
|
12
|
+
'STEP_UP_PASSED',
|
|
13
|
+
'STEP_UP_FAILED',
|
|
14
|
+
];
|
|
15
|
+
function isOfauthEventType(value) {
|
|
16
|
+
return exports.OFAUTH_AUDIT_EVENT_CATALOG.includes(value);
|
|
17
|
+
}
|
|
18
|
+
function toMember360Audit(event) {
|
|
19
|
+
return {
|
|
20
|
+
eventId: event.eventId,
|
|
21
|
+
eventType: event.eventType,
|
|
22
|
+
occurredAt: event.timestamp,
|
|
23
|
+
message: event.reasonCode ?? event.result,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function toAuditTrailEvent(event, memberId) {
|
|
27
|
+
return {
|
|
28
|
+
eventId: event.eventId,
|
|
29
|
+
sourceDomain: 'ofauth',
|
|
30
|
+
eventType: event.eventType,
|
|
31
|
+
occurredAt: event.timestamp,
|
|
32
|
+
memberId: memberId ?? undefined,
|
|
33
|
+
tenantId: event.scopeRef?.tenantId,
|
|
34
|
+
branchId: event.scopeRef?.branchId,
|
|
35
|
+
summary: event.reasonCode ?? event.result,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function createOfauthCompositionProviders(authAuditService, resolver) {
|
|
39
|
+
const member360 = {
|
|
40
|
+
async getAuditByMember(memberId) {
|
|
41
|
+
const identityIds = await resolver.resolveIdentityIdsByMemberId(memberId);
|
|
42
|
+
if (identityIds.length === 0)
|
|
43
|
+
return [];
|
|
44
|
+
const all = await Promise.all(identityIds.map((identityId) => authAuditService.queryEvents({ identityId })));
|
|
45
|
+
return all
|
|
46
|
+
.flat()
|
|
47
|
+
.sort((a, b) => b.timestamp.localeCompare(a.timestamp))
|
|
48
|
+
.slice(0, 100)
|
|
49
|
+
.map(toMember360Audit);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
const auditTrailProvider = {
|
|
53
|
+
async listEvents(query) {
|
|
54
|
+
let identityIds = [];
|
|
55
|
+
if (query.memberId) {
|
|
56
|
+
identityIds = await resolver.resolveIdentityIdsByMemberId(query.memberId);
|
|
57
|
+
if (identityIds.length === 0)
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const requestedTypes = (query.eventTypes ?? []).filter(isOfauthEventType);
|
|
61
|
+
const baseQuery = {
|
|
62
|
+
...(query.fromTimestamp ? { fromTimestamp: query.fromTimestamp } : {}),
|
|
63
|
+
...(query.toTimestamp ? { toTimestamp: query.toTimestamp } : {}),
|
|
64
|
+
...(requestedTypes.length > 0 ? { eventTypes: requestedTypes } : {}),
|
|
65
|
+
};
|
|
66
|
+
const batches = identityIds.length > 0
|
|
67
|
+
? await Promise.all(identityIds.map((identityId) => authAuditService.queryEvents({ ...baseQuery, identityId })))
|
|
68
|
+
: [await authAuditService.queryEvents(baseQuery)];
|
|
69
|
+
const mapped = await Promise.all(batches
|
|
70
|
+
.flat()
|
|
71
|
+
.map(async (event) => toAuditTrailEvent(event, event.identityId ? (await resolver.resolveMemberIdByIdentityId?.(event.identityId)) ?? null : null)));
|
|
72
|
+
return mapped;
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
member360,
|
|
77
|
+
auditTrailProvider,
|
|
78
|
+
eventCatalog: [...exports.OFAUTH_AUDIT_EVENT_CATALOG],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DashboardSummaryProviders } from './DashboardSummaryService';
|
|
2
|
+
import type { Member360Providers } from './Member360Service';
|
|
3
|
+
import type { ReportSummaryProviders } from './ReportSummaryService';
|
|
4
|
+
interface LoanRef {
|
|
5
|
+
id: string;
|
|
6
|
+
memberId: string;
|
|
7
|
+
principalAmount: number;
|
|
8
|
+
status: 'active' | 'closed' | 'defaulted';
|
|
9
|
+
startDate: string;
|
|
10
|
+
}
|
|
11
|
+
interface LoanBoardItemRef {
|
|
12
|
+
loanId: string;
|
|
13
|
+
memberId: string;
|
|
14
|
+
status: 'active' | 'closed' | 'defaulted';
|
|
15
|
+
principalAmount: number;
|
|
16
|
+
outstandingAmount: number;
|
|
17
|
+
overdueInstallmentCount: number;
|
|
18
|
+
nextDueDate?: string | null;
|
|
19
|
+
}
|
|
20
|
+
interface LoanDueWindowItemRef {
|
|
21
|
+
loanId: string;
|
|
22
|
+
memberId: string;
|
|
23
|
+
dueDate: string;
|
|
24
|
+
installmentStatus: 'scheduled' | 'partial' | 'paid' | 'overdue';
|
|
25
|
+
outstandingAmount: number;
|
|
26
|
+
}
|
|
27
|
+
interface CreditServicesRef {
|
|
28
|
+
loanService: {
|
|
29
|
+
listLoansByMember: (memberId: string, options?: {
|
|
30
|
+
includeDeleted?: boolean;
|
|
31
|
+
tenantId?: string | null;
|
|
32
|
+
branchId?: string | null;
|
|
33
|
+
}) => Promise<LoanRef[]>;
|
|
34
|
+
};
|
|
35
|
+
loanBoardService: {
|
|
36
|
+
listLoanBoard: (scope: {
|
|
37
|
+
tenantId: string;
|
|
38
|
+
branchId?: string | null;
|
|
39
|
+
}, options?: {
|
|
40
|
+
memberId?: string;
|
|
41
|
+
}) => Promise<LoanBoardItemRef[]>;
|
|
42
|
+
};
|
|
43
|
+
loanDueWindowService: {
|
|
44
|
+
listLoansDueInWindow: (scope: {
|
|
45
|
+
tenantId: string;
|
|
46
|
+
branchId?: string | null;
|
|
47
|
+
}, input: {
|
|
48
|
+
dateFrom: string;
|
|
49
|
+
dateTo: string;
|
|
50
|
+
memberId?: string;
|
|
51
|
+
}) => Promise<LoanDueWindowItemRef[]>;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export declare function createOfcoopCreditCompositionProviders(credit: CreditServicesRef): {
|
|
55
|
+
member360: Pick<Member360Providers, 'getCreditByMember' | 'getSettlementSummaryByMember'>;
|
|
56
|
+
dashboard: Pick<DashboardSummaryProviders, 'getLoanStatusComposition' | 'getLoanAgingBuckets' | 'getTotalOverdueAmount' | 'getAnggotaCreditSummary' | 'getLoanRiskMap'>;
|
|
57
|
+
report: Pick<ReportSummaryProviders, 'getCreditSummary'>;
|
|
58
|
+
};
|
|
59
|
+
export {};
|