From 5232fb1f2d4125d0a5252750b3b147534e27c361 Mon Sep 17 00:00:00 2001 From: seaznCode Date: Wed, 11 Mar 2026 22:29:46 +0100 Subject: [PATCH] feat: update invoice template loading to fetch from S3 and streamline user type handling --- services/invoice/InvoiceService.js | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/services/invoice/InvoiceService.js b/services/invoice/InvoiceService.js index 3d97225..04485fc 100644 --- a/services/invoice/InvoiceService.js +++ b/services/invoice/InvoiceService.js @@ -8,8 +8,6 @@ const { GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3'); const { s3: sharedExoscaleClient } = require('../../utils/exoscaleUploader'); const { logger } = require('../../middleware/logger'); const puppeteer = require('puppeteer'); -const fs = require('fs'); -const path = require('path'); const CompanySettingsRepository = require('../../repositories/settings/CompanySettingsRepository'); @@ -165,10 +163,19 @@ class InvoiceService { }).join(''); } - _loadInvoiceHtmlTemplate() { + async _loadInvoiceHtmlTemplate() { + // Load the latest active invoice template from the contract manager (S3) try { - const templatePath = path.join(__dirname, '..', '..', 'templates', 'invoice', 'invoiceTemplate.html'); - return fs.readFileSync(templatePath, 'utf8'); + const templates = await DocumentTemplateService.getActiveTemplatesForUserType('both', 'invoice'); + if (!Array.isArray(templates) || !templates.length) return null; + const selected = templates[0]; // latest active version + if (!selected?.storageKey) return null; + const command = new GetObjectCommand({ + Bucket: process.env.EXOSCALE_BUCKET, + Key: selected.storageKey, + }); + const obj = await sharedExoscaleClient.send(command); + return await this._s3BodyToString(obj.Body) || null; } catch (e) { logger.warn('InvoiceService._loadInvoiceHtmlTemplate:error', { message: e?.message }); return null; @@ -267,7 +274,7 @@ class InvoiceService { async _buildFallbackInvoiceHtml({ invoice, items, abonement, lang }) { const variables = await this._buildInvoiceTemplateVariables({ invoice, items, abonement, lang }); - const template = this._loadInvoiceHtmlTemplate(); + const template = await this._loadInvoiceHtmlTemplate(); if (template) { return this._renderTemplate(template, variables); } @@ -288,9 +295,9 @@ class InvoiceService { `; } - async _loadInvoiceTemplateHtml({ userType = 'personal', lang = 'en' } = {}) { + async _loadInvoiceTemplateHtml({ lang = 'en' } = {}) { try { - const templates = await DocumentTemplateService.getActiveTemplatesForUserType(userType, 'invoice'); + const templates = await DocumentTemplateService.getActiveTemplatesForUserType('both', 'invoice'); if (!Array.isArray(templates) || !templates.length) return null; const selected = templates.find((t) => t.lang === lang) || templates.find((t) => t.lang === 'en') || templates[0]; @@ -347,7 +354,7 @@ class InvoiceService { return key; } - async _sendInvoiceEmail({ invoice, abonement, userType = 'personal', lang = 'en' }) { + async _sendInvoiceEmail({ invoice, abonement, lang = 'en' }) { const recipientEmail = invoice.buyer_email || abonement?.email; if (!recipientEmail) { logger.warn('InvoiceService._sendInvoiceEmail:missing_recipient', { invoiceId: invoice.id }); @@ -361,7 +368,7 @@ class InvoiceService { // Build the full set of template variables once – used by both S3 and local paths const variables = await this._buildInvoiceTemplateVariables({ invoice, items, abonement, lang }); - const templateHtml = await this._loadInvoiceTemplateHtml({ userType, lang }); + const templateHtml = await this._loadInvoiceTemplateHtml({ lang }); let html = null; if (templateHtml) { @@ -414,7 +421,7 @@ class InvoiceService { } // Issue invoice for a subscription period, with items from pack_breakdown - async issueForAbonement(abonement, periodStart, periodEnd, { actorUserId, userType = 'personal', lang = 'en' } = {}) { + async issueForAbonement(abonement, periodStart, periodEnd, { actorUserId, lang = 'en' } = {}) { console.log('[INVOICE ISSUE] Inputs:', { abonement_id: abonement?.id, abonement_user_id: abonement?.user_id, @@ -505,7 +512,6 @@ class InvoiceService { await this._sendInvoiceEmail({ invoice, abonement, - userType, lang, }); logger.info('InvoiceService.issueForAbonement:invoice_email_sent', {