From ff90dba39e0ae242300be317c27c419538a48689 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 10 Feb 2023 18:20:57 +0100 Subject: [PATCH] many small fixes --- Admin/Install/Media/bill.pdf.php | 226 ++++++----- Admin/Install/Navigation.install.json | 4 +- Admin/Install/db.json | 238 +++++++++++- Admin/Install/types.json | 100 +++-- Admin/Installer.php | 1 + Admin/Routes/Web/Api.php | 32 ++ Controller/ApiController.php | 245 ++++++++++-- Controller/BackendController.php | 48 ++- Models/Bill.php | 37 ++ Models/BillMapper.php | 7 + Models/BillType.php | 15 +- Models/BillTypeMapper.php | 35 +- Models/PricingMapper.php | 94 +++++ Models/PricingType.php | 32 ++ Theme/Backend/Lang/en.lang.php | 7 + Theme/Backend/bill-create.tpl.php | 538 ++++++++++++++++++++++++++ Theme/Backend/invoice-create.tpl.php | 269 ------------- Theme/Backend/sales-bill.tpl.php | 333 ---------------- 18 files changed, 1459 insertions(+), 802 deletions(-) create mode 100644 Admin/Routes/Web/Api.php create mode 100644 Models/PricingMapper.php create mode 100644 Models/PricingType.php create mode 100755 Theme/Backend/bill-create.tpl.php delete mode 100755 Theme/Backend/invoice-create.tpl.php delete mode 100755 Theme/Backend/sales-bill.tpl.php diff --git a/Admin/Install/Media/bill.pdf.php b/Admin/Install/Media/bill.pdf.php index 35e7107..ddc4054 100755 --- a/Admin/Install/Media/bill.pdf.php +++ b/Admin/Install/Media/bill.pdf.php @@ -5,55 +5,53 @@ declare(strict_types=1); class MYPDF extends TCPDF { public string $fontName = ''; - public int $fontSize = 8; - public int $sideMargin = 15; //Page header - public function Header() : void { - if ($this->header_xobjid === false) { - $this->header_xobjid = $this->startTemplate($this->w, 0); + public function Header() { + if ($this->header_xobjid === false) { + $this->header_xobjid = $this->startTemplate($this->w, 0); - // Set Logo - $image_file = __DIR__ . '/logo.png'; - $this->Image($image_file, 15, 15, 15, 15, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); + // Set Logo + $image_file = __DIR__ . '/logo.png'; + $this->Image($image_file, 15, 15, 15, 15, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); - // Set Title - $this->SetFont('helvetica', 'B', 20); - $this->setX(15 + 15 + 3); - $this->Cell(0, 14, $this->header_title, 0, false, 'L', 0, '', 0, false, 'T', 'M'); + // Set Title + $this->SetFont('helvetica', 'B', 20); + $this->setX(15 + 15 + 3); + $this->Cell(0, 14, $this->header_title, 0, false, 'L', 0, '', 0, false, 'T', 'M'); - $this->SetFont('helvetica', '', 10); - $this->setX(15 + 15 + 3); - $this->Cell(0, 26, $this->header_string, 0, false, 'L', 0, '', 0, false, 'T', 'M'); + $this->SetFont('helvetica', '', 10); + $this->setX(15 + 15 + 3); + $this->Cell(0, 26, $this->header_string, 0, false, 'L', 0, '', 0, false, 'T', 'M'); - $this->endTemplate(); - } + $this->endTemplate(); + } - $x = 0; - $dx = 0; + $x = 0; + $dx = 0; - if (!$this->header_xobj_autoreset && $this->booklet && (($this->page % 2) == 0)) { - // adjust margins for booklet mode - $dx = ($this->original_lMargin - $this->original_rMargin); - } + if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) { + // adjust margins for booklet mode + $dx = ($this->original_lMargin - $this->original_rMargin); + } - if ($this->rtl) { - $x = $this->w + $dx; - } else { - $x = 0 + $dx; - } + if ($this->rtl) { + $x = $this->w + $dx; + } else { + $x = 0 + $dx; + } - $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); - if ($this->header_xobj_autoreset) { - // reset header xobject template at each page - $this->header_xobjid = false; - } + $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); + if ($this->header_xobj_autoreset) { + // reset header xobject template at each page + $this->header_xobjid = false; + } } // Page footer - public function Footer() : void { + public function Footer() { $this->SetY(-25); $this->SetFont('helvetica', 'I', 7); @@ -82,15 +80,56 @@ class MYPDF extends TCPDF $pdf = new MYPDF('P', 'mm', 'A4', true, 'UTF-8', false); +$creator = $this->getData('bill_creator') ?? 'Jingga'; +$author = 'Jingga'; +$title = $this->getData('bill_title') ?? 'Invoice'; +$subtitle = $this->getData('bill_subtitle') ?? 'Sub title'; +$keywords = $this->getData('keywords') ?? []; +$logoName = $this->getData('bill_logo_name') ?? 'Jingga'; +$slogan = $this->getData('bill_slogan') ?? 'Business solutions made simple.'; + +$legalCompanyName = $this->getData('legal_company_name') ?? 'Jingga e.K.'; +$companyAddress = $this->getData('bill_company_address') ?? 'Gartenstr. 26'; +$companyCity = $this->getData('bill_company_city') ?? '61206 Woellstadt'; +$companyCEO = $this->getData('bill_company_ceo') ?? 'Dennis Eichhorn'; +$companyWebsite = $this->getData('bill_company_website') ?? 'www.jingga.app'; +$companyEmail = $this->getData('bill_company_email') ?? 'info@jingga.app'; +$companyPhone = $this->getData('bill_company_phone') ?? '+49 0152 ????'; + +$taxOffice = $this->getData('bill_company_tax_office') ?? 'HRB'; +$taxId = $this->getData('bill_company_tax_id') ?? 'DE ?????????'; +$vatId = $this->getData('bill_company_vat_id') ?? 'DE ??????'; + +$bankName = $this->getData('bill_company_bank_name') ?? 'Volksbank Mittelhessen'; +$bic = $this->getData('bill_company_bic') ?? ''; +$iban = $this->getData('bill_company_iban') ?? ''; + +$billTypeName = $this->getData('bill_type_name') ?? 'INVOICE'; + +$billInvoiceNumber = $this->getData('bill_invoice_no') ?? ''; +$billInvoiceDate = $this->getData('bill_invoice_date') ?? ''; +$billServiceDate = $this->getData('bill_service_date') ?? ''; +$billCustomerNo = $this->getData('bill_customer_no') ?? ''; +$billPO = $this->getData('bill_po') ?? ''; +$billDueDate = $this->getData('bill_due_date') ?? ''; + +$invoiceLines = $this->getData('bill_lines') ?? []; + +$paymentTerms = $this->getData('bill_payment_terms') ?? ''; +$terms = $this->getData('bill_terms') ?? 'https://jingga.app/terms'; +$taxes = $this->getData('bill_taxes') ?? ['19%' => '0.00']; +$currency = $this->getData('bill_currency') ?? 'EUR'; + + // set document information -$pdf->SetCreator("Jingga"); -$pdf->SetAuthor('Jingga'); -$pdf->SetTitle('Invoice'); -$pdf->SetSubject('Sub title'); -$pdf->SetKeywords('Invoice, 2022'); +$pdf->SetCreator($creator); +$pdf->SetAuthor($author); +$pdf->SetTitle($title); +$pdf->SetSubject($subtitle); +$pdf->SetKeywords(\implode(', ', $keywords)); // set default header data -$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, 'Jingga', 'Business solutions made simple.'); +$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $logoName, $slogan); // set header and footer fonts $pdf->SetHeaderFont([PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN]); @@ -123,18 +162,17 @@ $lineHeight = ($lineHeight - $pdf->getY()) / 3; // Document head $pdf->SetFont('helvetica', 'B', 20); -$title = 'INVOICE'; -$titleWidth = $pdf->GetStringWidth($title, 'helvetica', 'B', 20); +$titleWidth = $pdf->GetStringWidth($billTypeName, 'helvetica', 'B', 20); $pdf->SetXY( - $rightPos = ($pdf->getPageWidth() - $titleWidth - ($titleWidth < 55 ? 55 : 35) + 15), - $topPos + 50 + $lineHeight * 3 - 38, - true + $rightPos = ($pdf->getPageWidth() - $titleWidth - ($titleWidth < 55 ? 55 : 35) + 15), + $topPos + 50 + $lineHeight * 3 - 38, + true ); $pdf->SetTextColor(255, 255, 255); $pdf->SetFillColor(255, 162, 7); -$pdf->Cell($pdf->getPageWidth() - $rightPos - 15, 0, $title, 0, 0, 'L', true); +$pdf->Cell($pdf->getPageWidth() - $rightPos - 15, 0, $billTypeName, 0, 0, 'L', true); $pdf->SetFont('helvetica', '', 8); $pdf->SetTextColor(255, 162, 7); @@ -151,37 +189,37 @@ $pdf->Ln(); $pdf->SetY($pdf->GetY() - 30); $pdf->writeHTMLCell( - $pdf->getPageWidth() - 15 * 2, 0, null, null, - "Lorem ipsum dolor sit amet,

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. 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.", - 0, 0, false, true, 'J' + $pdf->getPageWidth() - 15 * 2, 0, null, null, + "Lorem ipsum dolor sit amet,

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. 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.", + 0, 0, false, true, 'J' ); $pdf->Ln(); $pdf->SetY($pdf->GetY() + 5); $header = ['Item', 'Quantity', 'Rate', 'Total']; -$data = [ - ['ASDF', 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer.", 2.0, "199.90\n-10 %", "150.399.80\n-15.039"], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains. Here we are testing how it looks like if a very long text is posted in the description without any additional line breaks. It should auto-break!", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], - ['ASDF', 2.0, 199.90, 399.80], +$data = [ + ['ASDF', 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer.", 2.0, "199.90\n-10 %", "150.399.80\n-15.039"], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains. Here we are testing how it looks like if a very long text is posted in the description without any additional line breaks. It should auto-break!", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ["123-456-789
This is a item name
This is the item description in more detail for the customer so he knows what this content actually contains.", 2.0, 199.90, 399.80], + ['ASDF', 2.0, 199.90, 399.80], ]; // Header -$w = [$pdf->getPageWidth() - 20 - 20 - 20 - 2 * 15, 20, 20, 20]; -$num_headers = \count($header); +$w = array($pdf->getPageWidth() - 20 - 20 - 20 - 2*15, 20, 20, 20); +$num_headers = count($header); $pdf->setCellPadding(1, 1, 1, 1); @@ -190,31 +228,31 @@ $first = true; // Data $fill = false; foreach($data as $row) { - if ($row === null || $first || $pdf->getY() > $pdf->getPageHeight() - 40) { - $pdf->SetFillColor(255, 162, 7); - $pdf->SetTextColor(255); - $pdf->SetDrawColor(255, 162, 7); - //$pdf->SetLineWidth(0.3); - $pdf->SetFont('helvetica', 'B', 8); + if ($row === null || $first || $pdf->getY() > $pdf->getPageHeight() - 40) { + $pdf->SetFillColor(255, 162, 7); + $pdf->SetTextColor(255); + $pdf->SetDrawColor(255, 162, 7); + //$pdf->SetLineWidth(0.3); + $pdf->SetFont('helvetica', 'B', 8); - if (!$first || $row === null) { - $pdf->AddPage(); - $pdf->Ln(); - } + if (!$first || $row === null) { + $pdf->AddPage(); + $pdf->Ln(); + } - for($i = 0; $i < $num_headers; ++$i) { - $pdf->Cell($w[$i], 7, $header[$i], 1, 0, 'L', true); - } + for($i = 0; $i < $num_headers; ++$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', '', 8); + $pdf->Ln(); + $pdf->SetFillColor(245, 245, 245); + $pdf->SetTextColor(0); + $pdf->SetFont('helvetica', '', 8); - $first = false; - } + $first = false; + } - $tempY = $pdf->getY(); + $tempY = $pdf->getY(); $pdf->writeHTMLCell($w[0], 10, null, null, $row[0], 0, 2, $fill); $height = $pdf->getY() - $tempY; @@ -222,7 +260,7 @@ foreach($data as $row) { $pdf->writeHTMLCell($w[1], $height, 15 + $w[0], $tempY, $row[1], 0, 0, $fill); $pdf->writeHTMLCell($w[2], $height, 15 + $w[0] + $w[1], $tempY, $row[2], 0, 0, $fill); $pdf->writeHTMLCell($w[3], $height, 15 + $w[0] + $w[1] + $w[2], $tempY, $row[3], 0, 1, $fill); - */ + */ $pdf->MultiCell($w[1], $height, $row[1], 0, 'L', $fill, 0, 15 + $w[0], $tempY, true, 0, false, true, 0, 'M', true); $pdf->MultiCell($w[2], $height, $row[2], 0, 'L', $fill, 0, 15 + $w[0] + $w[1], $tempY, true, 0, false, true, 0, 'M', true); @@ -235,7 +273,7 @@ $pdf->Cell(\array_sum($w), 0, '', 'T'); $pdf->Ln(); if ($pdf->getY() > $pdf->getPageHeight() - 40) { - $pdf->AddPage(); + $pdf->AddPage(); } $pdf->SetFillColor(240, 240, 240); @@ -295,11 +333,11 @@ $pdf->Ln(); // $pdf->SetY($pdf->GetY() - 30); $pdf->writeHTMLCell( - $pdf->getPageWidth() - 15 * 2, 0, null, null, - "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.

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.", - 0, 0, false, true, 'J' + $pdf->getPageWidth() - 15 * 2, 0, null, null, + "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.

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.", + 0, 0, false, true, 'J' ); $pdf->Ln(); //Close and output PDF document -$pdf->Output('example_048.pdf', 'I'); +$pdf->Output('example_048.pdf', 'I'); \ No newline at end of file diff --git a/Admin/Install/Navigation.install.json b/Admin/Install/Navigation.install.json index 76d131d..ebc7102 100755 --- a/Admin/Install/Navigation.install.json +++ b/Admin/Install/Navigation.install.json @@ -8,7 +8,7 @@ "uri": "{/lang}/{/app}/sales/bill/list", "target": "self", "icon": null, - "order": 5, + "order": 10, "from": "Billing", "permission": { "permission": 2, "category": null, "element": null }, "parent": 1001601001, @@ -69,7 +69,7 @@ "uri": "{/lang}/{/app}/purchase/bill/list", "target": "self", "icon": null, - "order": 5, + "order": 10, "from": "Billing", "permission": { "permission": 2, "category": null, "element": null }, "parent": 1002101001, diff --git a/Admin/Install/db.json b/Admin/Install/db.json index 2a1d8cc..59de8d2 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -1,4 +1,185 @@ { + "billing_prices": { + "name": "billing_prices", + "fields": { + "billing_prices_id": { + "name": "billing_prices_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "billing_prices_name": { + "name": "billing_prices_name", + "type": "VARCHAR(255)", + "null": false + }, + "billing_prices_promocode": { + "name": "billing_prices_promocode", + "type": "INT", + "null": false + }, + "billing_prices_item": { + "name": "billing_prices_item", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "itemmgmt_item", + "foreignKey": "itemmgmt_item_id" + }, + "billing_prices_itemgroup": { + "name": "billing_prices_itemgroup", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "itemmgmt_attr_value", + "foreignKey": "itemmgmt_attr_value_id" + }, + "billing_prices_itemsegment": { + "name": "billing_prices_itemsegment", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "itemmgmt_attr_value", + "foreignKey": "itemmgmt_attr_value_id" + }, + "billing_prices_itemsection": { + "name": "billing_prices_itemsection", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "itemmgmt_attr_value", + "foreignKey": "itemmgmt_attr_value_id" + }, + "billing_prices_itemtype": { + "name": "billing_prices_itemtype", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "itemmgmt_attr_value", + "foreignKey": "itemmgmt_attr_value_id" + }, + "billing_prices_client": { + "name": "billing_prices_client", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "clientmgmt_client", + "foreignKey": "clientmgmt_client_id" + }, + "billing_prices_clientgroup": { + "name": "billing_prices_clientgroup", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "clientmgmt_attr_value", + "foreignKey": "clientmgmt_attr_value_id" + }, + "billing_prices_clientsegment": { + "name": "billing_prices_clientsegment", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "clientmgmt_attr_value", + "foreignKey": "clientmgmt_attr_value_id" + }, + "billing_prices_clientsection": { + "name": "billing_prices_clientsection", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "clientmgmt_attr_value", + "foreignKey": "clientmgmt_attr_value_id" + }, + "billing_prices_clienttype": { + "name": "billing_prices_clienttype", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "clientmgmt_attr_value", + "foreignKey": "clientmgmt_attr_value_id" + }, + "billing_prices_clientcountry": { + "name": "billing_prices_clientcountry", + "type": "VARCHAR(2)", + "null": true, + "default": null, + "foreignTable": "country", + "foreignKey": "country_code2" + }, + "billing_prices_supplier": { + "name": "billing_prices_supplier", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "suppliermgmt_supplier", + "foreignKey": "suppliermgmt_supplier_id" + }, + "billing_prices_unit": { + "name": "billing_prices_unit", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "unit", + "foreignKey": "unit_id" + }, + "billing_prices_type": { + "name": "billing_prices_type", + "type": "TINYINT(1)", + "null": false + }, + "billing_prices_quantity": { + "name": "billing_prices_quantity", + "type": "BIGINT", + "null": false + }, + "billing_prices_price": { + "name": "billing_prices_price", + "type": "BIGINT", + "null": false + }, + "billing_prices_discount": { + "name": "billing_prices_discount", + "type": "BIGINT", + "null": false + }, + "billing_prices_discountp": { + "name": "billing_prices_discountp", + "type": "BIGINT", + "null": false + }, + "billing_prices_bonus": { + "name": "billing_prices_bonus", + "type": "BIGINT", + "null": false + }, + "billing_prices_multiply": { + "name": "billing_prices_multiply", + "type": "TINYINT(1)", + "null": false + }, + "billing_prices_currency": { + "name": "billing_prices_currency", + "type": "VARCHAR(3)", + "null": true, + "default": null, + "foreignTable": "currency", + "foreignKey": "currency_code" + }, + "billing_prices_start": { + "name": "billing_prices_start", + "type": "DATETIME", + "null": true, + "default": null + }, + "billing_prices_end": { + "name": "billing_prices_end", + "type": "DATETIME", + "null": true, + "default": null + } + } + }, "billing_type": { "name": "billing_type", "fields": { @@ -19,19 +200,20 @@ "type": "VARCHAR(255)", "null": false }, - "billing_type_template": { - "name": "billing_type_template", - "type": "INT", - "null": false, - "foreignTable": "media", - "foreignKey": "media_id" - }, "billing_type_transfer_type": { "description": "What kind of bill is it?", "name": "billing_type_transfer_type", "type": "TINYINT", "null": false }, + "billing_type_default_template": { + "name": "billing_type_default_template", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "media", + "foreignKey": "media_id" + }, "billing_type_transfer_stock": { "description": "Does this bill type move stock?", "name": "billing_type_transfer_stock", @@ -46,6 +228,32 @@ } } }, + "billing_bill_type_media_rel": { + "name": "billing_bill_type_media_rel", + "fields": { + "billing_bill_type_media_rel_id": { + "name": "billing_bill_type_media_rel_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "billing_bill_type_media_rel_src": { + "name": "billing_bill_type_media_rel_src", + "type": "INT", + "null": false, + "foreignTable": "billing_type", + "foreignKey": "billing_type_id" + }, + "billing_bill_type_media_rel_dst": { + "name": "billing_bill_type_media_rel_dst", + "type": "INT", + "null": false, + "foreignTable": "media", + "foreignKey": "media_id" + } + } + }, "billing_type_l11n": { "name": "billing_type_l11n", "fields": { @@ -115,6 +323,14 @@ "foreignTable": "billing_type", "foreignKey": "billing_type_id" }, + "billing_bill_template": { + "name": "billing_bill_template", + "type": "INT", + "null": true, + "default": null, + "foreignTable": "media", + "foreignKey": "media_id" + }, "billing_bill_supplier": { "name": "billing_bill_supplier", "type": "INT", @@ -285,6 +501,14 @@ "type": "VARCHAR(3)", "null": false }, + "billing_bill_language": { + "name": "billing_bill_language", + "type": "VARCHAR(3)", + "null": true, + "default": null, + "foreignTable": "language", + "foreignKey": "language_639_1" + }, "billing_bill_referral": { "name": "billing_bill_referral", "type": "INT", diff --git a/Admin/Install/types.json b/Admin/Install/types.json index a9bc760..8850d52 100644 --- a/Admin/Install/types.json +++ b/Admin/Install/types.json @@ -4,9 +4,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Offer", - "en": "Angebot" + "en": "Offer", + "de": "Angebot" } }, { @@ -14,9 +15,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Order Confirmation", - "en": "Auftragsbestaetigung" + "en": "Order Confirmation", + "de": "Auftragsbestaetigung" } }, { @@ -24,9 +26,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": true, + "isTemplate": false, "l11n": { - "de": "Delivery Note", - "en": "Lieferschein" + "en": "Delivery Note", + "de": "Lieferschein" } }, { @@ -34,9 +37,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Invoice", - "en": "Rechnung" + "en": "Invoice", + "de": "Rechnung" } }, { @@ -44,9 +48,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Proforma Invoice", - "en": "Proforma Rechnung" + "en": "Proforma Invoice", + "de": "Proforma Rechnung" } }, { @@ -54,9 +59,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Credit Note", - "en": "Rechnungskorrektur" + "en": "Credit Note", + "de": "Rechnungskorrektur" } }, { @@ -64,9 +70,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Reverse Invoice", - "en": "Gutschrift" + "en": "Reverse Invoice", + "de": "Gutschrift" } }, { @@ -74,9 +81,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Offer", - "en": "Angebot" + "en": "Offer", + "de": "Angebot" } }, { @@ -84,9 +92,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Order Confirmation", - "en": "Auftragsbestaetigung" + "en": "Order Confirmation", + "de": "Auftragsbestaetigung" } }, { @@ -94,9 +103,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": true, + "isTemplate": false, "l11n": { - "de": "Delivery Note", - "en": "Lieferschein" + "en": "Delivery Note", + "de": "Lieferschein" } }, { @@ -104,9 +114,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Invoice", - "en": "Rechnung" + "en": "Invoice", + "de": "Rechnung" } }, { @@ -114,9 +125,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Proforma Invoice", - "en": "Proforma Rechnung" + "en": "Proforma Invoice", + "de": "Proforma Rechnung" } }, { @@ -124,9 +136,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Credit Note", - "en": "Rechnungskorrektur" + "en": "Credit Note", + "de": "Rechnungskorrektur" } }, { @@ -134,9 +147,10 @@ "numberFormat": "{y}-{id}", "transferType": 2, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Reverse Invoice", - "en": "Gutschrift" + "en": "Reverse Invoice", + "de": "Gutschrift" } }, { @@ -144,9 +158,10 @@ "numberFormat": "{y}-{id}", "transferType": 4, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Stock Movement", - "en": "Lagerumbuchung" + "en": "Stock Movement", + "de": "Lagerumbuchung" } }, { @@ -154,9 +169,10 @@ "numberFormat": "{y}-{id}", "transferType": 4, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Scrapping", - "en": "Verschrottung" + "en": "Scrapping", + "de": "Verschrottung" } }, { @@ -164,9 +180,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Subscription", - "en": "Abonnement" + "en": "Subscription", + "de": "Abonnement" } }, { @@ -174,9 +191,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": true, "l11n": { - "de": "Template", - "en": "Vorlage" + "en": "Template", + "de": "Vorlage" } }, { @@ -184,9 +202,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": false, "l11n": { - "de": "Subscription", - "en": "Abonnement" + "en": "Subscription", + "de": "Abonnement" } }, { @@ -194,9 +213,10 @@ "numberFormat": "{y}-{id}", "transferType": 1, "transferStock": false, + "isTemplate": true, "l11n": { - "de": "Template", - "en": "Vorlage" + "en": "Template", + "de": "Vorlage" } } ] \ No newline at end of file diff --git a/Admin/Installer.php b/Admin/Installer.php index 3c1f0b3..87e01da 100755 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -95,6 +95,7 @@ final class Installer extends InstallerAbstract $request->setData('language', \array_keys($type['l11n'])[0] ?? 'en'); $request->setData('number_format', $type['numberFormat'] ?? '{id}'); $request->setData('transfer_stock', $type['transferStock'] ?? false); + $request->setData('is_template', $type['isTemplate'] ?? false); $request->setData('transfer_type', $type['transferType'] ?? BillTransferType::SALES); $request->setData('template', $template); diff --git a/Admin/Routes/Web/Api.php b/Admin/Routes/Web/Api.php new file mode 100644 index 0000000..a2eca4c --- /dev/null +++ b/Admin/Routes/Web/Api.php @@ -0,0 +1,32 @@ + [ + [ + 'dest' => '\Modules\Billing\Controller\ApiController:apiPreviewRender', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::CREATE, + 'state' => PermissionCategory::SALES_INVOICE, + ], + ], + ], +]; \ No newline at end of file diff --git a/Controller/ApiController.php b/Controller/ApiController.php index fedf72f..e20c070 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -26,6 +26,8 @@ use Modules\Billing\Models\BillTransferType; use Modules\Billing\Models\BillType; use Modules\Billing\Models\BillTypeL11nMapper; use Modules\Billing\Models\BillTypeMapper; +use Modules\Billing\Models\PricingMapper; +use Modules\Billing\Models\PricingType; use Modules\Billing\Models\SettingsEnum; use Modules\ClientManagement\Models\ClientMapper; use Modules\ItemManagement\Models\ItemMapper; @@ -47,6 +49,7 @@ use phpOMS\Message\NotificationLevel; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; use phpOMS\Model\Message\FormValidation; +use phpOMS\System\MimeType; use phpOMS\Uri\HttpUri; use phpOMS\Views\View; @@ -60,6 +63,73 @@ use phpOMS\Views\View; */ final class ApiController extends Controller { + /** + * Api method to find items + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiPricingFind(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + // tax based on customer location + item tax definition = matrix + // price based on + // item quantity + // customer price for item / item group + // customer location + + $queryMapper = PricingMapper::getAll(); + + if ($request->hasData('price_name')) { + $queryMapper->where('name', $request->getData('price_name')); + } + + $queryMapper->where('promocode', \array_unique([$request->getData('price_promocode'), null]), 'IN'); + $queryMapper->where('item', \array_unique([$request->getData('price_item'), null]), 'IN'); + $queryMapper->where('itemgroup', \array_unique([$request->getData('price_itemgroup'), null]), 'IN'); + $queryMapper->where('itemsegment', \array_unique([$request->getData('price_itemsegment'), null]), 'IN'); + $queryMapper->where('itemsection', \array_unique([$request->getData('price_itemsection'), null]), 'IN'); + $queryMapper->where('itemtype', \array_unique([$request->getData('price_itemtype'), null]), 'IN'); + $queryMapper->where('client', \array_unique([$request->getData('price_client'), null]), 'IN'); + $queryMapper->where('clientgroup', \array_unique([$request->getData('price_clientgroup'), null]), 'IN'); + $queryMapper->where('clientsegment', \array_unique([$request->getData('price_clientsegment'), null]), 'IN'); + $queryMapper->where('clientsection', \array_unique([$request->getData('price_clientsection'), null]), 'IN'); + $queryMapper->where('clienttype', \array_unique([$request->getData('price_clienttype'), null]), 'IN'); + $queryMapper->where('clientcountry', \array_unique([$request->getData('price_clientcountry'), null]), 'IN'); + $queryMapper->where('supplier', \array_unique([$request->getData('price_supplier'), null]), 'IN'); + $queryMapper->where('unit', \array_unique([$request->getData('price_unit'), null]), 'IN'); + $queryMapper->where('type', $request->getData('price_type', 'int') ?? PricingType::SALES); + $queryMapper->where('currency', array_unique([$request->getData('price_currency'), null]), 'IN'); + + /* + if ($request->hasData('price_quantity')) { + $whereQuery = new Where(); + $whereQuery->where('quantity', (int) $request->getData('price_quantity'), '<=') + ->where('quantity', null, '=', 'OR') + + $queryMapper->where('quantity', $whereQuery); + } + */ + + $result = $queryMapper->execute(); + + $response->header->set('Content-Type', MimeType::M_JSON, true); + $response->set( + $request->uri->__toString(), + \array_values( + ItemMapper::getAll() + ->where('name', '%' . ($request->getData('search') ?? '') . '%', 'LIKE') + ->execute() + ) + ); + } + /** * Api method to update a bill * @@ -281,7 +351,6 @@ final class ApiController extends Controller $request->header->account, __DIR__ . '/../../../Modules/Media/Files' . $path, $path, - type: $request->getData('type', 'int'), pathSettings: PathSettings::FILE_PATH, hasAccountRelation: false, readContent: (bool) ($request->getData('parse_content') ?? false) @@ -294,11 +363,23 @@ final class ApiController extends Controller $bill->getId(), $media->getId(), BillMapper::class, - 'bill_media', + 'media', '', $request->getOrigin() ); + if ($request->hasData('type')) { + $this->createModelRelation( + $request->header->account, + $media->getId(), + $request->getData('type', 'int'), + MediaMapper::class, + 'types', + '', + $request->getOrigin() + ); + } + if ($collection === null) { $collection = MediaMapper::getParentCollection($path)->limit(1)->execute(); @@ -311,7 +392,15 @@ final class ApiController extends Controller } } - CollectionMapper::writer()->createRelationTable('sources', [$media->getId()], $collection->getId()); + $this->createModelRelation( + $request->header->account, + $collection->getId(), + $media->getId(), + CollectionMapper::class, + 'sources', + '', + $request->getOrigin() + ); } } @@ -320,9 +409,9 @@ final class ApiController extends Controller $this->createModelRelation( $request->header->account, $bill->getId(), - $media, + (int) $media, BillMapper::class, - 'bill_media', + 'media', '', $request->getOrigin() ); @@ -432,7 +521,9 @@ final class ApiController extends Controller /** @var \Modules\ItemManagement\Models\Item $item */ $item = ItemMapper::get() ->with('l11n') + ->with('l11n/type') ->where('id', $element->item) + ->where('l11n/type/title', ['name1', 'name2', 'name3'], 'IN') ->where('l11n/language', $response->getLanguage()) ->execute(); @@ -502,6 +593,80 @@ final class ApiController extends Controller return []; } + public function apiPreviewRender(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + Autoloader::addPath(__DIR__ . '/../../../Resources/'); + + $templateId = $request->getData('bill_template', 'int'); + if ($templateId === null) { + $billTypeId = $request->getData('bill_type', 'int'); + $billType = BillTypeMapper::get() + ->where('id', $billTypeId) + ->execute(); + + $templateId = $billType->defaultTemplate->getId(); + } + + $template = CollectionMapper::get() + ->with('sources') + ->where('id', $templateId) + ->execute(); + + require_once __DIR__ . '/../../../Resources/tcpdf/tcpdf.php'; + + $response->header->set('Content-Type', MimeType::M_PDF, true); + + $view = new View($this->app->l11nManager, $request, $response); + $view->setTemplate('/' . \substr($template->getSourceByName('bill.pdf.php')->getPath(), 0, -8), 'pdf.php'); + $view->setData('bill', $bill); + $view->setData('path', $pdfDir . '/' . $request->getData('bill') . '.pdf'); + + $view->setData('bill_creator', $request->getData('bill_creator')); + $view->setData('bill_title', $request->getData('bill_title')); + $view->setData('bill_subtitle', $request->getData('bill_subtitle')); + $view->setData('keywords', $request->getData('keywords')); + $view->setData('bill_logo_name', $request->getData('bill_logo_name')); + $view->setData('bill_slogan', $request->getData('bill_slogan')); + + $view->setData('legal_company_name', $request->getData('legal_company_name')); + $view->setData('bill_company_address', $request->getData('bill_company_address')); + $view->setData('bill_company_city', $request->getData('bill_company_city')); + $view->setData('bill_company_ceo', $request->getData('bill_company_ceo')); + $view->setData('bill_company_website', $request->getData('bill_company_website')); + $view->setData('bill_company_email', $request->getData('bill_company_email')); + $view->setData('bill_company_phone', $request->getData('bill_company_phone')); + + $view->setData('bill_company_tax_office', $request->getData('bill_company_tax_office')); + $view->setData('bill_company_tax_id', $request->getData('bill_company_tax_id')); + $view->setData('bill_company_vat_id', $request->getData('bill_company_vat_id')); + + $view->setData('bill_company_bank_name', $request->getData('bill_company_bank_name')); + $view->setData('bill_company_bic', $request->getData('bill_company_bic')); + $view->setData('bill_company_iban', $request->getData('bill_company_iban')); + + $view->setData('bill_type_name', $request->getData('bill_type_name')); + + $view->setData('bill_invoice_no', $request->getData('bill_invoice_no')); + $view->setData('bill_invoice_date', $request->getData('bill_invoice_date')); + $view->setData('bill_service_date', $request->getData('bill_service_date')); + $view->setData('bill_customer_no', $request->getData('bill_customer_no')); + $view->setData('bill_po', $request->getData('bill_po')); + $view->setData('bill_due_date', $request->getData('bill_due_date')); + + $view->setData('bill_start_text', $request->getData('bill_start_text')); + $view->setData('bill_lines', $request->getData('bill_lines')); + $view->setData('bill_end_text', $request->getData('bill_end_text')); + + $view->setData('bill_payment_terms', $request->getData('bill_payment_terms')); + $view->setData('bill_terms', $request->getData('bill_terms')); + $view->setData('bill_taxes', $request->getData('bill_taxes')); + $view->setData('bill_currency', $request->getData('bill_currency')); + + $pdf = $view->render(); + + $response->set('', $pdf); + } + /** * Api method to create and archive a bill * @@ -517,23 +682,39 @@ final class ApiController extends Controller */ public function apiBillPdfArchiveCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void { - Autoloader::addPath(__DIR__ . '/../../../Resources/'); - /** @var \Modules\Billing\Models\Bill $bill */ $bill = BillMapper::get() - ->with('type') - ->with('type/template') - ->with('type/template/sources') + ->with('elements') ->where('id', $request->getData('bill') ?? 0) ->execute(); - /** @var \Model\Setting $previewType */ - $previewType = $this->app->appSettings->get( - names: SettingsEnum::PREVIEW_MEDIA_TYPE, - module: self::NAME - ); + Autoloader::addPath(__DIR__ . '/../../../Resources/'); - $template = $bill->type->template; + $templateId = $request->getData('bill_template', 'int'); + if ($templateId === null) { + $billTypeId = $bill->type->getId(); + $billType = BillTypeMapper::get() + ->where('id', $billTypeId) + ->execute(); + + $templateId = $billType->defaultTemplate->getId(); + } + + $template = CollectionMapper::get() + ->with('sources') + ->where('id', $templateId) + ->execute(); + + require_once __DIR__ . '/../../../Resources/tcpdf/tcpdf.php'; + + $view = new View($this->app->l11nManager, $request, $response); + $view->setTemplate('/' . \substr($template->getSourceByName('bill.pdf.php')->getPath(), 0, -8), 'pdf.php'); + + /** + @todo: pass data to bill + */ + + $pdf = $view->render(); $path = $this->createBillDir($bill); $pdfDir = __DIR__ . '/../../../Modules/Media/Files' . $path; @@ -548,15 +729,7 @@ final class ApiController extends Controller // @codeCoverageIgnoreEnd } - require_once __DIR__ . '/../../../Resources/tcpdf/tcpdf.php'; - - $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/' . \substr($template->getSourceByName('bill.pdf.php')->getPath(), 0, -8), 'pdf.php'); - $view->setData('bill', $bill); - $view->setData('path', $pdfDir . '/' . $request->getData('bill') . '.pdf'); - - $pdf = $view->build(); - + \file_put_contents($pdfDir . '/' . $request->getData('bill') . '.pdf', $pdf); if (!\is_file($pdfDir . '/' . $request->getData('bill') . '.pdf')) { $response->header->status = RequestStatusCode::R_400; @@ -564,7 +737,7 @@ final class ApiController extends Controller } $media = $this->app->moduleManager->get('Media')->createDbEntry( - [ + status: [ 'status' => UploadStatus::OK, 'name' => $request->getData('bill') . '.pdf', 'path' => $pdfDir, @@ -572,9 +745,12 @@ final class ApiController extends Controller 'size' => \filesize($pdfDir . '/' . $request->getData('bill') . '.pdf'), 'extension' => 'pdf', ], - $request->header->account, - $path, - (int) $previewType->content + account: $request->header->account, + virtualPath: $path, + ip: $request->getOrigin(), + app: $this->app, + readContent: true, + unit: $this->app->unitId ); $this->createModelRelation( @@ -582,7 +758,7 @@ final class ApiController extends Controller $bill->getId(), $media->getId(), BillMapper::class, - 'bill_media', + 'media', '', $request->getOrigin() ); @@ -782,10 +958,17 @@ final class ApiController extends Controller { $billType = new BillType($request->getData('name') ?? ''); $billType->setL11n((string) ($request->getData('title') ?? ''), $request->getData('language') ?? ISO639x1Enum::_EN); - $billType->template = new NullCollection((int) ($request->getData('template') ?? 0)); $billType->numberFormat = (string) ($request->getData('number_format') ?? '{id}'); $billType->transferStock = (bool) ($request->getData('transfer_stock') ?? false); + $billType->isTemplate = (bool) ($request->getData('is_template') ?? false); $billType->transferType = (int) ($request->getData('transfer_type') ?? BillTransferType::SALES); + $billType->defaultTemplate = $request->hasData('template') + ? new NullCollection((int) $request->getData('template')) + : null; + + if ($request->hasData('template')) { + $billType->addTemplate(new NullCollection((int) $request->getData('template'))); + } return $billType; } diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 8bb8dae..9461100 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -14,8 +14,12 @@ declare(strict_types=1); namespace Modules\Billing\Controller; +use Modules\Auditor\Models\AuditMapper; +use Modules\Billing\Models\BillElementMapper; +use Modules\Billing\Models\BillMapper; use Modules\Billing\Models\BillStatus; use Modules\Billing\Models\BillTransferType; +use Modules\Billing\Models\BillTypeMapper; use Modules\Billing\Models\PurchaseBillMapper; use Modules\Billing\Models\SalesBillMapper; use Modules\Billing\Models\SettingsEnum; @@ -27,6 +31,7 @@ use phpOMS\Localization\ISO3166CharEnum; use phpOMS\Localization\ISO3166NameEnum; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; +use phpOMS\Utils\StringUtils; use phpOMS\Views\View; /** @@ -108,7 +113,7 @@ final class BackendController extends Controller public function viewBillingSalesInvoice(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/Billing/Theme/Backend/sales-bill'); + $view->setTemplate('/Modules/Billing/Theme/Backend/bill-create'); $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response)); $bill = SalesBillMapper::get() @@ -120,13 +125,23 @@ final class BackendController extends Controller $view->setData('bill', $bill); - /** @var \Model\Setting $previewType */ - $previewType = $this->app->appSettings->get( - names: SettingsEnum::PREVIEW_MEDIA_TYPE, - module: self::NAME - ); + $logsBill = AuditMapper::getAll() + ->with('createdBy') + ->where('module', 'Billing') + ->where('type', StringUtils::intHash(BillMapper::class)) + ->where('ref', $bill->getId()) + ->execute(); - $view->setData('previewType', (int) $previewType->content); + $logsElements = AuditMapper::getAll() + ->with('createdBy') + ->where('module', 'Billing') + ->where('type', StringUtils::intHash(BillElementMapper::class)) + ->where('ref', \array_keys($bill->getElements()), 'IN') + ->execute(); + + $logs = \array_merge($logsBill, $logsElements); + + $view->setData('logs', $logs); return $view; } @@ -146,9 +161,22 @@ final class BackendController extends Controller public function viewBillingSalesInvoiceCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/Billing/Theme/Backend/invoice-create'); + $view->setTemplate('/Modules/Billing/Theme/Backend/bill-create'); $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response)); + $billTypes = BillTypeMapper::getAll() + ->with('l11n') + ->where('isTemplate', false) + ->where('transferType', BillTransferType::SALES) + ->where('l11n/language', $request->getLanguage()) + ->execute(); + + $view->setData('billtypes', $billTypes); + + $mediaListView = new \Modules\Media\Theme\Backend\Components\Media\ListView($this->app->l11nManager, $request, $response); + $mediaListView->setTemplate('/Modules/Media/Theme/Backend/Components/Media/list'); + $view->addData('medialist', $mediaListView); + return $view; } @@ -167,7 +195,7 @@ final class BackendController extends Controller public function viewBillingPurchaseInvoiceCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/Billing/Theme/Backend/invoice-create'); + $view->setTemplate('/Modules/Billing/Theme/Backend/bill-create'); $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response)); return $view; @@ -188,7 +216,7 @@ final class BackendController extends Controller public function viewBillingStockInvoiceCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/Billing/Theme/Backend/invoice-create'); + $view->setTemplate('/Modules/Billing/Theme/Backend/bill-create'); $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response)); return $view; diff --git a/Models/Bill.php b/Models/Bill.php index f9ab7da..67a0e94 100755 --- a/Models/Bill.php +++ b/Models/Bill.php @@ -18,10 +18,13 @@ use Modules\Admin\Models\Account; use Modules\Admin\Models\NullAccount; use Modules\ClientManagement\Models\Client; use Modules\Editor\Models\EditorDoc; +use Modules\Media\Models\Collection; use Modules\Media\Models\Media; use Modules\Media\Models\NullMedia; use Modules\SupplierManagement\Models\Supplier; +use phpOMS\Localization\ISO3166TwoEnum; use phpOMS\Localization\ISO4217CharEnum; +use phpOMS\Localization\ISO639x1Enum; use phpOMS\Localization\Money; /** @@ -42,6 +45,8 @@ class Bill implements \JsonSerializable */ protected int $id = 0; + public int $source = 0; + /** * Number ID. * @@ -66,6 +71,8 @@ class Bill implements \JsonSerializable */ public BillType $type; + public ?Collection $template = null; + /** * Bill status. * @@ -118,6 +125,8 @@ class Bill implements \JsonSerializable public ?Supplier $supplier = null; + public string $language = ISO639x1Enum::_EN; + /** * Receiver. * @@ -214,6 +223,8 @@ class Bill implements \JsonSerializable */ public string $billCountry = ''; + public string $billEmail = ''; + /** * Person refering for this order. * @@ -555,6 +566,32 @@ class Bill implements \JsonSerializable return $this->currency; } + /** + * Set language. + * + * @param string $language Language + * + * @return void + * + * @since 1.0.0 + */ + public function setLanguage(string $language) : void + { + $this->language = $language; + } + + /** + * Get language. + * + * @return string + * + * @since 1.0.0 + */ + public function getLanguage() : string + { + return $this->language; + } + /** * Get vouchers. * diff --git a/Models/BillMapper.php b/Models/BillMapper.php index a241f87..96e136f 100755 --- a/Models/BillMapper.php +++ b/Models/BillMapper.php @@ -17,6 +17,7 @@ namespace Modules\Billing\Models; use Modules\Admin\Models\AccountMapper; use Modules\ClientManagement\Models\ClientMapper; use Modules\Editor\Models\EditorDocMapper; +use Modules\Media\Models\CollectionMapper; use Modules\Media\Models\MediaMapper; use Modules\SupplierManagement\Models\SupplierMapper; use phpOMS\DataStorage\Database\Mapper\DataMapperFactory; @@ -42,6 +43,7 @@ class BillMapper extends DataMapperFactory 'billing_bill_number' => ['name' => 'billing_bill_number', 'type' => 'string', 'internal' => 'number'], 'billing_bill_numberformat' => ['name' => 'billing_bill_numberformat', 'type' => 'string', 'internal' => 'numberFormat'], 'billing_bill_type' => ['name' => 'billing_bill_type', 'type' => 'int', 'internal' => 'type'], + 'billing_bill_template' => ['name' => 'billing_bill_template', 'type' => 'int', 'internal' => 'template'], 'billing_bill_header' => ['name' => 'billing_bill_header', 'type' => 'string', 'internal' => 'header'], 'billing_bill_footer' => ['name' => 'billing_bill_footer', 'type' => 'string', 'internal' => 'footer'], 'billing_bill_info' => ['name' => 'billing_bill_info', 'type' => 'string', 'internal' => 'info'], @@ -67,6 +69,7 @@ class BillMapper extends DataMapperFactory 'billing_bill_netdiscount' => ['name' => 'billing_bill_netdiscount', 'type' => 'Serializable', 'internal' => 'netDiscount'], 'billing_bill_grossdiscount' => ['name' => 'billing_bill_grossdiscount', 'type' => 'Serializable', 'internal' => 'grossDiscount'], 'billing_bill_currency' => ['name' => 'billing_bill_currency', 'type' => 'string', 'internal' => 'currency'], + 'billing_bill_language' => ['name' => 'billing_bill_language', 'type' => 'string', 'internal' => 'language'], 'billing_bill_referral' => ['name' => 'billing_bill_referral', 'type' => 'int', 'internal' => 'referral'], 'billing_bill_referral_name' => ['name' => 'billing_bill_referral_name', 'type' => 'string', 'internal' => 'referralName'], 'billing_bill_reference' => ['name' => 'billing_bill_reference', 'type' => 'int', 'internal' => 'reference'], @@ -125,6 +128,10 @@ class BillMapper extends DataMapperFactory 'mapper' => AccountMapper::class, 'external' => 'billing_bill_referral', ], + 'template' => [ + 'mapper' => CollectionMapper::class, + 'external' => 'billing_bill_template', + ], ]; /** diff --git a/Models/BillType.php b/Models/BillType.php index c295115..4a42242 100755 --- a/Models/BillType.php +++ b/Models/BillType.php @@ -39,7 +39,9 @@ class BillType implements \JsonSerializable public string $name = ''; - public Collection $template; + public array $templates = []; + + public ?Collection $defaultTemplate = null; public string $numberFormat = ''; @@ -66,7 +68,6 @@ class BillType implements \JsonSerializable public function __construct(string $name = '') { $this->name = $name; - $this->template = new NullCollection(); } /** @@ -120,6 +121,16 @@ class BillType implements \JsonSerializable return $this->l11n instanceof BaseStringL11n ? $this->l11n->content : $this->l11n; } + public function addTemplate(Collection $template) : void + { + $this->templates[] = $template; + } + + public function getTemplates() : array + { + return $this->templates; + } + /** * {@inheritdoc} */ diff --git a/Models/BillTypeMapper.php b/Models/BillTypeMapper.php index c907924..3c8cd9d 100755 --- a/Models/BillTypeMapper.php +++ b/Models/BillTypeMapper.php @@ -15,6 +15,7 @@ declare(strict_types=1); namespace Modules\Billing\Models; use Modules\Media\Models\CollectionMapper; +use Modules\Media\Models\MediaMapper; use phpOMS\DataStorage\Database\Mapper\DataMapperFactory; /** @@ -37,25 +38,12 @@ final class BillTypeMapper extends DataMapperFactory 'billing_type_id' => ['name' => 'billing_type_id', 'type' => 'int', 'internal' => 'id'], 'billing_type_name' => ['name' => 'billing_type_name', 'type' => 'string', 'internal' => 'name'], 'billing_type_number_format' => ['name' => 'billing_type_number_format', 'type' => 'string', 'internal' => 'numberFormat'], - 'billing_type_template' => ['name' => 'billing_type_template', 'type' => 'int', 'internal' => 'template'], 'billing_type_transfer_type' => ['name' => 'billing_type_transfer_type', 'type' => 'int', 'internal' => 'transferType'], + 'billing_type_default_template' => ['name' => 'billing_type_default_template', 'type' => 'int', 'internal' => 'defaultTemplate'], 'billing_type_transfer_stock' => ['name' => 'billing_type_transfer_stock', 'type' => 'bool', 'internal' => 'transferStock'], 'billing_type_is_template' => ['name' => 'billing_type_is_template', 'type' => 'bool', 'internal' => 'isTemplate'], ]; - /** - * Belongs to. - * - * @var array - * @since 1.0.0 - */ - public const OWNS_ONE = [ - 'template' => [ - 'mapper' => CollectionMapper::class, - 'external' => 'billing_type_template', - ], - ]; - /** * Has many relation. * @@ -70,6 +58,25 @@ final class BillTypeMapper extends DataMapperFactory 'column' => 'content', 'external' => null, ], + 'templates' => [ + 'mapper' => MediaMapper::class, + 'table' => 'billing_bill_type_media_rel', + 'external' => 'billing_bill_type_media_rel_dst', + 'self' => 'billing_bill_type_media_rel_src', + ], + ]; + + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + public const OWNS_ONE = [ + 'defaultTemplate' => [ + 'mapper' => CollectionMapper::class, + 'external' => 'billing_type_default_template', + ], ]; /** diff --git a/Models/PricingMapper.php b/Models/PricingMapper.php new file mode 100644 index 0000000..985220d --- /dev/null +++ b/Models/PricingMapper.php @@ -0,0 +1,94 @@ + + * @since 1.0.0 + */ + public const COLUMNS = [ + 'billing_type_id' => ['name' => 'billing_type_id', 'type' => 'int', 'internal' => 'id'], + 'billing_type_name' => ['name' => 'billing_type_name', 'type' => 'string', 'internal' => 'name'], + 'billing_type_number_format' => ['name' => 'billing_type_number_format', 'type' => 'string', 'internal' => 'numberFormat'], + 'billing_type_transfer_type' => ['name' => 'billing_type_transfer_type', 'type' => 'int', 'internal' => 'transferType'], + 'billing_type_default_template' => ['name' => 'billing_type_default_template', 'type' => 'int', 'internal' => 'defaultTemplate'], + 'billing_type_transfer_stock' => ['name' => 'billing_type_transfer_stock', 'type' => 'bool', 'internal' => 'transferStock'], + 'billing_type_is_template' => ['name' => 'billing_type_is_template', 'type' => 'bool', 'internal' => 'isTemplate'], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = Pricing::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'billing_price'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD ='billing_price_id'; + + public static function findClientPrice() : array + { + /* + select * from prices + where + (promoID = ? OR promoID = null) + AND (itemID = ? OR itemID = null) + AND (itemGroup = IN (?) OR itemGroup = null) + AND (itemSegment = ? OR itemSegment = null) + AND (itemSection = ? OR itemSection = null) + AND (productType = ? OR productType = null) + AND (customerID = ? OR customerID = null) + AND (customerGroup IN (?) OR customerGroup = null) + AND (customerCountry = IN (?) OR customerCountry = null) + AND (quantity < ? OR quantity = null) + AND (start <= ? OR start = null) + AND (end >= ? OR start = null) + AND (unit = ? OR unit = null) + */ + + // @todo: allow nested where clause (already possible with the query builder, but not with the mappers) + + return []; + } +} diff --git a/Models/PricingType.php b/Models/PricingType.php new file mode 100644 index 0000000..69853b0 --- /dev/null +++ b/Models/PricingType.php @@ -0,0 +1,32 @@ + [ + 'Amount' => 'Amount', 'Address' => 'Address', 'Addresses' => 'Addresses', 'Africa' => 'Africa', + 'Currency' => 'Currency', + 'Language' => 'Language', 'AlreadyPaid' => 'Already Paid', 'America' => 'America', 'Analyse' => 'Analyse', @@ -23,6 +26,7 @@ return ['Billing' => [ 'Asia' => 'Asia', 'Attribute' => 'Attribute', 'BaseTime' => 'Base time', + 'Billing' => 'Billing', 'Bills' => 'Bills', 'Bonus' => 'Bonus', 'CIS' => 'CIS', @@ -52,6 +56,7 @@ return ['Billing' => [ 'Invoice' => 'Invoice', 'Invoices' => 'Invoices', 'Item' => 'Item', + 'Email' => 'Email', 'Items' => 'Items', 'Log' => 'Log', 'Logs' => 'Logs', @@ -62,6 +67,7 @@ return ['Billing' => [ 'Offer' => 'Offer', 'Other' => 'Other', 'Payment' => 'Payment', + 'PaymentPlan' => 'Payment Plan', 'Postal' => 'Postal', 'Prepaid' => 'Prepaid', 'Preview' => 'Preview', @@ -81,6 +87,7 @@ return ['Billing' => [ 'TermsOfDelivery' => 'Terms Of Delivery', 'Total' => 'Total', 'Type' => 'Type', + 'Types' => 'Types', 'Upload' => 'Upload', 'Value' => 'Value', 'Variation' => 'Variation', diff --git a/Theme/Backend/bill-create.tpl.php b/Theme/Backend/bill-create.tpl.php new file mode 100755 index 0000000..625392c --- /dev/null +++ b/Theme/Backend/bill-create.tpl.php @@ -0,0 +1,538 @@ +getData('media') ?? []; + +/** @var \Modules\Billing\Models\Bill $bill */ +$bill = $this->getData('bill') ?? new NullBill(); +$elements = $bill->getElements(); + +$billTypes = $this->getData('billtypes') ?? []; + +/** @var \Modules\Auditor\Models\Audit */ +$logs = $this->getData('logs') ?? []; + +// @todo: false needs to be replaced with status->NOT_FINALIZED (check which status it actually is) +$editable = $bill instanceof NullBill || false; +$disabled = !$editable ? ' disabled' : ''; + +echo $this->getData('nav')->render(); ?> + +
+
+ +
+
+ +
+
+
+
+
+
getHtml('Invoice'); ?>
+
+
+ + +
+ +
+ + +
+ +
+ + + + > + +
+ +
+ + +
+ +
+ + + + > + +
+ +
+ + > +
+ +
+ + > +
+ +
+ + > +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+
+
getHtml('Billing'); ?>
+
+
+
+ + +
+ +
+ + > +
+ +
+ + > +
+ +
+ + > +
+ +
+ + > +
+ +
+ + +
+ +
+ + > +
+
+
+
+
+ +
+
+
getHtml('Delivery'); ?>
+
+
+
+ + +
+ +
+ + > +
+ +
+ + > +
+ +
+ + > +
+ +
+ + > +
+ +
+ + +
+
+
+
+
+
+
+ +
+
+
+
+
getHtml('Invoice'); ?>
+ + + + + + + + + + +
+ getHtml('Item'); ?> + getHtml('Name'); ?> + getHtml('Quantity'); ?> + getHtml('Discount'); ?> + getHtml('DiscountP'); ?> + getHtml('Bonus'); ?> + getHtml('Tax'); ?> + getHtml('Price'); ?> + getHtml('Net'); ?> +
+ + + + + > + + > + > + > + > + > + > + totalSalesPriceNet->getCurrency(); ?> + + +
+ + + + + + + + + + + +
+ +
+ + +
+ +
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
getHtml('Payment'); ?>
+
+
+
+ + > +
+ +
+ + +
+ +
+ + > +
+
+ +
+ +
+
+ + > +
+ +
+ + > +
+
+ +
+ +
+
+ + > +
+ +
+ + > +
+ +
+
+
+ +
+
+
getHtml('PaymentPlan'); ?>
+ + + + + +
+ getHtml('Date'); ?> + getHtml('Amount'); ?> +
+
+ + +
+ +
+ +
+
+
+ +
+
+
+
+
getHtml('Media'); ?>
+
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+
+
+ +
+ getData('medialist')?->render($media); ?> +
+
+
+ +
+ l11nManager, $this->request, $this->response); + $footerView->setTemplate('/Web/Templates/Lists/Footer/PaginationBig'); + $footerView->setPages(20); + $footerView->setPage(1); + ?> +
+
+
+
getHtml('Logs'); ?>
+ + + + + getId()); + ?> + +
getHtml('ID', '0', '0'); ?> + getHtml('Trigger', 'Auditor', 'Backend'); ?> + getHtml('Action', 'Auditor', 'Backend'); ?> + getHtml('CreatedBy', 'Auditor', 'Backend'); ?> + getHtml('CreatedAt', 'Auditor', 'Backend'); ?> +
getId(); ?> + trigger; ?> + old === null) : echo $this->getHtml('CREATE', 'Auditor', 'Backend'); ?> + old !== null && $audit->new !== null) : echo $this->getHtml('UPDATE', 'Auditor', 'Backend'); ?> + new === null) : echo $this->getHtml('DELETE', 'Auditor', 'Backend'); ?> + getHtml('UNKNOWN', 'Auditor', 'Backend'); ?> + + printHtml( + $this->renderUserName('%3$s %2$s %1$s', [$audit->createdBy->name1, $audit->createdBy->name2, $audit->createdBy->name3, $audit->createdBy->login]) + ); ?> + createdAt->format('Y-m-d'); ?> + +
+
+
+
+
+
+
+ diff --git a/Theme/Backend/invoice-create.tpl.php b/Theme/Backend/invoice-create.tpl.php deleted file mode 100755 index 133a15f..0000000 --- a/Theme/Backend/invoice-create.tpl.php +++ /dev/null @@ -1,269 +0,0 @@ -getData('nav')->render(); ?> - -
-
- -
-
- -
-
-
-
-

