oms-Billing/Admin/Install/Media/bill.pdf.php
Dennis Eichhorn 548a4aab7b
Some checks failed
Image optimization / general_image_workflow (push) Has been cancelled
CI / general_module_workflow_php (push) Has been cancelled
CI / general_module_workflow_js (push) Has been cancelled
fix version and bugs
2024-05-21 00:09:06 +02:00

316 lines
11 KiB
PHP
Executable File

<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\Media
* @copyright Dennis Eichhorn
* @license OMS License 2.2
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
use Modules\Billing\Models\NullBill;
use Modules\Media\Models\NullCollection;
use phpOMS\Localization\ISO3166NameEnum;
use phpOMS\Localization\Money;
use phpOMS\Stdlib\Base\FloatInt;
/** @var \phpOMS\Views\View $this */
/** @var \Modules\Media\Models\Collection $collection */
$collection = $this->data['defaultTemplates'] ?? new NullCollection();
require_once $collection->findFile('.pdf.php')->getAbsolutePath();
/** @var \Modules\Billing\Models\Bill $bill */
$bill = $this->data['bill'] ?? new NullBill();
// Set up default pdf template
/** @phpstan-import-type DefaultPdf from ../../../../Admin/Install/Media/PdfDefaultTemplate/pdfTemplate.pdf.php */
$pdf = new DefaultPdf();
$lang = include __DIR__ . '/lang.php';
$pdf->attributes['title_name'] = $this->data['bill_logo_name'] ?? 'Jingga';
$pdf->attributes['slogan'] = $this->data['bill_slogan'] ?? 'Business solutions made simple.';
$pdf->setHeaderData(
__DIR__ . '/logo.png', 15,
$pdf->attributes['title_name'],
$pdf->attributes['slogan'],
);
$pdf->setCreator((string) ($this->data['bill_creator'] ?? 'Jingga'));
$pdf->setAuthor((string) ($this->data['bill_creator'] ?? 'Jingga'));
$pdf->setTitle((string) ($this->data['bill_title'] ?? $bill->type->getL11n()));
$pdf->setSubject((string) ($this->data['bill_subtitle'] ?? ''));
$pdf->setKeywords(\implode(', ', (array) ($this->data['keywords'] ?? [])));
$pdf->language = $bill->language;
$pdf->attributes['legal_name'] = $this->data['legal_company_name'] ?? 'Jingga e. K.';
$pdf->attributes['address'] = $this->data['bill_company_address'] ?? 'Kirchstr. 33';
$pdf->attributes['city'] = $this->data['bill_company_city'] ?? '61191 Rosbach';
$pdf->attributes['ceo'] = $this->data['bill_company_ceo'] ?? 'Dennis Eichhorn';
$pdf->attributes['tax_office'] = $this->data['bill_company_tax_office'] ?? 'HRA 5058';
$pdf->attributes['tax_number'] = $this->data['bill_company_tax_id'] ?? 'DE362646968';
$pdf->attributes['terms'] = $this->data['bill_company_terms'] ?? 'https://jingga.app/terms';
$pdf->attributes['bank_name'] = $this->data['bill_company_bank_name'] ?? 'Volksbank Mittelhessen';
$pdf->attributes['swift'] = $this->data['bill_company_swift'] ?? 'VBMHDE5F';
$pdf->attributes['bank_account'] = $this->data['bill_company_bank_account'] ?? 'DE62 5139 0000 0084 8044 10';
$pdf->attributes['website'] = $this->data['bill_company_website'] ?? 'www.jingga.app';
$pdf->attributes['email'] = $this->data['bill_company_email'] ?? 'info@jingga.app';
$pdf->attributes['phone'] = $this->data['bill_company_phone'] ?? '+49 152 04337728';
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
// add a page
$pdf->AddPage();
$topPos = $pdf->getY();
// Set up default bill template
$billTypeName = \strtoupper($bill->type->getL11n());
// Address
$pdf->setY(50);
$pdf->setFont('helvetica', '', 10);
$toCountry = ISO3166NameEnum::getBy2Code($bill->billCountry);
$addressString = \trim(
$bill->billTo . "\n"
. (empty($bill->billAddress) ? '' : ($bill->billAddress . "\n"))
. (empty($bill->billCity) ? '' : ($bill->billCity . "\n"))
. (empty($toCountry) ? '' : ($toCountry . "\n")),
"\n "
);
// Count the char "\n" in $addressString
$addressLineCount = \substr_count($addressString, "\n") + 1;
$lineHeight = $pdf->getY();
$pdf->Write(
0,
$addressString,
'', false, 'L', false, 0, false, false, 0
);
$lineHeight = ($lineHeight - $pdf->getY()) / $addressLineCount;
$pageWidth = $pdf->getPageWidth();
$pageHeight = $pdf->getPageHeight();
// Bill head
$pdf->setFont('helvetica', 'B', 16);
$titleWidth = $pdf->getStringWidth($billTypeName, 'helvetica', 'B', 16);
$titleWidth = \is_array($titleWidth) ? \array_sum($titleWidth) : $titleWidth;
$pdf->setXY(
$rightPos = ($pageWidth - $titleWidth - \max(60 - $titleWidth, 0) - 15 - 2),
$topPos + 50 + $lineHeight * $addressLineCount - 38,
true
);
$pdf->setTextColor(255, 255, 255);
$pdf->setFillColor(255, 162, 7);
$pdf->Cell($pageWidth - $rightPos - 15, 0, $billTypeName, 0, 0, 'L', true);
$pdf->setFont('helvetica', '', 10);
$pdf->setTextColor(255, 162, 7);
$pdf->setXY($rightPos, $tempY = $pdf->getY() + 10, true);
$pdf->MultiCell(
29, 30,
$lang[$pdf->language]['InvoiceNo'] . "\n"
. $lang[$pdf->language]['InvoiceDate'] . "\n"
. $lang[$pdf->language]['ServiceDate'] . "\n"
. $lang[$pdf->language]['CustomerNo'] . "\n"
. $lang[$pdf->language]['REF'] . "\n"
. $lang[$pdf->language]['DueDate'],
0, 'L'
);
//$pdf->setFont('helvetica', '', 10);
$pdf->setTextColor(0, 0, 0);
$pdf->setXY($rightPos + 29 + 2, $tempY, true);
$pdf->MultiCell(
25, 30,
$bill->number . "\n"
. ($bill->billDate?->format('Y-m-d') ?? '0') . "\n"
. ($bill->performanceDate?->format('Y-m-d') ?? '0') . "\n"
. $bill->accountNumber . "\n"
. $bill->external . "\n"
. ($bill->billDate?->format('Y-m-d') ?? '0'), /* Consider to add dueDate in addition */
0, 'L'
);
$pdf->Ln();
$tempY = $pdf->getY();
$height = 0;
$pdf->setY($tempY - 20);
$header = [
$lang[$pdf->language]['Item'],
$lang[$pdf->language]['Quantity'],
$lang[$pdf->language]['UnitPrice'],
$lang[$pdf->language]['Total'],
];
// Header
$headerCount = \count($header);
$w = [$pageWidth - 20 - 20 - 20 - 2 * 15, 20, 20, 20];
$pdf->setCellPadding(1);
$taxes = [];
$first = true;
// Data
$fill = false;
foreach($bill->elements as $line) {
// @todo depending on amount of lines, there is a solution (html, or use backtracking of tcpdf)
if ($first || $pdf->getY() > $pageHeight - 40) {
$pdf->setFillColor(255, 162, 7);
$pdf->setTextColor(255);
$pdf->setDrawColor(255, 162, 7);
//$pdf->SetLineWidth(0.3);
$pdf->setFont('helvetica', 'B', 10);
if (!$first/* || $row === null*/) {
$pdf->AddPage();
$pdf->Ln();
}
for($i = 0; $i < $headerCount; ++$i) {
$pdf->Cell($w[$i], 7, $header[$i], 1, 0, 'L', true);
}
$pdf->Ln();
$pdf->setFillColor(245, 245, 245);
$pdf->setTextColor(0);
$pdf->setFont('helvetica', '', 10);
$first = false;
}
// Discounts are shown below the original price -> additional line
// We don't want discount columns because that hints at customers they might be able to get discounts.
$lines = 1
+ ((int) ($line->discountQ->value > 0))
+ ((int) ($line->singleDiscountP->value > 0))
+ ((int) ($line->singleDiscountR->value > 0));
$tempY = $pdf->getY();
//$pdf->writeHTMLCell($w[0], 10, null, null, $line->itemNumber . ' ' . $line->itemName, 0, 2, $fill);
$pdf->MultiCell($w[0], 10 * $lines, \trim($line->itemNumber . ' ' . $line->itemName), 0, 'L', $fill, 2, null, null, true, 0, true, true, 0, 'M', false);
$height = $pdf->getY() - $tempY;
$singleListPriceNet = Money::fromFloatInt($line->singleListPriceNet);
$totalSalesPriceNet = Money::fromFloatInt($line->totalSalesPriceNet);
if ($line->quantity->value === 0) {
$pdf->MultiCell($w[1] + $w[2] + $w[3], $height, '', 0, 'L', $fill, 0, 15 + $w[0], $tempY, true, 0, false, true, 0, 'M', true);
} else {
$pdf->MultiCell($w[1], $height, (string) $line->quantity->getAmount($line->container?->quantityDecimals ?? 0), 0, 'L', $fill, 0, 15 + $w[0], $tempY, true, 0, false, true, 0, 'M', true);
$pdf->MultiCell($w[2], $height, $singleListPriceNet->getCurrency(2, symbol: ''), 0, 'L', $fill, 0, 15 + $w[0] + $w[1], $tempY, true, 0, false, true, 0, 'M', true);
$pdf->MultiCell($w[3], $height, $totalSalesPriceNet->getCurrency(2, symbol: ''), 0, 'L', $fill, 1, 15 + $w[0] + $w[1] + $w[2], $tempY, true, 0, false, true, 0, 'M', true);
}
$fill = !$fill;
// get taxes
if (!isset($taxes[$line->taxR->value / FloatInt::DIVISOR])) {
$taxes[$line->taxR->value / FloatInt::DIVISOR] = $line->taxP;
} else {
$taxes[$line->taxR->value / FloatInt::DIVISOR]->add($line->taxP);
}
}
// We have to do the following because in some cases it doesn't set the Y position correctly after the table
// I assume it is related to if/else above. A html multicell might not correctly set the y position.
if (!empty($bill->elements)) {
$pdf->setY($tempY + $height);
$pdf->Cell(\array_sum($w), 0, '', 'T');
$pdf->Ln();
if ($pdf->getY() > $pageHeight - 40) {
$pdf->AddPage();
}
$pdf->setFillColor(240, 240, 240);
$pdf->setTextColor(0);
$pdf->setDrawColor(240, 240, 240);
$pdf->setFont('helvetica', 'B', 10);
$tempY = $pdf->getY();
$netSales = Money::fromFloatInt($bill->netSales);
$pdf->setX($w[0] + $w[1] + 12);
$pdf->Cell($w[2], 7, $lang[$pdf->language]['Subtotal'], 0, 0, 'L', false);
$pdf->Cell($w[3], 7, $netSales->getCurrency(2, symbol: ''), 0, 0, 'L', false);
$pdf->Ln();
foreach ($taxes as $rate => $tax) {
$tax = Money::fromFloatInt($tax);
$pdf->setX($w[0] + $w[1] + 12);
$pdf->Cell($w[2], 7, $lang[$pdf->language]['Taxes'] . ' (' . $rate . '%)', 0, 0, 'L', false);
$pdf->Cell($w[3], 7, $tax->getCurrency(2, symbol: ''), 0, 0, 'L', false);
$pdf->Ln();
}
$pdf->setFillColor(255, 162, 7);
$pdf->setTextColor(255);
$pdf->setDrawColor(255, 162, 7);
//$pdf->setFont('helvetica', 'B', 10);
$grossSales = Money::fromFloatInt($bill->grossSales);
$pdf->setX($w[0] + $w[1] + 12);
$pdf->Cell($w[2], 7, \strtoupper($lang[$pdf->language]['Total']), 1, 0, 'L', true);
$pdf->Cell($w[3] + 3, 7, $grossSales->getCurrency(2, symbol: ''), 1, 0, 'L', true);
$pdf->Ln();
$tempY2 = $pdf->getY();
// @todo fix payment terms
$pdf->setTextColor(0);
$pdf->setFont('helvetica', 'B', 8);
$pdf->setY($tempY);
$pdf->Write(0, $lang[$pdf->language]['PaymentTerms'] . ': CreditCard', '', false, 'L', false, 0, false, false, 0);
$pdf->setFont('helvetica', '', 8);
$pdf->Write(0, $bill->paymentText, '', false, 'L', false, 0, false, false, 0);
$pdf->Ln();
// @todo fix terms
$pdf->setFont('helvetica', 'B', 8);
$pdf->Write(0, $lang[$pdf->language]['Terms'] . ': ' . $pdf->attributes['terms'], '', false, 'L', false, 0, false, false, 0);
$pdf->Ln();
//$pdf->setFont('helvetica', 'B', 8);
$pdf->Write(0, $lang[$pdf->language]['Currency'] . ': ' . $bill->currency, '', false, 'L', false, 0, false, false, 0);
$pdf->Ln();
//$pdf->setFont('helvetica', 'B', 8);
$pdf->Write(0, $lang[$pdf->language]['TaxRemark'], '', false, 'L', false, 0, false, false, 0);
$pdf->Ln();
$pdf->setFont('helvetica', '', 8);
$pdf->Write(0, $bill->termsText, '', false, 'L', false, 0, false, false, 0);
//$pdf->Ln();
//$pdf->setY($tempY2);
//$pdf->Ln();
}
//Close and output PDF document
$path = (string) ($this->data['path'] ?? (($bill->billDate?->format('Y-m-d') ?? '0') . '_' . $bill->number . '.pdf'));
$pdf->Output($path, 'I');