@goweekdays/core 1.0.0 → 1.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.
- package/CHANGELOG.md +6 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +127 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1995,10 +1995,37 @@ declare function useInvoiceRepo(): {
|
|
|
1995
1995
|
} | undefined;
|
|
1996
1996
|
createdAt?: Date | undefined;
|
|
1997
1997
|
} | null>;
|
|
1998
|
+
getByTransactionId: (id: string) => Promise<{
|
|
1999
|
+
type: "organization-subscription" | "affiliate-subscription" | "one-time-payment" | "other";
|
|
2000
|
+
status: "pending" | "cancelled" | "paid" | "overdue";
|
|
2001
|
+
amount: number;
|
|
2002
|
+
invoiceNumber: string;
|
|
2003
|
+
dueDate: Date;
|
|
2004
|
+
items: {
|
|
2005
|
+
description: string;
|
|
2006
|
+
unitPrice: number;
|
|
2007
|
+
quantity: number;
|
|
2008
|
+
total: number;
|
|
2009
|
+
seats?: number | undefined;
|
|
2010
|
+
}[];
|
|
2011
|
+
_id?: ObjectId | undefined;
|
|
2012
|
+
updatedAt?: Date | undefined;
|
|
2013
|
+
metadata?: {
|
|
2014
|
+
description?: string | undefined;
|
|
2015
|
+
userId?: string | ObjectId | undefined;
|
|
2016
|
+
orgId?: string | ObjectId | undefined;
|
|
2017
|
+
transactionId?: string | undefined;
|
|
2018
|
+
currency?: string | undefined;
|
|
2019
|
+
subscriptionId?: string | ObjectId | undefined;
|
|
2020
|
+
billingCycle?: "monthly" | "yearly" | "quarterly" | undefined;
|
|
2021
|
+
} | undefined;
|
|
2022
|
+
createdAt?: Date | undefined;
|
|
2023
|
+
} | null>;
|
|
1998
2024
|
};
|
|
1999
2025
|
|
|
2000
2026
|
declare function useInvoiceService(): {
|
|
2001
2027
|
processOverDueInvoices: (BATCH_SIZE?: number, MAX_RETRIES?: number) => Promise<void>;
|
|
2028
|
+
paypalPaidInvoiceWebhookHandler: (invoiceId: string, status: string) => Promise<"Payment processed successfully." | undefined>;
|
|
2002
2029
|
};
|
|
2003
2030
|
|
|
2004
2031
|
declare function useInvoiceController(): {
|
package/dist/index.js
CHANGED
|
@@ -21101,6 +21101,15 @@ function useInvoiceRepo() {
|
|
|
21101
21101
|
throw new import_utils63.InternalServerError("Failed to get invoice by invoice number.");
|
|
21102
21102
|
}
|
|
21103
21103
|
}
|
|
21104
|
+
async function getByTransactionId(id) {
|
|
21105
|
+
try {
|
|
21106
|
+
return await collection.findOne({
|
|
21107
|
+
"metadata.transactionId": id
|
|
21108
|
+
});
|
|
21109
|
+
} catch (error) {
|
|
21110
|
+
throw new import_utils63.InternalServerError("Failed to get invoice by transaction ID.");
|
|
21111
|
+
}
|
|
21112
|
+
}
|
|
21104
21113
|
async function getBySubscriptionId({ page, search, limit, sort, id } = {}) {
|
|
21105
21114
|
try {
|
|
21106
21115
|
try {
|
|
@@ -21183,7 +21192,8 @@ function useInvoiceRepo() {
|
|
|
21183
21192
|
updateStatusByInvoiceNumber,
|
|
21184
21193
|
getOverdueInvoices,
|
|
21185
21194
|
getBySubscriptionId,
|
|
21186
|
-
getByNumber
|
|
21195
|
+
getByNumber,
|
|
21196
|
+
getByTransactionId
|
|
21187
21197
|
};
|
|
21188
21198
|
}
|
|
21189
21199
|
|
|
@@ -24781,16 +24791,18 @@ function useOrderController() {
|
|
|
24781
24791
|
// src/services/invoice.service.ts
|
|
24782
24792
|
var import_utils84 = require("@goweekdays/utils");
|
|
24783
24793
|
function useInvoiceService() {
|
|
24784
|
-
const {
|
|
24794
|
+
const {
|
|
24795
|
+
getOverdueInvoices,
|
|
24796
|
+
updateStatusByInvoiceNumber,
|
|
24797
|
+
getByTransactionId
|
|
24798
|
+
} = useInvoiceRepo();
|
|
24785
24799
|
const {
|
|
24786
24800
|
getById,
|
|
24787
24801
|
processSuccessfulPayment,
|
|
24788
24802
|
updateMaxSeatsById,
|
|
24789
|
-
markSubscriptionAsFailed,
|
|
24790
24803
|
updateStatusById
|
|
24791
24804
|
} = useSubscriptionRepo();
|
|
24792
|
-
const {
|
|
24793
|
-
const { add: addPayment, getByInvoiceId } = usePaymentRepo();
|
|
24805
|
+
const { add: addPayment } = usePaymentRepo();
|
|
24794
24806
|
const { getInvoiceById } = usePaypalService();
|
|
24795
24807
|
async function processOverDueInvoices(BATCH_SIZE = 100, MAX_RETRIES = 7) {
|
|
24796
24808
|
while (true) {
|
|
@@ -24933,8 +24945,95 @@ function useInvoiceService() {
|
|
|
24933
24945
|
});
|
|
24934
24946
|
}
|
|
24935
24947
|
}
|
|
24948
|
+
async function paypalPaidInvoiceWebhookHandler(invoiceId, status) {
|
|
24949
|
+
if (!invoiceId) {
|
|
24950
|
+
throw new import_utils84.BadRequestError("Invoice ID is required.");
|
|
24951
|
+
}
|
|
24952
|
+
if (!status) {
|
|
24953
|
+
throw new import_utils84.BadRequestError("Status is required.");
|
|
24954
|
+
}
|
|
24955
|
+
const session = import_utils84.useAtlas.getClient()?.startSession();
|
|
24956
|
+
if (!session) {
|
|
24957
|
+
import_utils84.logger.log({
|
|
24958
|
+
level: "error",
|
|
24959
|
+
message: "Failed to start session."
|
|
24960
|
+
});
|
|
24961
|
+
return;
|
|
24962
|
+
}
|
|
24963
|
+
try {
|
|
24964
|
+
const invoice = await getByTransactionId(invoiceId);
|
|
24965
|
+
if (!invoice) {
|
|
24966
|
+
throw new import_utils84.NotFoundError("Invoice not found.");
|
|
24967
|
+
}
|
|
24968
|
+
if (!invoice.metadata?.subscriptionId) {
|
|
24969
|
+
throw new import_utils84.BadRequestError(
|
|
24970
|
+
"Subscription ID is missing in invoice metadata."
|
|
24971
|
+
);
|
|
24972
|
+
}
|
|
24973
|
+
session?.startTransaction();
|
|
24974
|
+
const subscription = await getById(invoice.metadata.subscriptionId);
|
|
24975
|
+
if (!subscription) {
|
|
24976
|
+
throw new import_utils84.NotFoundError("Subscription not found.");
|
|
24977
|
+
}
|
|
24978
|
+
if (!subscription._id) {
|
|
24979
|
+
throw new import_utils84.BadRequestError("Subscription ID is missing.");
|
|
24980
|
+
}
|
|
24981
|
+
if (subscription.status !== "active") {
|
|
24982
|
+
await updateStatusById(subscription._id.toString(), "active", session);
|
|
24983
|
+
}
|
|
24984
|
+
await updateStatusByInvoiceNumber(invoice.invoiceNumber, "paid", session);
|
|
24985
|
+
await processSuccessfulPayment(
|
|
24986
|
+
{
|
|
24987
|
+
_id: subscription._id,
|
|
24988
|
+
nextBillingDate: subscription.nextBillingDate
|
|
24989
|
+
},
|
|
24990
|
+
session
|
|
24991
|
+
);
|
|
24992
|
+
const paymentData = {
|
|
24993
|
+
invoiceId: invoice.invoiceNumber,
|
|
24994
|
+
amount: invoice.amount,
|
|
24995
|
+
status: "completed",
|
|
24996
|
+
paymentMethod: "PAYPAL",
|
|
24997
|
+
metadata: {
|
|
24998
|
+
userId: String(subscription.user || ""),
|
|
24999
|
+
orgId: String(subscription.org || ""),
|
|
25000
|
+
currency: subscription.currency,
|
|
25001
|
+
payment: invoice.metadata.transactionId,
|
|
25002
|
+
subscriptionId: subscription._id?.toString()
|
|
25003
|
+
}
|
|
25004
|
+
};
|
|
25005
|
+
if (!paymentData.metadata.userId) {
|
|
25006
|
+
delete paymentData.metadata.userId;
|
|
25007
|
+
}
|
|
25008
|
+
if (!paymentData.metadata.orgId) {
|
|
25009
|
+
delete paymentData.metadata.orgId;
|
|
25010
|
+
}
|
|
25011
|
+
await addPayment(paymentData, session);
|
|
25012
|
+
if (!subscription.paidSeats) {
|
|
25013
|
+
throw new Error("Subscription paid seats is missing.");
|
|
25014
|
+
}
|
|
25015
|
+
await updateMaxSeatsById(
|
|
25016
|
+
{
|
|
25017
|
+
_id: subscription._id.toString(),
|
|
25018
|
+
seats: subscription.paidSeats
|
|
25019
|
+
},
|
|
25020
|
+
session
|
|
25021
|
+
);
|
|
25022
|
+
await session.commitTransaction();
|
|
25023
|
+
return "Payment processed successfully.";
|
|
25024
|
+
} catch (error) {
|
|
25025
|
+
session?.abortTransaction();
|
|
25026
|
+
import_utils84.logger.log({
|
|
25027
|
+
level: "error",
|
|
25028
|
+
message: String(error)
|
|
25029
|
+
});
|
|
25030
|
+
} finally {
|
|
25031
|
+
session?.endSession();
|
|
25032
|
+
}
|
|
25033
|
+
}
|
|
24936
25034
|
return {
|
|
24937
|
-
processOverDueInvoices
|
|
25035
|
+
processOverDueInvoices,
|
|
25036
|
+
paypalPaidInvoiceWebhookHandler
|
|
24938
25037
|
};
|
|
24939
25038
|
}
|
|
24940
25039
|
|
|
@@ -25025,6 +25124,28 @@ function useInvoiceController() {
|
|
|
25025
25124
|
next(error2);
|
|
25026
25125
|
}
|
|
25027
25126
|
}
|
|
25127
|
+
const { paypalPaidInvoiceWebhookHandler } = useInvoiceService();
|
|
25128
|
+
async function paidInvoiceWebhookHandler(req, res, next) {
|
|
25129
|
+
const invoiceId = req.body.resource.id ?? "";
|
|
25130
|
+
const status = req.body.resource.status ?? "";
|
|
25131
|
+
const validation = import_joi28.default.object({
|
|
25132
|
+
invoiceId: import_joi28.default.string().required(),
|
|
25133
|
+
status: import_joi28.default.string().valid("PAID").required()
|
|
25134
|
+
});
|
|
25135
|
+
const { error } = validation.validate({ invoiceId, status });
|
|
25136
|
+
if (error) {
|
|
25137
|
+
next(new import_utils85.BadRequestError(error.message));
|
|
25138
|
+
return;
|
|
25139
|
+
}
|
|
25140
|
+
try {
|
|
25141
|
+
await paypalPaidInvoiceWebhookHandler(invoiceId, status);
|
|
25142
|
+
res.status(200).json({ message: "Webhook processed successfully." });
|
|
25143
|
+
return;
|
|
25144
|
+
} catch (error2) {
|
|
25145
|
+
next(error2);
|
|
25146
|
+
return;
|
|
25147
|
+
}
|
|
25148
|
+
}
|
|
25028
25149
|
return {
|
|
25029
25150
|
getBySubscriptionId,
|
|
25030
25151
|
getByNumber,
|