Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 191
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   Modules\Media
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15use Modules\Billing\Models\NullBill;
16use phpOMS\Localization\ISO3166NameEnum;
17use phpOMS\Localization\ISO3166TwoEnum;
18use phpOMS\Localization\Money;
19
20/** @var \phpOMS\Views\View $this */
21/** @var \Modules\Media\Models\Collection $media */
22$media = $this->getData('defaultTemplates');
23
24require_once $media->findFile('.pdf.php')->getAbsolutePath();
25
26/** @var \Modules\Billing\Models\Bill $bill */
27$bill = $this->data['bill'] ?? new NullBill();
28
29// Set up default pdf template
30/** @phpstan-import-type DefaultPdf from ../../../../Admin/Install/Media/PdfDefaultTemplate/pdfTemplate.pdf.php */
31$pdf = new DefaultPdf();
32
33$lang = include __DIR__ . '/lang.php';
34
35$pdf->attributes['title_name'] = (string) ($this->data['bill_logo_name'] ?? 'Jingga');
36$pdf->attributes['slogan']     = (string) ($this->data['bill_slogan'] ?? 'Business solutions made simple.');
37
38$pdf->setHeaderData(
39    __DIR__ . '/logo.png', 15,
40    $pdf->attributes['title_name'],
41    $pdf->attributes['slogan'],
42);
43$pdf->setCreator((string) ($this->data['bill_creator'] ?? 'Jingga'));
44$pdf->setAuthor((string) ($this->data['bill_creator'] ?? 'Jingga'));
45$pdf->setTitle((string) ($this->data['bill_title'] ?? $bill->type->getL11n()));
46$pdf->setSubject((string) ($this->data['bill_subtitle'] ?? ''));
47$pdf->setKeywords(\implode(', ', (array) ($this->data['keywords'] ?? [])));
48$pdf->language = $bill->language;
49
50$pdf->attributes['legal_name'] = (string) ($this->data['legal_company_name'] ?? 'Jingga e. K.');
51$pdf->attributes['address']    = (string) ($this->data['bill_company_address'] ?? 'Kirchstr. 33');
52$pdf->attributes['city']       = (string) ($this->data['bill_company_city'] ?? '61191 Rosbach');
53
54$pdf->attributes['ceo']        = (string) ($this->data['bill_company_ceo'] ?? 'Dennis Eichhorn');
55$pdf->attributes['tax_office'] = (string) ($this->data['bill_company_tax_office'] ?? 'HRA 5058');
56$pdf->attributes['tax_number'] = (string) ($this->data['bill_company_tax_id'] ?? 'DE362646968');
57$pdf->attributes['terms']      = (string) ($this->data['bill_company_terms'] ?? 'https://jingga.app/terms');
58
59$pdf->attributes['bank_name']    = (string) ($this->data['bill_company_bank_name'] ?? 'Volksbank Mittelhessen');
60$pdf->attributes['swift']        = (string) ($this->data['bill_company_swift'] ?? 'VBMHDE5F');
61$pdf->attributes['bank_account'] = (string) ($this->data['bill_company_bank_account'] ?? 'DE62 5139 0000 0084 8044 10');
62
63$pdf->attributes['website'] = (string) ($this->data['bill_company_website'] ?? 'www.jingga.app');
64$pdf->attributes['email']   = (string) ($this->data['bill_company_email'] ?? 'info@jingga.app');
65$pdf->attributes['phone']   = (string) ($this->data['bill_company_phone'] ?? '+49 152 04337728');
66
67$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
68
69// add a page
70$pdf->AddPage();
71$topPos = $pdf->getY();
72
73// Set up default bill template
74$billTypeName = \strtoupper($bill->type->getL11n());
75
76// @todo: depending on amount of lines, there is a solution (html, or use backtracking of tcpdf)
77
78// Address
79$pdf->setY(50);
80$pdf->setFont('helvetica', '', 10);
81
82$countries       = ISO3166NameEnum::getConstants();
83$countryEnumName = ISO3166TwoEnum::getName($bill->billCountry);
84$toCountry       = \is_string($countryEnumName) && ($country = ISO3166NameEnum::getByName($countryEnumName)) !== null
85    ? $country
86    : '';
87
88$addressString = \trim(
89    $bill->billTo . "\n"
90    . (empty($bill->billAddress) ? '' : ($bill->billAddress . "\n"))
91    . (empty($bill->billCity) ? '' : ($bill->billCity . "\n"))
92    . (empty($toCountry) ? '' : ($toCountry . "\n")),
93    "\n "
94);
95
96// Count the char "\n" in $addressString
97$addressLineCount = \substr_count($addressString, "\n") + 1;
98
99$lineHeight = $pdf->getY();
100$pdf->Write(
101    0,
102    $addressString,
103    '', false, 'L', false, 0, false, false, 0
104);
105$lineHeight = ($lineHeight - $pdf->getY()) / $addressLineCount;
106
107// Bill head
108$pdf->setFont('helvetica', 'B', 16);
109$titleWidth = $pdf->getStringWidth($billTypeName, 'helvetica', 'B', 16);
110$titleWidth = \is_array($titleWidth) ? \array_sum($titleWidth) : $titleWidth;
111
112$pdf->setXY(
113    $rightPos = ($pdf->getPageWidth() - $titleWidth - \max(60 - $titleWidth, 0) - 15 - 2),
114    $topPos + 50 + $lineHeight * $addressLineCount - 38,
115    true
116);
117
118$pdf->setTextColor(255, 255, 255);
119$pdf->setFillColor(255, 162, 7);
120$pdf->Cell($pdf->getPageWidth() - $rightPos - 15, 0, $billTypeName, 0, 0, 'L', true);
121
122$pdf->setFont('helvetica', '', 10);
123$pdf->setTextColor(255, 162, 7);
124
125$pdf->setXY($rightPos, $tempY = $pdf->getY() + 10, true);
126$pdf->MultiCell(
127    26, 30,
128    $lang[$pdf->language]['InvoiceNo'] . "\n"
129    . $lang[$pdf->language]['InvoiceDate'] . "\n"
130    . $lang[$pdf->language]['ServiceDate'] . "\n"
131    . $lang[$pdf->language]['CustomerNo'] . "\n"
132    . $lang[$pdf->language]['PO'] . "\n"
133    . $lang[$pdf->language]['DueDate'],
134    0, 'L'
135);
136
137$pdf->setFont('helvetica', '', 10);
138$pdf->setTextColor(0, 0, 0);
139
140$pdf->setXY($rightPos + 26 + 2, $tempY, true);
141$pdf->MultiCell(
142    25, 30,
143    $bill->number . "\n"
144    . ($bill->billDate?->format('Y-m-d') ?? '0') . "\n"
145    . ($bill->performanceDate?->format('Y-m-d') ?? '0') . "\n"
146    . $bill->accountNumber . "\n"
147    . '' . "\n" /* @todo: implement customer / supplier reference as string */
148    .  ($bill->billDate?->format('Y-m-d') ?? '0'), /* Consider to add dueDate in addition */
149    0, 'L'
150);
151$pdf->Ln();
152
153$pdf->setY($pdf->getY() - 30);
154
155/*
156$pdf->writeHTMLCell(
157    $pdf->getPageWidth() - 15 * 2, 0, null, null,
158    "<strong>Lorem ipsum dolor sit amet,</strong><br \><br \>Consectetur adipiscing elit. Vivamus ac massa sit amet eros posuere accumsan feugiat vel est. Maecenas ultricies enim eu eros rhoncus, volutpat cursus enim imperdiet. Aliquam et odio ipsum. Quisque dapibus scelerisque tempor. Phasellus purus lorem, venenatis eget pretium ac, convallis et ante. Aenean pulvinar justo consectetur mi tincidunt venenatis. Suspendisse ultricies enim id nulla facilisis lacinia. <br /><br />Nam congue nunc nunc, eu pellentesque eros aliquam ac. Nunc placerat elementum turpis, quis facilisis diam volutpat at. Suspendisse enim leo, convallis nec ornare eu, auctor nec purus. Nunc neque metus, feugiat quis justo nec, mollis dignissim risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In at ornare sem. Cras placerat, sapien sed ornare lacinia, mauris nulla volutpat nisl, eget dapibus nisl ipsum non est. Suspendisse ut nisl a ipsum rhoncus sodales.",
159    0, 0, false, true, 'J'
160);
161$pdf->Ln();
162*/
163
164$pdf->setY($pdf->getY() + 10);
165
166$header = [
167    $lang[$pdf->language]['Item'],
168    $lang[$pdf->language]['Quantity'],
169    $lang[$pdf->language]['UnitPrice'],
170    $lang[$pdf->language]['Total'],
171];
172
173$lines = $bill->getElements();
174
175// Header
176$headerCount = \count($header);
177$w           = [$pdf->getPageWidth() - 20 - 20 - 20 - 2 * 15, 20, 20, 20];
178
179$pdf->setCellPadding(1);
180
181$taxes = [];
182$first = true;
183
184// Data
185$fill = false;
186foreach($lines as $line) {
187    // @todo: add support for empty lines (row = line)
188    if (/*$row === null || */$first || $pdf->getY() > $pdf->getPageHeight() - 40) {
189        $pdf->setFillColor(255, 162, 7);
190        $pdf->setTextColor(255);
191        $pdf->setDrawColor(255, 162, 7);
192        //$pdf->SetLineWidth(0.3);
193        $pdf->setFont('helvetica', 'B', 10);
194
195        if (!$first/* || $row === null*/) {
196            $pdf->AddPage();
197            $pdf->Ln();
198        }
199
200        for($i = 0; $i < $headerCount; ++$i) {
201            $pdf->Cell($w[$i], 7, $header[$i], 1, 0, 'L', true);
202        }
203
204        $pdf->Ln();
205        $pdf->setFillColor(245, 245, 245);
206        $pdf->setTextColor(0);
207        $pdf->setFont('helvetica', '', 10);
208
209        $first = false;
210    }
211
212    $tempY = $pdf->getY();
213    $pdf->writeHTMLCell($w[0], 10, null, null, $line->itemNumber . ' ' . $line->itemName, 0, 2, $fill);
214    $height = $pdf->getY() - $tempY;
215
216    $singleSalesPriceNet = Money::fromFloatInt($line->singleSalesPriceNet);
217    $totalSalesPriceNet  = Money::fromFloatInt($line->totalSalesPriceNet);
218
219    $pdf->MultiCell($w[1], $height, (string) $line->getQuantity(), 0, 'L', $fill, 0, 15 + $w[0], $tempY, true, 0, false, true, 0, 'M', true);
220    $pdf->MultiCell($w[2], $height, $singleSalesPriceNet->getCurrency(2, symbol: ''), 0, 'L', $fill, 0, 15 + $w[0] + $w[1], $tempY, true, 0, false, true, 0, 'M', true);
221    $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);
222
223    $fill = !$fill;
224
225    // get taxes
226    if (!isset($taxes[$line->taxR->getInt() / 100])) {
227        $taxes[$line->taxR->getInt() / 100] = $line->taxP;
228    } else {
229        $taxes[$line->taxR->getInt() / 100]->add($line->taxP);
230    }
231}
232
233$pdf->Cell(\array_sum($w), 0, '', 'T');
234$pdf->Ln();
235
236if ($pdf->getY() > $pdf->getPageHeight() - 40) {
237    $pdf->AddPage();
238}
239
240$pdf->setFillColor(240, 240, 240);
241$pdf->setTextColor(0);
242$pdf->setDrawColor(240, 240, 240);
243$pdf->setFont('helvetica', 'B', 10);
244
245$tempY = $pdf->getY();
246
247$netSales = Money::fromFloatInt($bill->netSales);
248
249$pdf->setX($w[0] + $w[1] + 15);
250$pdf->Cell($w[2], 7, $lang[$pdf->language]['Subtotal'], 0, 0, 'L', false);
251$pdf->Cell($w[3], 7, $netSales->getCurrency(2, symbol: ''), 0, 0, 'L', false);
252$pdf->Ln();
253
254foreach ($taxes as $rate => $tax) {
255    $tax = Money::fromFloatInt($tax);
256
257    $pdf->setX($w[0] + $w[1] + 15);
258    $pdf->Cell($w[2], 7,  $lang[$pdf->language]['Taxes'] . ' (' . $rate . '%)', 0, 0, 'L', false);
259    $pdf->Cell($w[3], 7, $tax->getCurrency(2, symbol: ''), 0, 0, 'L', false);
260    $pdf->Ln();
261}
262
263// @todo: add currency
264
265$pdf->setFillColor(255, 162, 7);
266$pdf->setTextColor(255);
267$pdf->setDrawColor(255, 162, 7);
268$pdf->setFont('helvetica', 'B', 10);
269
270$grossSales = Money::fromFloatInt($bill->grossSales);
271
272$pdf->setX($w[0] + $w[1] + 15);
273$pdf->Cell($w[2], 7, \strtoupper($lang[$pdf->language]['Total']), 1, 0, 'L', true);
274$pdf->Cell($w[3], 7,  $grossSales->getCurrency(2, symbol: ''), 1, 0, 'L', true);
275$pdf->Ln();
276
277$tempY2 = $pdf->getY();
278
279// @todo: fix payment terms
280$pdf->setTextColor(0);
281$pdf->setFont('helvetica', 'B', 8);
282$pdf->setY($tempY);
283$pdf->Write(0, $lang[$pdf->language]['PaymentTerms'] . ': CreditCard', '', false, 'L', false, 0, false, false, 0);
284
285$pdf->setFont('helvetica', '', 8);
286$pdf->Write(0, $bill->paymentText, '', false, 'L', false, 0, false, false, 0);
287$pdf->Ln();
288
289// @todo: fix terms
290$pdf->setFont('helvetica', 'B', 8);
291$pdf->Write(0, $lang[$pdf->language]['Terms'] . ': ' . $pdf->attributes['terms'], '', false, 'L', false, 0, false, false, 0);
292$pdf->Ln();
293
294$pdf->setFont('helvetica', 'B', 8);
295$pdf->Write(0, $lang[$pdf->language]['Currency'] . ': ' . $bill->currency, '', false, 'L', false, 0, false, false, 0);
296$pdf->Ln();
297
298$pdf->setFont('helvetica', 'B', 8);
299$pdf->Write(0, $lang[$pdf->language]['TaxRemark'], '', false, 'L', false, 0, false, false, 0);
300$pdf->Ln();
301
302$pdf->setFont('helvetica', '', 8);
303$pdf->Write(0, $bill->termsText, '', false, 'L', false, 0, false, false, 0);
304$pdf->Ln();
305
306$pdf->setY($tempY2);
307$pdf->Ln();
308
309/*
310$pdf->writeHTMLCell(
311    $pdf->getPageWidth() - 15 * 2, 0, null, null,
312    "Consectetur adipiscing elit. Vivamus ac massa sit amet eros posuere accumsan feugiat vel est. Maecenas ultricies enim eu eros rhoncus, volutpat cursus enim imperdiet. Aliquam et odio ipsum. Quisque dapibus scelerisque tempor. Phasellus purus lorem, venenatis eget pretium ac, convallis et ante. Aenean pulvinar justo consectetur mi tincidunt venenatis. Suspendisse ultricies enim id nulla facilisis lacinia. Nam congue nunc nunc, eu pellentesque eros aliquam ac.<br /><br />Nunc placerat elementum turpis, quis facilisis diam volutpat at. Suspendisse enim leo, convallis nec ornare eu, auctor nec purus. Nunc neque metus, feugiat quis justo nec, mollis dignissim risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In at ornare sem. Cras placerat, sapien sed ornare lacinia, mauris nulla volutpat nisl, eget dapibus nisl ipsum non est. Suspendisse ut nisl a ipsum rhoncus sodales.",
313    0, 0, false, true, 'J'
314);
315$pdf->Ln();
316*/
317
318//Close and output PDF document
319$path = (string) ($this->data['path'] ?? (($bill->billDate?->format('Y-m-d') ?? '0') . '_' . $bill->number . '.pdf'));
320$pdf->Output($path, 'I');