@ambushsoftworks/nestjs-payments-graphql 0.1.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.
Files changed (217) hide show
  1. package/dist/constants.d.ts +17 -0
  2. package/dist/constants.js +21 -0
  3. package/dist/constants.js.map +1 -0
  4. package/dist/dto/create-installment.input.d.ts +5 -0
  5. package/dist/dto/create-installment.input.js +39 -0
  6. package/dist/dto/create-installment.input.js.map +1 -0
  7. package/dist/dto/create-invoice.input.d.ts +13 -0
  8. package/dist/dto/create-invoice.input.js +95 -0
  9. package/dist/dto/create-invoice.input.js.map +1 -0
  10. package/dist/dto/create-line-item.input.d.ts +10 -0
  11. package/dist/dto/create-line-item.input.js +77 -0
  12. package/dist/dto/create-line-item.input.js.map +1 -0
  13. package/dist/dto/create-payment-plan.input.d.ts +11 -0
  14. package/dist/dto/create-payment-plan.input.js +76 -0
  15. package/dist/dto/create-payment-plan.input.js.map +1 -0
  16. package/dist/dto/create-recurring-invoice.input.d.ts +18 -0
  17. package/dist/dto/create-recurring-invoice.input.js +117 -0
  18. package/dist/dto/create-recurring-invoice.input.js.map +1 -0
  19. package/dist/dto/create-recurring-line-item.input.d.ts +10 -0
  20. package/dist/dto/create-recurring-line-item.input.js +77 -0
  21. package/dist/dto/create-recurring-line-item.input.js.map +1 -0
  22. package/dist/dto/create-refund.input.d.ts +5 -0
  23. package/dist/dto/create-refund.input.js +43 -0
  24. package/dist/dto/create-refund.input.js.map +1 -0
  25. package/dist/dto/index.d.ts +8 -0
  26. package/dist/dto/index.js +20 -0
  27. package/dist/dto/index.js.map +1 -0
  28. package/dist/dto/invoice-filter.input.d.ts +10 -0
  29. package/dist/dto/invoice-filter.input.js +64 -0
  30. package/dist/dto/invoice-filter.input.js.map +1 -0
  31. package/dist/dto/payment-plan-filter.input.d.ts +7 -0
  32. package/dist/dto/payment-plan-filter.input.js +46 -0
  33. package/dist/dto/payment-plan-filter.input.js.map +1 -0
  34. package/dist/dto/record-manual-payment.input.d.ts +9 -0
  35. package/dist/dto/record-manual-payment.input.js +58 -0
  36. package/dist/dto/record-manual-payment.input.js.map +1 -0
  37. package/dist/dto/recurring-invoice-filter.input.d.ts +7 -0
  38. package/dist/dto/recurring-invoice-filter.input.js +46 -0
  39. package/dist/dto/recurring-invoice-filter.input.js.map +1 -0
  40. package/dist/dto/update-invoice-metadata.input.d.ts +3 -0
  41. package/dist/dto/update-invoice-metadata.input.js +30 -0
  42. package/dist/dto/update-invoice-metadata.input.js.map +1 -0
  43. package/dist/dto/update-payment-config.input.d.ts +8 -0
  44. package/dist/dto/update-payment-config.input.js +61 -0
  45. package/dist/dto/update-payment-config.input.js.map +1 -0
  46. package/dist/dto/update-recurring-template.input.d.ts +12 -0
  47. package/dist/dto/update-recurring-template.input.js +89 -0
  48. package/dist/dto/update-recurring-template.input.js.map +1 -0
  49. package/dist/dto/upsert-payment-provider.input.d.ts +5 -0
  50. package/dist/dto/upsert-payment-provider.input.js +43 -0
  51. package/dist/dto/upsert-payment-provider.input.js.map +1 -0
  52. package/dist/dto/validators/is-metadata.d.ts +1 -0
  53. package/dist/dto/validators/is-metadata.js +41 -0
  54. package/dist/dto/validators/is-metadata.js.map +1 -0
  55. package/dist/exceptions/index.d.ts +34 -0
  56. package/dist/exceptions/index.js +73 -0
  57. package/dist/exceptions/index.js.map +1 -0
  58. package/dist/gateways/gateway-registry.service.d.ts +10 -0
  59. package/dist/gateways/gateway-registry.service.js +45 -0
  60. package/dist/gateways/gateway-registry.service.js.map +1 -0
  61. package/dist/gateways/payment-gateway.interface.d.ts +50 -0
  62. package/dist/gateways/payment-gateway.interface.js +3 -0
  63. package/dist/gateways/payment-gateway.interface.js.map +1 -0
  64. package/dist/gateways/recurring-payment-gateway.interface.d.ts +32 -0
  65. package/dist/gateways/recurring-payment-gateway.interface.js +3 -0
  66. package/dist/gateways/recurring-payment-gateway.interface.js.map +1 -0
  67. package/dist/gateways/stripe/stripe-webhook.controller.d.ts +24 -0
  68. package/dist/gateways/stripe/stripe-webhook.controller.js +150 -0
  69. package/dist/gateways/stripe/stripe-webhook.controller.js.map +1 -0
  70. package/dist/gateways/stripe/stripe.gateway.d.ts +84 -0
  71. package/dist/gateways/stripe/stripe.gateway.js +424 -0
  72. package/dist/gateways/stripe/stripe.gateway.js.map +1 -0
  73. package/dist/index.d.ts +70 -0
  74. package/dist/index.js +147 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/interfaces/invoice-repository.interface.d.ts +23 -0
  77. package/dist/interfaces/invoice-repository.interface.js +3 -0
  78. package/dist/interfaces/invoice-repository.interface.js.map +1 -0
  79. package/dist/interfaces/payment-config-repository.interface.d.ts +11 -0
  80. package/dist/interfaces/payment-config-repository.interface.js +3 -0
  81. package/dist/interfaces/payment-config-repository.interface.js.map +1 -0
  82. package/dist/interfaces/payment-customer-repository.interface.d.ts +6 -0
  83. package/dist/interfaces/payment-customer-repository.interface.js +3 -0
  84. package/dist/interfaces/payment-customer-repository.interface.js.map +1 -0
  85. package/dist/interfaces/payment-email.interfaces.d.ts +74 -0
  86. package/dist/interfaces/payment-email.interfaces.js +3 -0
  87. package/dist/interfaces/payment-email.interfaces.js.map +1 -0
  88. package/dist/interfaces/payment-event-listener.interface.d.ts +61 -0
  89. package/dist/interfaces/payment-event-listener.interface.js +3 -0
  90. package/dist/interfaces/payment-event-listener.interface.js.map +1 -0
  91. package/dist/interfaces/payment-plan-repository.interface.d.ts +16 -0
  92. package/dist/interfaces/payment-plan-repository.interface.js +3 -0
  93. package/dist/interfaces/payment-plan-repository.interface.js.map +1 -0
  94. package/dist/interfaces/payment-repository.interface.d.ts +13 -0
  95. package/dist/interfaces/payment-repository.interface.js +3 -0
  96. package/dist/interfaces/payment-repository.interface.js.map +1 -0
  97. package/dist/interfaces/recurring-invoice-repository.interface.d.ts +16 -0
  98. package/dist/interfaces/recurring-invoice-repository.interface.js +3 -0
  99. package/dist/interfaces/recurring-invoice-repository.interface.js.map +1 -0
  100. package/dist/interfaces/refund-repository.interface.d.ts +8 -0
  101. package/dist/interfaces/refund-repository.interface.js +3 -0
  102. package/dist/interfaces/refund-repository.interface.js.map +1 -0
  103. package/dist/interfaces/transaction-manager.interface.d.ts +19 -0
  104. package/dist/interfaces/transaction-manager.interface.js +3 -0
  105. package/dist/interfaces/transaction-manager.interface.js.map +1 -0
  106. package/dist/interfaces/webhook-idempotency-repository.interface.d.ts +5 -0
  107. package/dist/interfaces/webhook-idempotency-repository.interface.js +3 -0
  108. package/dist/interfaces/webhook-idempotency-repository.interface.js.map +1 -0
  109. package/dist/models/e-transfer-instructions.model.d.ts +11 -0
  110. package/dist/models/e-transfer-instructions.model.js +56 -0
  111. package/dist/models/e-transfer-instructions.model.js.map +1 -0
  112. package/dist/models/index.d.ts +13 -0
  113. package/dist/models/index.js +36 -0
  114. package/dist/models/index.js.map +1 -0
  115. package/dist/models/invoice-client.model.d.ts +5 -0
  116. package/dist/models/invoice-client.model.js +32 -0
  117. package/dist/models/invoice-client.model.js.map +1 -0
  118. package/dist/models/invoice-line-item.model.d.ts +14 -0
  119. package/dist/models/invoice-line-item.model.js +72 -0
  120. package/dist/models/invoice-line-item.model.js.map +1 -0
  121. package/dist/models/invoice.model.d.ts +86 -0
  122. package/dist/models/invoice.model.js +210 -0
  123. package/dist/models/invoice.model.js.map +1 -0
  124. package/dist/models/online-payment-session.model.d.ts +6 -0
  125. package/dist/models/online-payment-session.model.js +40 -0
  126. package/dist/models/online-payment-session.model.js.map +1 -0
  127. package/dist/models/paginated-invoices.model.d.ts +5 -0
  128. package/dist/models/paginated-invoices.model.js +19 -0
  129. package/dist/models/paginated-invoices.model.js.map +1 -0
  130. package/dist/models/paginated-payment-plans.model.d.ts +5 -0
  131. package/dist/models/paginated-payment-plans.model.js +19 -0
  132. package/dist/models/paginated-payment-plans.model.js.map +1 -0
  133. package/dist/models/paginated-recurring-invoices.model.d.ts +5 -0
  134. package/dist/models/paginated-recurring-invoices.model.js +19 -0
  135. package/dist/models/paginated-recurring-invoices.model.js.map +1 -0
  136. package/dist/models/paginated.model.d.ts +6 -0
  137. package/dist/models/paginated.model.js +30 -0
  138. package/dist/models/paginated.model.js.map +1 -0
  139. package/dist/models/payment-config.model.d.ts +21 -0
  140. package/dist/models/payment-config.model.js +98 -0
  141. package/dist/models/payment-config.model.js.map +1 -0
  142. package/dist/models/payment-method-setup.model.d.ts +4 -0
  143. package/dist/models/payment-method-setup.model.js +32 -0
  144. package/dist/models/payment-method-setup.model.js.map +1 -0
  145. package/dist/models/payment-plan-installment.model.d.ts +12 -0
  146. package/dist/models/payment-plan-installment.model.js +57 -0
  147. package/dist/models/payment-plan-installment.model.js.map +1 -0
  148. package/dist/models/payment-plan.model.d.ts +25 -0
  149. package/dist/models/payment-plan.model.js +105 -0
  150. package/dist/models/payment-plan.model.js.map +1 -0
  151. package/dist/models/payment.model.d.ts +23 -0
  152. package/dist/models/payment.model.js +102 -0
  153. package/dist/models/payment.model.js.map +1 -0
  154. package/dist/models/recurring-invoice-line-item.model.d.ts +14 -0
  155. package/dist/models/recurring-invoice-line-item.model.js +72 -0
  156. package/dist/models/recurring-invoice-line-item.model.js.map +1 -0
  157. package/dist/models/recurring-invoice.model.d.ts +43 -0
  158. package/dist/models/recurring-invoice.model.js +157 -0
  159. package/dist/models/recurring-invoice.model.js.map +1 -0
  160. package/dist/models/refund.model.d.ts +15 -0
  161. package/dist/models/refund.model.js +73 -0
  162. package/dist/models/refund.model.js.map +1 -0
  163. package/dist/payments.module.d.ts +54 -0
  164. package/dist/payments.module.js +211 -0
  165. package/dist/payments.module.js.map +1 -0
  166. package/dist/register-payment-enums.d.ts +1 -0
  167. package/dist/register-payment-enums.js +18 -0
  168. package/dist/register-payment-enums.js.map +1 -0
  169. package/dist/services/customer.service.d.ts +15 -0
  170. package/dist/services/customer.service.js +63 -0
  171. package/dist/services/customer.service.js.map +1 -0
  172. package/dist/services/default-payment-email-templates.d.ts +8 -0
  173. package/dist/services/default-payment-email-templates.js +249 -0
  174. package/dist/services/default-payment-email-templates.js.map +1 -0
  175. package/dist/services/e-transfer.service.d.ts +35 -0
  176. package/dist/services/e-transfer.service.js +93 -0
  177. package/dist/services/e-transfer.service.js.map +1 -0
  178. package/dist/services/invoice-number.service.d.ts +9 -0
  179. package/dist/services/invoice-number.service.js +56 -0
  180. package/dist/services/invoice-number.service.js.map +1 -0
  181. package/dist/services/invoice.service.d.ts +66 -0
  182. package/dist/services/invoice.service.js +293 -0
  183. package/dist/services/invoice.service.js.map +1 -0
  184. package/dist/services/payment-config.service.d.ts +26 -0
  185. package/dist/services/payment-config.service.js +90 -0
  186. package/dist/services/payment-config.service.js.map +1 -0
  187. package/dist/services/payment-email.service.d.ts +20 -0
  188. package/dist/services/payment-email.service.js +153 -0
  189. package/dist/services/payment-email.service.js.map +1 -0
  190. package/dist/services/payment-plan.service.d.ts +47 -0
  191. package/dist/services/payment-plan.service.js +264 -0
  192. package/dist/services/payment-plan.service.js.map +1 -0
  193. package/dist/services/payment.service.d.ts +65 -0
  194. package/dist/services/payment.service.js +532 -0
  195. package/dist/services/payment.service.js.map +1 -0
  196. package/dist/services/recurring-interval.util.d.ts +3 -0
  197. package/dist/services/recurring-interval.util.js +43 -0
  198. package/dist/services/recurring-interval.util.js.map +1 -0
  199. package/dist/services/recurring-invoice.service.d.ts +88 -0
  200. package/dist/services/recurring-invoice.service.js +450 -0
  201. package/dist/services/recurring-invoice.service.js.map +1 -0
  202. package/dist/services/refund.service.d.ts +44 -0
  203. package/dist/services/refund.service.js +373 -0
  204. package/dist/services/refund.service.js.map +1 -0
  205. package/dist/services/static-branding-resolver.d.ts +6 -0
  206. package/dist/services/static-branding-resolver.js +13 -0
  207. package/dist/services/static-branding-resolver.js.map +1 -0
  208. package/dist/types/index.d.ts +240 -0
  209. package/dist/types/index.js +19 -0
  210. package/dist/types/index.js.map +1 -0
  211. package/dist/types/payment-customer.types.d.ts +15 -0
  212. package/dist/types/payment-customer.types.js +3 -0
  213. package/dist/types/payment-customer.types.js.map +1 -0
  214. package/dist/types/recurring-invoice.types.d.ts +84 -0
  215. package/dist/types/recurring-invoice.types.js +3 -0
  216. package/dist/types/recurring-invoice.types.js.map +1 -0
  217. package/package.json +70 -0
