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.
Files changed (39) hide show
  1. package/.medusa/server/src/admin/index.js +2427 -0
  2. package/.medusa/server/src/admin/index.mjs +2428 -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/models/document-link.js +12 -0
  21. package/.medusa/server/src/modules/documents/models/document-record.js +33 -0
  22. package/.medusa/server/src/modules/documents/models/document-settings.js +61 -0
  23. package/.medusa/server/src/modules/documents/service.js +456 -0
  24. package/.medusa/server/src/services/notification-sender.js +293 -0
  25. package/.medusa/server/src/services/pdf-post-processor.js +64 -0
  26. package/.medusa/server/src/services/pdfkit-generator.js +438 -0
  27. package/.medusa/server/src/services/zoho-books.js +221 -0
  28. package/.medusa/server/src/subscribers/order-documents.js +178 -0
  29. package/.medusa/server/src/subscribers/repair-documents.js +162 -0
  30. package/.medusa/server/src/utils/integrate.js +37 -0
  31. package/.medusa/server/src/utils/payment-link.js +69 -0
  32. package/.medusa/server/src/workflows/create-manual-document.js +27 -0
  33. package/.medusa/server/src/workflows/generate-document.js +24 -0
  34. package/.medusa/server/src/workflows/index.js +20 -0
  35. package/.medusa/server/src/workflows/send-document-notification.js +41 -0
  36. package/CHANGELOG.md +87 -0
  37. package/LICENSE +21 -0
  38. package/README.md +201 -2
  39. package/package.json +86 -4
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationSender = void 0;
4
+ exports.renderTemplatePlaceholders = renderTemplatePlaceholders;
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ /**
7
+ * Replaces placeholders in format {variable_name} with actual values.
8
+ * Supported variables are case-insensitive.
9
+ */
10
+ function renderTemplatePlaceholders(template, variables) {
11
+ if (!template)
12
+ return "";
13
+ return template.replace(/\{([a-zA-Z0-9_]+)\}/g, (match, key) => {
14
+ if (key in variables && variables[key] != null) {
15
+ return String(variables[key]);
16
+ }
17
+ const lowerKey = key.toLowerCase();
18
+ for (const [k, v] of Object.entries(variables)) {
19
+ if (k.toLowerCase() === lowerKey && v != null) {
20
+ return String(v);
21
+ }
22
+ }
23
+ return "";
24
+ });
25
+ }
26
+ class NotificationSender {
27
+ static async send(options) {
28
+ const { container, document, settings } = options;
29
+ const logger = container.resolve("logger");
30
+ const sent = [];
31
+ const failed = [];
32
+ let notificationModule = null;
33
+ try {
34
+ notificationModule = container.resolve(utils_1.ModuleRegistrationName.NOTIFICATION, {
35
+ allowUnregistered: true,
36
+ });
37
+ }
38
+ catch (e) {
39
+ try {
40
+ notificationModule = container.resolve("notification", { allowUnregistered: true });
41
+ }
42
+ catch (err) { }
43
+ }
44
+ if (!notificationModule) {
45
+ logger.warn(`[Documents-Notify] Notification module not found in container. Skipping dispatch.`);
46
+ return { sent, failed: ["Notification module not found"] };
47
+ }
48
+ // Determine target channels based on settings & options
49
+ const activeChannels = options.channels || [];
50
+ if (activeChannels.length === 0) {
51
+ if (settings?.email_notifications_enabled !== false)
52
+ activeChannels.push("email");
53
+ if (settings?.sms_notifications_enabled !== false)
54
+ activeChannels.push("sms");
55
+ if (settings?.whatsapp_notifications_enabled !== false)
56
+ activeChannels.push("whatsapp");
57
+ }
58
+ const companyName = settings?.company_name || "Company Store";
59
+ const customerName = document.customer_name || "Valued Customer";
60
+ const currency = (document.currency_code || "USD").toUpperCase();
61
+ const formattedTotal = new Intl.NumberFormat("en-US", {
62
+ style: "currency",
63
+ currency: currency,
64
+ }).format(Number(document.total_amount || 0));
65
+ const docUrl = document.short_pdf_link || document.pdf_url || "";
66
+ const payUrl = document.short_payment_link || document.payment_link || "";
67
+ const isUnpaid = document.payment_status === "unpaid" && Number(document.total_amount || 0) > 0;
68
+ const docTitle = document.title || (document.type === "job_card" ? "Repair Job Card" :
69
+ document.type === "invoice" ? "Invoice" :
70
+ document.type === "receipt" ? "Receipt" :
71
+ document.type === "packing_slip" ? "Packing Slip" :
72
+ document.type === "estimate" ? "Estimate" : "Document");
73
+ // Build common action HTML blocks
74
+ let paymentButtonHtml = "";
75
+ if (isUnpaid && payUrl) {
76
+ paymentButtonHtml = `
77
+ <div style="margin: 20px 0; padding: 16px; background-color: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px;">
78
+ <p style="margin: 0 0 10px 0; font-weight: bold; color: #166534; font-size: 15px;">Payment Due: ${formattedTotal}</p>
79
+ <a href="${payUrl}" style="background-color: #16a34a; color: #ffffff; padding: 10px 20px; text-decoration: none; border-radius: 6px; font-weight: bold; display: inline-block;">Pay Balance Online</a>
80
+ </div>
81
+ `;
82
+ }
83
+ let docDownloadHtml = "";
84
+ if (docUrl) {
85
+ docDownloadHtml = `
86
+ <div style="margin: 15px 0;">
87
+ <a href="${docUrl}" style="background-color: #2563eb; color: #ffffff; padding: 10px 20px; text-decoration: none; border-radius: 6px; font-weight: bold; display: inline-block;">📄 View / Download ${docTitle}</a>
88
+ </div>
89
+ `;
90
+ }
91
+ let customMsgHtml = "";
92
+ if (document.custom_message) {
93
+ customMsgHtml = `
94
+ <div style="margin: 15px 0; padding: 12px; background-color: #f8fafc; border-left: 4px solid #3b82f6; color: #334155;">
95
+ <p style="margin: 0; white-space: pre-wrap;">${document.custom_message}</p>
96
+ </div>
97
+ `;
98
+ }
99
+ // Template replacement variables
100
+ const variables = {
101
+ customer_name: customerName,
102
+ customer_email: document.customer_email || "",
103
+ customer_phone: document.customer_phone || "",
104
+ company_name: companyName,
105
+ document_title: docTitle,
106
+ display_id: document.display_id,
107
+ total_amount: formattedTotal,
108
+ total: formattedTotal,
109
+ currency: currency,
110
+ currency_code: currency,
111
+ payment_status: document.payment_status || "",
112
+ payment_link: payUrl,
113
+ document_link: docUrl,
114
+ download_link: docUrl,
115
+ pdf_url: docUrl,
116
+ custom_message: document.custom_message || "",
117
+ payment_button: paymentButtonHtml,
118
+ download_button: docDownloadHtml,
119
+ };
120
+ // -------------------------------------------------------------
121
+ // 1. EMAIL DISPATCH
122
+ // -------------------------------------------------------------
123
+ if (activeChannels.includes("email") && document.customer_email) {
124
+ try {
125
+ let subject = document.subject;
126
+ if (!subject) {
127
+ if (settings?.email_subject_template && settings.email_subject_template.trim()) {
128
+ subject = renderTemplatePlaceholders(settings.email_subject_template, variables);
129
+ }
130
+ else {
131
+ subject = `${companyName}: ${docTitle} #${document.display_id}`;
132
+ }
133
+ }
134
+ let emailHtml = "";
135
+ if (settings?.email_body_template && settings.email_body_template.trim()) {
136
+ let customBody = renderTemplatePlaceholders(settings.email_body_template, variables);
137
+ // If the custom template didn't explicitly use button placeholders, append action blocks if relevant
138
+ const hasPayTag = settings.email_body_template.includes("{payment_button}") || settings.email_body_template.includes("{payment_link}");
139
+ const hasDocTag = settings.email_body_template.includes("{download_button}") || settings.email_body_template.includes("{document_link}") || settings.email_body_template.includes("{pdf_url}");
140
+ let appendedActions = "";
141
+ if (!hasPayTag && paymentButtonHtml)
142
+ appendedActions += paymentButtonHtml;
143
+ if (!hasDocTag && docDownloadHtml)
144
+ appendedActions += docDownloadHtml;
145
+ if (appendedActions) {
146
+ customBody += appendedActions;
147
+ }
148
+ if (customBody.includes("<html") || (customBody.includes("<div") && customBody.includes("max-width:"))) {
149
+ emailHtml = customBody;
150
+ }
151
+ else {
152
+ emailHtml = `
153
+ <div style="font-family: Arial, sans-serif; color: #1e293b; max-width: 600px; margin: 0 auto; line-height: 1.6; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;">
154
+ <div style="background-color: #2563eb; padding: 20px; color: #ffffff;">
155
+ <h2 style="margin: 0; font-size: 20px;">${companyName}</h2>
156
+ <p style="margin: 5px 0 0 0; opacity: 0.9; font-size: 14px;">${docTitle} #${document.display_id}</p>
157
+ </div>
158
+ <div style="padding: 24px;">
159
+ ${customBody}
160
+ </div>
161
+ </div>
162
+ `;
163
+ }
164
+ }
165
+ else {
166
+ emailHtml = `
167
+ <div style="font-family: Arial, sans-serif; color: #1e293b; max-width: 600px; margin: 0 auto; line-height: 1.6; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;">
168
+ <div style="background-color: #2563eb; padding: 20px; color: #ffffff;">
169
+ <h2 style="margin: 0; font-size: 20px;">${companyName}</h2>
170
+ <p style="margin: 5px 0 0 0; opacity: 0.9; font-size: 14px;">${docTitle} #${document.display_id}</p>
171
+ </div>
172
+ <div style="padding: 24px;">
173
+ <p>Hello <strong>${customerName}</strong>,</p>
174
+ <p>Your ${docTitle.toLowerCase()} <strong>#${document.display_id}</strong> is ready.</p>
175
+ ${customMsgHtml}
176
+ ${paymentButtonHtml}
177
+ ${docDownloadHtml}
178
+ <p style="margin-top: 25px; font-size: 13px; color: #64748b;">
179
+ Thank you for choosing ${companyName}. If you have any questions, please feel free to reach out.
180
+ </p>
181
+ </div>
182
+ </div>
183
+ `;
184
+ }
185
+ await notificationModule.createNotifications({
186
+ to: document.customer_email,
187
+ channel: "email",
188
+ template: "document-notification-email",
189
+ content: {
190
+ subject: subject,
191
+ html: emailHtml,
192
+ },
193
+ data: {
194
+ document_id: document.id,
195
+ display_id: document.display_id,
196
+ type: document.type,
197
+ total: document.total_amount,
198
+ pdf_url: docUrl,
199
+ payment_link: payUrl,
200
+ },
201
+ });
202
+ sent.push("email");
203
+ logger.info(`[Documents-Notify] Email sent to ${document.customer_email} for ${document.display_id}`);
204
+ }
205
+ catch (err) {
206
+ failed.push(`email: ${err.message}`);
207
+ logger.error(`[Documents-Notify] Failed to send email to ${document.customer_email}: ${err.message}`);
208
+ }
209
+ }
210
+ // -------------------------------------------------------------
211
+ // 2. SMS DISPATCH
212
+ // -------------------------------------------------------------
213
+ if (activeChannels.includes("sms") && document.customer_phone) {
214
+ try {
215
+ let smsText = "";
216
+ if (settings?.sms_body_template && settings.sms_body_template.trim()) {
217
+ smsText = renderTemplatePlaceholders(settings.sms_body_template, variables);
218
+ }
219
+ else {
220
+ smsText = `[${companyName}] Hi ${customerName}, your ${docTitle} #${document.display_id} is ready.`;
221
+ if (Number(document.total_amount || 0) > 0) {
222
+ smsText += ` Total: ${formattedTotal}.`;
223
+ }
224
+ if (isUnpaid && payUrl) {
225
+ smsText += ` Pay: ${payUrl}`;
226
+ }
227
+ if (docUrl) {
228
+ smsText += ` View: ${docUrl}`;
229
+ }
230
+ }
231
+ await notificationModule.createNotifications({
232
+ to: document.customer_phone,
233
+ channel: "sms",
234
+ template: "document-notification-sms",
235
+ data: {
236
+ body: smsText,
237
+ text: smsText,
238
+ document_id: document.id,
239
+ },
240
+ });
241
+ sent.push("sms");
242
+ logger.info(`[Documents-Notify] SMS sent to ${document.customer_phone} for ${document.display_id}`);
243
+ }
244
+ catch (err) {
245
+ failed.push(`sms: ${err.message}`);
246
+ logger.error(`[Documents-Notify] Failed to send SMS to ${document.customer_phone}: ${err.message}`);
247
+ }
248
+ }
249
+ // -------------------------------------------------------------
250
+ // 3. WHATSAPP DISPATCH
251
+ // -------------------------------------------------------------
252
+ if (activeChannels.includes("whatsapp") && document.customer_phone) {
253
+ try {
254
+ let waText = "";
255
+ if (settings?.whatsapp_body_template && settings.whatsapp_body_template.trim()) {
256
+ waText = renderTemplatePlaceholders(settings.whatsapp_body_template, variables);
257
+ }
258
+ else {
259
+ waText = `*${companyName}*\nHello *${customerName}*,\nYour *${docTitle} #${document.display_id}* has been generated.`;
260
+ if (Number(document.total_amount || 0) > 0) {
261
+ waText += `\n*Amount:* ${formattedTotal}`;
262
+ }
263
+ if (isUnpaid && payUrl) {
264
+ waText += `\n*Pay Online:* ${payUrl}`;
265
+ }
266
+ if (docUrl) {
267
+ waText += `\n*Download PDF:* ${docUrl}`;
268
+ }
269
+ }
270
+ await notificationModule.createNotifications({
271
+ to: document.customer_phone,
272
+ channel: "whatsapp",
273
+ template: "document-notification-whatsapp",
274
+ data: {
275
+ body: waText,
276
+ text: waText,
277
+ document_id: document.id,
278
+ },
279
+ });
280
+ sent.push("whatsapp");
281
+ logger.info(`[Documents-Notify] WhatsApp sent to ${document.customer_phone} for ${document.display_id}`);
282
+ }
283
+ catch (err) {
284
+ failed.push(`whatsapp: ${err.message}`);
285
+ logger.error(`[Documents-Notify] Failed to send WhatsApp to ${document.customer_phone}: ${err.message}`);
286
+ }
287
+ }
288
+ return { sent, failed };
289
+ }
290
+ }
291
+ exports.NotificationSender = NotificationSender;
292
+ exports.default = NotificationSender;
293
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9uLXNlbmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9ub3RpZmljYXRpb24tc2VuZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQStCQSxnRUFpQkM7QUEvQ0QscURBQW1FO0FBMEJuRTs7O0dBR0c7QUFDSCxTQUFnQiwwQkFBMEIsQ0FDeEMsUUFBZ0IsRUFDaEIsU0FBNkQ7SUFFN0QsSUFBSSxDQUFDLFFBQVE7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUN6QixPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDN0QsSUFBSSxHQUFHLElBQUksU0FBUyxJQUFJLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMvQyxPQUFPLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25DLEtBQUssTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLEtBQUssUUFBUSxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDOUMsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkIsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELE1BQWEsa0JBQWtCO0lBQzdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQWdDO1FBQ2hELE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFHLE9B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
@@ -0,0 +1,64 @@
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.postProcessPdf = postProcessPdf;
7
+ const pdf_lib_1 = require("pdf-lib");
8
+ const qrcode_1 = __importDefault(require("qrcode"));
9
+ /**
10
+ * Post-processes PDF buffers to embed QR codes and clean up headers/footers.
11
+ * (Note: Watermarks removed per user instruction)
12
+ */
13
+ async function postProcessPdf(pdfBuffer, options = {}) {
14
+ try {
15
+ const pdfDoc = await pdf_lib_1.PDFDocument.load(pdfBuffer);
16
+ // 1. Generate & Embed QR Code if URL is provided
17
+ let qrImage = null;
18
+ if (options.qrUrl) {
19
+ try {
20
+ const qrBufferLib = await qrcode_1.default.toBuffer(options.qrUrl, {
21
+ errorCorrectionLevel: "H",
22
+ type: "png",
23
+ margin: 1,
24
+ width: 75,
25
+ });
26
+ qrImage = await pdfDoc.embedPng(qrBufferLib);
27
+ }
28
+ catch (qrErr) {
29
+ console.error("[postProcessPdf] QR Code generation error:", qrErr);
30
+ }
31
+ }
32
+ const pages = pdfDoc.getPages();
33
+ if (pages.length > 0 && qrImage) {
34
+ const firstPage = pages[0];
35
+ // Draw QR Code on top right
36
+ firstPage.drawImage(qrImage, {
37
+ x: firstPage.getWidth() - 105,
38
+ y: 40,
39
+ width: 65,
40
+ height: 65,
41
+ });
42
+ }
43
+ // 2. Obscure external footer (e.g. "Powered by Zoho Books") if requested
44
+ if (options.obscureZohoFooter) {
45
+ for (const page of pages) {
46
+ page.drawRectangle({
47
+ x: 0,
48
+ y: 0,
49
+ width: page.getWidth(),
50
+ height: 35,
51
+ color: (0, pdf_lib_1.rgb)(1, 1, 1),
52
+ });
53
+ }
54
+ }
55
+ const modifiedPdfBytes = await pdfDoc.save();
56
+ return Buffer.from(modifiedPdfBytes);
57
+ }
58
+ catch (err) {
59
+ console.error("[postProcessPdf] Error processing PDF:", err?.message || err);
60
+ return pdfBuffer; // fallback cleanly to original buffer
61
+ }
62
+ }
63
+ exports.default = postProcessPdf;
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmLXBvc3QtcHJvY2Vzc29yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3BkZi1wb3N0LXByb2Nlc3Nvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVlBLHdDQXVEQztBQW5FRCxxQ0FBd0Q7QUFDeEQsb0RBQTRCO0FBTzVCOzs7R0FHRztBQUNJLEtBQUssVUFBVSxjQUFjLENBQ2xDLFNBQWlCLEVBQ2pCLFVBQThCLEVBQUU7SUFFaEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLEdBQUcsTUFBTSxxQkFBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUUvQyxpREFBaUQ7UUFDakQsSUFBSSxPQUFPLEdBQVEsSUFBSSxDQUFDO1FBQ3hCLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQztnQkFDSCxNQUFNLFdBQVcsR0FBRyxNQUFNLGdCQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUU7b0JBQ3ZELG9CQUFvQixFQUFFLEdBQUc7b0JBQ3pCLElBQUksRUFBRSxLQUFLO29CQUNYLE1BQU0sRUFBRSxDQUFDO29CQUNULEtBQUssRUFBRSxFQUFFO2lCQUNWLENBQUMsQ0FBQztnQkFDSCxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQy9DLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsNENBQTRDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDckUsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFaEMsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNoQyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDM0IsNEJBQTRCO1lBQzVCLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFO2dCQUMzQixDQUFDLEVBQUUsU0FBUyxDQUFDLFFBQVEsRUFBRSxHQUFHLEdBQUc7Z0JBQzdCLENBQUMsRUFBRSxFQUFFO2dCQUNMLEtBQUssRUFBRSxFQUFFO2dCQUNULE1BQU0sRUFBRSxFQUFFO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHlFQUF5RTtRQUN6RSxJQUFJLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzlCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxhQUFhLENBQUM7b0JBQ2pCLENBQUMsRUFBRSxDQUFDO29CQUNKLENBQUMsRUFBRSxDQUFDO29CQUNKLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFO29CQUN0QixNQUFNLEVBQUUsRUFBRTtvQkFDVixLQUFLLEVBQUUsSUFBQSxhQUFHLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7aUJBQ3BCLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO1FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM3QyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBQUMsT0FBTyxHQUFRLEVBQUUsQ0FBQztRQUNsQixPQUFPLENBQUMsS0FBSyxDQUFDLHdDQUF3QyxFQUFFLEdBQUcsRUFBRSxPQUFPLElBQUksR0FBRyxDQUFDLENBQUM7UUFDN0UsT0FBTyxTQUFTLENBQUMsQ0FBQyxzQ0FBc0M7SUFDMUQsQ0FBQztBQUNILENBQUM7QUFFRCxrQkFBZSxjQUFjLENBQUMifQ==