getHtml('Invoice'); ?>

-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-

getHtml('Invoice'); ?>

-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-

getHtml('Delivery'); ?>

-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- - - - - - - - -
getHtml('Invoice'); ?>
- getHtml('Item'); ?> - getHtml('Variation'); ?> - getHtml('Name'); ?> - getHtml('Quantity'); ?> - getHtml('Discount'); ?> - getHtml('DiscountP'); ?> - getHtml('Bonus'); ?> - getHtml('Tax'); ?> - getHtml('Net'); ?> -
- getHtml('Freightage'); ?>: 0.00 - - getHtml('Net'); ?>: 0.00 - - getHtml('Tax'); ?>: 0.00 - - getHtml('Total'); ?>: 0.00 -
- - - - - - - - - -
-
-
-
-
- -
-
- -
-
-
-
-

getHtml('Payment'); ?>

-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-

getHtml('Media'); ?>

- -
-
- - -
-
-
-
-
-
-
-
-
-
-
- -
- l11nManager, $this->request, $this->response); - $footerView->setTemplate('/Web/Templates/Lists/Footer/PaginationBig'); - $footerView->setPages(20); - $footerView->setPage(1); - ?> -
-
-
- - - - - - -
getHtml('Logs'); ?>
IP - getHtml('ID', '0', '0'); ?> - getHtml('Name'); ?> - getHtml('Log'); ?> - getHtml('Date'); ?> -
printHtml($this->request->getOrigin()); ?> - printHtml((string) $this->request->header->account); ?> - printHtml((string) $this->request->header->account); ?> - Create Invoice - printHtml((new \DateTime('now'))->format('Y-m-d H:i:s')); ?> -
-
-
-
-
-
-
- diff --git a/Theme/Backend/sales-bill.tpl.php b/Theme/Backend/sales-bill.tpl.php deleted file mode 100755 index 789d2b8..0000000 --- a/Theme/Backend/sales-bill.tpl.php +++ /dev/null @@ -1,333 +0,0 @@ -getData('bill'); -$elements = $bill->getElements(); -$media = $bill->getMedia(); - -$previewType = $this->getData('previewType'); -$billPdf = $bill->getFileByType($previewType); - -echo $this->getData('nav')->render(); ?> - -
-
- -
-
- -
-
-
-
-
-
getHtml('Invoice'); ?>
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
getHtml('Invoice'); ?>
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
getHtml('Delivery'); ?>
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
getHtml('Invoice'); ?>
-
- - - - - - - -
- getHtml('Item'); ?> - getHtml('Name'); ?> - getHtml('Quantity'); ?> - getHtml('Price'); ?> - getHtml('Discount'); ?> - getHtml('DiscountP'); ?> - getHtml('Bonus'); ?> - getHtml('Tax'); ?> - getHtml('Net'); ?> -
- - - - - - - - - totalSalesPriceNet->getCurrency(); ?> - -
- - - - - - - - - -
-
-
- getHtml('Freightage'); ?>: 0.00 - - getHtml('Net'); ?>: netSales->getCurrency(); ?> - - getHtml('Tax'); ?>: 0.00 - - getHtml('Total'); ?>: grossSales->getCurrency(); ?> -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-

