vr-commons 1.0.139 → 1.0.140
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.
|
@@ -37,10 +37,12 @@ export declare const DPP_OperationsUtil: {
|
|
|
37
37
|
};
|
|
38
38
|
/**
|
|
39
39
|
* Generate installments for a hire purchase plan
|
|
40
|
+
* ✅ Updated to use unitPrice and create one installment at a time
|
|
40
41
|
*/
|
|
41
42
|
generateInstallments(plan: DevicePaymentPlan, transaction?: Transaction): Promise<void>;
|
|
42
43
|
/**
|
|
43
44
|
* Format plan for operation response
|
|
45
|
+
* ✅ Updated to use unitPrice and totalAmount
|
|
44
46
|
*/
|
|
45
47
|
formatPlanForOps(plan: DevicePaymentPlan | null): any;
|
|
46
48
|
};
|
|
@@ -75,7 +75,7 @@ exports.DPP_OperationsUtil = {
|
|
|
75
75
|
}
|
|
76
76
|
// For now, require exact installment amount
|
|
77
77
|
// Could be modified to allow overpayment later
|
|
78
|
-
if (amount !== nextInstallment.amount) {
|
|
78
|
+
if (amount !== Number(nextInstallment.amount)) {
|
|
79
79
|
return {
|
|
80
80
|
valid: false,
|
|
81
81
|
reason: `Payment amount must equal the next installment amount of ${nextInstallment.amount}`,
|
|
@@ -88,12 +88,13 @@ exports.DPP_OperationsUtil = {
|
|
|
88
88
|
* Calculate new values after payment
|
|
89
89
|
*/
|
|
90
90
|
calculatePaymentEffects(plan, amount) {
|
|
91
|
-
|
|
92
|
-
const
|
|
91
|
+
// ✅ Use plan.totalAmount instead of pricingSnapshot.totalAmount
|
|
92
|
+
const totalAmount = Number(plan.totalAmount) || 0;
|
|
93
|
+
const newPaidAmount = Number(plan.paidAmount) + amount;
|
|
94
|
+
const newOutstandingAmount = Math.max(0, totalAmount - newPaidAmount);
|
|
93
95
|
const wasCompleted = plan.status === "COMPLETED";
|
|
94
96
|
const isNowCompleted = newOutstandingAmount <= 0;
|
|
95
|
-
const
|
|
96
|
-
const progress = (newPaidAmount / totalAmount) * 100;
|
|
97
|
+
const progress = totalAmount > 0 ? (newPaidAmount / totalAmount) * 100 : 0;
|
|
97
98
|
return {
|
|
98
99
|
newPaidAmount,
|
|
99
100
|
newOutstandingAmount,
|
|
@@ -104,6 +105,7 @@ exports.DPP_OperationsUtil = {
|
|
|
104
105
|
},
|
|
105
106
|
/**
|
|
106
107
|
* Generate installments for a hire purchase plan
|
|
108
|
+
* ✅ Updated to use unitPrice and create one installment at a time
|
|
107
109
|
*/
|
|
108
110
|
async generateInstallments(plan, transaction) {
|
|
109
111
|
const pricing = plan.pricingSnapshot;
|
|
@@ -112,7 +114,10 @@ exports.DPP_OperationsUtil = {
|
|
|
112
114
|
}
|
|
113
115
|
const InstallmentModel = vr_models_1.Installment;
|
|
114
116
|
const installments = [];
|
|
115
|
-
|
|
117
|
+
// ✅ Get device count from plan
|
|
118
|
+
const deviceCount = plan.devices?.length || 1;
|
|
119
|
+
const installmentAmount = Number(pricing.installmentAmount) * deviceCount;
|
|
120
|
+
const dueDate = new Date();
|
|
116
121
|
if (pricing.installmentFrequency === "DAILY") {
|
|
117
122
|
dueDate.setDate(dueDate.getDate() + 1);
|
|
118
123
|
}
|
|
@@ -122,33 +127,29 @@ exports.DPP_OperationsUtil = {
|
|
|
122
127
|
else if (pricing.installmentFrequency === "MONTHLY") {
|
|
123
128
|
dueDate.setMonth(dueDate.getMonth() + 1);
|
|
124
129
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
else if (pricing.installmentFrequency === "MONTHLY") {
|
|
142
|
-
dueDate.setMonth(dueDate.getMonth() + 1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
await InstallmentModel.bulkCreate(installments, { transaction });
|
|
130
|
+
// ✅ Create only the first installment (not all at once)
|
|
131
|
+
const firstInstallment = {
|
|
132
|
+
devicePaymentPlanId: plan.id,
|
|
133
|
+
installmentNumber: 1,
|
|
134
|
+
amount: installmentAmount,
|
|
135
|
+
paidAmount: 0.0,
|
|
136
|
+
dueDate: new Date(dueDate),
|
|
137
|
+
status: "PENDING",
|
|
138
|
+
isAutoGenerated: true,
|
|
139
|
+
metadata: {
|
|
140
|
+
totalInstallments: pricing.installmentCount,
|
|
141
|
+
remainingInstallments: pricing.installmentCount - 1,
|
|
142
|
+
createdAt: new Date().toISOString(),
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
await InstallmentModel.create(firstInstallment, { transaction });
|
|
146
146
|
// Set the first installment as next due
|
|
147
|
-
plan.nextInstallmentDueAt =
|
|
147
|
+
plan.nextInstallmentDueAt = firstInstallment.dueDate;
|
|
148
148
|
await plan.save({ transaction });
|
|
149
149
|
},
|
|
150
150
|
/**
|
|
151
151
|
* Format plan for operation response
|
|
152
|
+
* ✅ Updated to use unitPrice and totalAmount
|
|
152
153
|
*/
|
|
153
154
|
formatPlanForOps(plan) {
|
|
154
155
|
if (!plan)
|
|
@@ -158,6 +159,7 @@ exports.DPP_OperationsUtil = {
|
|
|
158
159
|
id: plan.id,
|
|
159
160
|
userId: plan.userId,
|
|
160
161
|
pricingSnapshot: plan.pricingSnapshot,
|
|
162
|
+
totalAmount: plan.totalAmount, // ✅ Added
|
|
161
163
|
paidAmount: plan.paidAmount,
|
|
162
164
|
outstandingAmount: plan.outstandingAmount,
|
|
163
165
|
lastPaymentAt: plan.lastPaymentAt,
|
|
@@ -170,21 +172,27 @@ exports.DPP_OperationsUtil = {
|
|
|
170
172
|
user: plan.user || null,
|
|
171
173
|
installments: plan.installments || [],
|
|
172
174
|
};
|
|
173
|
-
|
|
175
|
+
// ✅ Use plan.totalAmount instead of pricingSnapshot.totalAmount
|
|
176
|
+
const totalAmount = Number(planData.totalAmount) || 0;
|
|
174
177
|
const hasInstallments = (planData.installments?.length ?? 0) > 0;
|
|
175
178
|
return {
|
|
176
179
|
id: planData.id,
|
|
177
180
|
userId: planData.userId,
|
|
178
181
|
pricingSnapshot: {
|
|
182
|
+
id: planData.pricingSnapshot?.id || null,
|
|
183
|
+
name: planData.pricingSnapshot?.name || null,
|
|
179
184
|
type: planData.pricingSnapshot?.type || null,
|
|
180
|
-
|
|
185
|
+
unitPrice: planData.pricingSnapshot?.unitPrice || 0, // ✅ Changed from totalAmount
|
|
181
186
|
downPayment: planData.pricingSnapshot?.downPayment || 0,
|
|
182
187
|
installmentAmount: planData.pricingSnapshot?.installmentAmount || null,
|
|
183
188
|
installmentFrequency: planData.pricingSnapshot?.installmentFrequency || null,
|
|
184
189
|
installmentCount: planData.pricingSnapshot?.installmentCount || null,
|
|
185
190
|
gracePeriodDays: planData.pricingSnapshot?.gracePeriodDays || 2,
|
|
186
191
|
autoLockOnMiss: planData.pricingSnapshot?.autoLockOnMiss ?? true,
|
|
192
|
+
minOrderQuantity: planData.pricingSnapshot?.minOrderQuantity || 1,
|
|
193
|
+
maxOrderQuantity: planData.pricingSnapshot?.maxOrderQuantity || 1,
|
|
187
194
|
},
|
|
195
|
+
totalAmount: totalAmount, // ✅ Added
|
|
188
196
|
paidAmount: planData.paidAmount || 0,
|
|
189
197
|
outstandingAmount: planData.outstandingAmount || 0,
|
|
190
198
|
lastPaymentAt: planData.lastPaymentAt,
|
|
@@ -196,9 +204,9 @@ exports.DPP_OperationsUtil = {
|
|
|
196
204
|
devices: planData.devices || [],
|
|
197
205
|
user: planData.user || null,
|
|
198
206
|
installments: planData.installments || [],
|
|
199
|
-
progress: totalAmount > 0 ? (plan.paidAmount / totalAmount) * 100 : 0,
|
|
200
|
-
canEdit: plan.paidAmount === 0,
|
|
201
|
-
canDelete: plan.paidAmount === 0,
|
|
207
|
+
progress: totalAmount > 0 ? (Number(plan.paidAmount) / totalAmount) * 100 : 0,
|
|
208
|
+
canEdit: Number(plan.paidAmount) === 0,
|
|
209
|
+
canDelete: Number(plan.paidAmount) === 0,
|
|
202
210
|
isOverdue: false,
|
|
203
211
|
hasInstallments,
|
|
204
212
|
};
|