ofcoop-credit-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 +17 -0
- package/dist/OfcoopCreditCore.d.ts +60 -0
- package/dist/OfcoopCreditCore.js +273 -0
- package/dist/contracts/CreditPolicyContract.d.ts +37 -0
- package/dist/contracts/CreditPolicyContract.js +2 -0
- package/dist/contracts/InstallmentContract.d.ts +39 -0
- package/dist/contracts/InstallmentContract.js +2 -0
- package/dist/contracts/LoanBoardContract.d.ts +24 -0
- package/dist/contracts/LoanBoardContract.js +2 -0
- package/dist/contracts/LoanContract.d.ts +36 -0
- package/dist/contracts/LoanContract.js +2 -0
- package/dist/contracts/LoanDueWindowContract.d.ts +25 -0
- package/dist/contracts/LoanDueWindowContract.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 +39 -0
- package/dist/data/repositories.js +167 -0
- package/dist/data/schemas.d.ts +8 -0
- package/dist/data/schemas.js +70 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +34 -0
- package/dist/services/CreditOrchestrationService.d.ts +32 -0
- package/dist/services/CreditOrchestrationService.js +27 -0
- package/dist/services/CreditPolicyService.d.ts +4 -0
- package/dist/services/CreditPolicyService.js +14 -0
- package/dist/services/DailyCreditOpsService.d.ts +2 -0
- package/dist/services/DailyCreditOpsService.js +7 -0
- package/dist/services/InstallmentService.d.ts +4 -0
- package/dist/services/InstallmentService.js +6 -0
- package/dist/services/LoanBoardService.d.ts +4 -0
- package/dist/services/LoanBoardService.js +6 -0
- package/dist/services/LoanDueWindowService.d.ts +4 -0
- package/dist/services/LoanDueWindowService.js +6 -0
- package/dist/services/LoanService.d.ts +4 -0
- package/dist/services/LoanService.js +16 -0
- package/dist/services/createDbAdapterOfcoopCreditServices.d.ts +16 -0
- package/dist/services/createDbAdapterOfcoopCreditServices.js +19 -0
- package/dist/services/errors.d.ts +8 -0
- package/dist/services/errors.js +23 -0
- package/dist/services/impl/DbAdapterCreditPolicyService.d.ts +12 -0
- package/dist/services/impl/DbAdapterCreditPolicyService.js +61 -0
- package/dist/services/impl/DbAdapterInstallmentService.d.ts +16 -0
- package/dist/services/impl/DbAdapterInstallmentService.js +129 -0
- package/dist/services/impl/DbAdapterLoanBoardService.d.ts +7 -0
- package/dist/services/impl/DbAdapterLoanBoardService.js +44 -0
- package/dist/services/impl/DbAdapterLoanDueWindowService.d.ts +7 -0
- package/dist/services/impl/DbAdapterLoanDueWindowService.js +48 -0
- package/dist/services/impl/DbAdapterLoanService.d.ts +13 -0
- package/dist/services/impl/DbAdapterLoanService.js +74 -0
- package/dist/services/impl/runtimeSupport.d.ts +18 -0
- package/dist/services/impl/runtimeSupport.js +29 -0
- package/package.json +40 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CreditPolicyRepository = exports.InstallmentRepository = exports.LoanRepository = void 0;
|
|
4
|
+
exports.createOfcoopCreditRepositories = createOfcoopCreditRepositories;
|
|
5
|
+
const schemas_1 = require("./schemas");
|
|
6
|
+
function toAnd(filters) {
|
|
7
|
+
if (filters.length === 0)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (filters.length === 1)
|
|
10
|
+
return filters[0];
|
|
11
|
+
return { and: filters };
|
|
12
|
+
}
|
|
13
|
+
class LoanRepository {
|
|
14
|
+
constructor(db) {
|
|
15
|
+
this.db = db;
|
|
16
|
+
}
|
|
17
|
+
async create(row) {
|
|
18
|
+
return this.db.create(schemas_1.OFCOOP_CREDIT_TABLES.loans, row);
|
|
19
|
+
}
|
|
20
|
+
async update(id, updates) {
|
|
21
|
+
return this.db.update(schemas_1.OFCOOP_CREDIT_TABLES.loans, id, updates);
|
|
22
|
+
}
|
|
23
|
+
async getById(id) {
|
|
24
|
+
return this.db.get(schemas_1.OFCOOP_CREDIT_TABLES.loans, id);
|
|
25
|
+
}
|
|
26
|
+
async listByMember(memberId, options) {
|
|
27
|
+
const filters = [{ memberId }];
|
|
28
|
+
if (!options?.includeDeleted)
|
|
29
|
+
filters.push({ deleted: false });
|
|
30
|
+
if (options?.status)
|
|
31
|
+
filters.push({ status: options.status });
|
|
32
|
+
if (options?.tenantId !== undefined)
|
|
33
|
+
filters.push({ tenantId: options.tenantId ?? null });
|
|
34
|
+
if (options?.branchId !== undefined)
|
|
35
|
+
filters.push({ branchId: options.branchId ?? null });
|
|
36
|
+
return this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.loans, {
|
|
37
|
+
filters: toAnd(filters),
|
|
38
|
+
sort: [{ field: 'lastModified', direction: 'desc' }],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async list(options) {
|
|
42
|
+
const filters = [];
|
|
43
|
+
if (!options?.includeDeleted)
|
|
44
|
+
filters.push({ deleted: false });
|
|
45
|
+
if (options?.status)
|
|
46
|
+
filters.push({ status: options.status });
|
|
47
|
+
if (options?.tenantId !== undefined)
|
|
48
|
+
filters.push({ tenantId: options.tenantId ?? null });
|
|
49
|
+
if (options?.branchId !== undefined)
|
|
50
|
+
filters.push({ branchId: options.branchId ?? null });
|
|
51
|
+
return this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.loans, {
|
|
52
|
+
filters: toAnd(filters),
|
|
53
|
+
sort: [{ field: 'lastModified', direction: 'desc' }],
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.LoanRepository = LoanRepository;
|
|
58
|
+
class InstallmentRepository {
|
|
59
|
+
constructor(db) {
|
|
60
|
+
this.db = db;
|
|
61
|
+
}
|
|
62
|
+
async createMany(rows) {
|
|
63
|
+
if (rows.length === 0)
|
|
64
|
+
return [];
|
|
65
|
+
return this.db.bulkCreate(schemas_1.OFCOOP_CREDIT_TABLES.installments, rows);
|
|
66
|
+
}
|
|
67
|
+
async update(id, updates) {
|
|
68
|
+
return this.db.update(schemas_1.OFCOOP_CREDIT_TABLES.installments, id, updates);
|
|
69
|
+
}
|
|
70
|
+
async listByLoan(loanId, options) {
|
|
71
|
+
const filters = [{ loanId }];
|
|
72
|
+
if (!options?.includeDeleted)
|
|
73
|
+
filters.push({ deleted: false });
|
|
74
|
+
if (options?.status)
|
|
75
|
+
filters.push({ status: options.status });
|
|
76
|
+
if (options?.dueDateFrom)
|
|
77
|
+
filters.push({ field: 'dueDate', operator: '>=', value: options.dueDateFrom });
|
|
78
|
+
if (options?.dueDateTo)
|
|
79
|
+
filters.push({ field: 'dueDate', operator: '<=', value: options.dueDateTo });
|
|
80
|
+
return this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.installments, {
|
|
81
|
+
filters: toAnd(filters),
|
|
82
|
+
sort: [{ field: 'installmentNo', direction: 'asc' }],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
async list(options) {
|
|
86
|
+
const filters = [];
|
|
87
|
+
if (options?.loanId)
|
|
88
|
+
filters.push({ loanId: options.loanId });
|
|
89
|
+
if (!options?.includeDeleted)
|
|
90
|
+
filters.push({ deleted: false });
|
|
91
|
+
if (options?.status)
|
|
92
|
+
filters.push({ status: options.status });
|
|
93
|
+
if (options?.dueDateFrom)
|
|
94
|
+
filters.push({ field: 'dueDate', operator: '>=', value: options.dueDateFrom });
|
|
95
|
+
if (options?.dueDateTo)
|
|
96
|
+
filters.push({ field: 'dueDate', operator: '<=', value: options.dueDateTo });
|
|
97
|
+
return this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.installments, {
|
|
98
|
+
filters: toAnd(filters),
|
|
99
|
+
sort: [{ field: 'dueDate', direction: 'asc' }],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async getByLoanAndInstallmentNo(loanId, installmentNo) {
|
|
103
|
+
const rows = await this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.installments, {
|
|
104
|
+
filters: {
|
|
105
|
+
and: [
|
|
106
|
+
{ deleted: false },
|
|
107
|
+
{ loanId },
|
|
108
|
+
{ installmentNo },
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
sort: [{ field: 'lastModified', direction: 'desc' }],
|
|
112
|
+
limit: 1,
|
|
113
|
+
});
|
|
114
|
+
return rows[0] ?? null;
|
|
115
|
+
}
|
|
116
|
+
async listOverdue(options) {
|
|
117
|
+
const filters = [{ status: 'overdue' }];
|
|
118
|
+
if (!options?.includeDeleted)
|
|
119
|
+
filters.push({ deleted: false });
|
|
120
|
+
if (options?.dueDateFrom)
|
|
121
|
+
filters.push({ field: 'dueDate', operator: '>=', value: options.dueDateFrom });
|
|
122
|
+
if (options?.dueDateTo)
|
|
123
|
+
filters.push({ field: 'dueDate', operator: '<=', value: options.dueDateTo });
|
|
124
|
+
return this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.installments, {
|
|
125
|
+
filters: toAnd(filters),
|
|
126
|
+
sort: [{ field: 'dueDate', direction: 'asc' }],
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.InstallmentRepository = InstallmentRepository;
|
|
131
|
+
class CreditPolicyRepository {
|
|
132
|
+
constructor(db) {
|
|
133
|
+
this.db = db;
|
|
134
|
+
}
|
|
135
|
+
async create(row) {
|
|
136
|
+
return this.db.create(schemas_1.OFCOOP_CREDIT_TABLES.creditPolicies, row);
|
|
137
|
+
}
|
|
138
|
+
async update(id, updates) {
|
|
139
|
+
return this.db.update(schemas_1.OFCOOP_CREDIT_TABLES.creditPolicies, id, updates);
|
|
140
|
+
}
|
|
141
|
+
async getById(id) {
|
|
142
|
+
return this.db.get(schemas_1.OFCOOP_CREDIT_TABLES.creditPolicies, id);
|
|
143
|
+
}
|
|
144
|
+
async getActive(scope) {
|
|
145
|
+
const rows = await this.db.query(schemas_1.OFCOOP_CREDIT_TABLES.creditPolicies, {
|
|
146
|
+
filters: {
|
|
147
|
+
and: [
|
|
148
|
+
{ deleted: false },
|
|
149
|
+
{ isActive: true },
|
|
150
|
+
{ tenantId: scope.tenantId },
|
|
151
|
+
{ branchId: scope.branchId ?? null },
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
sort: [{ field: 'lastModified', direction: 'desc' }],
|
|
155
|
+
limit: 1,
|
|
156
|
+
});
|
|
157
|
+
return rows[0] ?? null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
exports.CreditPolicyRepository = CreditPolicyRepository;
|
|
161
|
+
function createOfcoopCreditRepositories(db) {
|
|
162
|
+
return {
|
|
163
|
+
loanRepository: new LoanRepository(db),
|
|
164
|
+
installmentRepository: new InstallmentRepository(db),
|
|
165
|
+
creditPolicyRepository: new CreditPolicyRepository(db),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DbSchema, TableSchema } from 'ofcore';
|
|
2
|
+
export declare const OFCOOP_CREDIT_TABLES: {
|
|
3
|
+
readonly loans: "ofcoop_credit_loans";
|
|
4
|
+
readonly installments: "ofcoop_credit_installments";
|
|
5
|
+
readonly creditPolicies: "ofcoop_credit_policies";
|
|
6
|
+
};
|
|
7
|
+
export declare const ofcoopCreditSchema: DbSchema;
|
|
8
|
+
export declare function getOfcoopCreditTableSchemas(): TableSchema[];
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ofcoopCreditSchema = exports.OFCOOP_CREDIT_TABLES = void 0;
|
|
4
|
+
exports.getOfcoopCreditTableSchemas = getOfcoopCreditTableSchemas;
|
|
5
|
+
exports.OFCOOP_CREDIT_TABLES = {
|
|
6
|
+
loans: 'ofcoop_credit_loans',
|
|
7
|
+
installments: 'ofcoop_credit_installments',
|
|
8
|
+
creditPolicies: 'ofcoop_credit_policies',
|
|
9
|
+
};
|
|
10
|
+
const tableSchemas = [
|
|
11
|
+
{
|
|
12
|
+
name: exports.OFCOOP_CREDIT_TABLES.loans,
|
|
13
|
+
columns: [
|
|
14
|
+
{ name: 'id', type: 'string' },
|
|
15
|
+
{ name: 'memberId', type: 'string', isIndexed: true },
|
|
16
|
+
{ name: 'principalAmount', type: 'number' },
|
|
17
|
+
{ name: 'tenorMonths', type: 'number' },
|
|
18
|
+
{ name: 'serviceRate', type: 'number' },
|
|
19
|
+
{ name: 'startDate', type: 'string' },
|
|
20
|
+
{ name: 'status', type: 'string', enum: ['active', 'closed', 'defaulted'], isIndexed: true },
|
|
21
|
+
{ name: 'branchId', type: 'string', isOptional: true, isIndexed: true },
|
|
22
|
+
{ name: 'tenantId', type: 'string', isOptional: true, isIndexed: true },
|
|
23
|
+
{ name: 'version', type: 'number' },
|
|
24
|
+
{ name: 'lastModified', type: 'string' },
|
|
25
|
+
{ name: 'deleted', type: 'boolean', isIndexed: true },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: exports.OFCOOP_CREDIT_TABLES.installments,
|
|
30
|
+
columns: [
|
|
31
|
+
{ name: 'id', type: 'string' },
|
|
32
|
+
{ name: 'loanId', type: 'string', isIndexed: true },
|
|
33
|
+
{ name: 'installmentNo', type: 'number' },
|
|
34
|
+
{ name: 'dueDate', type: 'string', isIndexed: true },
|
|
35
|
+
{ name: 'principalDue', type: 'number' },
|
|
36
|
+
{ name: 'serviceDue', type: 'number' },
|
|
37
|
+
{ name: 'penaltyDue', type: 'number' },
|
|
38
|
+
{ name: 'paidAmount', type: 'number' },
|
|
39
|
+
{ name: 'status', type: 'string', enum: ['scheduled', 'partial', 'paid', 'overdue'], isIndexed: true },
|
|
40
|
+
{ name: 'branchId', type: 'string', isOptional: true, isIndexed: true },
|
|
41
|
+
{ name: 'tenantId', type: 'string', isOptional: true, isIndexed: true },
|
|
42
|
+
{ name: 'version', type: 'number' },
|
|
43
|
+
{ name: 'lastModified', type: 'string' },
|
|
44
|
+
{ name: 'deleted', type: 'boolean', isIndexed: true },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: exports.OFCOOP_CREDIT_TABLES.creditPolicies,
|
|
49
|
+
columns: [
|
|
50
|
+
{ name: 'id', type: 'string' },
|
|
51
|
+
{ name: 'policyCode', type: 'string', isIndexed: true },
|
|
52
|
+
{ name: 'penaltyRatePerDay', type: 'number' },
|
|
53
|
+
{ name: 'gracePeriodDays', type: 'number' },
|
|
54
|
+
{ name: 'maxTenorMonths', type: 'number' },
|
|
55
|
+
{ name: 'isActive', type: 'boolean', isIndexed: true },
|
|
56
|
+
{ name: 'branchId', type: 'string', isOptional: true, isIndexed: true },
|
|
57
|
+
{ name: 'tenantId', type: 'string', isOptional: true, isIndexed: true },
|
|
58
|
+
{ name: 'version', type: 'number' },
|
|
59
|
+
{ name: 'lastModified', type: 'string' },
|
|
60
|
+
{ name: 'deleted', type: 'boolean', isIndexed: true },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
exports.ofcoopCreditSchema = {
|
|
65
|
+
version: 1,
|
|
66
|
+
tables: tableSchemas,
|
|
67
|
+
};
|
|
68
|
+
function getOfcoopCreditTableSchemas() {
|
|
69
|
+
return exports.ofcoopCreditSchema.tables;
|
|
70
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './contracts/LoanContract';
|
|
2
|
+
export * from './contracts/InstallmentContract';
|
|
3
|
+
export * from './contracts/CreditPolicyContract';
|
|
4
|
+
export * from './contracts/LoanBoardContract';
|
|
5
|
+
export * from './contracts/LoanDueWindowContract';
|
|
6
|
+
export * from './OfcoopCreditCore';
|
|
7
|
+
export * from './services/LoanService';
|
|
8
|
+
export * from './services/InstallmentService';
|
|
9
|
+
export * from './services/CreditPolicyService';
|
|
10
|
+
export * from './services/LoanBoardService';
|
|
11
|
+
export * from './services/LoanDueWindowService';
|
|
12
|
+
export * from './services/CreditOrchestrationService';
|
|
13
|
+
export * from './services/errors';
|
|
14
|
+
export * from './services/createDbAdapterOfcoopCreditServices';
|
|
15
|
+
export * from './data/schemas';
|
|
16
|
+
export * from './data/migrations';
|
|
17
|
+
export * from './data/applyPendingMigrations';
|
|
18
|
+
export * from './data/repositories';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./contracts/LoanContract"), exports);
|
|
18
|
+
__exportStar(require("./contracts/InstallmentContract"), exports);
|
|
19
|
+
__exportStar(require("./contracts/CreditPolicyContract"), exports);
|
|
20
|
+
__exportStar(require("./contracts/LoanBoardContract"), exports);
|
|
21
|
+
__exportStar(require("./contracts/LoanDueWindowContract"), exports);
|
|
22
|
+
__exportStar(require("./OfcoopCreditCore"), exports);
|
|
23
|
+
__exportStar(require("./services/LoanService"), exports);
|
|
24
|
+
__exportStar(require("./services/InstallmentService"), exports);
|
|
25
|
+
__exportStar(require("./services/CreditPolicyService"), exports);
|
|
26
|
+
__exportStar(require("./services/LoanBoardService"), exports);
|
|
27
|
+
__exportStar(require("./services/LoanDueWindowService"), exports);
|
|
28
|
+
__exportStar(require("./services/CreditOrchestrationService"), exports);
|
|
29
|
+
__exportStar(require("./services/errors"), exports);
|
|
30
|
+
__exportStar(require("./services/createDbAdapterOfcoopCreditServices"), exports);
|
|
31
|
+
__exportStar(require("./data/schemas"), exports);
|
|
32
|
+
__exportStar(require("./data/migrations"), exports);
|
|
33
|
+
__exportStar(require("./data/applyPendingMigrations"), exports);
|
|
34
|
+
__exportStar(require("./data/repositories"), exports);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { InstallmentContract, InstallmentServiceContract, RecordInstallmentPaymentInput } from '../contracts/InstallmentContract';
|
|
2
|
+
import type { CreateLoanInput, LoanContract, LoanServiceContract } from '../contracts/LoanContract';
|
|
3
|
+
import type { LoanBoardItemContract, LoanBoardScope, LoanBoardServiceContract } from '../contracts/LoanBoardContract';
|
|
4
|
+
import type { LoanDueWindowItemContract, LoanDueWindowQueryInput, LoanDueWindowScope, LoanDueWindowServiceContract } from '../contracts/LoanDueWindowContract';
|
|
5
|
+
export interface CreditOrchestrationDependencies {
|
|
6
|
+
loanService: LoanServiceContract;
|
|
7
|
+
installmentService: InstallmentServiceContract;
|
|
8
|
+
loanBoardService: LoanBoardServiceContract;
|
|
9
|
+
loanDueWindowService: LoanDueWindowServiceContract;
|
|
10
|
+
}
|
|
11
|
+
export interface CreateLoanWithScheduleResult {
|
|
12
|
+
loan: LoanContract;
|
|
13
|
+
installments: InstallmentContract[];
|
|
14
|
+
}
|
|
15
|
+
export declare function createLoanWithSchedule(deps: Pick<CreditOrchestrationDependencies, 'loanService' | 'installmentService'>, input: CreateLoanInput): Promise<CreateLoanWithScheduleResult>;
|
|
16
|
+
export interface RecordPaymentAndBoardResult {
|
|
17
|
+
installment: InstallmentContract;
|
|
18
|
+
board: LoanBoardItemContract[];
|
|
19
|
+
}
|
|
20
|
+
export declare function recordPaymentAndRefreshBoard(deps: Pick<CreditOrchestrationDependencies, 'installmentService' | 'loanBoardService'>, payment: RecordInstallmentPaymentInput, scope: LoanBoardScope): Promise<RecordPaymentAndBoardResult>;
|
|
21
|
+
export interface MemberCreditDashboardInput {
|
|
22
|
+
memberId: string;
|
|
23
|
+
boardScope: LoanBoardScope;
|
|
24
|
+
dueScope: LoanDueWindowScope;
|
|
25
|
+
dueWindow: LoanDueWindowQueryInput;
|
|
26
|
+
}
|
|
27
|
+
export interface MemberCreditDashboardResult {
|
|
28
|
+
board: LoanBoardItemContract[];
|
|
29
|
+
dueWindowItems: LoanDueWindowItemContract[];
|
|
30
|
+
loans: LoanContract[];
|
|
31
|
+
}
|
|
32
|
+
export declare function getMemberCreditDashboard(deps: CreditOrchestrationDependencies, input: MemberCreditDashboardInput): Promise<MemberCreditDashboardResult>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLoanWithSchedule = createLoanWithSchedule;
|
|
4
|
+
exports.recordPaymentAndRefreshBoard = recordPaymentAndRefreshBoard;
|
|
5
|
+
exports.getMemberCreditDashboard = getMemberCreditDashboard;
|
|
6
|
+
async function createLoanWithSchedule(deps, input) {
|
|
7
|
+
const loan = await deps.loanService.createLoan(input);
|
|
8
|
+
const installments = await deps.installmentService.generateInstallmentSchedule(loan.id);
|
|
9
|
+
return { loan, installments };
|
|
10
|
+
}
|
|
11
|
+
async function recordPaymentAndRefreshBoard(deps, payment, scope) {
|
|
12
|
+
const installment = await deps.installmentService.recordInstallmentPayment(payment);
|
|
13
|
+
const board = await deps.loanBoardService.listLoanBoard(scope, { memberId: undefined });
|
|
14
|
+
return { installment, board };
|
|
15
|
+
}
|
|
16
|
+
async function getMemberCreditDashboard(deps, input) {
|
|
17
|
+
const board = await deps.loanBoardService.listLoanBoard(input.boardScope, { memberId: input.memberId });
|
|
18
|
+
const dueWindowItems = await deps.loanDueWindowService.listLoansDueInWindow(input.dueScope, {
|
|
19
|
+
...input.dueWindow,
|
|
20
|
+
memberId: input.memberId,
|
|
21
|
+
});
|
|
22
|
+
const loans = await deps.loanService.listLoansByMember(input.memberId, {
|
|
23
|
+
tenantId: input.boardScope.tenantId ?? null,
|
|
24
|
+
branchId: input.boardScope.branchId ?? null,
|
|
25
|
+
});
|
|
26
|
+
return { board, dueWindowItems, loans };
|
|
27
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CreateCreditPolicyInput, CreditPolicyServiceContract } from '../contracts/CreditPolicyContract';
|
|
2
|
+
export interface CreditPolicyService extends CreditPolicyServiceContract {
|
|
3
|
+
}
|
|
4
|
+
export declare function assertValidCreateCreditPolicyInput(input: CreateCreditPolicyInput): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidCreateCreditPolicyInput = assertValidCreateCreditPolicyInput;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
function assertValidCreateCreditPolicyInput(input) {
|
|
6
|
+
if (!input.policyCode?.trim())
|
|
7
|
+
throw (0, errors_1.invalidState)('policyCode is required');
|
|
8
|
+
if (input.penaltyRatePerDay < 0)
|
|
9
|
+
throw (0, errors_1.invalidState)('penaltyRatePerDay must be >= 0');
|
|
10
|
+
if (input.gracePeriodDays < 0)
|
|
11
|
+
throw (0, errors_1.invalidState)('gracePeriodDays must be >= 0');
|
|
12
|
+
if (input.maxTenorMonths <= 0)
|
|
13
|
+
throw (0, errors_1.invalidState)('maxTenorMonths must be > 0');
|
|
14
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { CreditOrchestrationDependencies as DailyCreditOpsDependencies, CreateLoanWithScheduleResult, RecordPaymentAndBoardResult, MemberCreditDashboardInput, MemberCreditDashboardResult, } from './CreditOrchestrationService';
|
|
2
|
+
export { createLoanWithSchedule, recordPaymentAndRefreshBoard, getMemberCreditDashboard, } from './CreditOrchestrationService';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMemberCreditDashboard = exports.recordPaymentAndRefreshBoard = exports.createLoanWithSchedule = void 0;
|
|
4
|
+
var CreditOrchestrationService_1 = require("./CreditOrchestrationService");
|
|
5
|
+
Object.defineProperty(exports, "createLoanWithSchedule", { enumerable: true, get: function () { return CreditOrchestrationService_1.createLoanWithSchedule; } });
|
|
6
|
+
Object.defineProperty(exports, "recordPaymentAndRefreshBoard", { enumerable: true, get: function () { return CreditOrchestrationService_1.recordPaymentAndRefreshBoard; } });
|
|
7
|
+
Object.defineProperty(exports, "getMemberCreditDashboard", { enumerable: true, get: function () { return CreditOrchestrationService_1.getMemberCreditDashboard; } });
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { InstallmentContract, InstallmentServiceContract } from '../contracts/InstallmentContract';
|
|
2
|
+
export interface InstallmentService extends InstallmentServiceContract {
|
|
3
|
+
}
|
|
4
|
+
export declare function calculateInstallmentDueTotal(installment: Pick<InstallmentContract, 'principalDue' | 'serviceDue' | 'penaltyDue'>): number;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateInstallmentDueTotal = calculateInstallmentDueTotal;
|
|
4
|
+
function calculateInstallmentDueTotal(installment) {
|
|
5
|
+
return installment.principalDue + installment.serviceDue + installment.penaltyDue;
|
|
6
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidCreateLoanInput = assertValidCreateLoanInput;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
function assertValidCreateLoanInput(input) {
|
|
6
|
+
if (!input.memberId?.trim())
|
|
7
|
+
throw (0, errors_1.invalidState)('memberId is required');
|
|
8
|
+
if (!input.startDate?.trim())
|
|
9
|
+
throw (0, errors_1.invalidState)('startDate is required');
|
|
10
|
+
if (!input.tenantId?.trim())
|
|
11
|
+
throw (0, errors_1.invalidState)('tenantId is required');
|
|
12
|
+
if (input.principalAmount <= 0)
|
|
13
|
+
throw (0, errors_1.invalidState)('principalAmount must be > 0');
|
|
14
|
+
if (input.tenorMonths <= 0)
|
|
15
|
+
throw (0, errors_1.invalidState)('tenorMonths must be > 0');
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DbAdapter } from 'ofcore';
|
|
2
|
+
import type { CreditPolicyServiceContract } from '../contracts/CreditPolicyContract';
|
|
3
|
+
import type { InstallmentServiceContract } from '../contracts/InstallmentContract';
|
|
4
|
+
import type { LoanBoardServiceContract } from '../contracts/LoanBoardContract';
|
|
5
|
+
import type { LoanDueWindowServiceContract } from '../contracts/LoanDueWindowContract';
|
|
6
|
+
import type { LoanServiceContract } from '../contracts/LoanContract';
|
|
7
|
+
import type { ServiceRuntimeOptions } from './impl/runtimeSupport';
|
|
8
|
+
export type { OfcoopCreditDomainEvent, OfcoopCreditDomainEventName, ServiceRuntimeOptions } from './impl/runtimeSupport';
|
|
9
|
+
export interface OfcoopCreditDomainServices {
|
|
10
|
+
loanService: LoanServiceContract;
|
|
11
|
+
installmentService: InstallmentServiceContract;
|
|
12
|
+
creditPolicyService: CreditPolicyServiceContract;
|
|
13
|
+
loanBoardService: LoanBoardServiceContract;
|
|
14
|
+
loanDueWindowService: LoanDueWindowServiceContract;
|
|
15
|
+
}
|
|
16
|
+
export declare function createDbAdapterOfcoopCreditServices(dbAdapter: DbAdapter, options?: ServiceRuntimeOptions): Promise<OfcoopCreditDomainServices>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDbAdapterOfcoopCreditServices = createDbAdapterOfcoopCreditServices;
|
|
4
|
+
const repositories_1 = require("../data/repositories");
|
|
5
|
+
const DbAdapterCreditPolicyService_1 = require("./impl/DbAdapterCreditPolicyService");
|
|
6
|
+
const DbAdapterInstallmentService_1 = require("./impl/DbAdapterInstallmentService");
|
|
7
|
+
const DbAdapterLoanBoardService_1 = require("./impl/DbAdapterLoanBoardService");
|
|
8
|
+
const DbAdapterLoanDueWindowService_1 = require("./impl/DbAdapterLoanDueWindowService");
|
|
9
|
+
const DbAdapterLoanService_1 = require("./impl/DbAdapterLoanService");
|
|
10
|
+
async function createDbAdapterOfcoopCreditServices(dbAdapter, options = {}) {
|
|
11
|
+
const repositories = (0, repositories_1.createOfcoopCreditRepositories)(dbAdapter);
|
|
12
|
+
return {
|
|
13
|
+
loanService: new DbAdapterLoanService_1.DbAdapterLoanService(repositories, options),
|
|
14
|
+
installmentService: new DbAdapterInstallmentService_1.DbAdapterInstallmentService(dbAdapter, repositories, options),
|
|
15
|
+
creditPolicyService: new DbAdapterCreditPolicyService_1.DbAdapterCreditPolicyService(repositories, options),
|
|
16
|
+
loanBoardService: new DbAdapterLoanBoardService_1.DbAdapterLoanBoardService(repositories),
|
|
17
|
+
loanDueWindowService: new DbAdapterLoanDueWindowService_1.DbAdapterLoanDueWindowService(repositories),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type OfcoopCreditErrorCode = 'RESOURCE_NOT_FOUND' | 'CONFLICT' | 'INVALID_STATE';
|
|
2
|
+
export declare class OfcoopCreditDomainError extends Error {
|
|
3
|
+
readonly code: OfcoopCreditErrorCode;
|
|
4
|
+
constructor(code: OfcoopCreditErrorCode, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function notFound(entity: string, id: string): OfcoopCreditDomainError;
|
|
7
|
+
export declare function conflict(message: string): OfcoopCreditDomainError;
|
|
8
|
+
export declare function invalidState(message: string): OfcoopCreditDomainError;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OfcoopCreditDomainError = void 0;
|
|
4
|
+
exports.notFound = notFound;
|
|
5
|
+
exports.conflict = conflict;
|
|
6
|
+
exports.invalidState = invalidState;
|
|
7
|
+
class OfcoopCreditDomainError extends Error {
|
|
8
|
+
constructor(code, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.name = 'OfcoopCreditDomainError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.OfcoopCreditDomainError = OfcoopCreditDomainError;
|
|
15
|
+
function notFound(entity, id) {
|
|
16
|
+
return new OfcoopCreditDomainError('RESOURCE_NOT_FOUND', `${entity} not found: ${id}`);
|
|
17
|
+
}
|
|
18
|
+
function conflict(message) {
|
|
19
|
+
return new OfcoopCreditDomainError('CONFLICT', message);
|
|
20
|
+
}
|
|
21
|
+
function invalidState(message) {
|
|
22
|
+
return new OfcoopCreditDomainError('INVALID_STATE', message);
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CreateCreditPolicyInput, CreditPolicyContract, CreditPolicyScope, CreditPolicyServiceContract, UpdateCreditPolicyInput } from '../../contracts/CreditPolicyContract';
|
|
2
|
+
import type { OfcoopCreditRepositories } from '../../data/repositories';
|
|
3
|
+
import { type ServiceRuntimeOptions } from './runtimeSupport';
|
|
4
|
+
export declare class DbAdapterCreditPolicyService implements CreditPolicyServiceContract {
|
|
5
|
+
private readonly repos;
|
|
6
|
+
private readonly options;
|
|
7
|
+
private readonly newId;
|
|
8
|
+
constructor(repos: OfcoopCreditRepositories, options?: ServiceRuntimeOptions);
|
|
9
|
+
createCreditPolicy(input: CreateCreditPolicyInput): Promise<CreditPolicyContract>;
|
|
10
|
+
updateCreditPolicy(id: string, updates: UpdateCreditPolicyInput): Promise<CreditPolicyContract>;
|
|
11
|
+
getActiveCreditPolicy(scope: CreditPolicyScope): Promise<CreditPolicyContract | null>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DbAdapterCreditPolicyService = void 0;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const CreditPolicyService_1 = require("../CreditPolicyService");
|
|
6
|
+
const runtimeSupport_1 = require("./runtimeSupport");
|
|
7
|
+
class DbAdapterCreditPolicyService {
|
|
8
|
+
constructor(repos, options = {}) {
|
|
9
|
+
this.repos = repos;
|
|
10
|
+
this.options = options;
|
|
11
|
+
this.newId = (0, runtimeSupport_1.makeIdFactory)('credit-policy');
|
|
12
|
+
}
|
|
13
|
+
async createCreditPolicy(input) {
|
|
14
|
+
(0, CreditPolicyService_1.assertValidCreateCreditPolicyInput)(input);
|
|
15
|
+
const created = await this.repos.creditPolicyRepository.create({
|
|
16
|
+
id: this.newId(),
|
|
17
|
+
policyCode: input.policyCode,
|
|
18
|
+
penaltyRatePerDay: input.penaltyRatePerDay,
|
|
19
|
+
gracePeriodDays: input.gracePeriodDays,
|
|
20
|
+
maxTenorMonths: input.maxTenorMonths,
|
|
21
|
+
isActive: input.isActive ?? true,
|
|
22
|
+
branchId: input.branchId ?? null,
|
|
23
|
+
tenantId: input.tenantId ?? null,
|
|
24
|
+
version: 1,
|
|
25
|
+
lastModified: (0, runtimeSupport_1.nowIso)(),
|
|
26
|
+
deleted: false,
|
|
27
|
+
});
|
|
28
|
+
await (0, runtimeSupport_1.emitDomainEvent)(this.options, {
|
|
29
|
+
name: 'credit-policy.created',
|
|
30
|
+
occurredAt: (0, runtimeSupport_1.nowIso)(),
|
|
31
|
+
entityId: created.id,
|
|
32
|
+
tenantId: created.tenantId ?? null,
|
|
33
|
+
branchId: created.branchId ?? null,
|
|
34
|
+
payload: { policyCode: created.policyCode },
|
|
35
|
+
});
|
|
36
|
+
return created;
|
|
37
|
+
}
|
|
38
|
+
async updateCreditPolicy(id, updates) {
|
|
39
|
+
const current = await this.repos.creditPolicyRepository.getById(id);
|
|
40
|
+
if (!current || current.deleted)
|
|
41
|
+
throw (0, errors_1.notFound)('Credit policy', id);
|
|
42
|
+
const updated = await this.repos.creditPolicyRepository.update(id, {
|
|
43
|
+
...updates,
|
|
44
|
+
version: current.version + 1,
|
|
45
|
+
lastModified: (0, runtimeSupport_1.nowIso)(),
|
|
46
|
+
});
|
|
47
|
+
await (0, runtimeSupport_1.emitDomainEvent)(this.options, {
|
|
48
|
+
name: 'credit-policy.updated',
|
|
49
|
+
occurredAt: (0, runtimeSupport_1.nowIso)(),
|
|
50
|
+
entityId: updated.id,
|
|
51
|
+
tenantId: updated.tenantId ?? null,
|
|
52
|
+
branchId: updated.branchId ?? null,
|
|
53
|
+
payload: { policyCode: updated.policyCode },
|
|
54
|
+
});
|
|
55
|
+
return updated;
|
|
56
|
+
}
|
|
57
|
+
async getActiveCreditPolicy(scope) {
|
|
58
|
+
return this.repos.creditPolicyRepository.getActive(scope);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.DbAdapterCreditPolicyService = DbAdapterCreditPolicyService;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DbAdapter } from 'ofcore';
|
|
2
|
+
import type { InstallmentContract, InstallmentQueryOptions, InstallmentServiceContract, RecordInstallmentPaymentInput } from '../../contracts/InstallmentContract';
|
|
3
|
+
import { type OfcoopCreditRepositories } from '../../data/repositories';
|
|
4
|
+
import { type ServiceRuntimeOptions } from './runtimeSupport';
|
|
5
|
+
export declare class DbAdapterInstallmentService implements InstallmentServiceContract {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly repos;
|
|
8
|
+
private readonly options;
|
|
9
|
+
private readonly newId;
|
|
10
|
+
constructor(db: DbAdapter, repos: OfcoopCreditRepositories, options?: ServiceRuntimeOptions);
|
|
11
|
+
private inTx;
|
|
12
|
+
generateInstallmentSchedule(loanId: string): Promise<InstallmentContract[]>;
|
|
13
|
+
recordInstallmentPayment(input: RecordInstallmentPaymentInput): Promise<InstallmentContract>;
|
|
14
|
+
listInstallmentsByLoan(loanId: string, options?: InstallmentQueryOptions): Promise<InstallmentContract[]>;
|
|
15
|
+
listOverdueInstallments(options?: InstallmentQueryOptions): Promise<InstallmentContract[]>;
|
|
16
|
+
}
|