@@ -0,0 +1,47 @@
1
+ import type { IPaymentPlanRepository } from '../interfaces/payment-plan-repository.interface';
2
+ import type { IInvoiceRepository } from '../interfaces/invoice-repository.interface';
3
+ import type { ITransactionManager } from '../interfaces/transaction-manager.interface';
4
+ import type { PaymentPlan, PaymentPlanInstallment, PaymentPlanFilter } from '../types';
5
+ import { InvoiceService } from './invoice.service';
6
+ export interface CreatePaymentPlanInput {
7
+ clientDetailsId: string;
8
+ totalAmount: number;
9
+ currency?: string;
10
+ name?: string;
11
+ description?: string;
12
+ referenceType?: string;
13
+ referenceId?: string;
14
+ installments: Array<{
15
+ amount: number;
16
+ dueAt?: Date;
17
+ sequenceOrder: number;
18
+ }>;
19
+ }
20
+ export interface PaymentPlanWithComputed extends PaymentPlan {
21
+ amountPaid: number;
22
+ amountRemaining: number;
23
+ installments: PaymentPlanInstallment[];
24
+ }
25
+ export declare class PaymentPlanService {
26
+ private readonly planRepo;
27
+ private readonly invoiceRepo;
28
+ private readonly transactionManager;
29
+ private readonly defaultCurrency;
30
+ private readonly invoiceService;
31
+ private readonly logger;
32
+ constructor(planRepo: IPaymentPlanRepository, invoiceRepo: IInvoiceRepository, transactionManager: ITransactionManager, defaultCurrency: string, invoiceService: InvoiceService);
33
+ createPaymentPlan(divisionId: string, input: CreatePaymentPlanInput, createdBy: string): Promise<PaymentPlanWithComputed>;
34
+ invoiceInstallment(divisionId: string, installmentId: string, createdBy: string): Promise<import("../types").Invoice>;
35
+ waiveInstallment(divisionId: string, installmentId: string, reason?: string): Promise<PaymentPlanInstallment>;
36
+ cancelPaymentPlan(divisionId: string, planId: string, reason?: string, cancelledBy?: string): Promise<PaymentPlan>;
37
+ findPaymentPlan(divisionId: string, id: string): Promise<PaymentPlanWithComputed | null>;
38
+ findPaymentPlans(divisionId: string, filter?: PaymentPlanFilter, skip?: number, take?: number): Promise<{
39
+ items: PaymentPlan[];
40
+ totalCount: number;
41
+ }>;
42
+ onInvoicePaid(invoiceId: string): Promise<void>;
43
+ markInstallmentOverdue(invoiceId: string): Promise<void>;
44
+ findInstallmentsByPlan(planId: string): Promise<PaymentPlanInstallment[]>;
45
+ private requirePaymentPlans;
46
+ private checkAndCompletePlan;
47
+ }
@@ -0,0 +1,264 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var PaymentPlanService_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.PaymentPlanService = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const constants_1 = require("../constants");
19
+ const exceptions_1 = require("../exceptions");
20
+ const invoice_service_1 = require("./invoice.service");
21
+ const TERMINAL_INSTALLMENT_STATUSES = new Set(['PAID', 'WAIVED', 'CANCELLED']);
22
+ let PaymentPlanService = PaymentPlanService_1 = class PaymentPlanService {
23
+ constructor(planRepo, invoiceRepo, transactionManager, defaultCurrency, invoiceService) {
24
+ this.planRepo = planRepo;
25
+ this.invoiceRepo = invoiceRepo;
26
+ this.transactionManager = transactionManager;
27
+ this.defaultCurrency = defaultCurrency;
28
+ this.invoiceService = invoiceService;
29
+ this.logger = new common_1.Logger(PaymentPlanService_1.name);
30
+ }
31
+ async createPaymentPlan(divisionId, input, createdBy) {
32
+ const installmentSum = input.installments.reduce((sum, inst) => sum + inst.amount, 0);
33
+ if (installmentSum !== input.totalAmount) {
34
+ throw new exceptions_1.InvalidInvoiceStateException(`Installment amounts (${installmentSum}) do not sum to totalAmount (${input.totalAmount})`);
35
+ }
36
+ return this.transactionManager.runInTransaction(async (repos) => {
37
+ const planRepo = this.requirePaymentPlans(repos);
38
+ const plan = await planRepo.create({
39
+ divisionId,
40
+ clientDetailsId: input.clientDetailsId,
41
+ totalAmount: input.totalAmount,
42
+ currency: input.currency ?? this.defaultCurrency,
43
+ name: input.name,
44
+ description: input.description,
45
+ referenceType: input.referenceType,
46
+ referenceId: input.referenceId,
47
+ createdBy,
48
+ });
49
+ const installments = [];
50
+ for (const inst of input.installments) {
51
+ const installment = await planRepo.createInstallment({
52
+ paymentPlanId: plan.id,
53
+ sequenceOrder: inst.sequenceOrder,
54
+ amount: inst.amount,
55
+ dueAt: inst.dueAt,
56
+ });
57
+ installments.push(installment);
58
+ }
59
+ return {
60
+ ...plan,
61
+ amountPaid: 0,
62
+ amountRemaining: plan.totalAmount,
63
+ installments,
64
+ };
65
+ });
66
+ }
67
+ async invoiceInstallment(divisionId, installmentId, createdBy) {
68
+ const installment = await this.planRepo.findInstallmentById(installmentId);
69
+ if (!installment) {
70
+ throw new exceptions_1.InvalidInvoiceStateException(`Installment ${installmentId} not found`);
71
+ }
72
+ if (installment.invoiceId) {
73
+ this.logger.log(`Installment ${installmentId} already has invoice ${installment.invoiceId}, returning existing`);
74
+ const existing = await this.invoiceRepo.findById(installment.invoiceId);
75
+ if (existing)
76
+ return existing;
77
+ }
78
+ if (installment.status !== 'PENDING') {
79
+ throw new exceptions_1.InvalidInvoiceStateException(`Cannot invoice installment in "${installment.status}" status. Installment must be PENDING.`);
80
+ }
81
+ const plan = await this.planRepo.findById(installment.paymentPlanId);
82
+ if (!plan) {
83
+ throw new exceptions_1.InvalidInvoiceStateException(`Payment plan ${installment.paymentPlanId} not found`);
84
+ }
85
+ if (plan.divisionId !== divisionId) {
86
+ throw new exceptions_1.InvalidInvoiceStateException(`Payment plan does not belong to division ${divisionId}`);
87
+ }
88
+ const invoiceInput = {
89
+ clientDetailsId: plan.clientDetailsId,
90
+ currency: plan.currency,
91
+ referenceType: plan.referenceType ?? undefined,
92
+ referenceId: plan.referenceId ?? undefined,
93
+ dueAt: installment.dueAt ?? undefined,
94
+ lineItems: [
95
+ {
96
+ description: plan.name
97
+ ? `${plan.name} - Installment ${installment.sequenceOrder}`
98
+ : `Payment Plan Installment ${installment.sequenceOrder}`,
99
+ quantity: 1,
100
+ unitPrice: installment.amount,
101
+ isTaxable: false,
102
+ },
103
+ ],
104
+ };
105
+ const invoice = await this.invoiceService.createInvoice(divisionId, invoiceInput, createdBy);
106
+ await this.transactionManager.runInTransaction(async (repos) => {
107
+ const planRepo = this.requirePaymentPlans(repos);
108
+ await planRepo.updateInstallment(installment.id, {
109
+ status: 'INVOICED',
110
+ invoiceId: invoice.id,
111
+ });
112
+ await repos.invoices.update(invoice.id, {
113
+ paymentPlanId: plan.id,
114
+ installmentNumber: installment.sequenceOrder,
115
+ });
116
+ });
117
+ return invoice;
118
+ }
119
+ async waiveInstallment(divisionId, installmentId, reason) {
120
+ const installment = await this.planRepo.findInstallmentById(installmentId);
121
+ if (!installment) {
122
+ throw new exceptions_1.InvalidInvoiceStateException(`Installment ${installmentId} not found`);
123
+ }
124
+ if (installment.status !== 'PENDING') {
125
+ throw new exceptions_1.InvalidInvoiceStateException(`Cannot waive installment in "${installment.status}" status. Installment must be PENDING.`);
126
+ }
127
+ const plan = await this.planRepo.findById(installment.paymentPlanId);
128
+ if (!plan || plan.divisionId !== divisionId) {
129
+ throw new exceptions_1.InvalidInvoiceStateException(`Payment plan not found in division ${divisionId}`);
130
+ }
131
+ const updated = await this.planRepo.updateInstallment(installment.id, {
132
+ status: 'WAIVED',
133
+ });
134
+ if (reason) {
135
+ this.logger.log(`Installment ${installmentId} waived. Reason: ${reason}`);
136
+ }
137
+ await this.checkAndCompletePlan(installment.paymentPlanId);
138
+ return updated;
139
+ }
140
+ async cancelPaymentPlan(divisionId, planId, reason, cancelledBy) {
141
+ const plan = await this.planRepo.findById(planId);
142
+ if (!plan) {
143
+ throw new exceptions_1.InvalidInvoiceStateException(`Payment plan ${planId} not found`);
144
+ }
145
+ if (plan.divisionId !== divisionId) {
146
+ throw new exceptions_1.InvalidInvoiceStateException(`Payment plan does not belong to division ${divisionId}`);
147
+ }
148
+ if (plan.status !== 'ACTIVE') {
149
+ throw new exceptions_1.InvalidInvoiceStateException(`Cannot cancel payment plan in "${plan.status}" status. Plan must be ACTIVE.`);
150
+ }
151
+ return this.transactionManager.runInTransaction(async (repos) => {
152
+ const planRepo = this.requirePaymentPlans(repos);
153
+ const cancelledPlan = await planRepo.update(planId, {
154
+ status: 'CANCELLED',
155
+ cancelledBy: cancelledBy ?? null,
156
+ cancelledAt: new Date(),
157
+ cancelReason: reason ?? null,
158
+ });
159
+ const installments = await planRepo.findInstallmentsByPlan(planId);
160
+ for (const installment of installments) {
161
+ if (installment.status === 'PENDING') {
162
+ await planRepo.updateInstallment(installment.id, {
163
+ status: 'CANCELLED',
164
+ });
165
+ }
166
+ if (installment.status === 'INVOICED' && installment.invoiceId) {
167
+ try {
168
+ await this.invoiceService.voidInvoice(installment.invoiceId, `Payment plan cancelled: ${reason ?? 'No reason provided'}`, cancelledBy);
169
+ await planRepo.updateInstallment(installment.id, {
170
+ status: 'CANCELLED',
171
+ });
172
+ }
173
+ catch (error) {
174
+ this.logger.warn(`Could not void invoice ${installment.invoiceId} during plan cancellation: ${error instanceof Error ? error.message : String(error)}`);
175
+ }
176
+ }
177
+ }
178
+ return cancelledPlan;
179
+ });
180
+ }
181
+ async findPaymentPlan(divisionId, id) {
182
+ const plan = await this.planRepo.findById(id);
183
+ if (!plan || plan.divisionId !== divisionId) {
184
+ return null;
185
+ }
186
+ const installments = await this.planRepo.findInstallmentsByPlan(id);
187
+ const amountPaid = installments
188
+ .filter((i) => i.status === 'PAID')
189
+ .reduce((sum, i) => sum + i.amount, 0);
190
+ return {
191
+ ...plan,
192
+ amountPaid,
193
+ amountRemaining: plan.totalAmount - amountPaid,
194
+ installments,
195
+ };
196
+ }
197
+ async findPaymentPlans(divisionId, filter, skip, take) {
198
+ return this.planRepo.findByDivision(divisionId, filter, skip, take);
199
+ }
200
+ async onInvoicePaid(invoiceId) {
201
+ const installment = await this.planRepo.findInstallmentByInvoiceId(invoiceId);
202
+ if (!installment) {
203
+ return;
204
+ }
205
+ if (installment.status === 'PAID') {
206
+ return;
207
+ }
208
+ await this.planRepo.updateInstallment(installment.id, {
209
+ status: 'PAID',
210
+ });
211
+ await this.checkAndCompletePlan(installment.paymentPlanId);
212
+ }
213
+ async markInstallmentOverdue(invoiceId) {
214
+ const installment = await this.planRepo.findInstallmentByInvoiceId(invoiceId);
215
+ if (!installment)
216
+ return;
217
+ if (installment.status !== 'INVOICED')
218
+ return;
219
+ await this.planRepo.updateInstallment(installment.id, {
220
+ status: 'OVERDUE',
221
+ });
222
+ const allInstallments = await this.planRepo.findInstallmentsByPlan(installment.paymentPlanId);
223
+ const overdueCount = allInstallments.filter((i) => i.status === 'OVERDUE').length;
224
+ const OVERDUE_THRESHOLD = 2;
225
+ if (overdueCount >= OVERDUE_THRESHOLD) {
226
+ const plan = await this.planRepo.findById(installment.paymentPlanId);
227
+ if (plan && plan.status === 'ACTIVE') {
228
+ await this.planRepo.update(plan.id, { status: 'DEFAULTED' });
229
+ this.logger.warn(`Payment plan ${plan.id} defaulted — ${overdueCount} installments overdue`);
230
+ }
231
+ }
232
+ }
233
+ async findInstallmentsByPlan(planId) {
234
+ return this.planRepo.findInstallmentsByPlan(planId);
235
+ }
236
+ requirePaymentPlans(repos) {
237
+ if (!repos.paymentPlans) {
238
+ throw new Error('PaymentPlanService requires paymentPlans in TransactionRepositories, ' +
239
+ 'but it was not provided by the transaction manager.');
240
+ }
241
+ return repos.paymentPlans;
242
+ }
243
+ async checkAndCompletePlan(planId) {
244
+ const installments = await this.planRepo.findInstallmentsByPlan(planId);
245
+ const allTerminal = installments.every((i) => TERMINAL_INSTALLMENT_STATUSES.has(i.status));
246
+ if (allTerminal && installments.length > 0) {
247
+ const plan = await this.planRepo.findById(planId);
248
+ if (plan && plan.status === 'ACTIVE') {
249
+ await this.planRepo.update(planId, { status: 'COMPLETED' });
250
+ this.logger.log(`Payment plan ${planId} completed — all installments are terminal`);
251
+ }
252
+ }
253
+ }
254
+ };
255
+ exports.PaymentPlanService = PaymentPlanService;
256
+ exports.PaymentPlanService = PaymentPlanService = PaymentPlanService_1 = __decorate([
257
+ (0, common_1.Injectable)(),
258
+ __param(0, (0, common_1.Inject)(constants_1.PAYMENT_PLAN_REPOSITORY)),
259
+ __param(1, (0, common_1.Inject)(constants_1.INVOICE_REPOSITORY)),
260
+ __param(2, (0, common_1.Inject)(constants_1.TRANSACTION_MANAGER)),
261
+ __param(3, (0, common_1.Inject)(constants_1.DEFAULT_CURRENCY)),
262
+ __metadata("design:paramtypes", [Object, Object, Object, String, invoice_service_1.InvoiceService])
263
+ ], PaymentPlanService);
264
+ //# sourceMappingURL=payment-plan.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment-plan.service.js","sourceRoot":"","sources":["../../src/services/payment-plan.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { type OnModuleInit } from '@nestjs/common';
2
+ import { ModuleRef } from '@nestjs/core';
3
+ import type { IInvoiceRepository } from '../interfaces/invoice-repository.interface';
4
+ import type { IPaymentRepository } from '../interfaces/payment-repository.interface';
5
+ import type { IWebhookIdempotencyRepository } from '../interfaces/webhook-idempotency-repository.interface';
6
+ import type { ITransactionManager } from '../interfaces/transaction-manager.interface';
7
+ import type { Payment, PaymentMethod, PaymentStatus } from '../types';
8
+ import type { PaymentWebhookEvent } from '../gateways/payment-gateway.interface';
9
+ import { GatewayRegistryService } from '../gateways/gateway-registry.service';
10
+ export interface RecordManualPaymentInput {
11
+ invoiceId: string;
12
+ amount: number;
13
+ method: PaymentMethod;
14
+ currency?: string;
15
+ referenceNumber?: string;
16
+ notes?: string;
17
+ processedAt?: Date;
18
+ createdBy: string;
19
+ receivedBy?: string;
20
+ }
21
+ export interface CreatePendingPaymentInput {
22
+ invoiceId: string;
23
+ amount: number;
24
+ currency: string;
25
+ method: PaymentMethod;
26
+ provider: string;
27
+ providerPaymentId: string;
28
+ createdBy: string;
29
+ }
30
+ export declare class PaymentService implements OnModuleInit {
31
+ private readonly invoiceRepo;
32
+ private readonly paymentRepo;
33
+ private readonly webhookIdempotencyRepo;
34
+ private readonly transactionManager;
35
+ private readonly gatewayRegistry;
36
+ private readonly moduleRef;
37
+ private readonly logger;
38
+ private paymentEventListener;
39
+ private paymentEmailService;
40
+ private paymentPlanService;
41
+ constructor(invoiceRepo: IInvoiceRepository, paymentRepo: IPaymentRepository, webhookIdempotencyRepo: IWebhookIdempotencyRepository, transactionManager: ITransactionManager, gatewayRegistry: GatewayRegistryService, moduleRef: ModuleRef);
42
+ onModuleInit(): void;
43
+ recordManualPayment(input: RecordManualPaymentInput): Promise<Payment>;
44
+ createPendingPayment(input: CreatePendingPaymentInput): Promise<Payment>;
45
+ handlePaymentSucceeded(event: PaymentWebhookEvent): Promise<void>;
46
+ handlePaymentFailed(event: PaymentWebhookEvent): Promise<void>;
47
+ handlePaymentProcessing(event: PaymentWebhookEvent): Promise<void>;
48
+ reconcilePayment(paymentId: string): Promise<Payment>;
49
+ findStalePayments(statuses: PaymentStatus[], olderThan: Date): Promise<Payment[]>;
50
+ confirmPayment(paymentId: string): Promise<Payment>;
51
+ rejectPayment(paymentId: string, reason?: string): Promise<Payment>;
52
+ private buildEnrichedPaidEvent;
53
+ private mapLineItemEvents;
54
+ private validatePayable;
55
+ private validateAmount;
56
+ private applyPaymentToInvoice;
57
+ recordAutoChargePayment(input: {
58
+ invoiceId: string;
59
+ amount: number;
60
+ currency: string;
61
+ provider: string;
62
+ providerPaymentId: string;
63
+ receiptUrl?: string;
64
+ }): Promise<Payment>;
65
+ }