refactor: remove unused CompanySettingsRepository and QR code handling logic

This commit is contained in:
seaznCode 2026-05-05 21:44:35 +02:00
parent baf53e36c1
commit 10552488c0

View File

@ -11,7 +11,6 @@ const fs = require('fs/promises');
const path = require('path'); const path = require('path');
const pool = require('../../database/database'); const pool = require('../../database/database');
const CompanySettingsRepository = require('../../repositories/settings/CompanySettingsRepository');
const CoffeeShippingFeeService = require('../subscriptions/CoffeeShippingFeeService'); const CoffeeShippingFeeService = require('../subscriptions/CoffeeShippingFeeService');
class InvoiceService { class InvoiceService {
@ -19,15 +18,6 @@ class InvoiceService {
this.repo = new InvoiceRepository(); this.repo = new InvoiceRepository();
} }
_inferImageMimeFromBase64(base64) {
const s = String(base64 || '').trim();
if (!s) return 'image/png';
if (s.startsWith('iVBORw0KGgo')) return 'image/png';
if (s.startsWith('/9j/')) return 'image/jpeg';
if (s.startsWith('R0lGOD')) return 'image/gif';
return 'image/png';
}
_templateHasVars(template, varNames) { _templateHasVars(template, varNames) {
if (!template) return false; if (!template) return false;
return varNames.every((name) => { return varNames.every((name) => {
@ -47,15 +37,19 @@ class InvoiceService {
} }
_resolvePieceCountForQr(abonement) { _resolvePieceCountForQr(abonement) {
const breakdown = Array.isArray(abonement?.pack_breakdown) ? abonement.pack_breakdown : [];
const totalPacks = breakdown.reduce((sum, item) => sum + Number(item?.packs || item?.quantity || 0), 0);
const piecesByPack = totalPacks ? totalPacks * 10 : null;
if (piecesByPack != null) {
if (piecesByPack >= 120) return 120;
if (piecesByPack >= 60) return 60;
return null;
}
const packGroup = String(abonement?.pack_group || '').toLowerCase(); const packGroup = String(abonement?.pack_group || '').toLowerCase();
if (packGroup.includes('120')) return 120; if (packGroup.includes('120')) return 120;
if (packGroup.includes('60')) return 60; if (packGroup.includes('60')) return 60;
const breakdown = Array.isArray(abonement?.pack_breakdown) ? abonement.pack_breakdown : [];
const totalPacks = breakdown.reduce((sum, item) => sum + Number(item?.packs || 0), 0);
const piecesByPack = totalPacks ? totalPacks * 10 : null;
if (piecesByPack === 60 || piecesByPack === 120) return piecesByPack;
return null; return null;
} }
@ -107,35 +101,8 @@ class InvoiceService {
return items; return items;
} }
async _getCompanySettingsQrDataUri(pieceCount) {
const safePieceCount = pieceCount === 120 ? 120 : 60;
try {
const repo = new CompanySettingsRepository();
const row = await repo.get();
if (!row) return null;
const raw = safePieceCount === 120 ? row?.qr_code_120_base64 : row?.qr_code_60_base64;
const value = (raw == null) ? '' : String(raw).trim();
if (!value) return null;
if (value.startsWith('data:image/')) return value;
const mime = this._inferImageMimeFromBase64(value);
return `data:${mime};base64,${value}`;
} catch (e) {
logger.warn('InvoiceService._getCompanySettingsQrDataUri:error', {
pieceCount: safePieceCount,
message: e?.message,
});
return null;
}
}
async _buildQrCodeImageTag({ abonement }) { async _buildQrCodeImageTag({ abonement }) {
const pieceCount = this._resolvePieceCountForQr(abonement); return '';
if (!pieceCount) return '';
const dataUri = await this._getCompanySettingsQrDataUri(pieceCount);
if (!dataUri) return '';
return `<img alt="QR Code" src="${this._escapeHtml(dataUri)}" />`;
} }
_escapeHtml(value) { _escapeHtml(value) {
@ -312,11 +279,10 @@ class InvoiceService {
_prepareVariablesForTemplate(templateHtml, variables) { _prepareVariablesForTemplate(templateHtml, variables) {
// Ensure backwards compatibility with older templates that only contain {{paymentInfoText}} // Ensure backwards compatibility with older templates that only contain {{paymentInfoText}}
// by injecting the Profit Planet bank block (and optionally QR) into paymentInfoText. // by injecting the Profit Planet bank block into paymentInfoText.
if (!templateHtml) return variables; if (!templateHtml) return variables;
const supportsBankVars = this._templateHasVars(templateHtml, ['bankAccountHolder', 'bankIban', 'bankBic']); const supportsBankVars = this._templateHasVars(templateHtml, ['bankAccountHolder', 'bankIban', 'bankBic']);
const supportsQrVar = this._templateHasVars(templateHtml, ['qrCodeImage']);
const bankBlock = this._getProfitPlanetBankBlockHtml({ const bankBlock = this._getProfitPlanetBankBlockHtml({
bankAccountHolder: variables.bankAccountHolder || 'Profit Planet GmbH', bankAccountHolder: variables.bankAccountHolder || 'Profit Planet GmbH',
@ -330,11 +296,6 @@ class InvoiceService {
next.paymentInfoText = bankBlock; next.paymentInfoText = bankBlock;
} }
if (!supportsQrVar && variables.qrCodeImage) {
// Append QR under payment info text when there's no dedicated placeholder
next.paymentInfoText = `${next.paymentInfoText || ''}<br><br>${variables.qrCodeImage}`;
}
return next; return next;
} }
@ -559,29 +520,14 @@ class InvoiceService {
if (templateHtml) { if (templateHtml) {
const supportsBankVars = this._templateHasVars(templateHtml, ['bankAccountHolder', 'bankIban', 'bankBic']); const supportsBankVars = this._templateHasVars(templateHtml, ['bankAccountHolder', 'bankIban', 'bankBic']);
const supportsQrVar = this._templateHasVars(templateHtml, ['qrCodeImage']);
const pieceCountForQr = this._resolvePieceCountForQr(abonement);
logger.info('InvoiceService._sendInvoiceEmail:template_compat', { logger.info('InvoiceService._sendInvoiceEmail:template_compat', {
invoiceId: invoice?.id, invoiceId: invoice?.id,
lang, lang,
supportsBankVars, supportsBankVars,
supportsQrVar,
pieceCountForQr,
hasQrImage: Boolean(variables?.qrCodeImage),
}); });
const varsForTemplate = this._prepareVariablesForTemplate(templateHtml, variables); const varsForTemplate = this._prepareVariablesForTemplate(templateHtml, variables);
html = this._renderTemplate(templateHtml, varsForTemplate); html = this._renderTemplate(templateHtml, varsForTemplate);
// Final guard: if we still didn't embed QR but we expected one, force local template
const missingQr = variables.qrCodeImage && !html.includes('data:image/png;base64,');
if (missingQr) {
const localTemplate = await this._loadLocalInvoiceTemplateHtml();
if (localTemplate) {
const varsForLocal = this._prepareVariablesForTemplate(localTemplate, variables);
html = this._renderTemplate(localTemplate, varsForLocal);
}
}
} }
const htmlForPdf = html || await this._buildFallbackInvoiceHtml({ invoice, items, abonement, lang }); const htmlForPdf = html || await this._buildFallbackInvoiceHtml({ invoice, items, abonement, lang });