getHtml('Payment'); ?>

-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-

getHtml('Media'); ?>

- -
-
- - -
-
-
-
-
-
-
-
-
- -
-
-
getHtml('Media'); ?>
- - - - - extension === 'collection' - ? UriFactory::build('{/lang}/{/app}/media/list?path=' . \rtrim($file->getVirtualPath(), '/') . '/' . $file->name) - : UriFactory::build('{/lang}/{/app}/media/single?id=' . $file->getId() - . '&path={?path}' . ( - $file->getId() === 0 - ? '/' . $file->name - : '' - ) - ); - - $icon = $fileIconFunction(FileUtils::getExtensionType($file->extension)); - ?> - -
- - getHtml('Name'); ?> - getHtml('Type'); ?> -
- - name; ?> - extension; ?> - -
-
-
-
-
- -
-
-
-
- - - - - - -
getHtml('Logs'); ?>
IP - getHtml('ID', '0', '0'); ?> - getHtml('Name'); ?> - getHtml('Log'); ?> - getHtml('Date'); ?> -
printHtml($this->request->getOrigin()); ?> - printHtml((string) $this->request->header->account); ?> - printHtml((string) $this->request->header->account); ?> - Create Invoice - printHtml((new \DateTime('now'))->format('Y-m-d H:i:s')); ?> -
-
-
-
-
-
-
-