171 lines
7.0 KiB
PHP
171 lines
7.0 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../db/config.php';
|
|
require_once '/usr/share/php/tcpdf/tcpdf.php';
|
|
|
|
// Extend TCPDF with custom Header and Footer
|
|
class MYPDF extends TCPDF {
|
|
public function Header() {
|
|
$this->SetFont('helvetica', 'B', 20);
|
|
$this->Cell(0, 15, 'CRM PRO DOCUMENT', 0, false, 'L', 0, '', 0, false, 'M', 'M');
|
|
$this->Ln(10);
|
|
$this->SetFont('helvetica', '', 10);
|
|
$this->Cell(0, 10, 'Your Trusted Partner in Education', 0, false, 'L', 0, '', 0, false, 'M', 'M');
|
|
$this->Line(10, 30, 200, 30);
|
|
}
|
|
|
|
public function Footer() {
|
|
$this->SetY(-15);
|
|
$this->SetFont('helvetica', 'I', 8);
|
|
$this->Cell(0, 10, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
|
|
}
|
|
}
|
|
|
|
class DocumentService {
|
|
|
|
public static function generateQuotationPDF($id, $dest = 'I') {
|
|
$stmt = db()->prepare("SELECT q.*, c.name as customer_name, c.email as customer_email, c.phone as customer_phone, c.address as customer_address
|
|
FROM quotations q
|
|
JOIN customers c ON q.customer_id = c.id
|
|
WHERE q.id = ? AND q.deleted_at IS NULL");
|
|
$stmt->execute([$id]);
|
|
$quotation = $stmt->fetch();
|
|
|
|
if (!$quotation) return null;
|
|
|
|
$stmt = db()->prepare("SELECT qi.*, p.name as product_name
|
|
FROM quotation_items qi
|
|
JOIN products p ON qi.product_id = p.id
|
|
WHERE qi.quotation_id = ?");
|
|
$stmt->execute([$id]);
|
|
$items = $stmt->fetchAll();
|
|
|
|
$pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
|
$pdf->SetCreator(PDF_CREATOR);
|
|
$pdf->SetAuthor('CRM PRO');
|
|
$pdf->SetTitle('Quotation ' . $quotation['quotation_number']);
|
|
$pdf->SetMargins(PDF_MARGIN_LEFT, 40, PDF_MARGIN_RIGHT);
|
|
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
|
|
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
|
|
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->AddPage();
|
|
|
|
$html = self::buildHtml($quotation, $items, 'Quotation');
|
|
$pdf->writeHTML($html, true, false, true, false, '');
|
|
|
|
return $pdf->Output('Quotation_' . $quotation['quotation_number'] . '.pdf', $dest);
|
|
}
|
|
|
|
public static function generateInvoicePDF($id, $dest = 'I') {
|
|
$stmt = db()->prepare("SELECT i.*, c.name as customer_name, c.email as customer_email, c.phone as customer_phone, c.address as customer_address
|
|
FROM invoices i
|
|
JOIN customers c ON i.customer_id = c.id
|
|
WHERE i.id = ? AND i.deleted_at IS NULL");
|
|
$stmt->execute([$id]);
|
|
$invoice = $stmt->fetch();
|
|
|
|
if (!$invoice) return null;
|
|
|
|
$stmt = db()->prepare("SELECT ii.*, p.name as product_name
|
|
FROM invoice_items ii
|
|
JOIN products p ON ii.product_id = p.id
|
|
WHERE ii.invoice_id = ?");
|
|
$stmt->execute([$id]);
|
|
$items = $stmt->fetchAll();
|
|
|
|
$pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
|
$pdf->SetCreator(PDF_CREATOR);
|
|
$pdf->SetAuthor('CRM PRO');
|
|
$pdf->SetTitle('Invoice ' . $invoice['invoice_number']);
|
|
$pdf->SetMargins(PDF_MARGIN_LEFT, 40, PDF_MARGIN_RIGHT);
|
|
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
|
|
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
|
|
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->AddPage();
|
|
|
|
$html = self::buildHtml($invoice, $items, 'Invoice');
|
|
$pdf->writeHTML($html, true, false, true, false, '');
|
|
|
|
return $pdf->Output('Invoice_' . $invoice['invoice_number'] . '.pdf', $dest);
|
|
}
|
|
|
|
private static function buildHtml($doc, $items, $type) {
|
|
$number_key = ($type == 'Quotation') ? 'quotation_number' : 'invoice_number';
|
|
$date_key = 'issue_date';
|
|
$expiry_key = ($type == 'Quotation') ? 'expiry_date' : 'due_date';
|
|
$expiry_label = ($type == 'Quotation') ? 'Expiry' : 'Due Date';
|
|
|
|
$html = '
|
|
<table cellpadding="5">
|
|
<tr>
|
|
<td width="50%">
|
|
<strong>Bill To:</strong><br>
|
|
' . e($doc['customer_name']) . '<br>
|
|
' . nl2br(e($doc['customer_address'])) . '<br>
|
|
Email: ' . e($doc['customer_email']) . '<br>
|
|
Phone: ' . e($doc['customer_phone']) . '
|
|
</td>
|
|
<td width="50%" align="right">
|
|
<strong>' . $type . ' Details:</strong><br>
|
|
Number: ' . e($doc[$number_key]) . '<br>
|
|
Date: ' . date('M d, Y', strtotime($doc[$date_key])) . '<br>
|
|
' . $expiry_label . ': ' . date('M d, Y', strtotime($doc[$expiry_key])) . '<br>
|
|
Status: ' . e($doc['status']) . '
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<br><br>
|
|
<table border="1" cellpadding="5">
|
|
<thead>
|
|
<tr style="background-color: #f2f2f2; font-weight: bold;">
|
|
<th width="50%">Product/Service Description</th>
|
|
<th width="10%" align="center">Qty</th>
|
|
<th width="20%" align="right">Unit Price</th>
|
|
<th width="20%" align="right">Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>';
|
|
|
|
foreach ($items as $item) {
|
|
$html .= '
|
|
<tr>
|
|
<td>' . e($item['product_name']) . '</td>
|
|
<td align="center">' . number_format($item['quantity'], 2) . '</td>
|
|
<td align="right">' . format_currency($item['unit_price']) . '</td>
|
|
<td align="right">' . format_currency($item['total_price']) . '</td>
|
|
</tr>';
|
|
}
|
|
|
|
$html .= '
|
|
</tbody>
|
|
</table>
|
|
<br><br>
|
|
<table cellpadding="5">
|
|
<tr>
|
|
<td width="60%">
|
|
<strong>Notes:</strong><br>
|
|
' . nl2br(e($doc['notes'])) . '
|
|
</td>
|
|
<td width="40%">
|
|
<table cellpadding="2">
|
|
<tr>
|
|
<td><strong>Subtotal:</strong></td>
|
|
<td align="right">' . format_currency($doc['subtotal']) . '</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Tax (10%):</strong></td>
|
|
<td align="right">' . format_currency($doc['tax_amount']) . '</td>
|
|
</tr>
|
|
<tr style="font-size: 12pt; font-weight: bold;">
|
|
<td><strong>Total:</strong></td>
|
|
<td align="right">' . format_currency($doc['total_amount']) . '</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>';
|
|
return $html;
|
|
}
|
|
}
|