Files
ihaleist/src/services/pdf.js
T
hikmettan 0ab74143c0 feat: demo özelliklerini gerçekleştir — canlı veri + localStorage
- analytics.js: firmStats/itemStats/provinceDensity (gerçek hesaplama)
- Rakip Radar: canlı veriden kazanan firma analizi (mock 3 firma kaldırıldı)
- Fiyat Analizi: gerçek kalem min/medyan/ort/maks + CSV export
- TurkeyHeatMap: 81 il gerçek interaktif yoğunluk haritası (tıkla→filtrele)
- Favori kurumlar: kart yıldızı + hızlı filtre (localStorage)
- Ekip yönetimi: gerçek CRUD (RightSidebar) + Kanban ataması ekipten
- Bildirimler: gerçek Notification API + izin + test + sessiz saatler
- PDF: jsPDF ile gerçek birim fiyat teklif cetveli (kaşe/imza alanı)
2026-08-28 01:58:46 +03:00

98 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Gerçek PDF üretimi (jsPDF) — Birim Fiyat Teklif Cetveli.
* İhalenin kalemlerini tabloya döker, girilen birim fiyatlarla toplamı hesaplar,
* firma bilgisi + kaşe/imza alanı ekler ve indirir.
*/
import { jsPDF } from 'jspdf';
const money = (n) =>
(Number(n) || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
export function generateBidSheetPDF(tender, { firma = 'Firma Adı', prices = {}, stamp = true } = {}) {
const doc = new jsPDF({ unit: 'mm', format: 'a4' });
const W = 210;
const M = 15;
let y = 18;
doc.setFont('helvetica', 'bold');
doc.setFontSize(15);
doc.text('BIRIM FIYAT TEKLIF CETVELI', W / 2, y, { align: 'center' });
y += 8;
doc.setFontSize(9);
doc.setFont('helvetica', 'normal');
const ikn = tender.ikn || '';
const kurum = (tender.kurum || '').slice(0, 90);
doc.text(`Idare: ${kurum}`, M, y); y += 5;
doc.text(`Isin Adi: ${(tender.baslik || '').slice(0, 95)}`, M, y); y += 5;
doc.text(`IKN / DTN: ${ikn} Tarih: ${tender.tarih || ''}`, M, y); y += 5;
doc.text(`Teklif Veren: ${firma}`, M, y); y += 8;
// Tablo başlığı
const cols = [
{ t: 'No', x: M, w: 12, a: 'left' },
{ t: 'Mal / Hizmet Adi', x: M + 12, w: 88, a: 'left' },
{ t: 'Miktar', x: M + 100, w: 20, a: 'right' },
{ t: 'Birim', x: M + 120, w: 18, a: 'left' },
{ t: 'B.Fiyat', x: M + 138, w: 20, a: 'right' },
{ t: 'Tutar', x: M + 158, w: 22, a: 'right' },
];
doc.setFillColor(30, 58, 138);
doc.setTextColor(255);
doc.setFont('helvetica', 'bold');
doc.rect(M, y - 4.5, W - 2 * M, 7, 'F');
cols.forEach((c) => doc.text(c.t, c.a === 'right' ? c.x + c.w - 1 : c.x + 1, y, { align: c.a }));
y += 5;
doc.setTextColor(20);
doc.setFont('helvetica', 'normal');
doc.setFontSize(8.5);
const items = tender.items && tender.items.length ? tender.items : [{ id: 'x1', ad: '(Kalem girilmemis)', miktar: '', birim: '' }];
let total = 0;
items.forEach((it, i) => {
const bf = Number(prices[it.id] ?? it.birimFiyat ?? 0);
const miktar = parseFloat(String(it.miktar).replace(',', '.')) || 0;
const tutar = bf * miktar;
total += tutar;
if (i % 2 === 0) { doc.setFillColor(245, 247, 250); doc.rect(M, y - 4, W - 2 * M, 6, 'F'); }
doc.text(String(i + 1), M + 1, y);
doc.text(String(it.ad || '').slice(0, 60), M + 13, y);
doc.text(String(it.miktar || ''), M + 120 - 1, y, { align: 'right' });
doc.text(String(it.birim || ''), M + 120 + 1, y);
doc.text(bf ? money(bf) : '—', M + 158 - 1, y, { align: 'right' });
doc.text(tutar ? money(tutar) : '—', W - M - 1, y, { align: 'right' });
y += 6;
if (y > 250) { doc.addPage(); y = 20; }
});
// Toplam
doc.setFont('helvetica', 'bold');
doc.setFontSize(10);
doc.setDrawColor(200);
doc.line(M, y - 2, W - M, y - 2);
y += 4;
doc.text('GENEL TOPLAM (KDV Haric):', M + 90, y, { align: 'right' });
doc.text(`${money(total)} TL`, W - M - 1, y, { align: 'right' });
y += 16;
// Kaşe / imza alanı
if (stamp) {
doc.setFont('helvetica', 'normal');
doc.setFontSize(9);
doc.setDrawColor(150);
doc.roundedRect(W - M - 60, y, 60, 30, 2, 2);
doc.text('Kase ve Imza', W - M - 30, y + 17, { align: 'center' });
doc.setTextColor(120);
doc.setFontSize(7.5);
doc.text(firma, W - M - 30, y + 23, { align: 'center' });
}
doc.setTextColor(150);
doc.setFontSize(7);
doc.text('Ihaleist ile olusturulmustur — ihaleist.seymata.com', M, 288);
const safe = (ikn || tender.baslik || 'teklif').replace(/[^\w]+/g, '_').slice(0, 40);
doc.save(`teklif_cetveli_${safe}.pdf`);
return total;
}