medusajs-documents-plugin 0.0.0-stage → 1.1.2

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 (41) hide show
  1. package/.medusa/server/src/admin/index.js +2441 -0
  2. package/.medusa/server/src/admin/index.mjs +2442 -0
  3. package/.medusa/server/src/api/admin/documents/[id]/document/route.js +36 -0
  4. package/.medusa/server/src/api/admin/documents/[id]/send/route.js +41 -0
  5. package/.medusa/server/src/api/admin/documents/[id]/sync-zoho/route.js +68 -0
  6. package/.medusa/server/src/api/admin/documents/custom/route.js +48 -0
  7. package/.medusa/server/src/api/admin/documents/manual/route.js +46 -0
  8. package/.medusa/server/src/api/admin/documents/route.js +36 -0
  9. package/.medusa/server/src/api/admin/documents/settings/route.js +44 -0
  10. package/.medusa/server/src/api/admin/documents/templates/preview/route.js +159 -0
  11. package/.medusa/server/src/api/admin/documents/zoho/list/route.js +51 -0
  12. package/.medusa/server/src/api/documents/[id]/document/route.js +36 -0
  13. package/.medusa/server/src/api/documents/r/[code]/route.js +29 -0
  14. package/.medusa/server/src/api/documents/templates/preview/route.js +159 -0
  15. package/.medusa/server/src/api/store/documents/r/[code]/route.js +22 -0
  16. package/.medusa/server/src/index.js +27 -0
  17. package/.medusa/server/src/modules/documents/index.js +13 -0
  18. package/.medusa/server/src/modules/documents/migrations/Migration20261012164601.js +23 -0
  19. package/.medusa/server/src/modules/documents/migrations/Migration20261014150000.js +20 -0
  20. package/.medusa/server/src/modules/documents/migrations/Migration20261015160000.js +46 -0
  21. package/.medusa/server/src/modules/documents/models/document-link.js +12 -0
  22. package/.medusa/server/src/modules/documents/models/document-record.js +33 -0
  23. package/.medusa/server/src/modules/documents/models/document-settings.js +79 -0
  24. package/.medusa/server/src/modules/documents/service.js +587 -0
  25. package/.medusa/server/src/services/notification-sender.js +612 -0
  26. package/.medusa/server/src/services/order-notification-templates.js +510 -0
  27. package/.medusa/server/src/services/pdf-post-processor.js +64 -0
  28. package/.medusa/server/src/services/pdfkit-generator.js +438 -0
  29. package/.medusa/server/src/services/zoho-books.js +221 -0
  30. package/.medusa/server/src/subscribers/order-documents.js +424 -0
  31. package/.medusa/server/src/subscribers/repair-documents.js +216 -0
  32. package/.medusa/server/src/utils/integrate.js +37 -0
  33. package/.medusa/server/src/utils/payment-link.js +69 -0
  34. package/.medusa/server/src/workflows/create-manual-document.js +27 -0
  35. package/.medusa/server/src/workflows/generate-document.js +24 -0
  36. package/.medusa/server/src/workflows/index.js +20 -0
  37. package/.medusa/server/src/workflows/send-document-notification.js +41 -0
  38. package/CHANGELOG.md +87 -0
  39. package/LICENSE +21 -0
  40. package/README.md +201 -2
  41. package/package.json +86 -4
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZohoBooksService = void 0;
4
+ class ZohoBooksService {
5
+ constructor(config, logger) {
6
+ this.access_token = null;
7
+ this.token_expires_at = 0;
8
+ this.config = config;
9
+ this.logger = logger;
10
+ }
11
+ get baseAccountsUrl() {
12
+ return `https://accounts.zoho.${this.config.domain || "com"}`;
13
+ }
14
+ get baseApiUrl() {
15
+ return `https://www.zohoapis.${this.config.domain || "com"}/books/v3`;
16
+ }
17
+ async getAccessToken() {
18
+ if (this.access_token && Date.now() < this.token_expires_at) {
19
+ return this.access_token;
20
+ }
21
+ this.logger?.info(`[Zoho Books] Refreshing access token...`);
22
+ const params = new URLSearchParams();
23
+ params.append("refresh_token", this.config.refresh_token);
24
+ params.append("client_id", this.config.client_id);
25
+ params.append("client_secret", this.config.client_secret);
26
+ params.append("grant_type", "refresh_token");
27
+ const response = await fetch(`${this.baseAccountsUrl}/oauth/v2/token`, {
28
+ method: "POST",
29
+ body: params,
30
+ });
31
+ const data = await response.json();
32
+ if (!response.ok || data.error) {
33
+ this.logger?.error(`[Zoho Books] Failed to refresh token: ${JSON.stringify(data)}`);
34
+ throw new Error(`Zoho authentication failed: ${data.error || response.statusText}`);
35
+ }
36
+ this.access_token = data.access_token;
37
+ this.token_expires_at = Date.now() + (data.expires_in - 300) * 1000;
38
+ return this.access_token;
39
+ }
40
+ async request(method, endpoint, body, isBlob = false) {
41
+ const token = await this.getAccessToken();
42
+ const separator = endpoint.includes("?") ? "&" : "?";
43
+ const url = `${this.baseApiUrl}${endpoint}${separator}organization_id=${this.config.organization_id}`;
44
+ const headers = {
45
+ Authorization: `Zoho-oauthtoken ${token}`,
46
+ };
47
+ if (body) {
48
+ headers["Content-Type"] = "application/json";
49
+ }
50
+ const res = await fetch(url, {
51
+ method,
52
+ headers,
53
+ body: body ? JSON.stringify(body) : undefined,
54
+ });
55
+ if (isBlob) {
56
+ if (!res.ok) {
57
+ throw new Error(`Zoho API Blob Error: ${res.statusText}`);
58
+ }
59
+ return await res.arrayBuffer();
60
+ }
61
+ const data = await res.json();
62
+ if (!res.ok || data.code !== 0) {
63
+ this.logger?.error(`[Zoho Books] API Error: ${JSON.stringify(data)}`);
64
+ throw new Error(`Zoho API Error: ${data.message || res.statusText}`);
65
+ }
66
+ return data;
67
+ }
68
+ async syncContact(customer) {
69
+ const email = customer.email;
70
+ const name = customer.first_name
71
+ ? `${customer.first_name} ${customer.last_name || ""}`.trim()
72
+ : customer.company_name || email || "Guest Customer";
73
+ // 1. Search by email
74
+ if (email && email.includes("@")) {
75
+ try {
76
+ const searchRes = await this.request("GET", `/contacts?email=${encodeURIComponent(email)}`);
77
+ if (searchRes.contacts && searchRes.contacts.length > 0) {
78
+ return searchRes.contacts[0].contact_id;
79
+ }
80
+ }
81
+ catch (e) {
82
+ this.logger?.warn(`[Zoho Books] Failed searching contact by email: ${e.message}`);
83
+ }
84
+ }
85
+ // 2. Search by contact name
86
+ if (name) {
87
+ try {
88
+ const searchNameRes = await this.request("GET", `/contacts?contact_name=${encodeURIComponent(name)}`);
89
+ if (searchNameRes.contacts && searchNameRes.contacts.length > 0) {
90
+ return searchNameRes.contacts[0].contact_id;
91
+ }
92
+ }
93
+ catch (e) {
94
+ this.logger?.warn(`[Zoho Books] Failed searching contact by name: ${e.message}`);
95
+ }
96
+ }
97
+ // 3. Create new contact
98
+ const payload = {
99
+ contact_name: name,
100
+ company_name: customer.company_name || name,
101
+ contact_type: "customer",
102
+ contact_persons: [
103
+ {
104
+ first_name: customer.first_name || "Valued",
105
+ last_name: customer.last_name || "Customer",
106
+ email: email || "",
107
+ phone: customer.phone || "",
108
+ },
109
+ ],
110
+ };
111
+ const createRes = await this.request("POST", "/contacts", payload);
112
+ return createRes.contact.contact_id;
113
+ }
114
+ async createInvoice(contactId, invoiceData) {
115
+ const payload = {
116
+ customer_id: contactId,
117
+ reference_number: invoiceData.reference_number,
118
+ invoice_number: invoiceData.invoice_number,
119
+ due_date: invoiceData.due_date,
120
+ payment_terms: invoiceData.payment_terms || 0,
121
+ line_items: invoiceData.line_items,
122
+ notes: invoiceData.notes || "Thank you for your business.",
123
+ terms: invoiceData.terms || "",
124
+ is_inclusive_tax: invoiceData.is_inclusive_tax ?? false,
125
+ };
126
+ if (invoiceData.custom_fields && invoiceData.custom_fields.length > 0) {
127
+ payload.custom_fields = invoiceData.custom_fields;
128
+ }
129
+ const res = await this.request("POST", "/invoices", payload);
130
+ return {
131
+ invoice_id: res.invoice.invoice_id,
132
+ invoice_number: res.invoice.invoice_number,
133
+ };
134
+ }
135
+ async getInvoicePaymentQrCode(invoiceId) {
136
+ try {
137
+ return await this.request("GET", `/invoices/${invoiceId}/payment-qr-code`, undefined, true);
138
+ }
139
+ catch (e) {
140
+ try {
141
+ return await this.request("GET", `/invoices/${invoiceId}/qr_code`, undefined, true);
142
+ }
143
+ catch (err) {
144
+ return null;
145
+ }
146
+ }
147
+ }
148
+ async createEstimate(contactId, estimateData) {
149
+ const payload = {
150
+ customer_id: contactId,
151
+ reference_number: estimateData.reference_number,
152
+ line_items: estimateData.line_items,
153
+ notes: estimateData.notes || "Estimate for goods/services.",
154
+ terms: estimateData.terms || "",
155
+ is_inclusive_tax: estimateData.is_inclusive_tax ?? false,
156
+ };
157
+ const res = await this.request("POST", "/estimates", payload);
158
+ return {
159
+ estimate_id: res.estimate.estimate_id,
160
+ estimate_number: res.estimate.estimate_number,
161
+ };
162
+ }
163
+ async registerPayment(invoiceId, amount, contactId, paymentMode = "Online", referenceNumber) {
164
+ const payload = {
165
+ customer_id: contactId,
166
+ payment_mode: paymentMode,
167
+ amount: Number(amount).toFixed(2),
168
+ date: new Date().toISOString().split("T")[0],
169
+ invoices: [
170
+ {
171
+ invoice_id: invoiceId,
172
+ amount_applied: Number(amount).toFixed(2),
173
+ },
174
+ ],
175
+ };
176
+ if (referenceNumber) {
177
+ payload.reference_number = referenceNumber;
178
+ }
179
+ const res = await this.request("POST", "/customerpayments", payload);
180
+ return res.payment.payment_id;
181
+ }
182
+ async getDocumentPdf(documentId, type) {
183
+ const endpoint = type === "estimate" ? `/estimates/${documentId}` : `/invoices/${documentId}`;
184
+ return await this.request("GET", `${endpoint}?accept=pdf`, undefined, true);
185
+ }
186
+ async getPaymentReceiptPdf(paymentId) {
187
+ return await this.request("GET", `/customerpayments/${paymentId}?accept=pdf`, undefined, true);
188
+ }
189
+ async listInvoices(params = {}) {
190
+ const query = new URLSearchParams();
191
+ if (params.page)
192
+ query.append("page", String(params.page));
193
+ if (params.per_page)
194
+ query.append("per_page", String(params.per_page));
195
+ if (params.search_text)
196
+ query.append("search_text", params.search_text);
197
+ const res = await this.request("GET", `/invoices?${query.toString()}`);
198
+ return res.invoices || [];
199
+ }
200
+ async listEstimates(params = {}) {
201
+ const query = new URLSearchParams();
202
+ if (params.page)
203
+ query.append("page", String(params.page));
204
+ if (params.per_page)
205
+ query.append("per_page", String(params.per_page));
206
+ const res = await this.request("GET", `/estimates?${query.toString()}`);
207
+ return res.estimates || [];
208
+ }
209
+ async listPayments(params = {}) {
210
+ const query = new URLSearchParams();
211
+ if (params.page)
212
+ query.append("page", String(params.page));
213
+ if (params.per_page)
214
+ query.append("per_page", String(params.per_page));
215
+ const res = await this.request("GET", `/customerpayments?${query.toString()}`);
216
+ return res.customerpayments || [];
217
+ }
218
+ }
219
+ exports.ZohoBooksService = ZohoBooksService;
220
+ exports.default = ZohoBooksService;
221
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiem9oby1ib29rcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zZXJ2aWNlcy96b2hvLWJvb2tzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTZCQSxNQUFhLGdCQUFnQjtJQU0zQixZQUFZLE1BQWtCLEVBQUUsTUFBZTtRQUh2QyxpQkFBWSxHQUFrQixJQUFJLENBQUM7UUFDbkMscUJBQWdCLEdBQVcsQ0FBQyxDQUFDO1FBR25DLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxJQUFZLGVBQWU7UUFDekIsT0FBTyx5QkFBeUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksS0FBSyxFQUFFLENBQUM7SUFDaEUsQ0FBQztJQUVELElBQVksVUFBVTtRQUNwQixPQUFPLHdCQUF3QixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxLQUFLLFdBQVcsQ0FBQztJQUN4RSxDQUFDO0lBRU8sS0FBSyxDQUFDLGNBQWM7UUFDMUIsSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM1RCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDM0IsQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLHlDQUF5QyxDQUFDLENBQUM7UUFDN0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUNyQyxNQUFNLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzFELE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxl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