diff --git a/manager/server.selfhosted.js b/manager/server.selfhosted.js index b4975af..30c4eca 100644 --- a/manager/server.selfhosted.js +++ b/manager/server.selfhosted.js @@ -1674,36 +1674,85 @@ async function sendEvolutionMessage(asaasPaymentId, eventType, fallbackValorArg if (isPaymentConfirmation) { // GERAÇÃO DE RECIBO PROFISSIONAL (BACKEND - NODE COMPATIBLE) try { + let logoDataUrl = null; + let logoFormat = 'JPEG'; + try { + const appData = await getSchoolData(); + const logoUrl = firstRow.logo || appData.logo; + if (logoUrl) { + if (logoUrl.startsWith('data:image')) { + logoDataUrl = logoUrl; + logoFormat = logoUrl.toLowerCase().includes('png') ? 'PNG' : (logoUrl.toLowerCase().includes('webp') ? 'WEBP' : 'JPEG'); + } else if (logoUrl.startsWith('http')) { + const res = await fetch(logoUrl); + if (res.ok) { + const buffer = Buffer.from(await res.arrayBuffer()); + logoFormat = 'PNG'; + const pngBuffer = await sharp(buffer).png().toBuffer(); + logoDataUrl = `data:image/png;base64,${pngBuffer.toString('base64')}`; + } + } + } + } catch (e) { + console.error('[WhatsApp] Erro ao obter logo:', e.message); + } + const doc = new jsPDF(); + let currentY = 10; - // Moldura e Cabeçalho - doc.setDrawColor(0); - doc.setLineWidth(0.5); - doc.rect(10, 10, 190, 100); + if (logoDataUrl) { + try { + doc.addImage(logoDataUrl, logoFormat, 20, currentY + 5, 20, 20, undefined, 'FAST'); + } catch(e) { + console.error('[WhatsApp] Erro ao desenhar logo no PDF:', e.message); + } + } doc.setFontSize(14); doc.setFont('helvetica', 'bold'); - doc.text(profile.name || 'EduManager School', 105, 25, { align: 'center' }); + doc.text(profile.name || 'EduManager School', 105, currentY + 15, { align: 'center' }); doc.setFontSize(9); doc.setFont('helvetica', 'normal'); - doc.text(`CNPJ: ${profile.cnpj || '---'} | Contato: ${profile.phone || ''}`, 105, 32, { align: 'center' }); + doc.text(`CNPJ: ${profile.cnpj || '---'} | Contato: ${profile.phone || ''}`, 105, currentY + 22, { align: 'center' }); + currentY += 40; doc.setFontSize(16); - doc.text('RECIBO DE PAGAMENTO', 105, 50, { align: 'center' }); + doc.setFont('helvetica', 'bold'); + doc.text('RECIBO DE PAGAMENTO', 105, currentY, { align: 'center' }); + currentY += 15; doc.setFontSize(11); - doc.text(`Recebemos de: ${aluno.name}`, 20, 65); - doc.text(`A quantia de: R$ ${valorFormatado}`, 20, 75); - doc.text(`Referente a: ${descricao}`, 20, 85); + doc.setFont('helvetica', 'normal'); + doc.text(`Recebemos de: ${aluno.name}`, 20, currentY); + + currentY += 10; + doc.text(`A quantia de: R$ ${valorFormatado}`, 20, currentY); + + currentY += 10; + const refText = `Referente a: ${descricao}`; + const splitRef = doc.splitTextToSize(refText, 170); + doc.text(splitRef, 20, currentY); + + currentY += (splitRef.length * 6) + 4; const dataHj = new Date().toLocaleDateString('pt-BR'); const dataPagamento = fallbackVencimento ? formatCobrancaDate(typeof fallbackVencimento === 'string' ? fallbackVencimento : dataHj) : dataHj; - doc.text(`Data do Pagamento: ${dataPagamento}`, 20, 95); + doc.text(`Data do Pagamento: ${dataPagamento}`, 20, currentY); - doc.line(60, 105, 150, 105); + currentY += 15; + doc.line(60, currentY, 150, currentY); + + currentY += 5; doc.setFontSize(8); - doc.text('Autenticação Digital EduManager', 105, 108, { align: 'center' }); + doc.text('Autenticação Digital EduManager', 105, currentY, { align: 'center' }); + + currentY += 5; + + // Moldura Dinâmica + doc.setDrawColor(0); + doc.setLineWidth(0.5); + doc.rect(10, 10, 190, currentY - 10); const pdfArrayBuffer = doc.output('arraybuffer'); const pdfBuffer = Buffer.from(pdfArrayBuffer); diff --git a/manager/services/pdfService.ts b/manager/services/pdfService.ts index 6095fd1..ccb236f 100644 --- a/manager/services/pdfService.ts +++ b/manager/services/pdfService.ts @@ -599,8 +599,12 @@ export const pdfService = { const typeLabel = payment.type === 'registration' ? 'Taxa de Matrícula' : payment.type === 'monthly' ? 'Mensalidade do Curso' : 'Outros Serviços'; - doc.text(`Referente a: ${typeLabel} ${payment.description ? `(${payment.description})` : ''}`, 20, 95); - doc.text(`Data de Vencimento: ${payment.dueDate ? payment.dueDate.split('T')[0].split('-').reverse().join('/') : ''}`, 20, 105); + const refText = `Referente a: ${typeLabel} ${payment.description ? `(${payment.description})` : ''}`; + const splitRef = doc.splitTextToSize(refText, 170); + doc.text(splitRef, 20, 95); + + const nextY = 95 + (splitRef.length * 6); + doc.text(`Data de Vencimento: ${payment.dueDate ? payment.dueDate.split('T')[0].split('-').reverse().join('/') : ''}`, 20, nextY); if (payment.status === 'paid' && payment.paidDate) { doc.setFontSize(12);