diff --git a/controller/documentTemplate/DocumentTemplateController.js b/controller/documentTemplate/DocumentTemplateController.js index 1e9e490..d355752 100644 --- a/controller/documentTemplate/DocumentTemplateController.js +++ b/controller/documentTemplate/DocumentTemplateController.js @@ -1619,32 +1619,49 @@ exports.previewLatestForMe = async (req, res) => { const [rows] = await db.execute('SELECT * FROM company_profiles WHERE user_id = ? LIMIT 1', [targetUserId]); const c = rows && rows[0] ? rows[0] : null; if (c) { - vars.companyName = c.company_name || ''; - vars.registrationNumber = c.registration_number || ''; - vars.companyAddress = c.address || ''; - vars.address = vars.companyAddress; - vars.zip_code = c.zip_code || ''; - vars.city = c.city || ''; - vars.country = c.country || ''; - vars.contactPersonName = c.contact_person_name || ''; - vars.contactPersonPhone = c.contact_person_phone || c.phone || ''; - vars.companyEmail = c.email || c.company_email || c.contact_email || req.user.email || ''; - vars.companyPhone = c.phone || c.contact_person_phone || ''; - const parts = []; - if (vars.companyAddress) parts.push(vars.companyAddress); - const zipCity = [vars.zip_code, vars.city].filter(Boolean).join(' '); - if (zipCity) parts.push(zipCity); - vars.companyFullAddress = parts.join(', '); - - // Ensure template-prefixed company placeholders are populated - vars.companyCompanyName = vars.companyName; - vars.companyRegistrationNumber = vars.registrationNumber; - vars.companyZipCode = vars.zip_code; - vars.companyCity = vars.city; - - // Signature/display name for company preview - vars.fullName = vars.contactPersonName || vars.companyName || ''; + setIfEmpty('companyName', c.company_name); + setIfEmpty('registrationNumber', c.registration_number); + setIfEmpty('companyAddress', c.address); + setIfEmpty('address', c.address); + setIfEmpty('zip_code', c.zip_code); + setIfEmpty('city', c.city); + setIfEmpty('country', c.country); + setIfEmpty('contactPersonName', c.contact_person_name); + setIfEmpty('contactPersonPhone', c.contact_person_phone || c.phone); + setIfEmpty('companyEmail', c.email || c.company_email || c.contact_email || req.user.email); + setIfEmpty('companyPhone', c.phone || c.contact_person_phone); } + + // Fallbacks from authenticated user payload (helps dummy/local users without profile rows) + setIfEmpty('companyName', req.user.companyName || req.user.company_name || req.user.company); + setIfEmpty('registrationNumber', req.user.registrationNumber || req.user.registration_number || req.user.vatNumber); + setIfEmpty('companyAddress', req.user.address || req.user.street || req.user.street_address); + setIfEmpty('address', req.user.address || req.user.street || req.user.street_address); + setIfEmpty('zip_code', req.user.zip_code || req.user.zip || req.user.postalCode || req.user.postal_code); + setIfEmpty('city', req.user.city || req.user.town); + setIfEmpty('country', req.user.country); + setIfEmpty('contactPersonName', req.user.contactPersonName || req.user.contact_person_name); + setIfEmpty('contactPersonPhone', req.user.contactPersonPhone || req.user.contact_person_phone || req.user.companyPhone || req.user.phone); + setIfEmpty('companyEmail', req.user.companyEmail || req.user.email); + setIfEmpty('companyPhone', req.user.companyPhone || req.user.phone); + + if (!vars.companyAddress) setIfEmpty('companyAddress', vars.address); + if (!vars.address) setIfEmpty('address', vars.companyAddress); + + const parts = []; + if (vars.companyAddress) parts.push(vars.companyAddress); + const zipCity = [vars.zip_code, vars.city].filter(Boolean).join(' '); + if (zipCity) parts.push(zipCity); + vars.companyFullAddress = parts.join(', '); + + // Ensure template-prefixed company placeholders are populated + vars.companyCompanyName = vars.companyName || ''; + vars.companyRegistrationNumber = vars.registrationNumber || ''; + vars.companyZipCode = vars.zip_code || ''; + vars.companyCity = vars.city || ''; + + // Signature/display name for company preview + vars.fullName = vars.contactPersonName || vars.companyName || vars.fullName || ''; logger.debug('[previewLatestForMe] company vars', { userId: targetUserId, found: !!c, vars }); } catch (e) { logger.warn('[previewLatestForMe] company profile lookup failed', e && e.message); diff --git a/services/contracts/ContractUploadService.js b/services/contracts/ContractUploadService.js index 8a99628..d00b383 100644 --- a/services/contracts/ContractUploadService.js +++ b/services/contracts/ContractUploadService.js @@ -3,6 +3,7 @@ const { uploadBuffer, s3: exoS3 } = require('../../utils/exoscaleUploader'); const PDFDocument = require('pdfkit'); const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); const DocumentTemplateService = require('../template/DocumentTemplateService'); +const CompanyStampService = require('../stamp/company/CompanyStampService'); const db = require('../../database/database'); const fs = require('fs'); const path = require('path'); @@ -49,7 +50,7 @@ async function streamToBuffer(body) { } function fillTemplate(template, data) { - return template.replace(/{{(\w+)}}/g, (_, key) => data[key] || ''); + return template.replace(/{{\s*(\w+)\s*}}/g, (_, key) => data[key] || ''); } // Build placeholder variables by combining DB profile data with any contractData overrides (for both personal/company). @@ -310,7 +311,7 @@ class ContractUploadService { // Merge DB-derived vars with request data so placeholders fill like the preview endpoint const vars = await buildTemplateVars({ userId, user_type, contractData, unitOfWork }); Object.entries(vars).forEach(([key, value]) => { - const re = new RegExp(`{{\s*${key}\s*}}`, 'g'); + const re = new RegExp(`{{\\s*${key}\\s*}}`, 'g'); htmlTemplate = htmlTemplate.replace(re, String(value ?? '')); }); if (signatureImage) { @@ -319,6 +320,17 @@ class ContractUploadService { htmlTemplate = htmlTemplate.replace(/{{\s*signatureImage\s*}}/g, tag); } + // Apply Profit Planet signature stamp if placeholder exists + try { + if (htmlTemplate.match(/{{\s*profitplanetSignature\s*}}/i)) { + const tag = await CompanyStampService.getProfitPlanetSignatureTag({ maxW: 300, maxH: 300 }); + htmlTemplate = htmlTemplate.replace(/{{\s*profitplanetSignature\s*}}/gi, tag || ''); + } + } catch (e) { + logger.warn('ContractUploadService.uploadContract:profitplanetSignature failed', { userId, msg: e.message }); + htmlTemplate = htmlTemplate.replace(/{{\s*profitplanetSignature\s*}}/gi, ''); + } + // Render HTML to PDF via Puppeteer (closest to preview output) const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage();