medusajs-documents-plugin 0.0.0-stage → 1.1.1
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/.medusa/server/src/admin/index.js +2427 -0
- package/.medusa/server/src/admin/index.mjs +2428 -0
- package/.medusa/server/src/api/admin/documents/[id]/document/route.js +36 -0
- package/.medusa/server/src/api/admin/documents/[id]/send/route.js +41 -0
- package/.medusa/server/src/api/admin/documents/[id]/sync-zoho/route.js +68 -0
- package/.medusa/server/src/api/admin/documents/custom/route.js +48 -0
- package/.medusa/server/src/api/admin/documents/manual/route.js +46 -0
- package/.medusa/server/src/api/admin/documents/route.js +36 -0
- package/.medusa/server/src/api/admin/documents/settings/route.js +44 -0
- package/.medusa/server/src/api/admin/documents/templates/preview/route.js +159 -0
- package/.medusa/server/src/api/admin/documents/zoho/list/route.js +51 -0
- package/.medusa/server/src/api/documents/[id]/document/route.js +36 -0
- package/.medusa/server/src/api/documents/r/[code]/route.js +29 -0
- package/.medusa/server/src/api/documents/templates/preview/route.js +159 -0
- package/.medusa/server/src/api/store/documents/r/[code]/route.js +22 -0
- package/.medusa/server/src/index.js +27 -0
- package/.medusa/server/src/modules/documents/index.js +13 -0
- package/.medusa/server/src/modules/documents/migrations/Migration20261012164601.js +23 -0
- package/.medusa/server/src/modules/documents/migrations/Migration20261014150000.js +20 -0
- package/.medusa/server/src/modules/documents/models/document-link.js +12 -0
- package/.medusa/server/src/modules/documents/models/document-record.js +33 -0
- package/.medusa/server/src/modules/documents/models/document-settings.js +61 -0
- package/.medusa/server/src/modules/documents/service.js +456 -0
- package/.medusa/server/src/services/notification-sender.js +293 -0
- package/.medusa/server/src/services/pdf-post-processor.js +64 -0
- package/.medusa/server/src/services/pdfkit-generator.js +438 -0
- package/.medusa/server/src/services/zoho-books.js +221 -0
- package/.medusa/server/src/subscribers/order-documents.js +178 -0
- package/.medusa/server/src/subscribers/repair-documents.js +162 -0
- package/.medusa/server/src/utils/integrate.js +37 -0
- package/.medusa/server/src/utils/payment-link.js +69 -0
- package/.medusa/server/src/workflows/create-manual-document.js +27 -0
- package/.medusa/server/src/workflows/generate-document.js +24 -0
- package/.medusa/server/src/workflows/index.js +20 -0
- package/.medusa/server/src/workflows/send-document-notification.js +41 -0
- package/CHANGELOG.md +87 -0
- package/LICENSE +21 -0
- package/README.md +201 -2
- package/package.json +86 -4
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateOrderPaymentLink = generateOrderPaymentLink;
|
|
7
|
+
exports.generateRepairPaymentLink = generateRepairPaymentLink;
|
|
8
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
+
function generateOrderPaymentLink(order, storefrontUrl) {
|
|
10
|
+
let capturedAmount = 0;
|
|
11
|
+
if (order.payment_collections) {
|
|
12
|
+
for (const pc of order.payment_collections) {
|
|
13
|
+
if (pc.captured_amount != null) {
|
|
14
|
+
capturedAmount += Number(pc.captured_amount);
|
|
15
|
+
}
|
|
16
|
+
else if (pc.payments) {
|
|
17
|
+
capturedAmount += pc.payments.reduce((acc, p) => {
|
|
18
|
+
const isPaid = Boolean(p.captured_at) && !p.canceled_at;
|
|
19
|
+
return acc + (isPaid ? Number(p.amount) : 0);
|
|
20
|
+
}, 0);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const total = Number(order.total || 0);
|
|
25
|
+
const remainingBalance = Math.max(0, total - capturedAmount);
|
|
26
|
+
if (remainingBalance <= 0) {
|
|
27
|
+
return {
|
|
28
|
+
paymentLink: null,
|
|
29
|
+
remainingBalance: 0,
|
|
30
|
+
isUnpaid: false,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Generate secure Paystack HMAC storefront payment URL
|
|
34
|
+
const secretKey = process.env.MEDUSA_PUBLISHABLE_KEY ||
|
|
35
|
+
process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY ||
|
|
36
|
+
process.env.MEDUSA_PUBLISHABLE_API_KEY ||
|
|
37
|
+
"super_secret_fallback_key";
|
|
38
|
+
const hash = crypto_1.default
|
|
39
|
+
.createHmac("sha256", secretKey)
|
|
40
|
+
.update(order.id)
|
|
41
|
+
.digest("hex");
|
|
42
|
+
const cleanStorefrontUrl = storefrontUrl.replace(/\/$/, "");
|
|
43
|
+
const paymentLink = `${cleanStorefrontUrl}/pay/${hash}/${order.id}`;
|
|
44
|
+
return {
|
|
45
|
+
paymentLink,
|
|
46
|
+
remainingBalance,
|
|
47
|
+
isUnpaid: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function generateRepairPaymentLink(ticket, storefrontUrl) {
|
|
51
|
+
const targetTotal = Number((ticket.total_actual && ticket.total_actual > 0) ? ticket.total_actual : ticket.total_estimate || 0);
|
|
52
|
+
const paid = Number(ticket.amount_paid || 0);
|
|
53
|
+
const remainingBalance = Math.max(0, targetTotal - paid);
|
|
54
|
+
if (remainingBalance <= 0 || !ticket.approval_token) {
|
|
55
|
+
return {
|
|
56
|
+
paymentLink: null,
|
|
57
|
+
remainingBalance,
|
|
58
|
+
isUnpaid: false,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const cleanStorefrontUrl = storefrontUrl.replace(/\/$/, "");
|
|
62
|
+
const paymentLink = `${cleanStorefrontUrl}/repairs/track?token=${ticket.approval_token}`;
|
|
63
|
+
return {
|
|
64
|
+
paymentLink,
|
|
65
|
+
remainingBalance,
|
|
66
|
+
isUnpaid: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5bWVudC1saW5rLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3BheW1lbnQtbGluay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVFBLDREQStDQztBQUVELDhEQXFCQztBQTlFRCxvREFBNEI7QUFRNUIsU0FBZ0Isd0JBQXdCLENBQUMsS0FBVSxFQUFFLGFBQXFCO0lBQ3hFLElBQUksY0FBYyxHQUFHLENBQUMsQ0FBQztJQUV2QixJQUFJLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQzlCLEtBQUssTUFBTSxFQUFFLElBQUksS0FBSyxDQUFDLG1CQUE0QixFQUFFLENBQUM7WUFDcEQsSUFBSSxFQUFFLENBQUMsZUFBZSxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUMvQixjQUFjLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUMvQyxDQUFDO2lCQUFNLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUN2QixjQUFjLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFXLEVBQUUsQ0FBTSxFQUFFLEVBQUU7b0JBQzNELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO29CQUN4RCxPQUFPLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9DLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNSLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxHQUFHLGNBQWMsQ0FBQyxDQUFDO0lBRTdELElBQUksZ0JBQWdCLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDMUIsT0FBTztZQUNMLFdBQVcsRUFBRSxJQUFJO1lBQ2pCLGdCQUFnQixFQUFFLENBQUM7WUFDbkIsUUFBUSxFQUFFLEtBQUs7U0FDaEIsQ0FBQztJQUNKLENBQUM7SUFFRCx1REFBdUQ7SUFDdkQsTUFBTSxTQUFTLEdBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0I7UUFDbEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQ0FBa0M7UUFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEI7UUFDdEMsMkJBQTJCLENBQUM7SUFFOUIsTUFBTSxJQUFJLEdBQUcsZ0JBQU07U0FDaEIsVUFBVSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUM7U0FDL0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7U0FDaEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRWpCLE1BQU0sa0JBQWtCLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDNUQsTUFBTSxXQUFXLEdBQUcsR0FBRyxrQkFBa0IsUUFBUSxJQUFJLElBQUksS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBRXBFLE9BQU87UUFDTCxXQUFXO1FBQ1gsZ0JBQWdCO1FBQ2hCLFFBQVEsRUFBRSxJQUFJO0tBQ2YsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFnQix5QkFBeUIsQ0FBQyxNQUFXLEVBQUUsYUFBcUI7SUFDMUUsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksSUFBSSxNQUFNLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsY0FBYyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2hJLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsV0FBVyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBRXpELElBQUksZ0JBQWdCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3BELE9BQU87WUFDTCxXQUFXLEVBQUUsSUFBSTtZQUNqQixnQkFBZ0I7WUFDaEIsUUFBUSxFQUFFLEtBQUs7U0FDaEIsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLGtCQUFrQixHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVELE1BQU0sV0FBVyxHQUFHLEdBQUcsa0JBQWtCLHdCQUF3QixNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7SUFFekYsT0FBTztRQUNMLFdBQVc7UUFDWCxnQkFBZ0I7UUFDaEIsUUFBUSxFQUFFLElBQUk7S0FDZixDQUFDO0FBQ0osQ0FBQyJ9
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createManualDocumentWorkflow = exports.createManualDocumentStep = void 0;
|
|
4
|
+
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
5
|
+
const documents_1 = require("../modules/documents");
|
|
6
|
+
exports.createManualDocumentStep = (0, workflows_sdk_1.createStep)("create-manual-document-step", async (input, { container }) => {
|
|
7
|
+
const documentService = container.resolve(documents_1.DOCUMENTS_MODULE);
|
|
8
|
+
const result = await documentService.generateDocument({
|
|
9
|
+
...input,
|
|
10
|
+
auto_send: input.send_email_now || input.auto_send,
|
|
11
|
+
}, container);
|
|
12
|
+
return new workflows_sdk_1.StepResponse(result, { id: result.record.id });
|
|
13
|
+
}, async (compensationData, { container }) => {
|
|
14
|
+
if (compensationData?.id) {
|
|
15
|
+
try {
|
|
16
|
+
const documentService = container.resolve(documents_1.DOCUMENTS_MODULE);
|
|
17
|
+
await documentService.deleteDocumentRecords(compensationData.id);
|
|
18
|
+
}
|
|
19
|
+
catch (e) { }
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
exports.createManualDocumentWorkflow = (0, workflows_sdk_1.createWorkflow)("create-manual-document-workflow", (input) => {
|
|
23
|
+
const result = (0, exports.createManualDocumentStep)(input);
|
|
24
|
+
return new workflows_sdk_1.WorkflowResponse(result);
|
|
25
|
+
});
|
|
26
|
+
exports.default = exports.createManualDocumentWorkflow;
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLW1hbnVhbC1kb2N1bWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3MvY3JlYXRlLW1hbnVhbC1kb2N1bWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFLMkM7QUFDM0Msb0RBQXdEO0FBTzNDLFFBQUEsd0JBQXdCLEdBQUcsSUFBQSwwQkFBVSxFQUNoRCw2QkFBNkIsRUFDN0IsS0FBSyxFQUFFLEtBQWdDLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ3hELE1BQU0sZUFBZSxHQUEwQixTQUFTLENBQUMsT0FBTyxDQUFDLDRCQUFnQixDQUFDLENBQUM7SUFDbkYsTUFBTSxNQUFNLEdBQUcsTUFBTSxlQUFlLENBQUMsZ0JBQWdCLENBQUM7UUFDcEQsR0FBRyxLQUFLO1FBQ1IsU0FBUyxFQUFFLEtBQUssQ0FBQyxjQUFjLElBQUksS0FBSyxDQUFDLFNBQVM7S0FDbkQsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUVkLE9BQU8sSUFBSSw0QkFBWSxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDNUQsQ0FBQyxFQUNELEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDeEMsSUFBSSxnQkFBZ0IsRUFBRSxFQUFFLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUM7WUFDSCxNQUFNLGVBQWUsR0FBMEIsU0FBUyxDQUFDLE9BQU8sQ0FBQyw0QkFBZ0IsQ0FBQyxDQUFDO1lBQ25GLE1BQU0sZUFBZSxDQUFDLHFCQUFxQixDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ25FLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUEsQ0FBQztJQUNoQixDQUFDO0FBQ0gsQ0FBQyxDQUNGLENBQUM7QUFFVyxRQUFBLDRCQUE0QixHQUFHLElBQUEsOEJBQWMsRUFDeEQsaUNBQWlDLEVBQ2pDLENBQUMsS0FBZ0MsRUFBRSxFQUFFO0lBQ25DLE1BQU0sTUFBTSxHQUFHLElBQUEsZ0NBQXdCLEVBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsT0FBTyxJQUFJLGdDQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3RDLENBQUMsQ0FDRixDQUFDO0FBRUYsa0JBQWUsb0NBQTRCLENBQUMifQ==
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateDocumentWorkflow = exports.generateDocumentStep = void 0;
|
|
4
|
+
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
5
|
+
const documents_1 = require("../modules/documents");
|
|
6
|
+
exports.generateDocumentStep = (0, workflows_sdk_1.createStep)("generate-document-step", async (input, { container }) => {
|
|
7
|
+
const documentService = container.resolve(documents_1.DOCUMENTS_MODULE);
|
|
8
|
+
const result = await documentService.generateDocument(input, container);
|
|
9
|
+
return new workflows_sdk_1.StepResponse(result, { id: result.record.id });
|
|
10
|
+
}, async (compensationData, { container }) => {
|
|
11
|
+
if (compensationData?.id) {
|
|
12
|
+
try {
|
|
13
|
+
const documentService = container.resolve(documents_1.DOCUMENTS_MODULE);
|
|
14
|
+
await documentService.deleteDocumentRecords(compensationData.id);
|
|
15
|
+
}
|
|
16
|
+
catch (e) { }
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
exports.generateDocumentWorkflow = (0, workflows_sdk_1.createWorkflow)("generate-document-workflow", (input) => {
|
|
20
|
+
const result = (0, exports.generateDocumentStep)(input);
|
|
21
|
+
return new workflows_sdk_1.WorkflowResponse(result);
|
|
22
|
+
});
|
|
23
|
+
exports.default = exports.generateDocumentWorkflow;
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtZG9jdW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2dlbmVyYXRlLWRvY3VtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUsyQztBQUMzQyxvREFBd0Q7QUFHM0MsUUFBQSxvQkFBb0IsR0FBRyxJQUFBLDBCQUFVLEVBQzVDLHdCQUF3QixFQUN4QixLQUFLLEVBQUUsS0FBNEIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDcEQsTUFBTSxlQUFlLEdBQTBCLFNBQVMsQ0FBQyxPQUFPLENBQUMsNEJBQWdCLENBQUMsQ0FBQztJQUNuRixNQUFNLE1BQU0sR0FBRyxNQUFNLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDeEUsT0FBTyxJQUFJLDRCQUFZLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUM1RCxDQUFDLEVBQ0QsS0FBSyxFQUFFLGdCQUFnQixFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUN4QyxJQUFJLGdCQUFnQixFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQztZQUNILE1BQU0sZUFBZSxHQUEwQixTQUFTLENBQUMsT0FBTyxDQUFDLDRCQUFnQixDQUFDLENBQUM7WUFDbkYsTUFBTSxlQUFlLENBQUMscUJBQXFCLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkUsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQSxDQUFDO0lBQ2hCLENBQUM7QUFDSCxDQUFDLENBQ0YsQ0FBQztBQUVXLFFBQUEsd0JBQXdCLEdBQUcsSUFBQSw4QkFBYyxFQUNwRCw0QkFBNEIsRUFDNUIsQ0FBQyxLQUE0QixFQUFFLEVBQUU7SUFDL0IsTUFBTSxNQUFNLEdBQUcsSUFBQSw0QkFBb0IsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUMzQyxPQUFPLElBQUksZ0NBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUNGLENBQUM7QUFFRixrQkFBZSxnQ0FBd0IsQ0FBQyJ9
|
|
@@ -0,0 +1,20 @@
|
|
|
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("./generate-document"), exports);
|
|
18
|
+
__exportStar(require("./send-document-notification"), exports);
|
|
19
|
+
__exportStar(require("./create-manual-document"), exports);
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxzREFBb0M7QUFDcEMsK0RBQTZDO0FBQzdDLDJEQUF5QyJ9
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendDocumentNotificationWorkflow = exports.sendDocumentNotificationStep = void 0;
|
|
4
|
+
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
5
|
+
const documents_1 = require("../modules/documents");
|
|
6
|
+
const notification_sender_1 = require("../services/notification-sender");
|
|
7
|
+
exports.sendDocumentNotificationStep = (0, workflows_sdk_1.createStep)("send-document-notification-step", async (input, { container }) => {
|
|
8
|
+
const documentService = container.resolve(documents_1.DOCUMENTS_MODULE);
|
|
9
|
+
const record = await documentService.retrieveDocumentRecord(input.documentId);
|
|
10
|
+
const settings = await documentService.getSettings();
|
|
11
|
+
const dispatchResult = await notification_sender_1.NotificationSender.send({
|
|
12
|
+
container,
|
|
13
|
+
document: {
|
|
14
|
+
id: record.id,
|
|
15
|
+
display_id: record.display_id,
|
|
16
|
+
title: record.title,
|
|
17
|
+
type: record.type,
|
|
18
|
+
customer_name: record.customer_name,
|
|
19
|
+
customer_email: record.customer_email,
|
|
20
|
+
customer_phone: record.customer_phone,
|
|
21
|
+
total_amount: record.total_amount,
|
|
22
|
+
currency_code: record.currency_code,
|
|
23
|
+
payment_status: record.payment_status,
|
|
24
|
+
payment_link: record.payment_link,
|
|
25
|
+
short_payment_link: record.short_payment_link,
|
|
26
|
+
pdf_url: record.pdf_url,
|
|
27
|
+
short_pdf_link: record.short_pdf_link,
|
|
28
|
+
custom_message: input.custom_message,
|
|
29
|
+
subject: input.subject,
|
|
30
|
+
},
|
|
31
|
+
channels: input.channels,
|
|
32
|
+
settings,
|
|
33
|
+
});
|
|
34
|
+
return new workflows_sdk_1.StepResponse(dispatchResult);
|
|
35
|
+
});
|
|
36
|
+
exports.sendDocumentNotificationWorkflow = (0, workflows_sdk_1.createWorkflow)("send-document-notification-workflow", (input) => {
|
|
37
|
+
const result = (0, exports.sendDocumentNotificationStep)(input);
|
|
38
|
+
return new workflows_sdk_1.WorkflowResponse(result);
|
|
39
|
+
});
|
|
40
|
+
exports.default = exports.sendDocumentNotificationWorkflow;
|
|
41
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1kb2N1bWVudC1ub3RpZmljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3NlbmQtZG9jdW1lbnQtbm90aWZpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUsyQztBQUMzQyxvREFBd0Q7QUFFeEQseUVBQXFFO0FBU3hELFFBQUEsNEJBQTRCLEdBQUcsSUFBQSwwQkFBVSxFQUNwRCxpQ0FBaUMsRUFDakMsS0FBSyxFQUFFLEtBQW9DLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQzVELE1BQU0sZUFBZSxHQUEwQixTQUFTLENBQUMsT0FBTyxDQUFDLDRCQUFnQixDQUFDLENBQUM7SUFDbkYsTUFBTSxNQUFNLEdBQUcsTUFBTSxlQUFlLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlFLE1BQU0sUUFBUSxHQUFHLE1BQU0sZUFBZSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRXJELE1BQU0sY0FBYyxHQUFHLE1BQU0sd0NBQWtCLENBQUMsSUFBSSxDQUFDO1FBQ25ELFNBQVM7UUFDVCxRQUFRLEVBQUU7WUFDUixFQUFFLEVBQUUsTUFBTSxDQUFDLEVBQUU7WUFDYixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7WUFDN0IsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLO1lBQ25CLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtZQUNqQixhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDbkMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxjQUFjO1lBQ3JDLGNBQWMsRUFBRSxNQUFNLENBQUMsY0FBYztZQUNyQyxZQUFZLEVBQUUsTUFBTSxDQUFDLFlBQVk7WUFDakMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUFhO1lBQ25DLGNBQWMsRUFBRSxNQUFNLENBQUMsY0FBYztZQUNyQyxZQUFZLEVBQUUsTUFBTSxDQUFDLFlBQVk7WUFDakMsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLGtCQUFrQjtZQUM3QyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87WUFDdkIsY0FBYyxFQUFFLE1BQU0sQ0FBQyxjQUFjO1lBQ3JDLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYztZQUNwQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87U0FDdkI7UUFDRCxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7UUFDeEIsUUFBUTtLQUNULENBQUMsQ0FBQztJQUVILE9BQU8sSUFBSSw0QkFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQzFDLENBQUMsQ0FDRixDQUFDO0FBRVcsUUFBQSxnQ0FBZ0MsR0FBRyxJQUFBLDhCQUFjLEVBQzVELHFDQUFxQyxFQUNyQyxDQUFDLEtBQW9DLEVBQUUsRUFBRTtJQUN2QyxNQUFNLE1BQU0sR0FBRyxJQUFBLG9DQUE0QixFQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25ELE9BQU8sSUFBSSxnQ0FBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0QyxDQUFDLENBQ0YsQ0FBQztBQUVGLGtCQUFlLHdDQUFnQyxDQUFDIn0=
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `medusajs-documents-plugin` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [1.1.0] - 2026-10-12
|
|
11
|
+
|
|
12
|
+
### Minor Release: Repair Job Card Intake & Automated Release Pipeline
|
|
13
|
+
|
|
14
|
+
#### ✨ What's New in v1.1.0
|
|
15
|
+
|
|
16
|
+
- **First-Class Repair Job Card Generation (`type: "job_card"`)**:
|
|
17
|
+
- Automatically triggered upon repair intake (`repair.created`).
|
|
18
|
+
- Device specifications: Brand, Model, Serial Number, and IMEI.
|
|
19
|
+
- Workshop physical intake condition, accessories left, and customer reported fault.
|
|
20
|
+
- Workshop technician diagnostic checklist `[ ]`.
|
|
21
|
+
- Dual physical sign-off lines: **Customer Signature** & **Workshop Technician Signature**.
|
|
22
|
+
- Dynamic QR code directing straight to customer online repair tracking portal.
|
|
23
|
+
|
|
24
|
+
- **Repair Event Subscribers & Delegation**:
|
|
25
|
+
- Event listeners for `repair.created` and `repair.payment_received`.
|
|
26
|
+
- Automatic Query Graph hydration of repair ticket details for document rendering.
|
|
27
|
+
- Seamless delegation from `Meduajs-repair-plugin` with fallback protection.
|
|
28
|
+
|
|
29
|
+
- **Automated CI/CD & Distribution Pipeline**:
|
|
30
|
+
- GitHub Actions release pipeline with automated version tagging.
|
|
31
|
+
- Dynamic changelog extraction as release notes.
|
|
32
|
+
- Release asset bundling with compressed `.zip` distribution archive and `.tgz` npm package.
|
|
33
|
+
- Automated public publishing to the npm registry with authentication tokens.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## [1.0.0] - 2026-10-12
|
|
38
|
+
|
|
39
|
+
### Initial Release: Medusa v2 Documents & Accounting Plugin
|
|
40
|
+
|
|
41
|
+
Comprehensive document generation, accounting synchronization, and multi-channel notification engine for Medusa v2 with Zoho Books integration, local PDFKit fallback, dynamic QR codes, short links, and a unified Admin Documents Hub.
|
|
42
|
+
|
|
43
|
+
#### ✨ Key Features
|
|
44
|
+
|
|
45
|
+
- **First-Class Repair Job Cards (`job_card`)**:
|
|
46
|
+
- Automatic intake generation when `repair.created` fires.
|
|
47
|
+
- Device specifications (Brand, Model, Serial Number, IMEI).
|
|
48
|
+
- Cosmetic condition, accessories left with workshop, and reported fault description.
|
|
49
|
+
- Diagnostic checklist `[ ]` tasks for workshop technicians.
|
|
50
|
+
- Dual physical sign-off lines: **Customer Signature** & **Workshop Technician Signature**.
|
|
51
|
+
- Scannable QR code directing straight to customer online repair tracking portal.
|
|
52
|
+
|
|
53
|
+
- **Zoho Books Synchronization**:
|
|
54
|
+
- Automatic customer contact creation and matching.
|
|
55
|
+
- Real-time generation of Invoices, Estimates, and Payment Receipts via Zoho Books API.
|
|
56
|
+
- Native Zoho invoice QR code customization and notes injection.
|
|
57
|
+
- Two-way reference mapping with local fallback records.
|
|
58
|
+
|
|
59
|
+
- **Local PDFKit Generation Engine (Fallback)**:
|
|
60
|
+
- 3 modern, clean, print-ready document templates:
|
|
61
|
+
- **Modern Minimalist**: Crisp clean lines, typography-driven hierarchy, accent color branding.
|
|
62
|
+
- **Classic Corporate**: Traditional business layout with header grids and signature blocks.
|
|
63
|
+
- **Clean Tech Monospace**: Tech-repair inspired monospace layout with scannable barcodes and checklist grids.
|
|
64
|
+
- Document types: Job Cards, Tax Invoices, Payment Receipts, Estimates / Quotes, Packing Slips, and Custom Certificates.
|
|
65
|
+
- Complete removal of semi-transparent watermarks for sharp, professional PDFs.
|
|
66
|
+
|
|
67
|
+
- **Paystack Dynamic Scan-to-Pay QR Codes & Short Links**:
|
|
68
|
+
- Direct QR code embedded onto invoices and estimates for instant mobile checkout.
|
|
69
|
+
- Built-in URL shortener (`/store/documents/r/:code`) for clean, deliverable SMS and WhatsApp links.
|
|
70
|
+
|
|
71
|
+
- **Multi-Channel Notification Dispatcher**:
|
|
72
|
+
- **Email**: Responsive HTML emails with document branding, summary tables, and download/pay CTAs.
|
|
73
|
+
- **SMS**: Concise SMS notifications powered by TalkSasa SMS provider.
|
|
74
|
+
- **WhatsApp**: Rich formatting with emoji bullets and direct short links.
|
|
75
|
+
|
|
76
|
+
- **Unified Admin Documents Hub (`/app/documents`)**:
|
|
77
|
+
- **All Documents Tab**: Search, filter by document type (including Job Cards), view statuses, create manual invoices, and resend notifications.
|
|
78
|
+
- **PDF Templates Tab**: Live document previewers and template style switchers.
|
|
79
|
+
- **Automations Tab**: Per-event subscriber toggle switches for order and repair events.
|
|
80
|
+
- **Settings Tab**: Zoho Books OAuth configuration, domain selector, company branding, and QR options.
|
|
81
|
+
|
|
82
|
+
- **Automated Event Subscribers**:
|
|
83
|
+
- Order events: `order.placed`, `order.completed`, `payment.captured`, `order.fulfillment_created`.
|
|
84
|
+
- Repair events: `repair.created`, `repair.status_changed`, `repair.payment_received`, `repair.completed`, `repair.customer_reminder`.
|
|
85
|
+
|
|
86
|
+
- **Graceful Integration Utility**:
|
|
87
|
+
- Exported `delegateDocumentGeneration` and `DOCUMENTS_MODULE` helpers allowing external plugins (like `Meduajs-repair-plugin`) to delegate document generation while maintaining safe fallbacks.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Urban Device Care
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,202 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Medusa v2 Documents Plugin (`medusajs-documents-plugin`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A powerful, production-ready document generation, accounting, and multi-channel notification plugin for **Medusa v2**, modeled after `@rsc-labs/medusa-documents-v2` with deep **Zoho Books** accounting integration, **PDFKit multi-template fallback**, **Paystack QR codes & short payment links**, **Medusa Workflows**, and a **unified Admin Documents Hub**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
1. **Unified Documents Hub**
|
|
10
|
+
- Access all invoices, payment receipts, quotations/estimates, packing slips, and custom certificates in one single Medusa Admin tab.
|
|
11
|
+
- Eliminates the need to switch back and forth into the Zoho Books app for day-to-day document lookup.
|
|
12
|
+
- Includes full-text search, type filtering, source filtering (Zoho vs PDFKit), and direct actions: View PDF, Send Notification, Push to Zoho, and Copy Short Link.
|
|
13
|
+
|
|
14
|
+
2. **Zoho Books Integration & Exposed Customizations**
|
|
15
|
+
- Official Zoho Books API v3 integration with automated OAuth access token refreshing.
|
|
16
|
+
- Contacts, Invoices, and Estimates automatically sync to your Zoho organization.
|
|
17
|
+
- Exposes common Zoho customizations directly in the plugin settings (Terms & Conditions, Customer Notes, Net Payment Due Days, Tax Inclusive/Exclusive treatment, Invoice Prefix) so you don't have to open Zoho Books to tweak them.
|
|
18
|
+
|
|
19
|
+
3. **PDFKit Fallback with Multiple Design Templates**
|
|
20
|
+
- Automatically takes over when Zoho Books is disabled, credentials are unset, or for documents that Zoho doesn't support (such as Packing Slips and Custom Warranty Certificates).
|
|
21
|
+
- Choose between 3 distinct aesthetic templates in the **PDF Templates** tab:
|
|
22
|
+
- **Modern Minimalist**: Crisp headers, subtle borders, accent banners, and modern typography.
|
|
23
|
+
- **Classic Corporate**: Traditional formal grid, serif typography, double border lines.
|
|
24
|
+
- **Clean Tech Monospace**: High-contrast, monospace typography optimized for hardware, repairs, and technical orders.
|
|
25
|
+
- Instant live PDF preview button for each template directly in Admin.
|
|
26
|
+
|
|
27
|
+
4. **Paystack Payment Links & Embedded QR Codes**
|
|
28
|
+
- For all unpaid documents (orders with remaining balance or repair tickets):
|
|
29
|
+
- Computes exact balance due.
|
|
30
|
+
- Generates secure Paystack storefront HMAC checkout URL (`/pay/:hash/:order_id` or `/repairs/track?token=...`).
|
|
31
|
+
- Shortens the link to keep text messages clean.
|
|
32
|
+
- Appends the payment link directly to Zoho invoice notes and custom fields.
|
|
33
|
+
- Embeds a scan-to-pay QR code onto the top right of the PDF invoice!
|
|
34
|
+
|
|
35
|
+
5. **Automations & Captured Events Tab**
|
|
36
|
+
- Dedicated tab in the Admin UI with on/off switches for each event subscriber:
|
|
37
|
+
- `order.placed`: Autogenerates Tax Invoice + QR payment link.
|
|
38
|
+
- `order.completed`: Autogenerates Packing Slip.
|
|
39
|
+
- `payment.captured`: Autogenerates Payment Receipt.
|
|
40
|
+
- `order.fulfillment_created`: Autogenerates Packing Slip.
|
|
41
|
+
- `repair.status_changed`: Autogenerates updated repair invoice or quote.
|
|
42
|
+
- `repair.ticket.compliance_requested`: Autogenerates Quotation.
|
|
43
|
+
- `repair.created`: Autogenerates initial Job Card / Estimate.
|
|
44
|
+
- `repair.completed`: Autogenerates final Repair Invoice.
|
|
45
|
+
- `repair.customer_reminder`: Nudges customer with document link.
|
|
46
|
+
|
|
47
|
+
6. **Custom Document Creator with Direct Email Delivery**
|
|
48
|
+
- Create custom certificates (e.g. Warranty Certificates, Work Orders, Proforma Invoices, Agreements) with custom body text and optional line items.
|
|
49
|
+
- Immediately dispatches the document PDF link and customized message to the customer's email via the Medusa notification module.
|
|
50
|
+
|
|
51
|
+
7. **Multi-Channel Dispatch Optimized for Email, SMS & WhatsApp**
|
|
52
|
+
- **Email**: Responsive HTML email with document branding, summary, action buttons (download PDF, pay online if unpaid).
|
|
53
|
+
- **SMS**: Concise SMS message with company name, doc reference, amount, due status, and short links.
|
|
54
|
+
- **WhatsApp**: Clean message with emojis, bold formatting, and short links.
|
|
55
|
+
|
|
56
|
+
8. **Shortened Links Engine**
|
|
57
|
+
- Database model & public route (`/api/store/documents/r/:code`) providing 302 redirection for clean, short messages.
|
|
58
|
+
|
|
59
|
+
9. **Inter-Plugin Delegation Helper**
|
|
60
|
+
- Exported helper function `delegateDocumentGeneration` allowing `medusajs-repairshop-plugin` or custom checkout modules to resolve `documents` and offload document creation.
|
|
61
|
+
|
|
62
|
+
10. **Medusa v2 Workflows**
|
|
63
|
+
- `generateDocumentWorkflow`: Full compensation-safe document generation pipeline.
|
|
64
|
+
- `sendDocumentNotificationWorkflow`: Multi-channel notification pipeline.
|
|
65
|
+
- `createManualDocumentWorkflow`: Manual document creation pipeline.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## How to Enable the Zoho QR Code Feature
|
|
70
|
+
|
|
71
|
+
Our plugin gives you two complementary ways to enable and display QR codes on Zoho invoices:
|
|
72
|
+
|
|
73
|
+
### Method A: Plugin Automatic QR Code Embedding (Recommended)
|
|
74
|
+
Our plugin automatically embeds a high-resolution, scan-to-pay Paystack QR code on the top-right corner of the generated Zoho PDF, and includes the short payment link in the Zoho invoice customer notes:
|
|
75
|
+
1. In the Medusa Admin sidebar, open **Documents**.
|
|
76
|
+
2. Click the **Settings & Zoho** tab.
|
|
77
|
+
3. Under **Zoho Books Integration**, ensure **Enable Zoho Books Sync** is turned on.
|
|
78
|
+
4. Under **Exposed Zoho Invoice Customizations**, ensure **Embed Payment QR Code on Zoho Invoices** is switched **ON** (enabled by default).
|
|
79
|
+
5. (Optional) Set the **Custom Field Name for Payment Link** (e.g., `Payment Link`).
|
|
80
|
+
6. Click **Save All Settings**.
|
|
81
|
+
|
|
82
|
+
Whenever an invoice with an unpaid balance is generated, our post-processor streams the Zoho PDF, stamps the payment QR code on the top right, and adds the payment instructions directly into the document.
|
|
83
|
+
|
|
84
|
+
### Method B: Zoho Books Native Invoice QR Code Setting
|
|
85
|
+
If you also want Zoho Books' web portal and native email templates to display QR codes:
|
|
86
|
+
1. Log in to your [Zoho Books Dashboard](https://books.zoho.com).
|
|
87
|
+
2. Go to **Settings (Gear Icon)** > **Preferences** > **Invoices**.
|
|
88
|
+
3. Scroll down to the **Invoice QR Code** section and toggle it to **Enabled**.
|
|
89
|
+
4. Under **QR Code Type**, choose **Invoice URL** or **Custom**.
|
|
90
|
+
5. If using custom invoice templates, ensure the `%InvoiceQRCodeImage%` or `<img src="%InvQRCodeImgSrcURL%"/>` placeholder is positioned in your template header.
|
|
91
|
+
6. Click **Save** in Zoho Books.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Installation & Setup
|
|
96
|
+
|
|
97
|
+
### 1. Add to `medusa-config.ts`
|
|
98
|
+
In your Medusa project's `medusa-config.ts` (or `medusa-config.js`):
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
module.exports = defineConfig({
|
|
102
|
+
plugins: [
|
|
103
|
+
{
|
|
104
|
+
resolve: "medusajs-documents-plugin",
|
|
105
|
+
options: {}
|
|
106
|
+
},
|
|
107
|
+
// other plugins...
|
|
108
|
+
],
|
|
109
|
+
modules: [
|
|
110
|
+
{
|
|
111
|
+
key: "documents",
|
|
112
|
+
resolve: "medusajs-documents-plugin",
|
|
113
|
+
options: {}
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 2. Run Database Migrations
|
|
120
|
+
```bash
|
|
121
|
+
npx medusa db:migrate
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 3. Build & Run
|
|
125
|
+
```bash
|
|
126
|
+
yarn build
|
|
127
|
+
yarn dev
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Inter-Plugin Integration: How to Use in `medusajs-repairshop-plugin`
|
|
133
|
+
|
|
134
|
+
To delegate document generation from your repair plugin to this plugin:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { delegateDocumentGeneration } from "medusajs-documents-plugin";
|
|
138
|
+
|
|
139
|
+
// Inside your repair endpoint or service:
|
|
140
|
+
const result = await delegateDocumentGeneration(container, {
|
|
141
|
+
display_id: `RT-${ticket.ticket_number}`,
|
|
142
|
+
title: "Repair Invoice",
|
|
143
|
+
type: "invoice",
|
|
144
|
+
repair_ticket_id: ticket.id,
|
|
145
|
+
customer: {
|
|
146
|
+
name: customer.first_name,
|
|
147
|
+
email: customer.email,
|
|
148
|
+
phone: customer.phone,
|
|
149
|
+
},
|
|
150
|
+
items: [
|
|
151
|
+
{ title: "OEM Screen Replacement", quantity: 1, unit_price: 150 },
|
|
152
|
+
{ title: "Labor Fee", quantity: 1, unit_price: 45 }
|
|
153
|
+
],
|
|
154
|
+
total: 195,
|
|
155
|
+
currency_code: "usd",
|
|
156
|
+
payment_link: `https://store.example.com/repairs/track?token=${ticket.approval_token}`,
|
|
157
|
+
auto_send: true,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
if (result) {
|
|
161
|
+
// Successfully generated through Documents plugin (via Zoho or PDFKit)!
|
|
162
|
+
console.log("Generated Document ID:", result.record.id);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Running Automated Tests
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
yarn test
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Runs the 6 unit and integration test suites:
|
|
175
|
+
- PDFKit Generator (Modern, Classic, Minimal templates & Custom documents)
|
|
176
|
+
- PDF Post-Processor (QR Code embedding, watermark validation)
|
|
177
|
+
- Payment Link Generator (HMAC calculation & balance due validation)
|
|
178
|
+
- Zoho Books Service (OAuth & API payload mapping)
|
|
179
|
+
- Notification Sender (Channel routing & payload formatting)
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Automated Releases & NPM Publishing
|
|
184
|
+
|
|
185
|
+
This repository includes a fully automated GitHub Actions pipeline (`.github/workflows/release.yml`):
|
|
186
|
+
- **Automated Versioning**: Automatically detects existing release tags, tags the version, and bumps `patch` on pushes to `main`.
|
|
187
|
+
- **Changelog Extraction**: Extracts the corresponding version section from `CHANGELOG.md` to format the GitHub Release notes / release readme.
|
|
188
|
+
- **Compressed Release Assets**: Builds and packages:
|
|
189
|
+
- 📦 `medusajs-documents-plugin-vX.Y.Z.zip` (compressed distribution zipfile)
|
|
190
|
+
- 📦 `medusajs-documents-plugin-vX.Y.Z.tgz` (npm tarball)
|
|
191
|
+
- **NPM Publishing**: Publishes to [npm](https://www.npmjs.com/package/medusajs-documents-plugin) using `NODE_AUTH_TOKEN`.
|
|
192
|
+
|
|
193
|
+
### Setting Up NPM Publishing
|
|
194
|
+
To enable automated publishing to npm:
|
|
195
|
+
1. Generate an Automation or Publish token on [npmjs.com](https://www.npmjs.com) (`Access Tokens -> Generate New Token -> Automation`).
|
|
196
|
+
2. In your GitHub repository: Go to **Settings** > **Secrets and variables** > **Actions** > **New repository secret**.
|
|
197
|
+
3. Name: `NPM_TOKEN`, Value: `<your_npm_token>`.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
MIT © [Urban Device Care](https://urbandevicecare.co.uk)
|
package/package.json
CHANGED
|
@@ -1,6 +1,88 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medusajs-documents-plugin",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Comprehensive document generation and management module for Medusa v2 with Zoho Books integration, PDFKit fallback, QR codes, shortlinks, multi-channel notifications and unified admin hub.",
|
|
5
|
+
"author": "Urban Device Care <info@urbandevicecare.co.uk>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/urbandevicecare/medusajs-documents-plugin.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/urbandevicecare/medusajs-documents-plugin/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/urbandevicecare/medusajs-documents-plugin#readme",
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
".medusa/server",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"main": "./.medusa/server/src/index.js",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": "./.medusa/server/src/index.js",
|
|
27
|
+
"./package.json": "./package.json",
|
|
28
|
+
"./workflows": "./.medusa/server/src/workflows/index.js",
|
|
29
|
+
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
30
|
+
"./modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
31
|
+
"./*": "./.medusa/server/src/*.js",
|
|
32
|
+
"./admin": {
|
|
33
|
+
"import": "./.medusa/server/src/admin/index.mjs",
|
|
34
|
+
"require": "./.medusa/server/src/admin/index.js",
|
|
35
|
+
"default": "./.medusa/server/src/admin/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"medusa",
|
|
40
|
+
"plugin",
|
|
41
|
+
"medusa-plugin",
|
|
42
|
+
"medusa-documents",
|
|
43
|
+
"medusa-documents-v2",
|
|
44
|
+
"zoho-books",
|
|
45
|
+
"pdfkit",
|
|
46
|
+
"invoices"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "medusa plugin:build",
|
|
50
|
+
"dev": "medusa plugin:dev",
|
|
51
|
+
"test": "npx tsx --test tests/run-all-tests.ts",
|
|
52
|
+
"prepack": "medusa plugin:build"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"pdf-lib": "^1.17.1",
|
|
56
|
+
"pdfkit": "^0.18.0",
|
|
57
|
+
"qrcode": "^1.5.4"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@medusajs/admin-sdk": "2.17.2",
|
|
61
|
+
"@medusajs/cli": "2.17.2",
|
|
62
|
+
"@medusajs/framework": "2.17.2",
|
|
63
|
+
"@medusajs/icons": "2.17.2",
|
|
64
|
+
"@medusajs/medusa": "2.17.2",
|
|
65
|
+
"@medusajs/ui": "4.1.8",
|
|
66
|
+
"@types/node": "^20.0.0",
|
|
67
|
+
"@types/pdfkit": "^0.17.6",
|
|
68
|
+
"@types/qrcode": "^1.5.6",
|
|
69
|
+
"@types/react": "^18.3.2",
|
|
70
|
+
"@types/react-dom": "^18.2.25",
|
|
71
|
+
"ts-node": "^10.9.2",
|
|
72
|
+
"typescript": "^5.6.2",
|
|
73
|
+
"vite": "^5.2.11"
|
|
74
|
+
},
|
|
75
|
+
"peerDependencies": {
|
|
76
|
+
"@medusajs/admin-sdk": "2.17.2",
|
|
77
|
+
"@medusajs/framework": "2.17.2",
|
|
78
|
+
"@medusajs/icons": "2.17.2",
|
|
79
|
+
"@medusajs/ui": "4.1.8",
|
|
80
|
+
"react": "^18.2.0",
|
|
81
|
+
"react-dom": "^18.2.0",
|
|
82
|
+
"react-router-dom": "^6.0.0"
|
|
83
|
+
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=20"
|
|
86
|
+
},
|
|
87
|
+
"packageManager": "yarn@4.18.0"
|
|
88
|
+
}
|