medusajs-documents-plugin 1.1.26 → 1.1.28

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.
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = POST;
4
+ exports.GET = GET;
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const documents_1 = require("../../../../modules/documents");
7
+ const service_1 = require("../../../../modules/documents/service");
8
+ const zoho_books_1 = require("../../../../services/zoho-books");
9
+ // POST & GET /admin/documents/sync
10
+ // Syncs all repair tickets and Zoho Books documents into document_record, creating missing job cards and accompanying quotes/invoices
11
+ async function POST(req, res) {
12
+ return handleSync(req, res);
13
+ }
14
+ async function GET(req, res) {
15
+ return handleSync(req, res);
16
+ }
17
+ async function handleSync(req, res) {
18
+ const logger = req.scope.resolve("logger", { allowUnregistered: true });
19
+ try {
20
+ const documentService = req.scope.resolve(documents_1.DOCUMENTS_MODULE);
21
+ const settings = await documentService.getSettings({}, req.scope).catch(() => ({}));
22
+ const specificTicketId = (req.query?.repair_ticket_id || req.body?.repair_ticket_id);
23
+ // 1. Fetch repair tickets from query graph or DB connection
24
+ let tickets = [];
25
+ try {
26
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
27
+ const queryFilters = {};
28
+ if (specificTicketId) {
29
+ queryFilters.id = specificTicketId;
30
+ }
31
+ const { data } = await query.graph({
32
+ entity: "repair_ticket",
33
+ fields: [
34
+ "*",
35
+ "device.*",
36
+ "product_variants.*",
37
+ "product_variants.prices.*",
38
+ "product_variants.product.*",
39
+ ],
40
+ filters: queryFilters,
41
+ });
42
+ tickets = data || [];
43
+ }
44
+ catch (graphErr) {
45
+ logger?.warn?.(`[Documents-Sync] query.graph failed (${graphErr.message}), falling back to direct db query`);
46
+ const conn = (0, service_1.getDatabaseConnection)(req.scope);
47
+ if (conn) {
48
+ let q = conn("repair_ticket").whereNull("deleted_at");
49
+ if (specificTicketId) {
50
+ q = q.where("id", specificTicketId);
51
+ }
52
+ tickets = await q;
53
+ }
54
+ }
55
+ if (!tickets || tickets.length === 0) {
56
+ return res.json({
57
+ success: true,
58
+ message: "No repair tickets found to synchronize.",
59
+ synced_count: 0,
60
+ documents_created: 0,
61
+ });
62
+ }
63
+ // 2. Fetch Zoho Books existing invoices & estimates if enabled
64
+ let zohoInvoices = [];
65
+ let zohoEstimates = [];
66
+ if (settings?.zoho_books_enabled &&
67
+ settings.zoho_client_id &&
68
+ settings.zoho_client_secret &&
69
+ settings.zoho_refresh_token &&
70
+ settings.zoho_organization_id) {
71
+ try {
72
+ const zoho = new zoho_books_1.ZohoBooksService({
73
+ client_id: settings.zoho_client_id,
74
+ client_secret: settings.zoho_client_secret,
75
+ refresh_token: settings.zoho_refresh_token,
76
+ organization_id: settings.zoho_organization_id,
77
+ domain: settings.zoho_domain || "com",
78
+ }, logger);
79
+ const [invRes, estRes] = await Promise.all([
80
+ zoho.listInvoices().catch(() => []),
81
+ zoho.listEstimates().catch(() => []),
82
+ ]);
83
+ zohoInvoices = Array.isArray(invRes) ? invRes : [];
84
+ zohoEstimates = Array.isArray(estRes) ? estRes : [];
85
+ }
86
+ catch (zohoErr) {
87
+ logger?.warn?.(`[Documents-Sync] Could not pre-fetch Zoho documents: ${zohoErr.message}`);
88
+ }
89
+ }
90
+ const createdRecords = [];
91
+ // 3. Process each ticket
92
+ for (const ticket of tickets) {
93
+ const cleanNum = String(ticket.ticket_number || "").replace(/^(JOB-|RT-)+/i, "");
94
+ const ticketNum = ticket.ticket_number || `RT-${cleanNum}`;
95
+ const meta = (ticket.metadata || {});
96
+ // A. Fetch existing documents for this ticket
97
+ let existingDocs = [];
98
+ try {
99
+ existingDocs = await documentService.listDocumentRecords({ repair_ticket_id: ticket.id }, {}, {}).catch(() => []);
100
+ }
101
+ catch (_) {
102
+ const conn = (0, service_1.getDatabaseConnection)(req.scope);
103
+ if (conn) {
104
+ existingDocs = await conn("document_record")
105
+ .where({ repair_ticket_id: ticket.id })
106
+ .whereNull("deleted_at");
107
+ }
108
+ }
109
+ const hasJobCard = existingDocs.some((d) => d.type === "job_card");
110
+ const hasInvoice = existingDocs.some((d) => d.type === "invoice");
111
+ const hasEstimate = existingDocs.some((d) => d.type === "estimate");
112
+ const hasReceipt = existingDocs.some((d) => d.type === "receipt");
113
+ const totalAmount = Number(ticket.total_actual > 0 ? ticket.total_actual : ticket.total_estimate || 0);
114
+ const currencyCode = ticket.currency_code || ticket.metadata?.currency_code || "kes";
115
+ // B. Ensure Job Card exists
116
+ if (!hasJobCard) {
117
+ try {
118
+ const genJob = await documentService.generateDocument({
119
+ display_id: `JOB-${cleanNum}`,
120
+ title: "Repair Job Card",
121
+ type: "job_card",
122
+ repair_ticket_id: ticket.id,
123
+ total: totalAmount,
124
+ currency_code: currencyCode,
125
+ force_source: "pdfkit",
126
+ }, req.scope);
127
+ if (genJob?.record) {
128
+ createdRecords.push(genJob.record);
129
+ }
130
+ }
131
+ catch (jobErr) {
132
+ logger?.warn?.(`[Documents-Sync] Could not generate job card for ${ticketNum}: ${jobErr.message}`);
133
+ }
134
+ }
135
+ // C. Match Zoho Invoice if not in document_record
136
+ if (!hasInvoice) {
137
+ let matchedZohoInv = zohoInvoices.find((zi) => zi.invoice_id === meta.zoho_invoice_id ||
138
+ zi.invoice_number === ticketNum ||
139
+ zi.invoice_number === cleanNum ||
140
+ zi.reference_number === ticketNum ||
141
+ zi.reference_number === `RT-${ticketNum}` ||
142
+ zi.reference_number === `RT-RT-${cleanNum}` ||
143
+ zi.reference_number?.includes(cleanNum));
144
+ if (matchedZohoInv || meta.zoho_invoice_id) {
145
+ try {
146
+ const genInv = await documentService.generateDocument({
147
+ display_id: matchedZohoInv?.invoice_number || ticketNum,
148
+ title: (ticket.status === "completed" || ticket.status === "repaired") ? "Final Repair Invoice" : "Repair Invoice",
149
+ type: "invoice",
150
+ repair_ticket_id: ticket.id,
151
+ total: totalAmount,
152
+ currency_code: currencyCode,
153
+ force_source: settings?.zoho_books_enabled ? "zoho" : undefined,
154
+ }, req.scope);
155
+ if (genInv?.record) {
156
+ createdRecords.push(genInv.record);
157
+ }
158
+ }
159
+ catch (invErr) {
160
+ logger?.warn?.(`[Documents-Sync] Could not sync invoice for ${ticketNum}: ${invErr.message}`);
161
+ }
162
+ }
163
+ else if (["repairing", "ready", "completed", "collected", "repaired"].includes(ticket.status)) {
164
+ // Ticket is in repair or completion phase: generate invoice
165
+ try {
166
+ const genInv = await documentService.generateDocument({
167
+ display_id: ticketNum,
168
+ title: (ticket.status === "completed" || ticket.status === "repaired") ? "Final Repair Invoice" : "Repair Invoice",
169
+ type: "invoice",
170
+ repair_ticket_id: ticket.id,
171
+ total: totalAmount,
172
+ currency_code: currencyCode,
173
+ force_source: settings?.zoho_books_enabled ? "zoho" : undefined,
174
+ }, req.scope);
175
+ if (genInv?.record) {
176
+ createdRecords.push(genInv.record);
177
+ }
178
+ }
179
+ catch (invErr) {
180
+ logger?.warn?.(`[Documents-Sync] Could not generate invoice for ${ticketNum}: ${invErr.message}`);
181
+ }
182
+ }
183
+ }
184
+ // D. Match Zoho Estimate if not in document_record
185
+ if (!hasEstimate) {
186
+ let matchedZohoEst = zohoEstimates.find((ze) => ze.estimate_id === meta.zoho_estimate_id ||
187
+ ze.estimate_number === ticketNum ||
188
+ ze.estimate_number === cleanNum ||
189
+ ze.reference_number === ticketNum ||
190
+ ze.reference_number === `RT-${ticketNum}` ||
191
+ ze.reference_number === `RT-RT-${cleanNum}` ||
192
+ ze.reference_number?.includes(cleanNum));
193
+ if (matchedZohoEst || meta.zoho_estimate_id) {
194
+ try {
195
+ const genEst = await documentService.generateDocument({
196
+ display_id: matchedZohoEst?.estimate_number || `EST-${cleanNum}`,
197
+ title: "Repair Estimate / Quote",
198
+ type: "estimate",
199
+ repair_ticket_id: ticket.id,
200
+ total: totalAmount,
201
+ currency_code: currencyCode,
202
+ force_source: settings?.zoho_books_enabled ? "zoho" : undefined,
203
+ }, req.scope);
204
+ if (genEst?.record) {
205
+ createdRecords.push(genEst.record);
206
+ }
207
+ }
208
+ catch (estErr) {
209
+ logger?.warn?.(`[Documents-Sync] Could not sync estimate for ${ticketNum}: ${estErr.message}`);
210
+ }
211
+ }
212
+ else {
213
+ // Generate estimate / quote for this ticket
214
+ try {
215
+ const genEst = await documentService.generateDocument({
216
+ display_id: `EST-${cleanNum}`,
217
+ title: "Repair Estimate / Quote",
218
+ type: "estimate",
219
+ repair_ticket_id: ticket.id,
220
+ total: totalAmount,
221
+ currency_code: currencyCode,
222
+ force_source: settings?.zoho_books_enabled ? "zoho" : undefined,
223
+ }, req.scope);
224
+ if (genEst?.record) {
225
+ createdRecords.push(genEst.record);
226
+ }
227
+ }
228
+ catch (estErr) {
229
+ logger?.warn?.(`[Documents-Sync] Could not generate estimate for ${ticketNum}: ${estErr.message}`);
230
+ }
231
+ }
232
+ }
233
+ // E. Check for Receipt if paid
234
+ const isPaid = ticket.payment_status === "paid" || ticket.payment_status === "captured" || Number(ticket.amount_paid || 0) > 0;
235
+ if (isPaid && !hasReceipt) {
236
+ try {
237
+ const genRcpt = await documentService.generateDocument({
238
+ display_id: `RCPT-${cleanNum}`,
239
+ title: "Repair Payment Receipt",
240
+ type: "receipt",
241
+ repair_ticket_id: ticket.id,
242
+ total: Number(ticket.amount_paid || totalAmount),
243
+ currency_code: currencyCode,
244
+ force_source: settings?.zoho_books_enabled ? "zoho" : undefined,
245
+ }, req.scope);
246
+ if (genRcpt?.record) {
247
+ createdRecords.push(genRcpt.record);
248
+ }
249
+ }
250
+ catch (rcptErr) {
251
+ logger?.warn?.(`[Documents-Sync] Could not generate receipt for ${ticketNum}: ${rcptErr.message}`);
252
+ }
253
+ }
254
+ }
255
+ return res.json({
256
+ success: true,
257
+ message: `Successfully synchronized ${tickets.length} repair tickets.`,
258
+ synced_tickets: tickets.length,
259
+ documents_created: createdRecords.length,
260
+ records: createdRecords.map((r) => ({
261
+ id: r.id,
262
+ display_id: r.display_id,
263
+ type: r.type,
264
+ source: r.source,
265
+ total_amount: r.total_amount,
266
+ })),
267
+ });
268
+ }
269
+ catch (error) {
270
+ logger?.error?.(`[Documents-Sync] Fatal error during synchronization: ${error.message}`);
271
+ return res.status(500).json({
272
+ success: false,
273
+ message: error.message || "Failed to synchronize documents",
274
+ error: true,
275
+ });
276
+ }
277
+ }
278
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2RvY3VtZW50cy9zeW5jL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBUUEsb0JBRUM7QUFFRCxrQkFFQztBQWJELHFEQUFzRTtBQUN0RSw2REFBaUU7QUFDakUsbUVBQXFHO0FBQ3JHLGdFQUFtRTtBQUVuRSxtQ0FBbUM7QUFDbkMsc0lBQXNJO0FBQy9ILEtBQUssVUFBVSxJQUFJLENBQUMsR0FBa0IsRUFBRSxHQUFtQjtJQUNoRSxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVNLEtBQUssVUFBVSxHQUFHLENBQUMsR0FBa0IsRUFBRSxHQUFtQjtJQUMvRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVELEtBQUssVUFBVSxVQUFVLENBQUMsR0FBa0IsRUFBRSxHQUFtQjtJQUMvRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLElBQUksQ0FBQztRQUNILE1BQU0sZUFBZSxHQUEwQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyw0QkFBZ0IsQ0FBQyxDQUFDO1FBQ25GLE1BQU0sUUFBUSxHQUFHLE1BQU0sZUFBZSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEYsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsZ0JBQWdCLElBQUssR0FBRyxDQUFDLElBQVksRUFBRSxnQkFBZ0IsQ0FBdUIsQ0FBQztRQUVw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
@@ -20,6 +20,68 @@ async function GET(req, res) {
20
20
  const isPackingSlip = type === "packing_slip";
21
21
  const isEstimate = type === "estimate";
22
22
  const companyName = settings.company_name || "Urban Device Care Ltd";
23
+ const rawPreset = String(req.query.preset || "").trim().toLowerCase();
24
+ // Preset dictionary for custom documents
25
+ const PRESETS = {
26
+ warranty: {
27
+ title: "Warranty Certificate",
28
+ body_text: "This official certificate verifies that the aforementioned device has undergone professional repairs with genuine OEM-specification components and has passed our multi-point quality assurance inspection.\n\nAll hardware replacements and associated workshop labor are covered under our comprehensive 90-day warranty against defects in parts and workmanship. Please retain this document for warranty verification.",
29
+ items: [
30
+ { title: "OEM Component & Hardware Warranty", description: "90-Day Comprehensive Hardware Protection", quantity: 1, unit_price: 0, total: 0 },
31
+ { title: "Workshop Quality Clearance", description: "Multi-Point Hardware Bench Certification", quantity: 1, unit_price: 0, total: 0 },
32
+ ],
33
+ },
34
+ diagnostic: {
35
+ title: "Diagnostic & Hardware Inspection Report",
36
+ body_text: "Our certified repair specialists have completed a hardware and firmware inspection of your equipment. Below are the confirmed technical findings, component test measurements, and technician notes regarding the state of your device.",
37
+ items: [
38
+ { title: "Logic Board & Power Rail Inspection", description: "Voltage drop and circuit continuity tested", quantity: 1, unit_price: 0, total: 0 },
39
+ { title: "Display & Touch Digitizer Diagnostic", description: "Digitizer touch grid, TrueTone, and Ambient Sensor test", quantity: 1, unit_price: 0, total: 0 },
40
+ { title: "Battery Health & Thermal Profiling", description: "Cycle count, capacity retention, and charge testing", quantity: 1, unit_price: 0, total: 0 },
41
+ ],
42
+ },
43
+ service_completion: {
44
+ title: "Certificate of Service Completion",
45
+ body_text: "This document certifies that the requested overhaul, maintenance, and repair services have been executed in full accordance with industry service standards. The device has cleared bench testing and is ready for customer collection.",
46
+ items: [
47
+ { title: "Hardware Servicing & Component Replacement", description: "Executed per work order specifications", quantity: 1, unit_price: 0, total: 0 },
48
+ { title: "Final Bench Testing & Quality Control", description: "Passed 100% functional test criteria", quantity: 1, unit_price: 0, total: 0 },
49
+ ],
50
+ },
51
+ handover: {
52
+ title: "Equipment Handover & Custody Release Agreement",
53
+ body_text: "This handover document certifies the return and physical custody release of customer equipment and associated accessories from Urban Device Care. The customer acknowledges receipt of equipment in verified working order.",
54
+ items: [
55
+ { title: "Device Handover & Physical Release", description: "Customer custody confirmed", quantity: 1, unit_price: 0, total: 0 },
56
+ { title: "Accessories Handover", description: "Chargers, cases, and cables returned in verified condition", quantity: 1, unit_price: 0, total: 0 },
57
+ ],
58
+ },
59
+ proforma: {
60
+ title: "Commercial Quotation (Proforma)",
61
+ body_text: "Thank you for choosing Urban Device Care. Below is an itemized breakdown of estimated hardware parts, workshop labor, and turnaround schedule for your project. This quote is valid for 14 calendar days.",
62
+ items: [
63
+ { title: "OEM Replacement Hardware Assembly", description: "Brand new replacement module", quantity: 1, unit_price: 15000, total: 15000 },
64
+ { title: "Workshop Labor & Clean-Room Installation", description: "Certified technician installation & calibration", quantity: 1, unit_price: 4500, total: 4500 },
65
+ ],
66
+ },
67
+ trade_in: {
68
+ title: "Device Trade-In & Buyback Agreement",
69
+ body_text: "This agreement confirms the valuation, transfer of title, and trade-in credit for the listed customer hardware. Customer verifies legal ownership and consents to complete data sanitation and ownership transfer.",
70
+ items: [
71
+ { title: "Trade-In Device Valuation & Credit", description: "Assessed Grade A condition allowance", quantity: 1, unit_price: 25000, total: 25000 },
72
+ { title: "Data Sanitization & Ownership Transfer", description: "Certified NIST 800-88 cryptographic wipe", quantity: 1, unit_price: 0, total: 0 },
73
+ ],
74
+ },
75
+ destruction: {
76
+ title: "Certificate of Destruction & Eco-Disposal",
77
+ body_text: "This certificate confirms that the decommissioned hardware listed below has been safely demanufactured, shredded, or recycled in full compliance with WEEE and data destruction standards.",
78
+ items: [
79
+ { title: "Hardware Demanufacturing & Shredding", description: "Certified environmental destruction", quantity: 1, unit_price: 0, total: 0 },
80
+ { title: "Hazardous Materials Recycling", description: "Zero-landfill lithium battery reclamation", quantity: 1, unit_price: 0, total: 0 },
81
+ ],
82
+ },
83
+ };
84
+ const activePreset = isCustom ? (PRESETS[rawPreset] || PRESETS.warranty) : null;
23
85
  const sampleData = {
24
86
  display_id: isJobCard
25
87
  ? "JOB-1042"
@@ -30,7 +92,7 @@ async function GET(req, res) {
30
92
  : isEstimate
31
93
  ? "EST-3091"
32
94
  : isCustom
33
- ? "CERT-7701"
95
+ ? `DOC-${(rawPreset || "CERT").toUpperCase().slice(0, 4)}-7701`
34
96
  : "INV-1092",
35
97
  title: isJobCard
36
98
  ? "Repair Job Card"
@@ -42,7 +104,7 @@ async function GET(req, res) {
42
104
  ? "Packing Slip"
43
105
  : isEstimate
44
106
  ? "Quotation / Estimate"
45
- : "Warranty Certificate",
107
+ : (activePreset?.title || "Warranty Certificate"),
46
108
  type: type,
47
109
  date: new Date().toISOString().split("T")[0],
48
110
  due_date: (type === "invoice" || isEstimate)
@@ -51,17 +113,17 @@ async function GET(req, res) {
51
113
  customer: {
52
114
  name: "Jane Doe",
53
115
  email: "jane.doe@example.com",
54
- phone: "+44 7911 123456",
55
- address: "221B Baker Street, Marylebone, London, NW1 6XE",
116
+ phone: "+254 712 345 678",
117
+ address: "Bekim House, Westlands Crossway Rd, Nairobi",
56
118
  },
57
119
  company: {
58
120
  name: companyName,
59
121
  logo_url: settings.pdf_logo_url,
60
- address: settings.pdf_address || "123 High Street, Tech Park, London",
61
- phone: settings.pdf_phone || "+44 20 7946 0991",
62
- email: settings.pdf_email || "support@urbandevicecare.co.uk",
122
+ address: settings.pdf_address || "Bekim House, 04 Westlands Crossway Rd, Westlands, Nairobi, Kenya",
123
+ phone: settings.pdf_phone || "0729 436 660 / 0794 700 241",
124
+ email: settings.pdf_email || "urbandevice.care@gmail.com",
63
125
  website: settings.pdf_website || "www.urbandevicecare.co.uk",
64
- payment_details: settings.pdf_payment_details || "Bank: Barclays | Acct: 12345678 | Sort: 20-00-00",
126
+ payment_details: settings.pdf_payment_details || "Paybill: 400200 | Acc: 1039764",
65
127
  terms: settings.pdf_terms || "Payment is due within 14 days of invoice date. Thank you for your business.",
66
128
  },
67
129
  items: isJobCard
@@ -73,66 +135,51 @@ async function GET(req, res) {
73
135
  { title: "Final Multi-Point Bench Clearance & Sanitization", quantity: 1, unit_price: 0, total: 0 },
74
136
  ]
75
137
  : isCustom
76
- ? [
77
- {
78
- title: "OEM Component & Hardware Warranty",
79
- description: "90-Day Comprehensive Hardware Protection",
80
- quantity: 1,
81
- unit_price: 0,
82
- total: 0,
83
- },
84
- {
85
- title: "Workshop Quality Clearance",
86
- description: "Multi-Point Hardware Bench Certification",
87
- quantity: 1,
88
- unit_price: 0,
89
- total: 0,
90
- },
91
- ]
138
+ ? activePreset.items
92
139
  : [
93
140
  {
94
141
  title: "Apple iPhone 14 Screen Replacement",
95
142
  description: "OEM Grade OLED Assembly with TrueTone restoration",
96
143
  quantity: 1,
97
- unit_price: 189.0,
98
- total: 189.0,
144
+ unit_price: 18500.0,
145
+ total: 18500.0,
99
146
  },
100
147
  {
101
148
  title: "Diagnostic & Workshop Labor Fee",
102
149
  description: "Full device diagnostic and multi-point hardware inspection",
103
150
  quantity: 1,
104
- unit_price: 45.0,
105
- total: 45.0,
151
+ unit_price: 4500.0,
152
+ total: 4500.0,
106
153
  },
107
154
  {
108
155
  title: "Tempered Glass Screen Protector",
109
156
  description: "9H Hardness Edge-to-Edge protection",
110
157
  quantity: 1,
111
- unit_price: 15.0,
112
- total: 15.0,
158
+ unit_price: 1500.0,
159
+ total: 1500.0,
113
160
  },
114
161
  ],
115
- subtotal: (isJobCard || isPackingSlip || isCustom) ? undefined : 249.0,
116
- tax_total: (isJobCard || isPackingSlip || isCustom) ? undefined : 24.9,
117
- discount_total: (isJobCard || isPackingSlip || isCustom) ? undefined : 10.0,
118
- total: (isJobCard || isPackingSlip || isCustom) ? 0 : 263.9,
162
+ subtotal: (isJobCard || isPackingSlip || (isCustom && !activePreset?.items.some((i) => i.unit_price > 0))) ? undefined : 24500.0,
163
+ tax_total: (isJobCard || isPackingSlip || isCustom) ? undefined : 0,
164
+ discount_total: (isJobCard || isPackingSlip || isCustom) ? undefined : 0,
165
+ total: (isJobCard || isPackingSlip || (isCustom && !activePreset?.items.some((i) => i.unit_price > 0))) ? 0 : 24500.0,
119
166
  currency_code: "kes",
120
167
  payment_status: isReceipt ? "paid" : "unpaid",
121
- payment_link: (type === "invoice" || isEstimate) ? "https://store.urbandevicecare.co.uk/pay/sample-preview-token" : undefined,
122
- qr_url: (type === "invoice" || isEstimate || isJobCard) ? "https://store.urbandevicecare.co.uk/track/JOB-1042" : undefined,
168
+ payment_link: (type === "invoice" || isEstimate) ? "https://urbandevicecare.co.uk/r/sample-preview" : undefined,
169
+ qr_url: (type === "invoice" || isEstimate || isJobCard) ? "https://urbandevicecare.co.uk/r/sample-preview" : undefined,
123
170
  notes: isJobCard
124
171
  ? "Customer acknowledges device physical intake condition and workshop repair terms."
125
172
  : isReceipt
126
- ? "Payment received in full via Paystack. Thank you for your custom!"
173
+ ? "Payment received in full. Thank you for your business!"
127
174
  : isPackingSlip
128
175
  ? "Please inspect contents immediately upon receipt. Keep this slip for your delivery records."
129
176
  : isEstimate
130
- ? "This quotation is valid for 30 calendar days from the date of issue."
177
+ ? "This quotation is valid for 14 calendar days from the date of issue."
131
178
  : isCustom
132
- ? "Retain this warranty certificate for official warranty claim verification."
133
- : "Please scan the QR code to complete payment securely via Paystack.",
179
+ ? "Please retain this official document for your records and compliance."
180
+ : "Thank you for choosing Urban Device Care. Payment details above.",
134
181
  body_text: isCustom
135
- ? "This official certificate verifies that the aforementioned device has undergone professional repairs with genuine OEM-specification components and has passed our multi-point quality assurance inspection.\n\nAll hardware replacements and associated workshop labor are covered under our comprehensive 90-day warranty against defects in parts and workmanship."
182
+ ? activePreset.body_text
136
183
  : undefined,
137
184
  custom_fields: isJobCard
138
185
  ? {
@@ -157,4 +204,4 @@ async function GET(req, res) {
157
204
  return res.status(500).send(`Failed to generate preview: ${err.message}`);
158
205
  }
159
206
  }
160
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2RvY3VtZW50cy90ZW1wbGF0ZXMvcHJldmlldy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU1BLGtCQThKQztBQW5LRCxnRUFBb0U7QUFFcEUsK0VBQXlGO0FBRXpGLCtJQUErSTtBQUN4SSxLQUFLLFVBQVUsR0FBRyxDQUFDLEdBQWtCLEVBQUUsR0FBbUI7SUFDL0QsSUFBSSxDQUFDO1FBQ0gsTUFBTSxlQUFlLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLDRCQUFnQixDQUFDLENBQUM7UUFDbkYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLGVBQWUsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTVGLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNwRSxNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMvRSxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUVuRSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbEUsTUFBTSxVQUFVLEdBQUcs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
207
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2RvY3VtZW50cy90ZW1wbGF0ZXMvcHJldmlldy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU1BLGtCQStNQztBQXBORCxnRUFBb0U7QUFFcEUsK0VBQXlGO0FBRXpGLCtJQUErSTtBQUN4SSxLQUFLLFVBQVUsR0FBRyxDQUFDLEdBQWtCLEVBQUUsR0FBbUI7SUFDL0QsSUFBSSxDQUFDO1FBQ0gsTUFBTSxlQUFlLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLDRCQUFnQixDQUFDLENBQUM7UUFDbkYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLGVBQWUsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTVGLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNwRSxNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMvRSxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUVuRSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbEUsTUFBTSxVQUFVLEdBQUcs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
package/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [1.1.27] - 2026-11-01
11
+
12
+ ### Repair Sync, 3-Column Template Gallery & Preset Previews
13
+ - **Repair Ticket & Zoho Books Bi-directional Sync (`/admin/documents/sync`)**: Added dedicated sync endpoint and Admin UI action to reconcile repair tickets with Zoho Books estimates/invoices, backfilling missing job cards, linking pre-existing quotes/invoices, and updating ticket metadata.
14
+ - **Enhanced PDF Templates UI**: Redesigned the Document Templates tab to match `Meduajs-repair-plugin` styling, with a modern 3-column responsive grid (`grid-cols-1 md:grid-cols-2 lg:grid-cols-3`) displaying 12 distinct cards (5 core operational document types + 7 specialized presets: Warranty, Diagnostic Report, Service Completion, Handover Protocol, Proforma Invoice, Trade-In Agreement, Equipment Destruction).
15
+ - **Preset Preview Endpoint**: Extended `/admin/documents/templates/preview` to accept `preset` query parameter, generating realistic contextual mock data and titles for all specialized document presets.
16
+ - **Documents Hub Default Filter**: Updated default document type filter from `"invoice"` to `"all"` so that job cards, estimates, and receipts are immediately accessible upon visiting the hub.
17
+
10
18
  ## [1.1.25] - 2026-11-01
11
19
 
12
20
  ### Receipt Companion Invoicing & Settings Tag Customization Hardening
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medusajs-documents-plugin",
3
- "version": "1.1.26",
3
+ "version": "1.1.28",
4
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
5
  "author": "Urban Device Care <info@urbandevicecare.co.uk>",
6
6
  "license": "MIT",