receipts.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. const express = require('express');
  2. const PDFDocument = require('pdfkit');
  3. const db = require('../db');
  4. const { authMiddleware } = require('../auth');
  5. const router = express.Router();
  6. router.use(authMiddleware);
  7. const MONTHS_FR = ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'];
  8. router.get('/:paymentId', (req, res) => {
  9. const payment = db.prepare(`
  10. SELECT p.*,
  11. l.rent_amount, l.charges_amount, l.deposit_amount,
  12. pr.name as property_name, pr.address as property_address, pr.city as property_city, pr.zip_code as property_zip,
  13. t.first_name as tenant_first_name, t.last_name as tenant_last_name, t.email as tenant_email,
  14. u.name as owner_name, u.email as owner_email
  15. FROM payments p
  16. JOIN leases l ON p.lease_id = l.id
  17. JOIN properties pr ON l.property_id = pr.id
  18. JOIN tenants t ON l.tenant_id = t.id
  19. JOIN users u ON p.user_id = u.id
  20. WHERE p.id = ? AND p.user_id = ?
  21. `).get(req.params.paymentId, req.userId);
  22. if (!payment) return res.status(404).json({ error: 'Paiement non trouvé' });
  23. const doc = new PDFDocument({ size: 'A4', margin: 50 });
  24. res.setHeader('Content-Type', 'application/pdf');
  25. res.setHeader('Content-Disposition', `attachment; filename=quittance_${payment.period_year}_${String(payment.period_month).padStart(2,'0')}.pdf`);
  26. doc.pipe(res);
  27. const monthName = MONTHS_FR[payment.period_month - 1];
  28. const total = payment.rent_paid + payment.charges_paid;
  29. // Header
  30. doc.fontSize(22).font('Helvetica-Bold').text('QUITTANCE DE LOYER', { align: 'center' });
  31. doc.moveDown(0.3);
  32. doc.fontSize(14).font('Helvetica').text(`Période : ${monthName} ${payment.period_year}`, { align: 'center' });
  33. doc.moveDown(1.5);
  34. // Separator
  35. doc.moveTo(50, doc.y).lineTo(545, doc.y).strokeColor('#2563eb').lineWidth(2).stroke();
  36. doc.moveDown(1);
  37. // Bailleur
  38. doc.fontSize(12).font('Helvetica-Bold').text('BAILLEUR');
  39. doc.font('Helvetica').fontSize(11)
  40. .text(payment.owner_name)
  41. .text(payment.owner_email);
  42. doc.moveDown(1);
  43. // Locataire
  44. doc.fontSize(12).font('Helvetica-Bold').text('LOCATAIRE');
  45. doc.font('Helvetica').fontSize(11)
  46. .text(`${payment.tenant_first_name} ${payment.tenant_last_name}`)
  47. .text(payment.tenant_email || '');
  48. doc.moveDown(1);
  49. // Bien loué
  50. doc.fontSize(12).font('Helvetica-Bold').text('BIEN LOUÉ');
  51. doc.font('Helvetica').fontSize(11)
  52. .text(payment.property_name)
  53. .text(`${payment.property_address}`)
  54. .text(`${payment.property_zip} ${payment.property_city}`);
  55. doc.moveDown(1);
  56. // Separator
  57. doc.moveTo(50, doc.y).lineTo(545, doc.y).strokeColor('#e5e7eb').lineWidth(1).stroke();
  58. doc.moveDown(1);
  59. // Détail paiement
  60. doc.fontSize(12).font('Helvetica-Bold').text('DÉTAIL DU RÈGLEMENT');
  61. doc.moveDown(0.5);
  62. const tableTop = doc.y;
  63. const col1 = 50, col2 = 400;
  64. const drawRow = (label, value, bold = false) => {
  65. const y = doc.y;
  66. doc.font(bold ? 'Helvetica-Bold' : 'Helvetica').fontSize(11);
  67. doc.text(label, col1, y);
  68. doc.text(`${value.toFixed(2)} €`, col2, y, { width: 100, align: 'right' });
  69. doc.moveDown(0.6);
  70. };
  71. drawRow('Loyer hors charges', payment.rent_paid);
  72. drawRow('Charges', payment.charges_paid);
  73. doc.moveTo(50, doc.y).lineTo(545, doc.y).strokeColor('#e5e7eb').lineWidth(0.5).stroke();
  74. doc.moveDown(0.3);
  75. drawRow('TOTAL', total, true);
  76. doc.moveDown(0.5);
  77. // Mode et date de paiement
  78. const paymentMethods = { virement: 'Virement bancaire', cheque: 'Chèque', especes: 'Espèces', prelevement: 'Prélèvement automatique' };
  79. doc.font('Helvetica').fontSize(11)
  80. .text(`Mode de paiement : ${paymentMethods[payment.payment_method] || payment.payment_method}`)
  81. .text(`Date de paiement : ${new Date(payment.payment_date).toLocaleDateString('fr-FR')}`);
  82. if (payment.notes) {
  83. doc.moveDown(0.5).text(`Notes : ${payment.notes}`);
  84. }
  85. doc.moveDown(2);
  86. // Attestation
  87. doc.moveTo(50, doc.y).lineTo(545, doc.y).strokeColor('#e5e7eb').lineWidth(1).stroke();
  88. doc.moveDown(1);
  89. doc.font('Helvetica').fontSize(10).fillColor('#6b7280')
  90. .text(
  91. `Je soussigné(e) ${payment.owner_name}, bailleur, donne quittance à ${payment.tenant_first_name} ${payment.tenant_last_name} ` +
  92. `pour la somme de ${total.toFixed(2)} € correspondant au paiement du loyer et des charges du logement situé ` +
  93. `${payment.property_address}, ${payment.property_zip} ${payment.property_city}, ` +
  94. `pour la période de ${monthName} ${payment.period_year}.`,
  95. { align: 'justify' }
  96. );
  97. doc.moveDown(3);
  98. doc.fontSize(11).fillColor('#000000').text(`Fait le ${new Date().toLocaleDateString('fr-FR')}`);
  99. doc.moveDown(2);
  100. doc.text('Signature du bailleur :', { continued: false });
  101. doc.moveDown(1);
  102. doc.moveTo(50, doc.y).lineTo(200, doc.y).strokeColor('#000').lineWidth(1).stroke();
  103. doc.end();
  104. });
  105. module.exports = router;