mirror of
https://github.com/Karaka-Management/oms-Billing.git
synced 2026-01-31 16:58:41 +00:00
too many changes
This commit is contained in:
parent
ff90dba39e
commit
44b4db558b
|
|
@ -2,83 +2,11 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
class MYPDF extends TCPDF
|
require_once $this->getData('defaultTemplates')
|
||||||
{
|
->findFile('.pdf.php')
|
||||||
public string $fontName = '';
|
->getAbsolutePath();
|
||||||
public int $fontSize = 8;
|
|
||||||
public int $sideMargin = 15;
|
|
||||||
|
|
||||||
//Page header
|
$pdf = new DefaultPdf('P', 'mm', 'A4', true, 'UTF-8', false);
|
||||||
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 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->endTemplate();
|
|
||||||
}
|
|
||||||
|
|
||||||
$x = 0;
|
|
||||||
$dx = 0;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$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() {
|
|
||||||
$this->SetY(-25);
|
|
||||||
|
|
||||||
$this->SetFont('helvetica', 'I', 7);
|
|
||||||
$this->Cell($this->getPageWidth() - 22, 0, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'R', 0, '', 0, false, 'T', 'M');
|
|
||||||
$this->Ln();
|
|
||||||
$this->Ln();
|
|
||||||
|
|
||||||
$this->SetFillColor(245, 245, 245);
|
|
||||||
$this->SetX(0);
|
|
||||||
$this->Cell($this->getPageWidth(), 25, '', 0, 0, 'L', true, '', 0, false, 'T', 'T');
|
|
||||||
|
|
||||||
$this->SetFont('helvetica', '', 7);
|
|
||||||
$this->SetXY(15 + 10, -15, true);
|
|
||||||
$this->MultiCell(30, 0, "Jingga e.K.\nGartenstr. 26\n61206 Woellstadt", 0, 'L', false, 1, null, null, true, 0, false, true, 0, 'B');
|
|
||||||
|
|
||||||
$this->SetXY(25 + 15 + 20, -15, true);
|
|
||||||
$this->MultiCell(40, 0, "Geschäftsführer: Dennis Eichhorn\nFinanzamt: HRB ???\nUSt Id: DE ??????????", 0, 'L', false, 1, null, null, true, 0, false, true, 0, 'B');
|
|
||||||
|
|
||||||
$this->SetXY(25 + 45 + 15 + 30, -15, true);
|
|
||||||
$this->MultiCell(35, 0, "Volksbank Mittelhessen\nBIC: ??????????\nIBAN: ???????????", 0, 'L', false, 1, null, null, true, 0, false, true, 0, 'B');
|
|
||||||
|
|
||||||
$this->SetXY(25 + 45 + 35 + 15 + 40, -15, true);
|
|
||||||
$this->MultiCell(35, 0, "www.jingga.app\ninfo@jingga.app\n+49 0152 ???????", 0, 'L', false, 1, null, null, true, 0, false, true, 0, 'B');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdf = new MYPDF('P', 'mm', 'A4', true, 'UTF-8', false);
|
|
||||||
|
|
||||||
$creator = $this->getData('bill_creator') ?? 'Jingga';
|
$creator = $this->getData('bill_creator') ?? 'Jingga';
|
||||||
$author = 'Jingga';
|
$author = 'Jingga';
|
||||||
|
|
@ -120,7 +48,6 @@ $terms = $this->getData('bill_terms') ?? 'https://jingga.app/terms';
|
||||||
$taxes = $this->getData('bill_taxes') ?? ['19%' => '0.00'];
|
$taxes = $this->getData('bill_taxes') ?? ['19%' => '0.00'];
|
||||||
$currency = $this->getData('bill_currency') ?? 'EUR';
|
$currency = $this->getData('bill_currency') ?? 'EUR';
|
||||||
|
|
||||||
|
|
||||||
// set document information
|
// set document information
|
||||||
$pdf->SetCreator($creator);
|
$pdf->SetCreator($creator);
|
||||||
$pdf->SetAuthor($author);
|
$pdf->SetAuthor($author);
|
||||||
|
|
@ -128,28 +55,9 @@ $pdf->SetTitle($title);
|
||||||
$pdf->SetSubject($subtitle);
|
$pdf->SetSubject($subtitle);
|
||||||
$pdf->SetKeywords(\implode(', ', $keywords));
|
$pdf->SetKeywords(\implode(', ', $keywords));
|
||||||
|
|
||||||
// set default header data
|
|
||||||
$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]);
|
|
||||||
$pdf->SetFooterFont([PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA]);
|
|
||||||
|
|
||||||
// set default monospaced font
|
|
||||||
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
|
|
||||||
|
|
||||||
// set margins
|
|
||||||
$pdf->SetMargins(15, 30, 15);
|
|
||||||
|
|
||||||
// set auto page breaks
|
|
||||||
$pdf->SetAutoPageBreak(true, 25);
|
|
||||||
|
|
||||||
// set image scale factor
|
// set image scale factor
|
||||||
$pdf->SetImageScale(PDF_IMAGE_SCALE_RATIO);
|
$pdf->SetImageScale(PDF_IMAGE_SCALE_RATIO);
|
||||||
|
|
||||||
// add a page
|
|
||||||
$pdf->AddPage();
|
|
||||||
|
|
||||||
$topPos = $pdf->getY();
|
$topPos = $pdf->getY();
|
||||||
|
|
||||||
// Address
|
// Address
|
||||||
|
|
|
||||||
15
Admin/Install/attributes.json
Normal file
15
Admin/Install/attributes.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "external_payment_id",
|
||||||
|
"l11n": {
|
||||||
|
"en": "External payment Id",
|
||||||
|
"de": "Externe Zahlungsid"
|
||||||
|
},
|
||||||
|
"value_type": 2,
|
||||||
|
"is_custom_allowed": true,
|
||||||
|
"validation_pattern": "",
|
||||||
|
"is_required": false,
|
||||||
|
"default_value": "",
|
||||||
|
"values": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -1,179 +1,271 @@
|
||||||
{
|
{
|
||||||
"billing_prices": {
|
"billing_price": {
|
||||||
"name": "billing_prices",
|
"name": "billing_price",
|
||||||
"fields": {
|
"fields": {
|
||||||
"billing_prices_id": {
|
"billing_price_id": {
|
||||||
"name": "billing_prices_id",
|
"name": "billing_price_id",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": false,
|
"null": false,
|
||||||
"primary": true,
|
"primary": true,
|
||||||
"autoincrement": true
|
"autoincrement": true
|
||||||
},
|
},
|
||||||
"billing_prices_name": {
|
"billing_price_name": {
|
||||||
"name": "billing_prices_name",
|
"name": "billing_price_name",
|
||||||
"type": "VARCHAR(255)",
|
"type": "VARCHAR(255)",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_promocode": {
|
"billing_price_promocode": {
|
||||||
"name": "billing_prices_promocode",
|
"name": "billing_price_promocode",
|
||||||
"type": "INT",
|
"type": "VARCHAR(50)",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_item": {
|
"billing_price_item": {
|
||||||
"name": "billing_prices_item",
|
"name": "billing_price_item",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "itemmgmt_item",
|
"foreignTable": "itemmgmt_item",
|
||||||
"foreignKey": "itemmgmt_item_id"
|
"foreignKey": "itemmgmt_item_id"
|
||||||
},
|
},
|
||||||
"billing_prices_itemgroup": {
|
"billing_price_itemgroup": {
|
||||||
"name": "billing_prices_itemgroup",
|
"name": "billing_price_itemgroup",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "itemmgmt_attr_value",
|
"foreignTable": "itemmgmt_attr_value",
|
||||||
"foreignKey": "itemmgmt_attr_value_id"
|
"foreignKey": "itemmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_itemsegment": {
|
"billing_price_itemsegment": {
|
||||||
"name": "billing_prices_itemsegment",
|
"name": "billing_price_itemsegment",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "itemmgmt_attr_value",
|
"foreignTable": "itemmgmt_attr_value",
|
||||||
"foreignKey": "itemmgmt_attr_value_id"
|
"foreignKey": "itemmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_itemsection": {
|
"billing_price_itemsection": {
|
||||||
"name": "billing_prices_itemsection",
|
"name": "billing_price_itemsection",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "itemmgmt_attr_value",
|
"foreignTable": "itemmgmt_attr_value",
|
||||||
"foreignKey": "itemmgmt_attr_value_id"
|
"foreignKey": "itemmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_itemtype": {
|
"billing_price_itemtype": {
|
||||||
"name": "billing_prices_itemtype",
|
"name": "billing_price_itemtype",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "itemmgmt_attr_value",
|
"foreignTable": "itemmgmt_attr_value",
|
||||||
"foreignKey": "itemmgmt_attr_value_id"
|
"foreignKey": "itemmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_client": {
|
"billing_price_client": {
|
||||||
"name": "billing_prices_client",
|
"name": "billing_price_client",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "clientmgmt_client",
|
"foreignTable": "clientmgmt_client",
|
||||||
"foreignKey": "clientmgmt_client_id"
|
"foreignKey": "clientmgmt_client_id"
|
||||||
},
|
},
|
||||||
"billing_prices_clientgroup": {
|
"billing_price_clientgroup": {
|
||||||
"name": "billing_prices_clientgroup",
|
"name": "billing_price_clientgroup",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "clientmgmt_attr_value",
|
"foreignTable": "clientmgmt_attr_value",
|
||||||
"foreignKey": "clientmgmt_attr_value_id"
|
"foreignKey": "clientmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_clientsegment": {
|
"billing_price_clientsegment": {
|
||||||
"name": "billing_prices_clientsegment",
|
"name": "billing_price_clientsegment",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "clientmgmt_attr_value",
|
"foreignTable": "clientmgmt_attr_value",
|
||||||
"foreignKey": "clientmgmt_attr_value_id"
|
"foreignKey": "clientmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_clientsection": {
|
"billing_price_clientsection": {
|
||||||
"name": "billing_prices_clientsection",
|
"name": "billing_price_clientsection",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "clientmgmt_attr_value",
|
"foreignTable": "clientmgmt_attr_value",
|
||||||
"foreignKey": "clientmgmt_attr_value_id"
|
"foreignKey": "clientmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_clienttype": {
|
"billing_price_clienttype": {
|
||||||
"name": "billing_prices_clienttype",
|
"name": "billing_price_clienttype",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "clientmgmt_attr_value",
|
"foreignTable": "clientmgmt_attr_value",
|
||||||
"foreignKey": "clientmgmt_attr_value_id"
|
"foreignKey": "clientmgmt_attr_value_id"
|
||||||
},
|
},
|
||||||
"billing_prices_clientcountry": {
|
"billing_price_clientcountry": {
|
||||||
"name": "billing_prices_clientcountry",
|
"name": "billing_price_clientcountry",
|
||||||
"type": "VARCHAR(2)",
|
"type": "VARCHAR(2)",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "country",
|
"foreignTable": "country",
|
||||||
"foreignKey": "country_code2"
|
"foreignKey": "country_code2"
|
||||||
},
|
},
|
||||||
"billing_prices_supplier": {
|
"billing_price_supplier": {
|
||||||
"name": "billing_prices_supplier",
|
"name": "billing_price_supplier",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "suppliermgmt_supplier",
|
"foreignTable": "suppliermgmt_supplier",
|
||||||
"foreignKey": "suppliermgmt_supplier_id"
|
"foreignKey": "suppliermgmt_supplier_id"
|
||||||
},
|
},
|
||||||
"billing_prices_unit": {
|
"billing_price_unit": {
|
||||||
"name": "billing_prices_unit",
|
"name": "billing_price_unit",
|
||||||
"type": "INT",
|
"type": "INT",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null
|
||||||
"foreignTable": "unit",
|
|
||||||
"foreignKey": "unit_id"
|
|
||||||
},
|
},
|
||||||
"billing_prices_type": {
|
"billing_price_type": {
|
||||||
"name": "billing_prices_type",
|
"name": "billing_price_type",
|
||||||
"type": "TINYINT(1)",
|
"type": "TINYINT(1)",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_quantity": {
|
"billing_price_quantity": {
|
||||||
"name": "billing_prices_quantity",
|
"name": "billing_price_quantity",
|
||||||
"type": "BIGINT",
|
"type": "BIGINT",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_price": {
|
"billing_price_price": {
|
||||||
"name": "billing_prices_price",
|
"name": "billing_price_price",
|
||||||
"type": "BIGINT",
|
"type": "BIGINT",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_discount": {
|
"billing_price_price_new": {
|
||||||
"name": "billing_prices_discount",
|
"name": "billing_price_price_new",
|
||||||
"type": "BIGINT",
|
"type": "BIGINT",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_discountp": {
|
"billing_price_discount": {
|
||||||
"name": "billing_prices_discountp",
|
"name": "billing_price_discount",
|
||||||
"type": "BIGINT",
|
"type": "BIGINT",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_bonus": {
|
"billing_price_discountp": {
|
||||||
"name": "billing_prices_bonus",
|
"name": "billing_price_discountp",
|
||||||
"type": "BIGINT",
|
"type": "BIGINT",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_multiply": {
|
"billing_price_bonus": {
|
||||||
"name": "billing_prices_multiply",
|
"name": "billing_price_bonus",
|
||||||
|
"type": "BIGINT",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_price_multiply": {
|
||||||
|
"name": "billing_price_multiply",
|
||||||
"type": "TINYINT(1)",
|
"type": "TINYINT(1)",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
"billing_prices_currency": {
|
"billing_price_currency": {
|
||||||
"name": "billing_prices_currency",
|
"name": "billing_price_currency",
|
||||||
"type": "VARCHAR(3)",
|
"type": "VARCHAR(3)",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"foreignTable": "currency",
|
"foreignTable": "currency",
|
||||||
"foreignKey": "currency_code"
|
"foreignKey": "currency_code"
|
||||||
},
|
},
|
||||||
"billing_prices_start": {
|
"billing_price_start": {
|
||||||
"name": "billing_prices_start",
|
"name": "billing_price_start",
|
||||||
"type": "DATETIME",
|
"type": "DATETIME",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null
|
"default": null
|
||||||
},
|
},
|
||||||
"billing_prices_end": {
|
"billing_price_end": {
|
||||||
"name": "billing_prices_end",
|
"name": "billing_price_end",
|
||||||
|
"type": "DATETIME",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"billing_tax": {
|
||||||
|
"name": "billing_tax",
|
||||||
|
"fields": {
|
||||||
|
"billing_tax_id": {
|
||||||
|
"name": "billing_tax_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_tax_client_code": {
|
||||||
|
"name": "billing_tax_client_code",
|
||||||
|
"type": "INT",
|
||||||
|
"null": true,
|
||||||
|
"default": null,
|
||||||
|
"foreignTable": "clientmgmt_attr_value",
|
||||||
|
"foreignKey": "clientmgmt_attr_value_id"
|
||||||
|
},
|
||||||
|
"billing_tax_supplier_code": {
|
||||||
|
"name": "billing_tax_supplier_code",
|
||||||
|
"type": "INT",
|
||||||
|
"null": true,
|
||||||
|
"default": null,
|
||||||
|
"foreignTable": "suppliermgmt_attr_value",
|
||||||
|
"foreignKey": "suppliermgmt_attr_value_id"
|
||||||
|
},
|
||||||
|
"billing_tax_item_code": {
|
||||||
|
"name": "billing_tax_item_code",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "itemmgmt_attr_value",
|
||||||
|
"foreignKey": "itemmgmt_attr_value_id"
|
||||||
|
},
|
||||||
|
"billing_tax_code": {
|
||||||
|
"description": "tax abbr. code",
|
||||||
|
"name": "billing_tax_code",
|
||||||
|
"type": "VARCHAR(10)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_tax_type": {
|
||||||
|
"description": "sales/purchase",
|
||||||
|
"name": "billing_tax_type",
|
||||||
|
"type": "TINYINT",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_tax_account": {
|
||||||
|
"name": "billing_tax_account",
|
||||||
|
"type": "VARCHAR(10)",
|
||||||
|
"null": false,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_tax_refund_account": {
|
||||||
|
"name": "billing_tax_refund_account",
|
||||||
|
"type": "VARCHAR(10)",
|
||||||
|
"null": false,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_tax_discount_account": {
|
||||||
|
"name": "billing_tax_discount_account",
|
||||||
|
"type": "VARCHAR(10)",
|
||||||
|
"null": false,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_tax_min_price": {
|
||||||
|
"name": "billing_tax_min_price",
|
||||||
|
"type": "BIGINT",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_tax_max_price": {
|
||||||
|
"name": "billing_tax_max_price",
|
||||||
|
"type": "BIGINT",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_tax_start": {
|
||||||
|
"name": "billing_tax_start",
|
||||||
|
"type": "DATETIME",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_tax_end": {
|
||||||
|
"name": "billing_tax_end",
|
||||||
"type": "DATETIME",
|
"type": "DATETIME",
|
||||||
"null": true,
|
"null": true,
|
||||||
"default": null
|
"default": null
|
||||||
|
|
@ -444,10 +536,17 @@
|
||||||
"type": "DATETIME",
|
"type": "DATETIME",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
|
"billing_bill_date": {
|
||||||
|
"name": "billing_bill_date",
|
||||||
|
"type": "DATETIME",
|
||||||
|
"default": null,
|
||||||
|
"null": true
|
||||||
|
},
|
||||||
"billing_bill_performance_date": {
|
"billing_bill_performance_date": {
|
||||||
"name": "billing_bill_performance_date",
|
"name": "billing_bill_performance_date",
|
||||||
"type": "DATETIME",
|
"type": "DATETIME",
|
||||||
"null": false
|
"default": null,
|
||||||
|
"null": true
|
||||||
},
|
},
|
||||||
"billing_bill_created_by": {
|
"billing_bill_created_by": {
|
||||||
"name": "billing_bill_created_by",
|
"name": "billing_bill_created_by",
|
||||||
|
|
@ -799,6 +898,235 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"billing_attr_type": {
|
||||||
|
"name": "billing_attr_type",
|
||||||
|
"fields": {
|
||||||
|
"billing_attr_type_id": {
|
||||||
|
"name": "billing_attr_type_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_attr_type_name": {
|
||||||
|
"name": "billing_attr_type_name",
|
||||||
|
"type": "VARCHAR(255)",
|
||||||
|
"null": false,
|
||||||
|
"unique": true
|
||||||
|
},
|
||||||
|
"billing_attr_type_datatype": {
|
||||||
|
"name": "billing_attr_type_datatype",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_type_fields": {
|
||||||
|
"name": "billing_attr_type_fields",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_type_custom": {
|
||||||
|
"name": "billing_attr_type_custom",
|
||||||
|
"type": "TINYINT(1)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_type_required": {
|
||||||
|
"description": "Every item must have this attribute type if set to true.",
|
||||||
|
"name": "billing_attr_type_required",
|
||||||
|
"type": "TINYINT(1)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_type_pattern": {
|
||||||
|
"description": "This is a regex validation pattern.",
|
||||||
|
"name": "billing_attr_type_pattern",
|
||||||
|
"type": "VARCHAR(255)",
|
||||||
|
"null": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"billing_attr_type_l11n": {
|
||||||
|
"name": "billing_attr_type_l11n",
|
||||||
|
"fields": {
|
||||||
|
"billing_attr_type_l11n_id": {
|
||||||
|
"name": "billing_attr_type_l11n_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_attr_type_l11n_title": {
|
||||||
|
"name": "billing_attr_type_l11n_title",
|
||||||
|
"type": "VARCHAR(255)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_type_l11n_type": {
|
||||||
|
"name": "billing_attr_type_l11n_type",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "billing_attr_type",
|
||||||
|
"foreignKey": "billing_attr_type_id"
|
||||||
|
},
|
||||||
|
"billing_attr_type_l11n_lang": {
|
||||||
|
"name": "billing_attr_type_l11n_lang",
|
||||||
|
"type": "VARCHAR(2)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "language",
|
||||||
|
"foreignKey": "language_639_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"billing_attr_value": {
|
||||||
|
"name": "billing_attr_value",
|
||||||
|
"fields": {
|
||||||
|
"billing_attr_value_id": {
|
||||||
|
"name": "billing_attr_value_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_attr_value_default": {
|
||||||
|
"name": "billing_attr_value_default",
|
||||||
|
"type": "TINYINT(1)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_value_valueStr": {
|
||||||
|
"name": "billing_attr_value_valueStr",
|
||||||
|
"type": "VARCHAR(255)",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_attr_value_valueInt": {
|
||||||
|
"name": "billing_attr_value_valueInt",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_attr_value_valueDec": {
|
||||||
|
"name": "billing_attr_value_valueDec",
|
||||||
|
"type": "DECIMAL(19,5)",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_attr_value_valueDat": {
|
||||||
|
"name": "billing_attr_value_valueDat",
|
||||||
|
"type": "DATETIME",
|
||||||
|
"null": true,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"billing_attr_value_unit": {
|
||||||
|
"name": "billing_attr_value_unit",
|
||||||
|
"type": "VARCHAR(255)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_value_deptype": {
|
||||||
|
"name": "billing_attr_value_deptype",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": true,
|
||||||
|
"default": null,
|
||||||
|
"foreignTable": "billing_attr_type",
|
||||||
|
"foreignKey": "billing_attr_type_id"
|
||||||
|
},
|
||||||
|
"billing_attr_value_depvalue": {
|
||||||
|
"name": "billing_attr_value_depvalue",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": true,
|
||||||
|
"default": null,
|
||||||
|
"foreignTable": "billing_attr_value",
|
||||||
|
"foreignKey": "billing_attr_value_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"billing_attr_value_l11n": {
|
||||||
|
"name": "billing_attr_value_l11n",
|
||||||
|
"fields": {
|
||||||
|
"billing_attr_value_l11n_id": {
|
||||||
|
"name": "billing_attr_value_l11n_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_attr_value_l11n_title": {
|
||||||
|
"name": "billing_attr_value_l11n_title",
|
||||||
|
"type": "VARCHAR(255)",
|
||||||
|
"null": false
|
||||||
|
},
|
||||||
|
"billing_attr_value_l11n_value": {
|
||||||
|
"name": "billing_attr_value_l11n_value",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "billing_attr_value",
|
||||||
|
"foreignKey": "billing_attr_value_id"
|
||||||
|
},
|
||||||
|
"billing_attr_value_l11n_lang": {
|
||||||
|
"name": "billing_attr_value_l11n_lang",
|
||||||
|
"type": "VARCHAR(2)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "language",
|
||||||
|
"foreignKey": "language_639_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"billing_bill_attr_default": {
|
||||||
|
"name": "billing_bill_attr_default",
|
||||||
|
"fields": {
|
||||||
|
"billing_bill_attr_default_id": {
|
||||||
|
"name": "billing_bill_attr_default_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_bill_attr_default_type": {
|
||||||
|
"name": "billing_bill_attr_default_type",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "billing_attr_type",
|
||||||
|
"foreignKey": "billing_attr_type_id"
|
||||||
|
},
|
||||||
|
"billing_bill_attr_default_value": {
|
||||||
|
"name": "billing_bill_attr_default_value",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "billing_attr_value",
|
||||||
|
"foreignKey": "billing_attr_value_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"billing_bill_attr": {
|
||||||
|
"name": "billing_bill_attr",
|
||||||
|
"fields": {
|
||||||
|
"billing_bill_attr_id": {
|
||||||
|
"name": "billing_bill_attr_id",
|
||||||
|
"type": "INT",
|
||||||
|
"null": false,
|
||||||
|
"primary": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"billing_bill_attr_bill": {
|
||||||
|
"name": "billing_bill_attr_bill",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "billing_bill",
|
||||||
|
"foreignKey": "billing_bill_id"
|
||||||
|
},
|
||||||
|
"billing_bill_attr_type": {
|
||||||
|
"name": "billing_bill_attr_type",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": false,
|
||||||
|
"foreignTable": "billing_attr_type",
|
||||||
|
"foreignKey": "billing_attr_type_id"
|
||||||
|
},
|
||||||
|
"billing_bill_attr_value": {
|
||||||
|
"name": "billing_bill_attr_value",
|
||||||
|
"type": "INT(11)",
|
||||||
|
"null": true,
|
||||||
|
"default": null,
|
||||||
|
"foreignTable": "billing_attr_value",
|
||||||
|
"foreignKey": "billing_attr_value_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"billing_bill_media": {
|
"billing_bill_media": {
|
||||||
"name": "billing_bill_media",
|
"name": "billing_bill_media",
|
||||||
"fields": {
|
"fields": {
|
||||||
|
|
|
||||||
362
Admin/Install/taxes.json
Normal file
362
Admin/Install/taxes.json
Normal file
|
|
@ -0,0 +1,362 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "EU",
|
||||||
|
"tax_code": "EU_S0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "AT",
|
||||||
|
"tax_code": "AT_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "BE",
|
||||||
|
"tax_code": "BE_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "BG",
|
||||||
|
"tax_code": "BG_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "HR",
|
||||||
|
"tax_code": "HR_S25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "CY",
|
||||||
|
"tax_code": "CY_S19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "CZ",
|
||||||
|
"tax_code": "CZ_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "DK",
|
||||||
|
"tax_code": "DK_S25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "EE",
|
||||||
|
"tax_code": "EE_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "FI",
|
||||||
|
"tax_code": "FI_S24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "FR",
|
||||||
|
"tax_code": "FR_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "DE",
|
||||||
|
"tax_code": "DE_S19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "GR",
|
||||||
|
"tax_code": "GR_S24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "HU",
|
||||||
|
"tax_code": "HU_S27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "IE",
|
||||||
|
"tax_code": "IE_S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "IT",
|
||||||
|
"tax_code": "IT_S22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "LV",
|
||||||
|
"tax_code": "LV_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "LT",
|
||||||
|
"tax_code": "LT_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "LU",
|
||||||
|
"tax_code": "LU_S17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "MT",
|
||||||
|
"tax_code": "MT_S18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "NL",
|
||||||
|
"tax_code": "NL_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "PL",
|
||||||
|
"tax_code": "PL_S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "PT",
|
||||||
|
"tax_code": "PT_S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "RO",
|
||||||
|
"tax_code": "RO_S19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "SK",
|
||||||
|
"tax_code": "SK_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "SI",
|
||||||
|
"tax_code": "SI_S22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "ES",
|
||||||
|
"tax_code": "ES_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "SE",
|
||||||
|
"tax_code": "SE_S25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "GB",
|
||||||
|
"tax_code": "GB_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SOFTWARE",
|
||||||
|
"account_code": "INT",
|
||||||
|
"tax_code": "S0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "EU",
|
||||||
|
"tax_code": "EU_S0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "AT",
|
||||||
|
"tax_code": "AT_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "BE",
|
||||||
|
"tax_code": "BE_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "BG",
|
||||||
|
"tax_code": "BG_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "HR",
|
||||||
|
"tax_code": "HR_S25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "CY",
|
||||||
|
"tax_code": "CY_S19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "CZ",
|
||||||
|
"tax_code": "CZ_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "DK",
|
||||||
|
"tax_code": "DK_S25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "EE",
|
||||||
|
"tax_code": "EE_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "FI",
|
||||||
|
"tax_code": "FI_S24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "FR",
|
||||||
|
"tax_code": "FR_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "DE",
|
||||||
|
"tax_code": "DE_S19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "GR",
|
||||||
|
"tax_code": "GR_S24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "HU",
|
||||||
|
"tax_code": "HU_S27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "IE",
|
||||||
|
"tax_code": "IE_S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "IT",
|
||||||
|
"tax_code": "IT_S22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "LV",
|
||||||
|
"tax_code": "LV_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "LT",
|
||||||
|
"tax_code": "LT_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "LU",
|
||||||
|
"tax_code": "LU_S17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "MT",
|
||||||
|
"tax_code": "MT_S18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "NL",
|
||||||
|
"tax_code": "NL_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "PL",
|
||||||
|
"tax_code": "PL_S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "PT",
|
||||||
|
"tax_code": "PT_S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "RO",
|
||||||
|
"tax_code": "RO_S19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "SK",
|
||||||
|
"tax_code": "SK_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "SI",
|
||||||
|
"tax_code": "SI_S22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "ES",
|
||||||
|
"tax_code": "ES_S21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "SE",
|
||||||
|
"tax_code": "SE_S25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "GB",
|
||||||
|
"tax_code": "GB_S20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"item_code": "SERVICE",
|
||||||
|
"account_code": "INT",
|
||||||
|
"tax_code": "S0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -200,7 +200,7 @@
|
||||||
{
|
{
|
||||||
"name": "purchase_subscritpion",
|
"name": "purchase_subscritpion",
|
||||||
"numberFormat": "{y}-{id}",
|
"numberFormat": "{y}-{id}",
|
||||||
"transferType": 1,
|
"transferType": 2,
|
||||||
"transferStock": false,
|
"transferStock": false,
|
||||||
"isTemplate": false,
|
"isTemplate": false,
|
||||||
"l11n": {
|
"l11n": {
|
||||||
|
|
@ -211,7 +211,7 @@
|
||||||
{
|
{
|
||||||
"name": "purchase_template",
|
"name": "purchase_template",
|
||||||
"numberFormat": "{y}-{id}",
|
"numberFormat": "{y}-{id}",
|
||||||
"transferType": 1,
|
"transferType": 2,
|
||||||
"transferStock": false,
|
"transferStock": false,
|
||||||
"isTemplate": true,
|
"isTemplate": true,
|
||||||
"l11n": {
|
"l11n": {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ declare(strict_types=1);
|
||||||
namespace Modules\Billing\Admin;
|
namespace Modules\Billing\Admin;
|
||||||
|
|
||||||
use Modules\Billing\Models\BillTransferType;
|
use Modules\Billing\Models\BillTransferType;
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeTypeMapper;
|
||||||
|
use Modules\ItemManagement\Models\ItemAttributeTypeMapper;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierAttributeTypeMapper;
|
||||||
use phpOMS\Application\ApplicationAbstract;
|
use phpOMS\Application\ApplicationAbstract;
|
||||||
use phpOMS\Config\SettingsInterface;
|
use phpOMS\Config\SettingsInterface;
|
||||||
use phpOMS\Message\Http\HttpRequest;
|
use phpOMS\Message\Http\HttpRequest;
|
||||||
|
|
@ -62,6 +65,208 @@ final class Installer extends InstallerAbstract
|
||||||
|
|
||||||
$types = \json_decode($fileContent, true);
|
$types = \json_decode($fileContent, true);
|
||||||
self::createBillTypes($app, $types, $defaultTemplate);
|
self::createBillTypes($app, $types, $defaultTemplate);
|
||||||
|
|
||||||
|
/* Tax types */
|
||||||
|
$fileContent = \file_get_contents(__DIR__ . '/Install/taxes.json');
|
||||||
|
if ($fileContent === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$taxes = \json_decode($fileContent, true);
|
||||||
|
self::createTaxCombination($app, $taxes);
|
||||||
|
|
||||||
|
/* Attributes */
|
||||||
|
$fileContent = \file_get_contents(__DIR__ . '/Install/attributes.json');
|
||||||
|
if ($fileContent === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes = \json_decode($fileContent, true);
|
||||||
|
$attrTypes = self::createBillAttributeTypes($app, $attributes);
|
||||||
|
$attrValues = self::createBillAttributeValues($app, $attrTypes, $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install default attribute types
|
||||||
|
*
|
||||||
|
* @param ApplicationAbstract $app Application
|
||||||
|
* @param array<array{name:string, l11n?:array<string, string>, is_required?:bool, is_custom_allowed?:bool, validation_pattern?:string, value_type?:string, values?:array<string, mixed>}> $attributes Attribute definition
|
||||||
|
*
|
||||||
|
* @return array<string, array>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private static function createBillAttributeTypes(ApplicationAbstract $app, array $attributes) : array
|
||||||
|
{
|
||||||
|
/** @var array<string, array> $billAttrType */
|
||||||
|
$billAttrType = [];
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Controller\ApiController $module */
|
||||||
|
$module = $app->moduleManager->getModuleInstance('Billing');
|
||||||
|
|
||||||
|
/** @var array $attribute */
|
||||||
|
foreach ($attributes as $attribute) {
|
||||||
|
$response = new HttpResponse();
|
||||||
|
$request = new HttpRequest(new HttpUri(''));
|
||||||
|
|
||||||
|
$request->header->account = 1;
|
||||||
|
$request->setData('name', $attribute['name'] ?? '');
|
||||||
|
$request->setData('title', \reset($attribute['l11n']));
|
||||||
|
$request->setData('language', \array_keys($attribute['l11n'])[0] ?? 'en');
|
||||||
|
$request->setData('is_required', $attribute['is_required'] ?? false);
|
||||||
|
$request->setData('is_custom_allowed', $attribute['is_custom_allowed'] ?? false);
|
||||||
|
$request->setData('validation_pattern', $attribute['validation_pattern'] ?? '');
|
||||||
|
$request->setData('datatype', (int) $attribute['value_type']);
|
||||||
|
|
||||||
|
$module->apiBillAttributeTypeCreate($request, $response);
|
||||||
|
|
||||||
|
$responseData = $response->get('');
|
||||||
|
|
||||||
|
if (!\is_array($responseData)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$billAttrType[$attribute['name']] = !\is_array($responseData['response'])
|
||||||
|
? $responseData['response']->toArray()
|
||||||
|
: $responseData['response'];
|
||||||
|
|
||||||
|
$isFirst = true;
|
||||||
|
foreach ($attribute['l11n'] as $language => $l11n) {
|
||||||
|
if ($isFirst) {
|
||||||
|
$isFirst = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = new HttpResponse();
|
||||||
|
$request = new HttpRequest(new HttpUri(''));
|
||||||
|
|
||||||
|
$request->header->account = 1;
|
||||||
|
$request->setData('title', $l11n);
|
||||||
|
$request->setData('language', $language);
|
||||||
|
$request->setData('type', $billAttrType[$attribute['name']]['id']);
|
||||||
|
|
||||||
|
$module->apiBillAttributeTypeL11nCreate($request, $response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $billAttrType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create default attribute values for types
|
||||||
|
*
|
||||||
|
* @param ApplicationAbstract $app Application
|
||||||
|
* @param array $billAttrType Attribute types
|
||||||
|
* @param array<array{name:string, l11n?:array<string, string>, is_required?:bool, is_custom_allowed?:bool, validation_pattern?:string, value_type?:string, values?:array<string, mixed>}> $attributes Attribute definition
|
||||||
|
*
|
||||||
|
* @return array<string, array>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private static function createBillAttributeValues(ApplicationAbstract $app, array $billAttrType, array $attributes) : array
|
||||||
|
{
|
||||||
|
/** @var array<string, array> $billAttrValue */
|
||||||
|
$billAttrValue = [];
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Controller\ApiController $module */
|
||||||
|
$module = $app->moduleManager->getModuleInstance('Billing');
|
||||||
|
|
||||||
|
foreach ($attributes as $attribute) {
|
||||||
|
$billAttrValue[$attribute['name']] = [];
|
||||||
|
|
||||||
|
/** @var array $value */
|
||||||
|
foreach ($attribute['values'] as $value) {
|
||||||
|
$response = new HttpResponse();
|
||||||
|
$request = new HttpRequest(new HttpUri(''));
|
||||||
|
|
||||||
|
$request->header->account = 1;
|
||||||
|
$request->setData('value', $value['value'] ?? '');
|
||||||
|
$request->setData('unit', $value['unit'] ?? '');
|
||||||
|
$request->setData('default', true); // always true since all defined values are possible default values
|
||||||
|
$request->setData('type', $billAttrType[$attribute['name']]['id']);
|
||||||
|
|
||||||
|
if (isset($value['l11n']) && !empty($value['l11n'])) {
|
||||||
|
$request->setData('title', \reset($value['l11n']));
|
||||||
|
$request->setData('language', \array_keys($value['l11n'])[0] ?? 'en');
|
||||||
|
}
|
||||||
|
|
||||||
|
$module->apiBillAttributeValueCreate($request, $response);
|
||||||
|
|
||||||
|
$responseData = $response->get('');
|
||||||
|
if (!\is_array($responseData)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrValue = !\is_array($responseData['response'])
|
||||||
|
? $responseData['response']->toArray()
|
||||||
|
: $responseData['response'];
|
||||||
|
|
||||||
|
$billAttrValue[$attribute['name']][] = $attrValue;
|
||||||
|
|
||||||
|
$isFirst = true;
|
||||||
|
foreach (($value['l11n'] ?? []) as $language => $l11n) {
|
||||||
|
if ($isFirst) {
|
||||||
|
$isFirst = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = new HttpResponse();
|
||||||
|
$request = new HttpRequest(new HttpUri(''));
|
||||||
|
|
||||||
|
$request->header->account = 1;
|
||||||
|
$request->setData('title', $l11n);
|
||||||
|
$request->setData('language', $language);
|
||||||
|
$request->setData('value', $attrValue['id']);
|
||||||
|
|
||||||
|
$module->apiBillAttributeValueL11nCreate($request, $response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $billAttrValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function createTaxCombination(ApplicationAbstract $app, array $taxes) : array
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Controller\ApiController $module */
|
||||||
|
$module = $app->moduleManager->getModuleInstance('Billing');
|
||||||
|
|
||||||
|
$itemAttributeSales = ItemAttributeTypeMapper::get()->with('defaults')->where('name', 'sales_tax_code')->execute();
|
||||||
|
$clientAttributeSales = ClientAttributeTypeMapper::get()->with('defaults')->where('name', 'sales_tax_code')->execute();
|
||||||
|
$supplierAttributeSales = SupplierAttributeTypeMapper::get()->with('defaults')->where('name', 'purchase_tax_code')->execute();
|
||||||
|
|
||||||
|
foreach ($taxes as $tax) {
|
||||||
|
$itemValue = $itemAttributeSales->getDefaultByValue($tax['item_code']);
|
||||||
|
$accountValue = $tax['type'] === 1
|
||||||
|
? $clientAttributeSales->getDefaultByValue($tax['account_code'])
|
||||||
|
: $supplierAttributeSales->getDefaultByValue($tax['account_code']);
|
||||||
|
|
||||||
|
$response = new HttpResponse();
|
||||||
|
$request = new HttpRequest(new HttpUri(''));
|
||||||
|
|
||||||
|
$request->header->account = 1;
|
||||||
|
$request->setData('tax_type', $tax['type']);
|
||||||
|
$request->setData('tax_code', $tax['tax_code']);
|
||||||
|
$request->setData('item_code', $itemValue->getId());
|
||||||
|
$request->setData('account_code', $accountValue->getId());
|
||||||
|
|
||||||
|
$module->apiTaxCombinationCreate($request, $response);
|
||||||
|
|
||||||
|
$responseData = $response->get('');
|
||||||
|
if (!\is_array($responseData)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = !\is_array($responseData['response'])
|
||||||
|
? $responseData['response']->toArray()
|
||||||
|
: $responseData['response'];
|
||||||
|
|
||||||
|
$results[] = $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
13
Admin/Routes/Cli.php
Normal file
13
Admin/Routes/Cli.php
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use phpOMS\Router\RouteVerb;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'^/billing/bill/purchase/parse.*$' => [
|
||||||
|
[
|
||||||
|
'dest' => '\Modules\Billing\Controller\CliController:cliParseSupplierBill',
|
||||||
|
'verb' => RouteVerb::ANY,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
419
Controller/ApiAttributeController.php
Normal file
419
Controller/ApiAttributeController.php
Normal file
|
|
@ -0,0 +1,419 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttribute;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeMapper;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeType;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeTypeL11nMapper;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeTypeMapper;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeValue;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeValueL11nMapper;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeValueMapper;
|
||||||
|
use Modules\Billing\Models\Attribute\NullBillAttributeType;
|
||||||
|
use Modules\Billing\Models\Attribute\NullBillAttributeValue;
|
||||||
|
use phpOMS\Localization\BaseStringL11n;
|
||||||
|
use phpOMS\Localization\ISO639x1Enum;
|
||||||
|
use phpOMS\Message\Http\RequestStatusCode;
|
||||||
|
use phpOMS\Message\NotificationLevel;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\Model\Message\FormValidation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ApiAttributeController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Api method to create item attribute
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillAttributeCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillAttributeCreate($request))) {
|
||||||
|
$response->set('attribute_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attribute = $this->createBillAttributeFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $attribute, BillAttributeMapper::class, 'attribute', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute', 'Attribute successfully created', $attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create item attribute from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BillAttribute
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillAttributeFromRequest(RequestAbstract $request) : BillAttribute
|
||||||
|
{
|
||||||
|
$attribute = new BillAttribute();
|
||||||
|
$attribute->bill = (int) $request->getData('bill');
|
||||||
|
$attribute->type = new NullBillAttributeType((int) $request->getData('type'));
|
||||||
|
|
||||||
|
if ($request->getData('value') !== null) {
|
||||||
|
$attribute->value = new NullBillAttributeValue((int) $request->getData('value'));
|
||||||
|
} else {
|
||||||
|
$newRequest = clone $request;
|
||||||
|
$newRequest->setData('value', $request->getData('custom'), true);
|
||||||
|
|
||||||
|
$value = $this->createBillAttributeValueFromRequest($newRequest);
|
||||||
|
|
||||||
|
$attribute->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bill attribute create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillAttributeCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['type'] = empty($request->getData('type')))
|
||||||
|
|| ($val['value'] = (empty($request->getData('value')) && empty($request->getData('custom'))))
|
||||||
|
|| ($val['bill'] = empty($request->getData('bill')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create bill attribute l11n
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillAttributeTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillAttributeTypeL11nCreate($request))) {
|
||||||
|
$response->set('attr_type_l11n_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrL11n = $this->createBillAttributeTypeL11nFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $attrL11n, BillAttributeTypeL11nMapper::class, 'attr_type_l11n', $request->getOrigin());
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Localization successfully created', $attrL11n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create bill attribute l11n from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BaseStringL11n
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillAttributeTypeL11nFromRequest(RequestAbstract $request) : BaseStringL11n
|
||||||
|
{
|
||||||
|
$attrL11n = new BaseStringL11n();
|
||||||
|
$attrL11n->ref = (int) ($request->getData('type') ?? 0);
|
||||||
|
$attrL11n->setLanguage((string) (
|
||||||
|
$request->getData('language') ?? $request->getLanguage()
|
||||||
|
));
|
||||||
|
$attrL11n->content = (string) ($request->getData('title') ?? '');
|
||||||
|
|
||||||
|
return $attrL11n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bill attribute l11n create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillAttributeTypeL11nCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['title'] = empty($request->getData('title')))
|
||||||
|
|| ($val['type'] = empty($request->getData('type')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create bill attribute type
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillAttributeTypeCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillAttributeTypeCreate($request))) {
|
||||||
|
$response->set('attr_type_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrType = $this->createBillAttributeTypeFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $attrType, BillAttributeTypeMapper::class, 'attr_type', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute type', 'Attribute type successfully created', $attrType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create bill attribute from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BillAttributeType
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillAttributeTypeFromRequest(RequestAbstract $request) : BillAttributeType
|
||||||
|
{
|
||||||
|
$attrType = new BillAttributeType($request->getData('name') ?? '');
|
||||||
|
$attrType->datatype = (int) ($request->getData('datatype') ?? 0);
|
||||||
|
$attrType->custom = (bool) ($request->getData('custom') ?? false);
|
||||||
|
$attrType->isRequired = (bool) ($request->getData('is_required') ?? false);
|
||||||
|
$attrType->validationPattern = (string) ($request->getData('validation_pattern') ?? '');
|
||||||
|
$attrType->setL11n((string) ($request->getData('title') ?? ''), $request->getData('language') ?? ISO639x1Enum::_EN);
|
||||||
|
$attrType->setFields((int) ($request->getData('fields') ?? 0));
|
||||||
|
|
||||||
|
return $attrType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bill attribute create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillAttributeTypeCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['title'] = empty($request->getData('title')))
|
||||||
|
|| ($val['name'] = empty($request->getData('name')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create bill attribute value
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillAttributeValueCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillAttributeValueCreate($request))) {
|
||||||
|
$response->set('attr_value_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrValue = $this->createBillAttributeValueFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $attrValue, BillAttributeValueMapper::class, 'attr_value', $request->getOrigin());
|
||||||
|
|
||||||
|
if ($attrValue->isDefault) {
|
||||||
|
$this->createModelRelation(
|
||||||
|
$request->header->account,
|
||||||
|
(int) $request->getData('type'),
|
||||||
|
$attrValue->getId(),
|
||||||
|
BillAttributeTypeMapper::class, 'defaults', '', $request->getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute value', 'Attribute value successfully created', $attrValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create bill attribute value from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BillAttributeValue
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillAttributeValueFromRequest(RequestAbstract $request) : BillAttributeValue
|
||||||
|
{
|
||||||
|
/** @var BillAttributeType $type */
|
||||||
|
$type = BillAttributeTypeMapper::get()
|
||||||
|
->where('id', (int) ($request->getData('type') ?? 0))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$attrValue = new BillAttributeValue();
|
||||||
|
$attrValue->isDefault = (bool) ($request->getData('default') ?? false);
|
||||||
|
$attrValue->setValue($request->getData('value'), $type->datatype);
|
||||||
|
|
||||||
|
if ($request->getData('title') !== null) {
|
||||||
|
$attrValue->setL11n($request->getData('title'), $request->getData('language') ?? ISO639x1Enum::_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attrValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bill attribute value create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillAttributeValueCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['type'] = empty($request->getData('type')))
|
||||||
|
|| ($val['value'] = empty($request->getData('value')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create bill attribute l11n
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillAttributeValueL11nCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillAttributeValueL11nCreate($request))) {
|
||||||
|
$response->set('attr_value_l11n_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrL11n = $this->createBillAttributeValueL11nFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $attrL11n, BillAttributeValueL11nMapper::class, 'attr_value_l11n', $request->getOrigin());
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Localization successfully created', $attrL11n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create bill attribute l11n from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BaseStringL11n
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillAttributeValueL11nFromRequest(RequestAbstract $request) : BaseStringL11n
|
||||||
|
{
|
||||||
|
$attrL11n = new BaseStringL11n();
|
||||||
|
$attrL11n->ref = (int) ($request->getData('value') ?? 0);
|
||||||
|
$attrL11n->setLanguage((string) (
|
||||||
|
$request->getData('language') ?? $request->getLanguage()
|
||||||
|
));
|
||||||
|
$attrL11n->content = (string) ($request->getData('title') ?? '');
|
||||||
|
|
||||||
|
return $attrL11n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bill attribute l11n create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillAttributeValueL11nCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['title'] = empty($request->getData('title')))
|
||||||
|
|| ($val['value'] = empty($request->getData('value')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
826
Controller/ApiBillController.php
Normal file
826
Controller/ApiBillController.php
Normal file
|
|
@ -0,0 +1,826 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Admin\Models\NullAccount;
|
||||||
|
use Modules\Admin\Models\SettingsEnum as AdminSettingsEnum;
|
||||||
|
use Modules\Billing\Models\Bill;
|
||||||
|
use Modules\Billing\Models\BillElement;
|
||||||
|
use Modules\Billing\Models\BillElementMapper;
|
||||||
|
use Modules\Billing\Models\BillMapper;
|
||||||
|
use Modules\Billing\Models\BillStatus;
|
||||||
|
use Modules\Billing\Models\BillTypeMapper;
|
||||||
|
use Modules\ClientManagement\Models\ClientMapper;
|
||||||
|
use Modules\ItemManagement\Models\ItemMapper;
|
||||||
|
use Modules\Media\Models\CollectionMapper;
|
||||||
|
use Modules\Media\Models\MediaMapper;
|
||||||
|
use Modules\Media\Models\NullCollection;
|
||||||
|
use Modules\Media\Models\PathSettings;
|
||||||
|
use Modules\Media\Models\UploadStatus;
|
||||||
|
use Modules\SupplierManagement\Models\NullSupplier;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierMapper;
|
||||||
|
use phpOMS\Autoloader;
|
||||||
|
use phpOMS\Localization\ISO3166TwoEnum;
|
||||||
|
use phpOMS\Localization\Money;
|
||||||
|
use phpOMS\Message\Http\RequestStatusCode;
|
||||||
|
use phpOMS\Message\NotificationLevel;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\Model\Message\FormValidation;
|
||||||
|
use phpOMS\System\MimeType;
|
||||||
|
use phpOMS\Views\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ApiBillController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Api method to update a bill
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillUpdate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillUpdate($request))) {
|
||||||
|
$response->set($request->uri->__toString(), new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\Bill $old */
|
||||||
|
$old = BillMapper::get()->where('id', (int) $request->getData('bill'));
|
||||||
|
$new = $this->updateBillFromRequest($request, $response, $data);
|
||||||
|
$this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill', 'Bill successfully created.', $new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to validate bill creation from request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillUpdate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['bill'] = empty($request->getData('bill')))) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create a bill from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return Bill
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function updateBillFromRequest(RequestAbstract $request, ResponseAbstract $response, $data = null) : Bill
|
||||||
|
{
|
||||||
|
/** @var Bill $bill */
|
||||||
|
$bill = BillMapper::get()->where('id', (int) $request->getData('bill'))->execute();
|
||||||
|
|
||||||
|
return $bill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create a bill
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillCreate($request))) {
|
||||||
|
$response->set($request->uri->__toString(), new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bill = $this->createBillFromRequest($request, $response, $data);
|
||||||
|
$this->createModel($request->header->account, $bill, BillMapper::class, 'bill', $request->getOrigin());
|
||||||
|
|
||||||
|
$new = clone $bill;
|
||||||
|
$new->buildNumber(); // The bill id is part of the number
|
||||||
|
$this->updateModel($request->header->account, $bill, $new, BillMapper::class, 'bill', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill', 'Bill successfully created.', $bill);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create a bill from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return Bill
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function createBillFromRequest(RequestAbstract $request, ResponseAbstract $response, $data = null) : Bill
|
||||||
|
{
|
||||||
|
/** @var \Modules\ClientManagement\Models\Client|\Modules\SupplierManagement\Models\Supplier $account */
|
||||||
|
$account = null;
|
||||||
|
if ($request->getData('client') !== null) {
|
||||||
|
/** @var \Modules\ClientManagement\Models\Client $account */
|
||||||
|
$account = ClientMapper::get()
|
||||||
|
->with('account')
|
||||||
|
->with('mainAddress')
|
||||||
|
->where('id', (int) $request->getData('client'))
|
||||||
|
->execute();
|
||||||
|
} elseif (((int) ($request->getData('supplier') ?? -1)) === 0) {
|
||||||
|
/** @var \Modules\SupplierManagement\Models\Supplier $account */
|
||||||
|
$account = new NullSupplier();
|
||||||
|
} elseif ($request->getData('supplier') !== null) {
|
||||||
|
/** @var \Modules\SupplierManagement\Models\Supplier $account */
|
||||||
|
$account = SupplierMapper::get()
|
||||||
|
->with('account')
|
||||||
|
->with('mainAddress')
|
||||||
|
->where('id', (int) $request->getData('supplier'))
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\BillType $billType */
|
||||||
|
$billType = BillTypeMapper::get()
|
||||||
|
->where('id', (int) ($request->getData('type') ?? 1))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
/* @var \Modules\Account\Models\Account $account */
|
||||||
|
$bill = new Bill();
|
||||||
|
$bill->createdBy = new NullAccount($request->header->account);
|
||||||
|
$bill->type = $billType;
|
||||||
|
$bill->numberFormat = $billType->numberFormat;
|
||||||
|
// @todo: use defaultInvoiceAddress or mainAddress. also consider to use billto1, billto2, billto3 (for multiple lines e.g. name2, fao etc.)
|
||||||
|
$bill->billTo = (string) ($request->getData('billto')
|
||||||
|
?? ($account->account->name1 . (!empty($account->account->name2)
|
||||||
|
? ', ' . $account->account->name2
|
||||||
|
: ''
|
||||||
|
)));
|
||||||
|
$bill->billAddress = (string) ($request->getData('billaddress') ?? $account->mainAddress->address);
|
||||||
|
$bill->billZip = (string) ($request->getData('billtopostal') ?? $account->mainAddress->postal);
|
||||||
|
$bill->billCity = (string) ($request->getData('billtocity') ?? $account->mainAddress->city);
|
||||||
|
$bill->billCountry = (string) (
|
||||||
|
$request->getData('billtocountry') ?? (
|
||||||
|
($country = $account->mainAddress->getCountry()) === ISO3166TwoEnum::_XXX ? '' : $country)
|
||||||
|
);
|
||||||
|
$bill->client = !$request->hasData('client') ? null : $account;
|
||||||
|
$bill->supplier = !$request->hasData('supplier') ? null : $account;
|
||||||
|
$bill->performanceDate = new \DateTime($request->getData('performancedate') ?? 'now');
|
||||||
|
$bill->setStatus((int) ($request->getData('status') ?? BillStatus::ACTIVE));
|
||||||
|
|
||||||
|
return $bill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to validate bill creation from request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['client/supplier'] = (empty($request->getData('client'))
|
||||||
|
&& (empty($request->getData('supplier'))
|
||||||
|
&& ((int) ($request->getData('supplier') ?? -1) !== 0)
|
||||||
|
)))
|
||||||
|
|| ($val['type'] = (empty($request->getData('type'))))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create a bill
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiMediaAddToBill(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateMediaAddToBill($request))) {
|
||||||
|
$response->set($request->uri->__toString(), new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\Bill $bill */
|
||||||
|
$bill = BillMapper::get()->where('id', (int) $request->getData('bill'))->execute();
|
||||||
|
$path = $this->createBillDir($bill);
|
||||||
|
|
||||||
|
$uploaded = [];
|
||||||
|
if (!empty($uploadedFiles = $request->getFiles())) {
|
||||||
|
$uploaded = $this->app->moduleManager->get('Media')->uploadFiles(
|
||||||
|
names: [],
|
||||||
|
fileNames: [],
|
||||||
|
files: $uploadedFiles,
|
||||||
|
account: $request->header->account,
|
||||||
|
basePath: __DIR__ . '/../../../Modules/Media/Files' . $path,
|
||||||
|
virtualPath: $path,
|
||||||
|
pathSettings: PathSettings::FILE_PATH,
|
||||||
|
hasAccountRelation: false,
|
||||||
|
readContent: (bool) ($request->getData('parse_content') ?? false)
|
||||||
|
);
|
||||||
|
|
||||||
|
$collection = null;
|
||||||
|
foreach ($uploaded as $media) {
|
||||||
|
$this->createModelRelation(
|
||||||
|
$request->header->account,
|
||||||
|
$bill->getId(),
|
||||||
|
$media->getId(),
|
||||||
|
BillMapper::class,
|
||||||
|
'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();
|
||||||
|
|
||||||
|
if ($collection instanceof NullCollection) {
|
||||||
|
$collection = $this->app->moduleManager->get('Media')->createRecursiveMediaCollection(
|
||||||
|
$path,
|
||||||
|
$request->header->account,
|
||||||
|
__DIR__ . '/../../../Modules/Media/Files' . $path,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->createModelRelation(
|
||||||
|
$request->header->account,
|
||||||
|
$collection->getId(),
|
||||||
|
$media->getId(),
|
||||||
|
CollectionMapper::class,
|
||||||
|
'sources',
|
||||||
|
'',
|
||||||
|
$request->getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($mediaFiles = $request->getDataJson('media'))) {
|
||||||
|
foreach ($mediaFiles as $media) {
|
||||||
|
$this->createModelRelation(
|
||||||
|
$request->header->account,
|
||||||
|
$bill->getId(),
|
||||||
|
(int) $media,
|
||||||
|
BillMapper::class,
|
||||||
|
'media',
|
||||||
|
'',
|
||||||
|
$request->getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Media', 'Media added to bill.', [
|
||||||
|
'upload' => $uploaded,
|
||||||
|
'media' => $mediaFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create media directory path
|
||||||
|
*
|
||||||
|
* @param Bill $bill Bill
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillDir(Bill $bill) : string
|
||||||
|
{
|
||||||
|
return '/Modules/Billing/Bills/'
|
||||||
|
. $this->app->unitId . '/'
|
||||||
|
. $bill->createdAt->format('Y') . '/'
|
||||||
|
. $bill->createdAt->format('m') . '/'
|
||||||
|
. $bill->createdAt->format('d') . '/'
|
||||||
|
. $bill->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to validate bill creation from request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateMediaAddToBill(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['media'] = (empty($request->getData('media')) && empty($request->getFiles())))
|
||||||
|
|| ($val['bill'] = empty($request->getData('bill')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create a bill element
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillElementCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillElementCreate($request))) {
|
||||||
|
$response->set($request->uri->__toString(), new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$element = $this->createBillElementFromRequest($request, $response, $data);
|
||||||
|
$this->createModel($request->header->account, $element, BillElementMapper::class, 'bill_element', $request->getOrigin());
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\Bill $old */
|
||||||
|
$old = BillMapper::get()->where('id', $element->bill)->execute();
|
||||||
|
$new = $this->updateBillWithBillElement(clone $old, $element, 1);
|
||||||
|
$this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill_element', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill element', 'Bill element successfully created.', $element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create a bill element from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return BillElement
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @todo in the database the customer localized version should be stored because this is the version which went out
|
||||||
|
*/
|
||||||
|
public function createBillElementFromRequest(RequestAbstract $request, ResponseAbstract $response, $data = null) : BillElement
|
||||||
|
{
|
||||||
|
$element = new BillElement();
|
||||||
|
$element->bill = (int) $request->getData('bill');
|
||||||
|
$element->item = (int) ($request->getData('item') ?? 0);
|
||||||
|
|
||||||
|
if ($element->item === null) {
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @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();
|
||||||
|
|
||||||
|
$element->itemNumber = $item->number;
|
||||||
|
$element->itemName = $item->getL11n('name1')->description;
|
||||||
|
$element->quantity = (int) ($request->getData('quantity') ?? 0);
|
||||||
|
|
||||||
|
$element->singleSalesPriceNet = new Money($request->getData('singlesalespricenet', 'int') ?? $item->salesPrice->getInt());
|
||||||
|
$element->totalSalesPriceNet = clone $element->singleSalesPriceNet;
|
||||||
|
$element->totalSalesPriceNet->mult($element->quantity);
|
||||||
|
|
||||||
|
// discounts
|
||||||
|
if ($request->getData('discount_percentage') !== null) {
|
||||||
|
$discount = (int) $request->getData('discount_percentage');
|
||||||
|
|
||||||
|
$element->singleSalesPriceNet
|
||||||
|
->sub((int) ($element->singleSalesPriceNet->getInt() / 100 * $discount));
|
||||||
|
|
||||||
|
$element->totalSalesPriceNet
|
||||||
|
->sub((int) ($element->totalSalesPriceNet->getInt() / 100 * $discount));
|
||||||
|
}
|
||||||
|
|
||||||
|
$element->singlePurchasePriceNet = new Money($item->purchasePrice->getInt());
|
||||||
|
$element->totalPurchasePriceNet = clone $element->singlePurchasePriceNet;
|
||||||
|
$element->totalPurchasePriceNet->mult($element->quantity);
|
||||||
|
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to update a bill because of a changed bill element (add, remove, change) from request.
|
||||||
|
*
|
||||||
|
* @param Bill $bill Bill
|
||||||
|
* @param BillElement $element Bill element
|
||||||
|
* @param int $type Change type (0 = update, -1 = remove, +1 = add)
|
||||||
|
*
|
||||||
|
* @return Bill
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function updateBillWithBillElement(Bill $bill, BillElement $element, int $type = 1) : Bill
|
||||||
|
{
|
||||||
|
if ($type === 1) {
|
||||||
|
$bill->netSales->add($element->totalSalesPriceNet);
|
||||||
|
$bill->netCosts->add($element->totalPurchasePriceNet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to validate bill element creation from request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillElementCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['bill'] = empty($request->getData('bill')))) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
|
||||||
|
$settings = $this->app->appSettings->get(null,
|
||||||
|
[
|
||||||
|
AdminSettingsEnum::DEFAULT_TEMPLATES,
|
||||||
|
AdminSettingsEnum::DEFAULT_ASSETS,
|
||||||
|
],
|
||||||
|
unit: $this->app->unitId,
|
||||||
|
module: 'Admin'
|
||||||
|
);
|
||||||
|
|
||||||
|
$postKey = '::' . $this->app->unitId . ':Admin';
|
||||||
|
|
||||||
|
if ($settings === false) {
|
||||||
|
$settings = $this->app->appSettings->get(null,
|
||||||
|
[
|
||||||
|
AdminSettingsEnum::DEFAULT_TEMPLATES,
|
||||||
|
AdminSettingsEnum::DEFAULT_ASSETS,
|
||||||
|
],
|
||||||
|
unit: null,
|
||||||
|
module: 'Admin'
|
||||||
|
);
|
||||||
|
|
||||||
|
$postKey = ':::Admin';
|
||||||
|
}
|
||||||
|
|
||||||
|
$defaultTemplates = CollectionMapper::get()
|
||||||
|
->with('sources')
|
||||||
|
->where('id', (int) $settings[AdminSettingsEnum::DEFAULT_TEMPLATES . $postKey]->content)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$defaultAssets = CollectionMapper::get()
|
||||||
|
->with('sources')
|
||||||
|
->where('id', (int) $settings[AdminSettingsEnum::DEFAULT_ASSETS . $postKey]->content)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$view->setData('defaultTemplates', $defaultTemplates);
|
||||||
|
$view->setData('defaultAssets', $defaultAssets);
|
||||||
|
|
||||||
|
$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
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
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('elements')
|
||||||
|
->where('id', $request->getData('bill') ?? 0)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$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');
|
||||||
|
|
||||||
|
$settings = $this->app->appSettings->get(null,
|
||||||
|
[
|
||||||
|
AdminSettingsEnum::DEFAULT_TEMPLATES,
|
||||||
|
AdminSettingsEnum::DEFAULT_ASSETS,
|
||||||
|
],
|
||||||
|
unit: $this->app->unitId,
|
||||||
|
module: 'Admin'
|
||||||
|
);
|
||||||
|
|
||||||
|
$postKey = '::' . $this->app->unitId . ':Admin';
|
||||||
|
|
||||||
|
if ($settings === false) {
|
||||||
|
$settings = $this->app->appSettings->get(null,
|
||||||
|
[
|
||||||
|
AdminSettingsEnum::DEFAULT_TEMPLATES,
|
||||||
|
AdminSettingsEnum::DEFAULT_ASSETS,
|
||||||
|
],
|
||||||
|
unit: null,
|
||||||
|
module: 'Admin'
|
||||||
|
);
|
||||||
|
|
||||||
|
$postKey = ':::Admin';
|
||||||
|
}
|
||||||
|
|
||||||
|
$defaultTemplates = CollectionMapper::get()
|
||||||
|
->with('sources')
|
||||||
|
->where('id', (int) $settings[AdminSettingsEnum::DEFAULT_TEMPLATES . $postKey]->content)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$defaultAssets = CollectionMapper::get()
|
||||||
|
->with('sources')
|
||||||
|
->where('id', (int) $settings[AdminSettingsEnum::DEFAULT_ASSETS . $postKey]->content)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$view->setData('defaultTemplates', $defaultTemplates);
|
||||||
|
$view->setData('defaultAssets', $defaultAssets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@todo: pass data to bill
|
||||||
|
*/
|
||||||
|
|
||||||
|
$pdf = $view->render();
|
||||||
|
|
||||||
|
$path = $this->createBillDir($bill);
|
||||||
|
$pdfDir = __DIR__ . '/../../../Modules/Media/Files' . $path;
|
||||||
|
|
||||||
|
$status = !\is_dir($pdfDir) ? \mkdir($pdfDir, 0755, true) : true;
|
||||||
|
if ($status === false) {
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
$response->set($request->uri->__toString(), new FormValidation(['status' => $status]));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
\file_put_contents($pdfDir . '/' . $request->getData('bill') . '.pdf', $pdf);
|
||||||
|
if (!\is_file($pdfDir . '/' . $request->getData('bill') . '.pdf')) {
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$media = $this->app->moduleManager->get('Media')->createDbEntry(
|
||||||
|
status: [
|
||||||
|
'status' => UploadStatus::OK,
|
||||||
|
'name' => $request->getData('bill') . '.pdf',
|
||||||
|
'path' => $pdfDir,
|
||||||
|
'filename' => $request->getData('bill') . '.pdf',
|
||||||
|
'size' => \filesize($pdfDir . '/' . $request->getData('bill') . '.pdf'),
|
||||||
|
'extension' => 'pdf',
|
||||||
|
],
|
||||||
|
account: $request->header->account,
|
||||||
|
virtualPath: $path,
|
||||||
|
ip: $request->getOrigin(),
|
||||||
|
app: $this->app,
|
||||||
|
readContent: true,
|
||||||
|
unit: $this->app->unitId
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->createModelRelation(
|
||||||
|
$request->header->account,
|
||||||
|
$bill->getId(),
|
||||||
|
$media->getId(),
|
||||||
|
BillMapper::class,
|
||||||
|
'media',
|
||||||
|
'',
|
||||||
|
$request->getOrigin()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'PDF', 'Bill Pdf successfully created.', $media);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create bill files
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiNoteCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateNoteCreate($request))) {
|
||||||
|
$response->set('bill_note_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\Bill $bill */
|
||||||
|
$bill = BillMapper::get()->where('id', (int) $request->getData('id'))->execute();
|
||||||
|
|
||||||
|
$request->setData('virtualpath', $this->createBillDir($bill), true);
|
||||||
|
$this->app->moduleManager->get('Editor')->apiEditorCreate($request, $response, $data);
|
||||||
|
|
||||||
|
if ($response->header->status !== RequestStatusCode::R_200) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$model = $response->get($request->uri->__toString())['response'];
|
||||||
|
$this->createModelRelation($request->header->account, $request->getData('id'), $model->getId(), BillMapper::class, 'bill_note', '', $request->getOrigin());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bill note create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateNoteCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['id'] = empty($request->getData('id')))) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
187
Controller/ApiBillTypeController.php
Normal file
187
Controller/ApiBillTypeController.php
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Billing\Models\BillTransferType;
|
||||||
|
use Modules\Billing\Models\BillType;
|
||||||
|
use Modules\Billing\Models\BillTypeL11nMapper;
|
||||||
|
use Modules\Billing\Models\BillTypeMapper;
|
||||||
|
use Modules\Media\Models\NullCollection;
|
||||||
|
use phpOMS\Localization\BaseStringL11n;
|
||||||
|
use phpOMS\Localization\ISO639x1Enum;
|
||||||
|
use phpOMS\Message\Http\RequestStatusCode;
|
||||||
|
use phpOMS\Message\NotificationLevel;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\Model\Message\FormValidation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ApiBillTypeController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Api method to create item bill type
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillTypeCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillTypeCreate($request))) {
|
||||||
|
$response->set('bill_type_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$billType = $this->createBillTypeFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $billType, BillTypeMapper::class, 'bill_type', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill type', 'Bill type successfully created', $billType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create item attribute from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BillType
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillTypeFromRequest(RequestAbstract $request) : BillType
|
||||||
|
{
|
||||||
|
$billType = new BillType($request->getData('name') ?? '');
|
||||||
|
$billType->setL11n((string) ($request->getData('title') ?? ''), $request->getData('language') ?? ISO639x1Enum::_EN);
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate item attribute create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillTypeCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['title'] = empty($request->getData('title')))
|
||||||
|
|| ($val['name'] = empty($request->getData('name')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create item attribute l11n
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiBillTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateBillTypeL11nCreate($request))) {
|
||||||
|
$response->set('bill_type_l11n_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$billTypeL11n = $this->createBillTypeL11nFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $billTypeL11n, BillTypeL11nMapper::class, 'bill_type_l11n', $request->getOrigin());
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Localization successfully created', $billTypeL11n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create item attribute l11n from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return BaseStringL11n
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createBillTypeL11nFromRequest(RequestAbstract $request) : BaseStringL11n
|
||||||
|
{
|
||||||
|
$billTypeL11n = new BaseStringL11n();
|
||||||
|
$billTypeL11n->ref = (int) ($request->getData('type') ?? 0);
|
||||||
|
$billTypeL11n->setLanguage((string) (
|
||||||
|
$request->getData('language') ?? $request->getLanguage()
|
||||||
|
));
|
||||||
|
$billTypeL11n->content = (string) ($request->getData('title') ?? '');
|
||||||
|
|
||||||
|
return $billTypeL11n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate item attribute l11n create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateBillTypeL11nCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['title'] = empty($request->getData('title')))
|
||||||
|
|| ($val['type'] = empty($request->getData('type')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
305
Controller/ApiPriceController.php
Normal file
305
Controller/ApiPriceController.php
Normal file
|
|
@ -0,0 +1,305 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Billing\Models\Price\Price;
|
||||||
|
use Modules\Billing\Models\Price\PriceMapper;
|
||||||
|
use Modules\Billing\Models\Price\PriceType;
|
||||||
|
use Modules\Billing\Models\Tax\TaxCombinationMapper;
|
||||||
|
use Modules\ClientManagement\Models\ClientMapper;
|
||||||
|
use Modules\ClientManagement\Models\NullClient;
|
||||||
|
use Modules\ClientManagement\Models\NullClientAttributeValue;
|
||||||
|
use Modules\ItemManagement\Models\ItemMapper;
|
||||||
|
use Modules\ItemManagement\Models\NullItem;
|
||||||
|
use Modules\ItemManagement\Models\NullItemAttributeValue;
|
||||||
|
use Modules\SupplierManagement\Models\NullSupplier;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierMapper;
|
||||||
|
use phpOMS\Localization\ISO4217CharEnum;
|
||||||
|
use phpOMS\Message\Http\RequestStatusCode;
|
||||||
|
use phpOMS\Message\NotificationLevel;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\Model\Message\FormValidation;
|
||||||
|
use phpOMS\System\MimeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ApiPriceController 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
|
||||||
|
{
|
||||||
|
// Get item
|
||||||
|
$item = null;
|
||||||
|
if ($request->hasData('price_item')) {
|
||||||
|
$item = ItemMapper::get()
|
||||||
|
->with('attributes')
|
||||||
|
->with('attributes/type')
|
||||||
|
->with('attributes/value')
|
||||||
|
->where('id', (int) $request->getData('price_item'))
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get account
|
||||||
|
$account = null;
|
||||||
|
|
||||||
|
/** @var null|\Modules\ClientManagement\Models\Client $client */
|
||||||
|
$client = null;
|
||||||
|
|
||||||
|
/** @var null|\Modules\SupplierManagement\Models\Supplier $supplier */
|
||||||
|
$supplier = null;
|
||||||
|
|
||||||
|
if ($request->hasData('price_client')) {
|
||||||
|
$client = ClientMapper::get()
|
||||||
|
->with('attributes/type')
|
||||||
|
->with('attributes/value')
|
||||||
|
->where('id', (int) $request->getData('price_client'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$account = $client;
|
||||||
|
} else {
|
||||||
|
$supplier = SupplierMapper::get()
|
||||||
|
->with('attributes/type')
|
||||||
|
->with('attributes/value')
|
||||||
|
->where('id', (int) $request->getData('price_supplier'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$account = $supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all relevant prices
|
||||||
|
// @todo: allow to define NOT IN somehow (e.g. not in France -> simple solution to define export prices etc.)
|
||||||
|
$queryMapper = PriceMapper::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', 'int'), null]), 'IN');
|
||||||
|
$queryMapper->where('itemgroup', \array_unique([$request->getData('price_itemgroup', 'int'), $item?->getAttribute('itemgroup')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('itemsegment', \array_unique([$request->getData('price_itemsegment', 'int'), $item?->getAttribute('itemsegment')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('itemsection', \array_unique([$request->getData('price_itemsection', 'int'), $item?->getAttribute('itemsection')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('itemtype', \array_unique([$request->getData('price_itemtype', 'int'), $item?->getAttribute('itemtype')?->getId(), null]), 'IN');
|
||||||
|
|
||||||
|
$queryMapper->where('client', \array_unique([$request->getData('price_client', 'int'), null]), 'IN');
|
||||||
|
$queryMapper->where('clientgroup', \array_unique([$request->getData('price_clientgroup', 'int'), $client?->getAttribute('clientgroup')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('clientsegment', \array_unique([$request->getData('price_clientsegment', 'int'), $client?->getAttribute('clientsegment')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('clientsection', \array_unique([$request->getData('price_clientsection', 'int'), $client?->getAttribute('clientsection')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('clienttype', \array_unique([$request->getData('price_clienttype', 'int'), $client?->getAttribute('clienttype')?->getId(), null]), 'IN');
|
||||||
|
$queryMapper->where('clientcountry', \array_unique([$request->getData('price_clientcountry'), $client?->mainAddress->getCountry(), null]), 'IN');
|
||||||
|
|
||||||
|
$queryMapper->where('supplier', \array_unique([$request->getData('price_supplier', 'int'), null]), 'IN');
|
||||||
|
$queryMapper->where('unit', \array_unique([$request->getData('price_unit', 'int'), null]), 'IN');
|
||||||
|
$queryMapper->where('type', $request->getData('price_type', 'int') ?? PriceType::SALES);
|
||||||
|
$queryMapper->where('currency', array_unique([$request->getData('price_currency', 'int'), null]), 'IN');
|
||||||
|
|
||||||
|
// @todo: implement start and end
|
||||||
|
|
||||||
|
/*
|
||||||
|
@todo: implement quantity
|
||||||
|
if ($request->hasData('price_quantity')) {
|
||||||
|
$whereQuery = new Where();
|
||||||
|
$whereQuery->where('quantity', (int) $request->getData('price_quantity'), '<=')
|
||||||
|
->where('quantity', null, '=', 'OR')
|
||||||
|
|
||||||
|
$queryMapper->where('quantity', $whereQuery);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
$prices = $queryMapper->execute();
|
||||||
|
|
||||||
|
// Find base price (@todo: probably not a good solution)
|
||||||
|
$bestBasePrice = null;
|
||||||
|
foreach ($prices as $price) {
|
||||||
|
if ($price->price !== 0 && $price->priceNew === 0
|
||||||
|
&& $price->item->getId() !== 0
|
||||||
|
&& $price->itemgroup->getId() === 0
|
||||||
|
&& $price->itemsegment->getId() === 0
|
||||||
|
&& $price->itemsection->getId() === 0
|
||||||
|
&& $price->itemtype->getId() === 0
|
||||||
|
&& $price->client->getId() === 0
|
||||||
|
&& $price->clientgroup->getId() === 0
|
||||||
|
&& $price->clientsegment->getId() === 0
|
||||||
|
&& $price->clientsection->getId() === 0
|
||||||
|
&& $price->clienttype->getId() === 0
|
||||||
|
&& $price->promocode === ''
|
||||||
|
) {
|
||||||
|
if ($price->price < $bestBasePrice?->price ?? \PHP_INT_MAX) {
|
||||||
|
$bestBasePrice = $price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: implement prices which cannot be improved even if there are better prices available (i.e. some customer groups may not get better prices, Dentagen Beispiel)
|
||||||
|
// alternatively set prices as 'improvable' => which whitelists a price as can be improved or 'alwaysimproces' which always overwrites other prices
|
||||||
|
// Find best price
|
||||||
|
$bestPrice = null;
|
||||||
|
$bestPriceValue = \PHP_INT_MAX;
|
||||||
|
|
||||||
|
foreach ($prices as $price) {
|
||||||
|
$newPrice = $bestBasePrice->price;
|
||||||
|
|
||||||
|
if ($price->price < $newPrice) {
|
||||||
|
$newPrice = $price->price;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($price->priceNew < $newPrice) {
|
||||||
|
$newPrice = $price->priceNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
$newPrice -= $price->discount;
|
||||||
|
$newPrice = (int) ((10000 / $price->discountPercentage) * $newPrice);
|
||||||
|
$newPrice = (int) (($price->quantity === 0 ? 10000 : $price->quantity) / (10000 + $price->bonus) * $newPrice);
|
||||||
|
|
||||||
|
// @todo: the calculation above regarding discount and bonus don't consider the purchased quantity.
|
||||||
|
// If a customer receives 1+1 but purchases 2, then he gets 2+2 (if multiply === true) which is better than 1+1 with multiply false.
|
||||||
|
|
||||||
|
if ($newPrice < $bestPriceValue) {
|
||||||
|
$bestPriceValue = $newPrice;
|
||||||
|
$bestPrice = $price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get tax definition
|
||||||
|
$tax = ($request->getData('price_type', 'int') ?? PriceType::SALES)
|
||||||
|
? TaxCombinationMapper::get()
|
||||||
|
->where('itemCode', $request->getData('price_item'))
|
||||||
|
->where('clientCode', $account->getAttribute('client_code')->getId())
|
||||||
|
->execute()
|
||||||
|
: TaxCombinationMapper::get()
|
||||||
|
->where('itemCode', $request->getData('price_item'))
|
||||||
|
->where('supplierCode', $account->getAttribute('supplier_code')->getId())
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$response->header->set('Content-Type', MimeType::M_JSON, true);
|
||||||
|
$response->set(
|
||||||
|
$request->uri->__toString(),
|
||||||
|
\array_values($prices)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api method to create item bill type
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiPriceCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validatePriceCreate($request))) {
|
||||||
|
$response->set('price_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tax = $this->createPriceFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $tax, PriceMapper::class, 'price', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Price', 'Price successfully created', $tax);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create item attribute from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return Price
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createPriceFromRequest(RequestAbstract $request) : Price
|
||||||
|
{
|
||||||
|
$price = new Price();
|
||||||
|
$price->name = $request->getData('name') ?? '';
|
||||||
|
$price->promocode = $request->getData('promocode') ?? '';
|
||||||
|
|
||||||
|
$price->item = new NullItem((int) $request->getData('item'));
|
||||||
|
$price->itemgroup = new NullItemAttributeValue((int) $request->getData('itemgroup'));
|
||||||
|
$price->itemsegment = new NullItemAttributeValue((int) $request->getData('itemsegment'));
|
||||||
|
$price->itemsection = new NullItemAttributeValue((int) $request->getData('itemsection'));
|
||||||
|
$price->itemtype = new NullItemAttributeValue((int) $request->getData('itemtype'));
|
||||||
|
|
||||||
|
$price->client = new NullClient((int) $request->getData('client'));
|
||||||
|
$price->clientgroup = new NullClientAttributeValue((int) $request->getData('clientgroup'));
|
||||||
|
$price->clientsegment = new NullClientAttributeValue((int) $request->getData('clientsegment'));
|
||||||
|
$price->clientsection = new NullClientAttributeValue((int) $request->getData('clientsection'));
|
||||||
|
$price->clienttype = new NullClientAttributeValue((int) $request->getData('clienttype'));
|
||||||
|
|
||||||
|
$price->supplier = new NullSupplier((int) $request->getData('supplier'));
|
||||||
|
$price->unit = (int) $request->getData('unit');
|
||||||
|
$price->type = (int) ($request->getData('type') ?? PriceType::SALES);
|
||||||
|
$price->quantity = (int) $request->getData('quantity');
|
||||||
|
$price->price = (int) $request->getData('price');
|
||||||
|
$price->priceNew = (int) $request->getData('price_name');
|
||||||
|
$price->discount = (int) $request->getData('discount');
|
||||||
|
$price->discountPercentage = (int) $request->getData('discountPercentage');
|
||||||
|
$price->bonus = (int) $request->getData('bonus');
|
||||||
|
$price->multiply = (bool) ($request->getData('multiply') ?? false);
|
||||||
|
$price->currency = $request->getData('currency') ?? ISO4217CharEnum::_EUR;
|
||||||
|
$price->start = $request->hasData('start') ? new \DateTime($request->getData('start')) : null;
|
||||||
|
$price->end = $request->hasData('end') ? new \DateTime($request->getData('end')) : null;
|
||||||
|
|
||||||
|
return $price;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate item attribute create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validatePriceCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (false) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
132
Controller/ApiPurchaseController.php
Normal file
132
Controller/ApiPurchaseController.php
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Billing\Models\BillStatus;
|
||||||
|
use Modules\Billing\Models\BillTransferType;
|
||||||
|
use Modules\Billing\Models\BillTypeMapper;
|
||||||
|
use Modules\Billing\Models\SettingsEnum;
|
||||||
|
use phpOMS\Message\Http\HttpRequest;
|
||||||
|
use phpOMS\Message\Http\HttpResponse;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\System\OperatingSystem;
|
||||||
|
use phpOMS\System\SystemType;
|
||||||
|
use phpOMS\System\SystemUtils;
|
||||||
|
use phpOMS\Uri\HttpUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ApiPurchaseController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Api method to create bill files
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function apiSupplierBillUpload(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
$originalType = (int) ($request->getData('type') ?? $this->app->appSettings->get(
|
||||||
|
names: SettingsEnum::ORIGINAL_MEDIA_TYPE,
|
||||||
|
module: self::NAME
|
||||||
|
)->content);
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\BillType $purchaseTransferType */
|
||||||
|
$purchaseTransferType = BillTypeMapper::get()
|
||||||
|
->where('transferType', BillTransferType::PURCHASE)
|
||||||
|
->limit(1)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$files = $request->getFiles();
|
||||||
|
foreach ($files as $file) {
|
||||||
|
// Create default bill
|
||||||
|
$billRequest = new HttpRequest(new HttpUri(''));
|
||||||
|
$billRequest->header->account = $request->header->account;
|
||||||
|
$billRequest->header->l11n = $request->header->l11n;
|
||||||
|
$billRequest->setData('supplier', 0);
|
||||||
|
$billRequest->setData('status', BillStatus::UNPARSED);
|
||||||
|
$billRequest->setData('type', $purchaseTransferType->getId());
|
||||||
|
|
||||||
|
$billResponse = new HttpResponse();
|
||||||
|
$billResponse->header->l11n = $response->header->l11n;
|
||||||
|
|
||||||
|
$this->app->moduleManager->get('Billing', 'Api')->apiBillCreate($billRequest, $billResponse, $data);
|
||||||
|
|
||||||
|
$billId = $billResponse->get('')['response']->getId();
|
||||||
|
|
||||||
|
// Upload and assign document to bill
|
||||||
|
$mediaRequest = new HttpRequest();
|
||||||
|
$mediaRequest->header->account = $request->header->account;
|
||||||
|
$mediaRequest->header->l11n = $request->header->l11n;
|
||||||
|
$mediaRequest->addFile($file);
|
||||||
|
|
||||||
|
$mediaResponse = new HttpResponse();
|
||||||
|
$mediaResponse->header->l11n = $response->header->l11n;
|
||||||
|
|
||||||
|
$mediaRequest->setData('bill', $billId);
|
||||||
|
$mediaRequest->setData('type', $originalType);
|
||||||
|
$mediaRequest->setData('parse_content', true, true);
|
||||||
|
$this->app->moduleManager->get('Billing', 'Api')->apiMediaAddToBill($mediaRequest, $mediaResponse, $data);
|
||||||
|
|
||||||
|
$uploaded = $mediaResponse->get('')['response']['upload'];
|
||||||
|
$in = \reset($uploaded)->getAbsolutePath(); // pdf is parsed in $in->content
|
||||||
|
|
||||||
|
if (!\is_file($in)) {
|
||||||
|
throw new \Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: Parse text and analyze text structure
|
||||||
|
|
||||||
|
// Create internal document
|
||||||
|
$billResponse = new HttpResponse();
|
||||||
|
$billRequest = new HttpRequest(new HttpUri(''));
|
||||||
|
|
||||||
|
$billRequest->header->account = $request->header->account;
|
||||||
|
$billRequest->setData('bill', $billId);
|
||||||
|
|
||||||
|
$this->app->moduleManager->get('Billing', 'Api')->apiBillPdfArchiveCreate($billRequest, $billResponse);
|
||||||
|
|
||||||
|
// Offload bill parsing to cli
|
||||||
|
$cliPath = \realpath(__DIR__ . '/../../../Cli/cli.php');
|
||||||
|
if ($cliPath === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemUtils::runProc(
|
||||||
|
OperatingSystem::getSystem() === SystemType::WIN ? 'php.exe' : 'php',
|
||||||
|
\escapeshellarg($cliPath)
|
||||||
|
. ' /billing/bill/purchase/parse '
|
||||||
|
. '-i ' . \escapeshellarg((string) $billId),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
Controller/ApiTaxController.php
Normal file
139
Controller/ApiTaxController.php
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Admin\Models\Address;
|
||||||
|
use Modules\Billing\Models\Tax\TaxCombination;
|
||||||
|
use Modules\Billing\Models\Tax\TaxCombinationMapper;
|
||||||
|
use Modules\ClientManagement\Models\Client;
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeTypeMapper;
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeValue;
|
||||||
|
use Modules\ClientManagement\Models\NullClientAttributeValue;
|
||||||
|
use Modules\ItemManagement\Models\NullItemAttributeValue;
|
||||||
|
use Modules\SupplierManagement\Models\NullSupplierAttributeValue;
|
||||||
|
use phpOMS\Localization\ISO3166CharEnum;
|
||||||
|
use phpOMS\Message\Http\RequestStatusCode;
|
||||||
|
use phpOMS\Message\NotificationLevel;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\Model\Message\FormValidation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ApiTaxController extends Controller
|
||||||
|
{
|
||||||
|
public function apiTaxCombinationCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
|
||||||
|
{
|
||||||
|
if (!empty($val = $this->validateTaxCombinationCreate($request))) {
|
||||||
|
$response->set('tax_combination_create', new FormValidation($val));
|
||||||
|
$response->header->status = RequestStatusCode::R_400;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tax = $this->createTaxCombinationFromRequest($request);
|
||||||
|
$this->createModel($request->header->account, $tax, TaxCombinationMapper::class, 'tax_combination', $request->getOrigin());
|
||||||
|
|
||||||
|
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Tax combination', 'Tax combination successfully created', $tax);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create item attribute from request.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return TaxCombination
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function createTaxCombinationFromRequest(RequestAbstract $request) : TaxCombination
|
||||||
|
{
|
||||||
|
$tax = new TaxCombination();
|
||||||
|
$tax->taxType = (int) $request->getData('tax_type') ?? 1;
|
||||||
|
$tax->taxCode = (string) $request->getData('tax_code');
|
||||||
|
$tax->itemCode = new NullItemAttributeValue((int) $request->getData('item_code'));
|
||||||
|
|
||||||
|
if ($tax->taxType === 1) {
|
||||||
|
$tax->clientCode = new NullClientAttributeValue((int) $request->getData('account_code'));
|
||||||
|
} else {
|
||||||
|
$tax->supplierCode = new NullSupplierAttributeValue((int) $request->getData('account_code'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tax;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate item attribute create request
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
*
|
||||||
|
* @return array<string, bool>
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private function validateTaxCombinationCreate(RequestAbstract $request) : array
|
||||||
|
{
|
||||||
|
$val = [];
|
||||||
|
if (($val['tax_type'] = empty($request->getData('tax_type')))
|
||||||
|
|| ($val['tax_code'] = empty($request->getData('tax_code')))
|
||||||
|
|| ($val['item_code'] = empty($request->getData('item_code')))
|
||||||
|
|| ($val['account_code'] = empty($request->getData('account_code')))
|
||||||
|
) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientTaxCode(Client $client, Address $taxOfficeAddress) : ClientAttributeValue
|
||||||
|
{
|
||||||
|
$codes = ClientAttributeTypeMapper::get()
|
||||||
|
->with('defaults')
|
||||||
|
->where('name', 'sales_tax_code')
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$taxCode = new NullClientAttributeValue();
|
||||||
|
|
||||||
|
if ($taxOfficeAddress->getCountry() === $client->mainAddress->getCountry()) {
|
||||||
|
$taxCode = $codes->getDefaultByValue($client->mainAddress->getCountry());
|
||||||
|
} elseif (\in_array($taxOfficeAddress->getCountry(), ISO3166CharEnum::getRegion('eu'))
|
||||||
|
&& \in_array($client->mainAddress->getCountry(), ISO3166CharEnum::getRegion('eu'))
|
||||||
|
) {
|
||||||
|
if (!empty($client->getAttribute('vat_id')?->value->getValue())) {
|
||||||
|
// Is EU company
|
||||||
|
$taxCode = $codes->getDefaultByValue('EU');
|
||||||
|
} else {
|
||||||
|
// Is EU private customer
|
||||||
|
$taxCode = $codes->getDefaultByValue($client->mainAddress->getCountry());
|
||||||
|
}
|
||||||
|
} elseif (\in_array($taxOfficeAddress->getCountry(), ISO3166CharEnum::getRegion('eu'))) {
|
||||||
|
// None EU company but we are EU company
|
||||||
|
$taxCode = $codes->getDefaultByValue('INT');
|
||||||
|
} else {
|
||||||
|
// None EU company and we are also none EU company
|
||||||
|
$taxCode = $codes->getDefaultByValue('INT');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $taxCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -296,6 +296,7 @@ final class BackendController extends Controller
|
||||||
$bill = PurchaseBillMapper::get()
|
$bill = PurchaseBillMapper::get()
|
||||||
->with('elements')
|
->with('elements')
|
||||||
->with('media')
|
->with('media')
|
||||||
|
->with('media/types')
|
||||||
->with('notes')
|
->with('notes')
|
||||||
->where('id', (int) $request->getData('id'))
|
->where('id', (int) $request->getData('id'))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
@ -803,6 +804,7 @@ final class BackendController extends Controller
|
||||||
$bill = PurchaseBillMapper::get()
|
$bill = PurchaseBillMapper::get()
|
||||||
->with('elements')
|
->with('elements')
|
||||||
->with('media')
|
->with('media')
|
||||||
|
->with('media/types')
|
||||||
->with('notes')
|
->with('notes')
|
||||||
->where('id', (int) $request->getData('id'))
|
->where('id', (int) $request->getData('id'))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
|
||||||
306
Controller/CliController.php
Normal file
306
Controller/CliController.php
Normal file
|
|
@ -0,0 +1,306 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Controller;
|
||||||
|
|
||||||
|
use Modules\Billing\Models\BillMapper;
|
||||||
|
use Modules\Billing\Models\BillTypeMapper;
|
||||||
|
use Modules\Billing\Models\NullBillType;
|
||||||
|
use Modules\Billing\Models\SettingsEnum;
|
||||||
|
use Modules\SupplierManagement\Models\NullSupplier;
|
||||||
|
use Modules\SupplierManagement\Models\Supplier;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierMapper;
|
||||||
|
use phpOMS\Contract\RenderableInterface;
|
||||||
|
use phpOMS\Localization\ISO639x1Enum;
|
||||||
|
use phpOMS\Localization\LanguageDetection\Language;
|
||||||
|
use phpOMS\Localization\Money;
|
||||||
|
use phpOMS\Message\RequestAbstract;
|
||||||
|
use phpOMS\Message\ResponseAbstract;
|
||||||
|
use phpOMS\Views\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing controller class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class CliController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Analyse supplier bill
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return RenderableInterface Response can be rendered
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function cliParseSupplierBill(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface
|
||||||
|
{
|
||||||
|
$originalType = (int) ($request->getData('type') ?? $this->app->appSettings->get(
|
||||||
|
names: SettingsEnum::ORIGINAL_MEDIA_TYPE,
|
||||||
|
module: self::NAME
|
||||||
|
)->content);
|
||||||
|
|
||||||
|
/** @var \Modules\Billing\Models\Bill $bill */
|
||||||
|
$bill = BillMapper::get()
|
||||||
|
->with('media')
|
||||||
|
->with('media/types')
|
||||||
|
->with('media/content')
|
||||||
|
->where('id', (int) $request->getData('i'))
|
||||||
|
->where('media/types/id', $originalType)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$old = clone $bill;
|
||||||
|
|
||||||
|
$content = \strtolower($bill->getFileByType($originalType)->content->content ?? '');
|
||||||
|
$lines = \explode("\n", $content);
|
||||||
|
|
||||||
|
$language = $this->detectLanguage($content);
|
||||||
|
$bill->language = $language;
|
||||||
|
|
||||||
|
$identifiers = \json_decode(\file_get_contents(__DIR__ . '/../Models/billIdentifier.json'), true);
|
||||||
|
|
||||||
|
/* Supplier */
|
||||||
|
$suppliers = SupplierMapper::getAll()
|
||||||
|
->with('account')
|
||||||
|
->with('mainAddress')
|
||||||
|
->with('attributes/type')
|
||||||
|
->where('attributes/type/name', ['bill_match_pattern', 'bill_date_format'], 'IN')
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$supplierId = $this->matchSupplier($content, $suppliers);
|
||||||
|
$bill->supplier = new NullSupplier($supplierId);
|
||||||
|
$supplier = $suppliers[$supplierId] ?? new NullSupplier();
|
||||||
|
|
||||||
|
$bill->billTo = $supplier->account->name1;
|
||||||
|
$bill->billAddress = $supplier->mainAddress->address;
|
||||||
|
$bill->billCity = $supplier->mainAddress->city;
|
||||||
|
$bill->billZip = $supplier->mainAddress->postal;
|
||||||
|
$bill->billCountry = $supplier->mainAddress->getCountry();
|
||||||
|
|
||||||
|
/* Type */
|
||||||
|
$type = $this->findSupplierInvoiceType($content, $identifiers['type'], $language);
|
||||||
|
$billType = BillTypeMapper::get()
|
||||||
|
->where('name', $type)
|
||||||
|
->execute();
|
||||||
|
$bill->type = new NullBillType($billType->getId());
|
||||||
|
|
||||||
|
/* Number */
|
||||||
|
$billNumber = $this->findBillNumber($lines, $identifiers['bill_no'][$language]);
|
||||||
|
$bill->number = $billNumber;
|
||||||
|
|
||||||
|
/* Date */
|
||||||
|
$billDateTemp = $this->findBillDate($lines, $identifiers['bill_date'][$language]);
|
||||||
|
$billDate = $this->parseDate($billDateTemp, $supplier, $identifiers['date_format']);
|
||||||
|
|
||||||
|
$bill->billDate = $billDate;
|
||||||
|
|
||||||
|
/* Total Gross */
|
||||||
|
$totalGross = $this->findBillGross($lines, $identifiers['total_gross'][$language]);
|
||||||
|
$bill->grossCosts = new Money($totalGross);
|
||||||
|
|
||||||
|
$this->updateModel($request->header->account, $old, $bill, BillMapper::class, 'bill_parsing', $request->getOrigin());
|
||||||
|
|
||||||
|
$view = new View($this->app->l11nManager, $request, $response);
|
||||||
|
$view->setTemplate('/Modules/Billing/Theme/Cli/bill-parsed');
|
||||||
|
$view->setData('bill', $bill);
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function detectLanguage(string $content) : string
|
||||||
|
{
|
||||||
|
$detector = new Language();
|
||||||
|
$language = $detector->detect($content)->bestResults()->close();
|
||||||
|
|
||||||
|
if (!\is_array($language) || \count($language) < 1) {
|
||||||
|
return 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
return \substr(\array_keys($language)[0], 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findSupplierInvoiceType(string $content, array $types, string $language) : string
|
||||||
|
{
|
||||||
|
$bestPos = \strlen($content);
|
||||||
|
$bestMatch = '';
|
||||||
|
|
||||||
|
foreach ($types as $name => $type) {
|
||||||
|
foreach ($type[$language] as $l11n) {
|
||||||
|
$found = \stripos($content, \strtolower($l11n));
|
||||||
|
|
||||||
|
if ($found !== false && $found < $bestPos) {
|
||||||
|
$bestPos = $found;
|
||||||
|
$bestMatch = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return empty($bestMatch) ? 'purchase_invoice' : $bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findBillNumber(array $lines, array $matches) : string
|
||||||
|
{
|
||||||
|
$bestPos = \count($lines);
|
||||||
|
$bestMatch = '';
|
||||||
|
|
||||||
|
$found = [];
|
||||||
|
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
foreach ($lines as $row => $line) {
|
||||||
|
if (\preg_match($match, $line, $found) === 1) {
|
||||||
|
if ($row < $bestPos) {
|
||||||
|
$bestPos = $row;
|
||||||
|
$bestMatch = \trim($found['bill_no']);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findBillDue(array $lines, array $matches) : string
|
||||||
|
{
|
||||||
|
$bestPos = \count($lines);
|
||||||
|
$bestMatch = '';
|
||||||
|
|
||||||
|
$found = [];
|
||||||
|
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
foreach ($lines as $row => $line) {
|
||||||
|
if (\preg_match($match, $line, $found) === 1) {
|
||||||
|
if ($row < $bestPos) {
|
||||||
|
// @question: don't many invoices have the due date at the bottom? bestPos doesn't make sense?!
|
||||||
|
$bestPos = $row;
|
||||||
|
$bestMatch = \trim($found['bill_due']);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findBillDate(array $lines, array $matches) : string
|
||||||
|
{
|
||||||
|
$bestPos = \count($lines);
|
||||||
|
$bestMatch = '';
|
||||||
|
|
||||||
|
$found = [];
|
||||||
|
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
foreach ($lines as $row => $line) {
|
||||||
|
if (\preg_match($match, $line, $found) === 1) {
|
||||||
|
if ($row < $bestPos) {
|
||||||
|
$bestPos = $row;
|
||||||
|
$bestMatch = \trim($found['bill_date']);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findBillGross(array $lines, array $matches) : int
|
||||||
|
{
|
||||||
|
$bestMatch = 0;
|
||||||
|
|
||||||
|
$found = [];
|
||||||
|
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
if (\preg_match($match, $line, $found) === 1) {
|
||||||
|
$temp = \trim($found['total_gross']);
|
||||||
|
|
||||||
|
$posD = \stripos($temp, '.');
|
||||||
|
$posK = \stripos($temp, ',');
|
||||||
|
|
||||||
|
$hasDecimal = ($posD !== false || $posK !== false)
|
||||||
|
&& \max((int) $posD, (int) $posK) + 3 >= \strlen($temp);
|
||||||
|
|
||||||
|
$gross = ((int) \str_replace(['.', ','], ['', ''], $temp)) * ($hasDecimal
|
||||||
|
? 100
|
||||||
|
: 10000);
|
||||||
|
|
||||||
|
if ($gross > $bestMatch) {
|
||||||
|
$bestMatch = $gross;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function matchSupplier(string $content, array $suppliers) : int
|
||||||
|
{
|
||||||
|
$bestMatch = 0;
|
||||||
|
|
||||||
|
foreach ($suppliers as $supplier) {
|
||||||
|
if ((!empty($supplier->getAttributeByTypeName('iban')->value->valueStr)
|
||||||
|
&& \stripos($content, $supplier->getAttributeByTypeName('iban')->value->valueStr) !== false)
|
||||||
|
|| (!empty($supplier->getAttributeByTypeName('bill_match_pattern')->value->valueStr)
|
||||||
|
&& \stripos($content, $supplier->getAttributeByTypeName('bill_match_pattern')->value->valueStr) !== false)
|
||||||
|
) {
|
||||||
|
return $supplier->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\stripos($content, $supplier->account->name1) !== false) {
|
||||||
|
if ((!empty($supplier->mainAddress->city)
|
||||||
|
&& \stripos($content, $supplier->mainAddress->city) !== false)
|
||||||
|
|| (!empty( $supplier->mainAddress->address)
|
||||||
|
&& \stripos($content, $supplier->mainAddress->address) !== false)
|
||||||
|
) {
|
||||||
|
return $supplier->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
$bestMatch = $supplier->getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseDate(string $date, Supplier $supplier, array $formats) : ?\DateTime
|
||||||
|
{
|
||||||
|
if ((!empty($supplier->getAttributeByTypeName('bill_date_format')->value->valueStr))) {
|
||||||
|
return \DateTime::createFromFormat(
|
||||||
|
$supplier->getAttributeByTypeName('bill_date_format')->value->valueStr,
|
||||||
|
$date
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($formats as $format) {
|
||||||
|
if (($obj = \DateTime::createFromFormat($format, $date)) !== false) {
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Models/Attribute/AttributeValueType.php
Executable file
40
Models/Attribute/AttributeValueType.php
Executable file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\Stdlib\Base\Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute value type enum.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
abstract class AttributeValueType extends Enum
|
||||||
|
{
|
||||||
|
public const _INT = 1;
|
||||||
|
|
||||||
|
public const _STRING = 2;
|
||||||
|
|
||||||
|
public const _FLOAT = 3;
|
||||||
|
|
||||||
|
public const _DATETIME = 4;
|
||||||
|
|
||||||
|
public const _BOOL = 5;
|
||||||
|
|
||||||
|
public const _FLOAT_INT = 6;
|
||||||
|
}
|
||||||
102
Models/Attribute/BillAttribute.php
Executable file
102
Models/Attribute/BillAttribute.php
Executable file
|
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class BillAttribute implements \JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Id.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected int $id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill this attribute belongs to
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public int $bill = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute type the attribute belongs to
|
||||||
|
*
|
||||||
|
* @var BillAttributeType
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public BillAttributeType $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute value the attribute belongs to
|
||||||
|
*
|
||||||
|
* @var BillAttributeValue
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public BillAttributeValue $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->type = new NullBillAttributeType();
|
||||||
|
$this->value = new NullBillAttributeValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getId() : int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toArray() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'bill' => $this->bill,
|
||||||
|
'type' => $this->type,
|
||||||
|
'value' => $this->value,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Models/Attribute/BillAttributeMapper.php
Executable file
74
Models/Attribute/BillAttributeMapper.php
Executable file
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class BillAttributeMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_bill_attr_id' => ['name' => 'billing_bill_attr_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_bill_attr_bill' => ['name' => 'billing_bill_attr_bill', 'type' => 'int', 'internal' => 'bill'],
|
||||||
|
'billing_bill_attr_type' => ['name' => 'billing_bill_attr_type', 'type' => 'int', 'internal' => 'type'],
|
||||||
|
'billing_bill_attr_value' => ['name' => 'billing_bill_attr_value', 'type' => 'int', 'internal' => 'value'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has one relation.
|
||||||
|
*
|
||||||
|
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const OWNS_ONE = [
|
||||||
|
'type' => [
|
||||||
|
'mapper' => BillAttributeTypeMapper::class,
|
||||||
|
'external' => 'billing_bill_attr_type',
|
||||||
|
],
|
||||||
|
'value' => [
|
||||||
|
'mapper' => BillAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_bill_attr_value',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const TABLE = 'billing_bill_attr';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary field name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const PRIMARYFIELD = 'billing_bill_attr_id';
|
||||||
|
}
|
||||||
216
Models/Attribute/BillAttributeType.php
Executable file
216
Models/Attribute/BillAttributeType.php
Executable file
|
|
@ -0,0 +1,216 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\Localization\BaseStringL11n;
|
||||||
|
use phpOMS\Localization\ISO639x1Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill Attribute Type class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class BillAttributeType implements \JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Id
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected int $id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name/string identifier by which it can be found/categorized
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public string $name = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which field data type is required (string, int, ...) in the value
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected int $fields = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a custom value allowed (e.g. custom string)
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public bool $custom = false;
|
||||||
|
|
||||||
|
public string $validationPattern = '';
|
||||||
|
|
||||||
|
public bool $isRequired = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datatype of the attribute
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public int $datatype = AttributeValueType::_STRING;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localization
|
||||||
|
*
|
||||||
|
* @var BaseStringL11n
|
||||||
|
*/
|
||||||
|
private string | BaseStringL11n $l11n = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible default attribute values
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private array $defaults = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default attribute value
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public int $default = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string $name Name/identifier of the attribute type
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(string $name = '')
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getId() : int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefaultByValue(mixed $value) : BillAttributeValue
|
||||||
|
{
|
||||||
|
foreach ($this->defaults as $default) {
|
||||||
|
if ($default->getValue() === $value) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NullBillAttributeValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set l11n
|
||||||
|
*
|
||||||
|
* @param string|BaseStringL11n $l11n Tag article l11n
|
||||||
|
* @param string $lang Language
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function setL11n(string | BaseStringL11n $l11n, string $lang = ISO639x1Enum::_EN) : void
|
||||||
|
{
|
||||||
|
if ($l11n instanceof BaseStringL11n) {
|
||||||
|
$this->l11n = $l11n;
|
||||||
|
} elseif (isset($this->l11n) && $this->l11n instanceof BaseStringL11n) {
|
||||||
|
$this->l11n->content = $l11n;
|
||||||
|
$this->l11n->setLanguage($lang);
|
||||||
|
} else {
|
||||||
|
$this->l11n = new BaseStringL11n();
|
||||||
|
$this->l11n->content = $l11n;
|
||||||
|
$this->l11n->setLanguage($lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getL11n() : string
|
||||||
|
{
|
||||||
|
if (!isset($this->l11n)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->l11n instanceof BaseStringL11n ? $this->l11n->content : $this->l11n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set fields
|
||||||
|
*
|
||||||
|
* @param int $fields Fields
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function setFields(int $fields) : void
|
||||||
|
{
|
||||||
|
$this->fields = $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default values
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @sicne 1.0.0
|
||||||
|
*/
|
||||||
|
public function getDefaults() : array
|
||||||
|
{
|
||||||
|
return $this->defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toArray() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'name' => $this->name,
|
||||||
|
'validationPattern' => $this->validationPattern,
|
||||||
|
'custom' => $this->custom,
|
||||||
|
'isRequired' => $this->isRequired,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
66
Models/Attribute/BillAttributeTypeL11nMapper.php
Executable file
66
Models/Attribute/BillAttributeTypeL11nMapper.php
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
use phpOMS\Localization\BaseStringL11n;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class BillAttributeTypeL11nMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_attr_type_l11n_id' => ['name' => 'billing_attr_type_l11n_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_attr_type_l11n_title' => ['name' => 'billing_attr_type_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true],
|
||||||
|
'billing_attr_type_l11n_type' => ['name' => 'billing_attr_type_l11n_type', 'type' => 'int', 'internal' => 'ref'],
|
||||||
|
'billing_attr_type_l11n_lang' => ['name' => 'billing_attr_type_l11n_lang', 'type' => 'string', 'internal' => 'language'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const TABLE = 'billing_attr_type_l11n';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary field name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const PRIMARYFIELD = 'billing_attr_type_l11n_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model to use by the mapper.
|
||||||
|
*
|
||||||
|
* @var class-string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const MODEL = BaseStringL11n::class;
|
||||||
|
}
|
||||||
82
Models/Attribute/BillAttributeTypeMapper.php
Executable file
82
Models/Attribute/BillAttributeTypeMapper.php
Executable file
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class BillAttributeTypeMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_attr_type_id' => ['name' => 'billing_attr_type_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_attr_type_name' => ['name' => 'billing_attr_type_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true],
|
||||||
|
'billing_attr_type_datatype' => ['name' => 'billing_attr_type_datatype', 'type' => 'int', 'internal' => 'datatype'],
|
||||||
|
'billing_attr_type_fields' => ['name' => 'billing_attr_type_fields', 'type' => 'int', 'internal' => 'fields'],
|
||||||
|
'billing_attr_type_custom' => ['name' => 'billing_attr_type_custom', 'type' => 'bool', 'internal' => 'custom'],
|
||||||
|
'billing_attr_type_pattern' => ['name' => 'billing_attr_type_pattern', 'type' => 'string', 'internal' => 'validationPattern'],
|
||||||
|
'billing_attr_type_required' => ['name' => 'billing_attr_type_required', 'type' => 'bool', 'internal' => 'isRequired'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has many relation.
|
||||||
|
*
|
||||||
|
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const HAS_MANY = [
|
||||||
|
'l11n' => [
|
||||||
|
'mapper' => BillAttributeTypeL11nMapper::class,
|
||||||
|
'table' => 'billing_attr_type_l11n',
|
||||||
|
'self' => 'billing_attr_type_l11n_type',
|
||||||
|
'column' => 'content',
|
||||||
|
'external' => null,
|
||||||
|
],
|
||||||
|
'defaults' => [
|
||||||
|
'mapper' => BillAttributeValueMapper::class,
|
||||||
|
'table' => 'billing_bill_attr_default',
|
||||||
|
'self' => 'billing_bill_attr_default_type',
|
||||||
|
'external' => 'billing_bill_attr_default_value',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const TABLE = 'billing_attr_type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary field name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const PRIMARYFIELD = 'billing_attr_type_id';
|
||||||
|
}
|
||||||
230
Models/Attribute/BillAttributeValue.php
Executable file
230
Models/Attribute/BillAttributeValue.php
Executable file
|
|
@ -0,0 +1,230 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\Localization\BaseStringL11n;
|
||||||
|
use phpOMS\Localization\ISO639x1Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill attribute value class.
|
||||||
|
*
|
||||||
|
* The relation with the type/bill is defined in the BillAttribute class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class BillAttributeValue implements \JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Id
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected int $id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending attribute type
|
||||||
|
*
|
||||||
|
* @var null|int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?int $dependingAttributeType = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending attribute value
|
||||||
|
*
|
||||||
|
* @var null|int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?int $dependingAttributeValue = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Int value
|
||||||
|
*
|
||||||
|
* @var null|int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?int $valueInt = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String value
|
||||||
|
*
|
||||||
|
* @var null|string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?string $valueStr = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decimal value
|
||||||
|
*
|
||||||
|
* @var null|float
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?float $valueDec = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DateTime value
|
||||||
|
*
|
||||||
|
* @var null|\DateTimeInterface
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?\DateTimeInterface $valueDat = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a default value which can be selected
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public bool $isDefault = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit of the value
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public string $unit = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localization
|
||||||
|
*
|
||||||
|
* @var null|BaseStringL11n
|
||||||
|
*/
|
||||||
|
private ?BaseStringL11n $l11n = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getId() : int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set l11n
|
||||||
|
*
|
||||||
|
* @param string|BaseStringL11n $l11n Tag article l11n
|
||||||
|
* @param string $lang Language
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function setL11n(string | BaseStringL11n $l11n, string $lang = ISO639x1Enum::_EN) : void
|
||||||
|
{
|
||||||
|
if ($l11n instanceof BaseStringL11n) {
|
||||||
|
$this->l11n = $l11n;
|
||||||
|
} elseif (isset($this->l11n) && $this->l11n instanceof BaseStringL11n) {
|
||||||
|
$this->l11n->content = $l11n;
|
||||||
|
$this->l11n->setLanguage($lang);
|
||||||
|
} else {
|
||||||
|
$this->l11n = new BaseStringL11n();
|
||||||
|
$this->l11n->content = $l11n;
|
||||||
|
$this->l11n->ref = $this->id;
|
||||||
|
$this->l11n->setLanguage($lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get localization
|
||||||
|
*
|
||||||
|
* @return null|string
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getL11n() : ?string
|
||||||
|
{
|
||||||
|
return $this->l11n instanceof BaseStringL11n ? $this->l11n->content : $this->l11n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set value
|
||||||
|
*
|
||||||
|
* @param int|string|float $value Value
|
||||||
|
* @param int $datatype Datatype
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function setValue(mixed $value, int $datatype) : void
|
||||||
|
{
|
||||||
|
if ($datatype === AttributeValueType::_STRING) {
|
||||||
|
$this->valueStr = (string) $value;
|
||||||
|
} elseif ($datatype === AttributeValueType::_INT
|
||||||
|
|| $datatype === AttributeValueType::_FLOAT_INT
|
||||||
|
|| $datatype === AttributeValueType::_BOOL
|
||||||
|
) {
|
||||||
|
$this->valueInt = (int) $value;
|
||||||
|
} elseif ($datatype === AttributeValueType::_FLOAT) {
|
||||||
|
$this->valueDec = (float) $value;
|
||||||
|
} elseif ($datatype === AttributeValueType::_DATETIME) {
|
||||||
|
$this->valueDat = new \DateTime((string) $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value
|
||||||
|
*
|
||||||
|
* @return null|int|string|float|\DateTimeInterface
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getValue() : mixed
|
||||||
|
{
|
||||||
|
if (!empty($this->valueStr)) {
|
||||||
|
return $this->valueStr;
|
||||||
|
} elseif (!empty($this->valueInt)) {
|
||||||
|
return $this->valueInt;
|
||||||
|
} elseif (!empty($this->valueDec)) {
|
||||||
|
return $this->valueDec;
|
||||||
|
} elseif ($this->valueDat instanceof \DateTimeInterface) {
|
||||||
|
return $this->valueDat;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toArray() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'valueInt' => $this->valueInt,
|
||||||
|
'valueStr' => $this->valueStr,
|
||||||
|
'valueDec' => $this->valueDec,
|
||||||
|
'valueDat' => $this->valueDat,
|
||||||
|
'isDefault' => $this->isDefault,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
66
Models/Attribute/BillAttributeValueL11nMapper.php
Executable file
66
Models/Attribute/BillAttributeValueL11nMapper.php
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
use phpOMS\Localization\BaseStringL11n;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class BillAttributeValueL11nMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_attr_value_l11n_id' => ['name' => 'billing_attr_value_l11n_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_attr_value_l11n_title' => ['name' => 'billing_attr_value_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true],
|
||||||
|
'billing_attr_value_l11n_value' => ['name' => 'billing_attr_value_l11n_value', 'type' => 'int', 'internal' => 'ref'],
|
||||||
|
'billing_attr_value_l11n_lang' => ['name' => 'billing_attr_value_l11n_lang', 'type' => 'string', 'internal' => 'language'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const TABLE = 'billing_attr_value_l11n';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary field name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const PRIMARYFIELD = 'billing_attr_value_l11n_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model to use by the mapper.
|
||||||
|
*
|
||||||
|
* @var class-string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const MODEL = BaseStringL11n::class;
|
||||||
|
}
|
||||||
77
Models/Attribute/BillAttributeValueMapper.php
Executable file
77
Models/Attribute/BillAttributeValueMapper.php
Executable file
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class BillAttributeValueMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_attr_value_id' => ['name' => 'billing_attr_value_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_attr_value_default' => ['name' => 'billing_attr_value_default', 'type' => 'bool', 'internal' => 'isDefault'],
|
||||||
|
'billing_attr_value_valueStr' => ['name' => 'billing_attr_value_valueStr', 'type' => 'string', 'internal' => 'valueStr'],
|
||||||
|
'billing_attr_value_valueInt' => ['name' => 'billing_attr_value_valueInt', 'type' => 'int', 'internal' => 'valueInt'],
|
||||||
|
'billing_attr_value_valueDec' => ['name' => 'billing_attr_value_valueDec', 'type' => 'float', 'internal' => 'valueDec'],
|
||||||
|
'billing_attr_value_valueDat' => ['name' => 'billing_attr_value_valueDat', 'type' => 'DateTime', 'internal' => 'valueDat'],
|
||||||
|
'billing_attr_value_unit' => ['name' => 'billing_attr_value_unit', 'type' => 'string', 'internal' => 'unit'],
|
||||||
|
'billing_attr_value_deptype' => ['name' => 'billing_attr_value_deptype', 'type' => 'int', 'internal' => 'dependingAttributeType'],
|
||||||
|
'billing_attr_value_depvalue' => ['name' => 'billing_attr_value_depvalue', 'type' => 'int', 'internal' => 'dependingAttributeValue'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has many relation.
|
||||||
|
*
|
||||||
|
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const HAS_MANY = [
|
||||||
|
'l11n' => [
|
||||||
|
'mapper' => BillAttributeValueL11nMapper::class,
|
||||||
|
'table' => 'billing_attr_value_l11n',
|
||||||
|
'self' => 'billing_attr_value_l11n_value',
|
||||||
|
'external' => null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const TABLE = 'billing_attr_value';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary field name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const PRIMARYFIELD = 'billing_attr_value_id';
|
||||||
|
}
|
||||||
47
Models/Attribute/NullBillAttribute.php
Executable file
47
Models/Attribute/NullBillAttribute.php
Executable file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null model
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class NullBillAttribute extends BillAttribute
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param int $id Model id
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(int $id = 0)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return ['id' => $this->id];
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Models/Attribute/NullBillAttributeType.php
Executable file
46
Models/Attribute/NullBillAttributeType.php
Executable file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null model
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class NullBillAttributeType extends BillAttributeType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param int $id Model id
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(int $id = 0)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return ['id' => $this->id];
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Models/Attribute/NullBillAttributeValue.php
Executable file
46
Models/Attribute/NullBillAttributeValue.php
Executable file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null model
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Attribute
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class NullBillAttributeValue extends BillAttributeValue
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param int $id Model id
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(int $id = 0)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return ['id' => $this->id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,13 +16,13 @@ namespace Modules\Billing\Models;
|
||||||
|
|
||||||
use Modules\Admin\Models\Account;
|
use Modules\Admin\Models\Account;
|
||||||
use Modules\Admin\Models\NullAccount;
|
use Modules\Admin\Models\NullAccount;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttribute;
|
||||||
use Modules\ClientManagement\Models\Client;
|
use Modules\ClientManagement\Models\Client;
|
||||||
use Modules\Editor\Models\EditorDoc;
|
use Modules\Editor\Models\EditorDoc;
|
||||||
use Modules\Media\Models\Collection;
|
use Modules\Media\Models\Collection;
|
||||||
use Modules\Media\Models\Media;
|
use Modules\Media\Models\Media;
|
||||||
use Modules\Media\Models\NullMedia;
|
use Modules\Media\Models\NullMedia;
|
||||||
use Modules\SupplierManagement\Models\Supplier;
|
use Modules\SupplierManagement\Models\Supplier;
|
||||||
use phpOMS\Localization\ISO3166TwoEnum;
|
|
||||||
use phpOMS\Localization\ISO4217CharEnum;
|
use phpOMS\Localization\ISO4217CharEnum;
|
||||||
use phpOMS\Localization\ISO639x1Enum;
|
use phpOMS\Localization\ISO639x1Enum;
|
||||||
use phpOMS\Localization\Money;
|
use phpOMS\Localization\Money;
|
||||||
|
|
@ -89,13 +89,21 @@ class Bill implements \JsonSerializable
|
||||||
*/
|
*/
|
||||||
public \DateTimeImmutable $createdAt;
|
public \DateTimeImmutable $createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill created at.
|
||||||
|
*
|
||||||
|
* @var null|\DateTime
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public ?\DateTime $billDate = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bill created at.
|
* Bill created at.
|
||||||
*
|
*
|
||||||
* @var \DateTime
|
* @var \DateTime
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public \DateTime $performanceDate;
|
public ?\DateTime $performanceDate = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bill send at.
|
* Bill send at.
|
||||||
|
|
@ -435,6 +443,14 @@ class Bill implements \JsonSerializable
|
||||||
*/
|
*/
|
||||||
protected array $media = [];
|
protected array $media = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attributes.
|
||||||
|
*
|
||||||
|
* @var BillAttribute[]
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private array $attributes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
|
|
@ -452,7 +468,6 @@ class Bill implements \JsonSerializable
|
||||||
$this->grossDiscount = new Money(0);
|
$this->grossDiscount = new Money(0);
|
||||||
|
|
||||||
$this->createdAt = new \DateTimeImmutable();
|
$this->createdAt = new \DateTimeImmutable();
|
||||||
$this->performanceDate = new \DateTime();
|
|
||||||
$this->createdBy = new NullAccount();
|
$this->createdBy = new NullAccount();
|
||||||
$this->referral = new NullAccount();
|
$this->referral = new NullAccount();
|
||||||
$this->type = new NullBillType();
|
$this->type = new NullBillType();
|
||||||
|
|
@ -514,6 +529,52 @@ class Bill implements \JsonSerializable
|
||||||
return $this->number;
|
return $this->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add attribute to client
|
||||||
|
*
|
||||||
|
* @param BillAttribute $attribute Attribute
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function addAttribute(BillAttribute $attribute) : void
|
||||||
|
{
|
||||||
|
$this->attributes[] = $attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get attributes
|
||||||
|
*
|
||||||
|
* @return BillAttribute[]
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getAttributes() : array
|
||||||
|
{
|
||||||
|
return $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get attribute
|
||||||
|
*
|
||||||
|
* @param string $attrName Attribute name
|
||||||
|
*
|
||||||
|
* @return null|BillAttribute
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getAttribute(string $attrName) : ?BillAttribute
|
||||||
|
{
|
||||||
|
foreach ($this->attributes as $attribute) {
|
||||||
|
if ($attribute->type->name === $attrName) {
|
||||||
|
return $attribute->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get status
|
* Get status
|
||||||
*
|
*
|
||||||
|
|
@ -759,7 +820,7 @@ class Bill implements \JsonSerializable
|
||||||
public function getFileByType(int $type) : Media
|
public function getFileByType(int $type) : Media
|
||||||
{
|
{
|
||||||
foreach ($this->media as $file) {
|
foreach ($this->media as $file) {
|
||||||
if ($file->type->getId() === $type) {
|
if ($file->hasMediaTypeId($type)) {
|
||||||
return $file;
|
return $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
||||||
namespace Modules\Billing\Models;
|
namespace Modules\Billing\Models;
|
||||||
|
|
||||||
use Modules\Admin\Models\AccountMapper;
|
use Modules\Admin\Models\AccountMapper;
|
||||||
|
use Modules\Billing\Models\Attribute\BillAttributeMapper;
|
||||||
use Modules\ClientManagement\Models\ClientMapper;
|
use Modules\ClientManagement\Models\ClientMapper;
|
||||||
use Modules\Editor\Models\EditorDocMapper;
|
use Modules\Editor\Models\EditorDocMapper;
|
||||||
use Modules\Media\Models\CollectionMapper;
|
use Modules\Media\Models\CollectionMapper;
|
||||||
|
|
@ -82,6 +83,7 @@ class BillMapper extends DataMapperFactory
|
||||||
'billing_bill_client' => ['name' => 'billing_bill_client', 'type' => 'int', 'internal' => 'client'],
|
'billing_bill_client' => ['name' => 'billing_bill_client', 'type' => 'int', 'internal' => 'client'],
|
||||||
'billing_bill_supplier' => ['name' => 'billing_bill_supplier', 'type' => 'int', 'internal' => 'supplier'],
|
'billing_bill_supplier' => ['name' => 'billing_bill_supplier', 'type' => 'int', 'internal' => 'supplier'],
|
||||||
'billing_bill_created_by' => ['name' => 'billing_bill_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
'billing_bill_created_by' => ['name' => 'billing_bill_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||||
|
'billing_bill_date' => ['name' => 'billing_bill_date', 'type' => 'DateTime', 'internal' => 'billDate'],
|
||||||
'billing_bill_performance_date' => ['name' => 'billing_bill_performance_date', 'type' => 'DateTime', 'internal' => 'performanceDate', 'readonly' => true],
|
'billing_bill_performance_date' => ['name' => 'billing_bill_performance_date', 'type' => 'DateTime', 'internal' => 'performanceDate', 'readonly' => true],
|
||||||
'billing_bill_created_at' => ['name' => 'billing_bill_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
'billing_bill_created_at' => ['name' => 'billing_bill_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||||
];
|
];
|
||||||
|
|
@ -153,6 +155,13 @@ class BillMapper extends DataMapperFactory
|
||||||
'mapper' => SupplierMapper::class,
|
'mapper' => SupplierMapper::class,
|
||||||
'external' => 'billing_bill_supplier',
|
'external' => 'billing_bill_supplier',
|
||||||
],
|
],
|
||||||
|
'attributes' => [
|
||||||
|
'mapper' => BillAttributeMapper::class,
|
||||||
|
'table' => 'billing_bill_attr',
|
||||||
|
'self' => 'billing_bill_attr_bill',
|
||||||
|
'conditional' => true,
|
||||||
|
'external' => null,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -161,7 +170,7 @@ class BillMapper extends DataMapperFactory
|
||||||
* @var string
|
* @var string
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public const PRIMARYFIELD ='billing_bill_id';
|
public const PRIMARYFIELD = 'billing_bill_id';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Primary table.
|
* Primary table.
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ final class BillTypeL11nMapper extends DataMapperFactory
|
||||||
* @var string
|
* @var string
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public const PRIMARYFIELD ='billing_type_l11n_id';
|
public const PRIMARYFIELD = 'billing_type_l11n_id';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model to use by the mapper.
|
* Model to use by the mapper.
|
||||||
|
|
|
||||||
|
|
@ -116,5 +116,5 @@ final class BillTypeMapper extends DataMapperFactory
|
||||||
* @var string
|
* @var string
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public const PRIMARYFIELD ='billing_type_id';
|
public const PRIMARYFIELD = 'billing_type_id';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
Models/NullBill.php
Executable file → Normal file
0
Models/NullBill.php
Executable file → Normal file
47
Models/Price/NullPrice.php
Normal file
47
Models/Price/NullPrice.php
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Price
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null bill type class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Price
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class NullPrice extends Price
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param int $id Model id
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(int $id = 0)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return ['id' => $this->id];
|
||||||
|
}
|
||||||
|
}
|
||||||
144
Models/Price/Price.php
Normal file
144
Models/Price/Price.php
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Price
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Price;
|
||||||
|
|
||||||
|
use Modules\ClientManagement\Models\Client;
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeValue;
|
||||||
|
use Modules\ClientManagement\Models\NullClient;
|
||||||
|
use Modules\ClientManagement\Models\NullClientAttributeValue;
|
||||||
|
use Modules\ItemManagement\Models\Item;
|
||||||
|
use Modules\ItemManagement\Models\ItemAttributeValue;
|
||||||
|
use Modules\ItemManagement\Models\NullItem;
|
||||||
|
use Modules\ItemManagement\Models\NullItemAttributeValue;
|
||||||
|
use Modules\SupplierManagement\Models\NullSupplier;
|
||||||
|
use Modules\SupplierManagement\Models\Supplier;
|
||||||
|
use phpOMS\Localization\ISO4217CharEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Price
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Price implements \JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ID.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected int $id = 0;
|
||||||
|
|
||||||
|
public string $name = '';
|
||||||
|
|
||||||
|
public string $promocode = '';
|
||||||
|
|
||||||
|
public Item $item;
|
||||||
|
|
||||||
|
public ItemAttributeValue $itemgroup;
|
||||||
|
|
||||||
|
public ItemAttributeValue $itemsegment;
|
||||||
|
|
||||||
|
public ItemAttributeValue $itemsection;
|
||||||
|
|
||||||
|
public ItemAttributeValue $itemtype;
|
||||||
|
|
||||||
|
public Client $client;
|
||||||
|
|
||||||
|
public ClientAttributeValue $clientgroup;
|
||||||
|
|
||||||
|
public ClientAttributeValue $clientsegment;
|
||||||
|
|
||||||
|
public ClientAttributeValue $clientsection;
|
||||||
|
|
||||||
|
public ClientAttributeValue $clienttype;
|
||||||
|
|
||||||
|
public ?string $clientcountry = null;
|
||||||
|
|
||||||
|
public Supplier $supplier;
|
||||||
|
|
||||||
|
public int $unit = 0;
|
||||||
|
|
||||||
|
public int $type = PriceType::SALES;
|
||||||
|
|
||||||
|
public int $quantity = 0;
|
||||||
|
|
||||||
|
public int $price = 0;
|
||||||
|
|
||||||
|
public int $priceNew = 0;
|
||||||
|
|
||||||
|
public int $discount = 0;
|
||||||
|
|
||||||
|
public int $discountPercentage = 0;
|
||||||
|
|
||||||
|
public int $bonus = 0;
|
||||||
|
|
||||||
|
public bool $multiply = false;
|
||||||
|
|
||||||
|
public string $currency = ISO4217CharEnum::_EUR;
|
||||||
|
|
||||||
|
public ?\DateTime $start = null;
|
||||||
|
public ?\DateTime $end = null;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->item = new NullItem();
|
||||||
|
$this->itemgroup = new NullItemAttributeValue();
|
||||||
|
$this->itemsegment = new NullItemAttributeValue();
|
||||||
|
$this->itemsection = new NullItemAttributeValue();
|
||||||
|
$this->itemtype = new NullItemAttributeValue();
|
||||||
|
|
||||||
|
$this->client = new NullClient();
|
||||||
|
$this->clientgroup = new NullClientAttributeValue();
|
||||||
|
$this->clientsegment = new NullClientAttributeValue();
|
||||||
|
$this->clientsection = new NullClientAttributeValue();
|
||||||
|
$this->clienttype = new NullClientAttributeValue();
|
||||||
|
|
||||||
|
$this->supplier = new NullSupplier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id.
|
||||||
|
*
|
||||||
|
* @return int Model id
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getId() : int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toArray() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
179
Models/Price/PriceMapper.php
Normal file
179
Models/Price/PriceMapper.php
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Price
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Price;
|
||||||
|
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeValueMapper;
|
||||||
|
use Modules\ClientManagement\Models\ClientMapper;
|
||||||
|
use Modules\ItemManagement\Models\ItemAttributeValueMapper;
|
||||||
|
use Modules\ItemManagement\Models\ItemMapper;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierMapper;
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
use phpOMS\Localization\Defaults\CountryMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Price
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class PriceMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_price_id' => ['name' => 'billing_price_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_price_name' => ['name' => 'billing_price_name', 'type' => 'string', 'internal' => 'name'],
|
||||||
|
'billing_price_promocode' => ['name' => 'billing_price_promocode', 'type' => 'string', 'internal' => 'promocode'],
|
||||||
|
'billing_price_item' => ['name' => 'billing_price_item', 'type' => 'int', 'internal' => 'item'],
|
||||||
|
'billing_price_itemgroup' => ['name' => 'billing_price_itemgroup', 'type' => 'int', 'internal' => 'itemgroup'],
|
||||||
|
'billing_price_itemsegment' => ['name' => 'billing_price_itemsegment', 'type' => 'int', 'internal' => 'itemsegment'],
|
||||||
|
'billing_price_itemsection' => ['name' => 'billing_price_itemsection', 'type' => 'int', 'internal' => 'itemsection'],
|
||||||
|
'billing_price_itemtype' => ['name' => 'billing_price_itemtype', 'type' => 'int', 'internal' => 'itemtype'],
|
||||||
|
'billing_price_client' => ['name' => 'billing_price_client', 'type' => 'int', 'internal' => 'client'],
|
||||||
|
'billing_price_clientgroup' => ['name' => 'billing_price_clientgroup', 'type' => 'int', 'internal' => 'clientgroup'],
|
||||||
|
'billing_price_clientsegment' => ['name' => 'billing_price_clientsegment', 'type' => 'int', 'internal' => 'clientsegment'],
|
||||||
|
'billing_price_clientsection' => ['name' => 'billing_price_clientsection', 'type' => 'int', 'internal' => 'clientsection'],
|
||||||
|
'billing_price_clienttype' => ['name' => 'billing_price_clienttype', 'type' => 'int', 'internal' => 'clienttype'],
|
||||||
|
'billing_price_clientcountry' => ['name' => 'billing_price_clientcountry', 'type' => 'string', 'internal' => 'clientcountry'],
|
||||||
|
'billing_price_supplier' => ['name' => 'billing_price_supplier', 'type' => 'int', 'internal' => 'supplier'],
|
||||||
|
'billing_price_unit' => ['name' => 'billing_price_unit', 'type' => 'int', 'internal' => 'unit'],
|
||||||
|
'billing_price_type' => ['name' => 'billing_price_type', 'type' => 'int', 'internal' => 'type'],
|
||||||
|
'billing_price_quantity' => ['name' => 'billing_price_quantity', 'type' => 'int', 'internal' => 'quantity'],
|
||||||
|
'billing_price_price' => ['name' => 'billing_price_price', 'type' => 'int', 'internal' => 'price'],
|
||||||
|
'billing_price_price_new' => ['name' => 'billing_price_price_new', 'type' => 'int', 'internal' => 'priceNew'],
|
||||||
|
'billing_price_discount' => ['name' => 'billing_price_discount', 'type' => 'int', 'internal' => 'discount'],
|
||||||
|
'billing_price_discountp' => ['name' => 'billing_price_discountp', 'type' => 'int', 'internal' => 'discountPercentage'],
|
||||||
|
'billing_price_bonus' => ['name' => 'billing_price_bonus', 'type' => 'int', 'internal' => 'bonus'],
|
||||||
|
'billing_price_multiply' => ['name' => 'billing_price_multiply', 'type' => 'bool', 'internal' => 'multiply'],
|
||||||
|
'billing_price_currency' => ['name' => 'billing_price_currency', 'type' => 'string', 'internal' => 'currency'],
|
||||||
|
'billing_price_start' => ['name' => 'billing_price_start', 'type' => 'DateTime', 'internal' => 'start'],
|
||||||
|
'billing_price_end' => ['name' => 'billing_price_end', 'type' => 'DateTime', 'internal' => 'end'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has one relation.
|
||||||
|
*
|
||||||
|
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const OWNS_ONE = [
|
||||||
|
'item' => [
|
||||||
|
'mapper' => ItemMapper::class,
|
||||||
|
'external' => 'billing_price_item',
|
||||||
|
],
|
||||||
|
'itemgroup' => [
|
||||||
|
'mapper' => ItemAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_itemgroup',
|
||||||
|
],
|
||||||
|
'itemsegment' => [
|
||||||
|
'mapper' => ItemAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_itemsegment',
|
||||||
|
],
|
||||||
|
'itemsection' => [
|
||||||
|
'mapper' => ItemAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_itemsection',
|
||||||
|
],
|
||||||
|
'itemtype' => [
|
||||||
|
'mapper' => ItemAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_itemtype',
|
||||||
|
],
|
||||||
|
'client' => [
|
||||||
|
'mapper' => ClientMapper::class,
|
||||||
|
'external' => 'billing_price_client',
|
||||||
|
],
|
||||||
|
'clientgroup' => [
|
||||||
|
'mapper' => ClientAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_clientgroup',
|
||||||
|
],
|
||||||
|
'clientsegment' => [
|
||||||
|
'mapper' => ClientAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_clientsegment',
|
||||||
|
],
|
||||||
|
'clientsection' => [
|
||||||
|
'mapper' => ClientAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_clientsection',
|
||||||
|
],
|
||||||
|
'clienttype' => [
|
||||||
|
'mapper' => ClientAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_price_clienttype',
|
||||||
|
],
|
||||||
|
'clientcountry' => [
|
||||||
|
'mapper' => CountryMapper::class,
|
||||||
|
'external' => 'billing_price_clientcountry',
|
||||||
|
'by' => 'code2',
|
||||||
|
'column' => 'code2',
|
||||||
|
'conditional' => true,
|
||||||
|
],
|
||||||
|
'supplier' => [
|
||||||
|
'mapper' => SupplierMapper::class,
|
||||||
|
'external' => 'billing_price_supplier',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model to use by the mapper.
|
||||||
|
*
|
||||||
|
* @var class-string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const MODEL = Price::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 [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.1
|
||||||
*
|
*
|
||||||
* @package Modules\Billing\Models
|
* @package Modules\Billing\Models\Price
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|
@ -12,19 +12,19 @@
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Modules\Billing\Models;
|
namespace Modules\Billing\Models\Price;
|
||||||
|
|
||||||
use phpOMS\Stdlib\Base\Enum;
|
use phpOMS\Stdlib\Base\Enum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module settings enum.
|
* Module settings enum.
|
||||||
*
|
*
|
||||||
* @package Modules\Billing\Models
|
* @package Modules\Billing\Models\Price
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
abstract class PricingType extends Enum
|
abstract class PriceType extends Enum
|
||||||
{
|
{
|
||||||
public const SALES = 1;
|
public const SALES = 1;
|
||||||
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Karaka
|
|
||||||
*
|
|
||||||
* PHP Version 8.1
|
|
||||||
*
|
|
||||||
* @package Modules\Billing\Models
|
|
||||||
* @copyright Dennis Eichhorn
|
|
||||||
* @license OMS License 1.0
|
|
||||||
* @version 1.0.0
|
|
||||||
* @link https://jingga.app
|
|
||||||
*/
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Modules\Billing\Models;
|
|
||||||
|
|
||||||
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
|
||||||
use phpOMS\DataStorage\Database\Query\Where;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Billing mapper class.
|
|
||||||
*
|
|
||||||
* @package Modules\Billing\Models
|
|
||||||
* @license OMS License 1.0
|
|
||||||
* @link https://jingga.app
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
final class PricingMapper extends DataMapperFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Columns.
|
|
||||||
*
|
|
||||||
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
|
||||||
* @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 [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
Models/Tax/BillTaxType.php
Normal file
32
Models/Tax/BillTaxType.php
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Tax;
|
||||||
|
|
||||||
|
use phpOMS\Stdlib\Base\Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill transfer type enum.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
abstract class BillTaxType extends Enum
|
||||||
|
{
|
||||||
|
public const SALES = 1;
|
||||||
|
|
||||||
|
public const PURCHASE = 2;
|
||||||
|
}
|
||||||
46
Models/Tax/NullTaxCombination.php
Normal file
46
Models/Tax/NullTaxCombination.php
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Tax;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null model
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class NullTaxCombination extends TaxCombination
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param int $id Model id
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(int $id = 0)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return ['id' => $this->id];
|
||||||
|
}
|
||||||
|
}
|
||||||
100
Models/Tax/TaxCombination.php
Normal file
100
Models/Tax/TaxCombination.php
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Tax;
|
||||||
|
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeValue;
|
||||||
|
use Modules\ClientManagement\Models\NullClientAttributeValue;
|
||||||
|
use Modules\ItemManagement\Models\ItemAttributeValue;
|
||||||
|
use Modules\ItemManagement\Models\NullItemAttributeValue;
|
||||||
|
use Modules\SupplierManagement\Models\NullSupplierAttributeValue;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierAttributeValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class TaxCombination implements \JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Article ID.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected int $id = 0;
|
||||||
|
|
||||||
|
public ?ClientAttributeValue $clientCode = null;
|
||||||
|
|
||||||
|
public ?SupplierAttributeValue $supplierCode = null;
|
||||||
|
|
||||||
|
public ItemAttributeValue $itemCode;
|
||||||
|
|
||||||
|
public string $taxCode = '';
|
||||||
|
|
||||||
|
public int $taxType = BillTaxType::SALES;
|
||||||
|
|
||||||
|
public string $account = '';
|
||||||
|
|
||||||
|
public string $refundAccount = '';
|
||||||
|
|
||||||
|
public string $discountAccount = '';
|
||||||
|
|
||||||
|
public ?int $minPrice = null;
|
||||||
|
|
||||||
|
public ?int $maxPrice = null;
|
||||||
|
|
||||||
|
public ?\DateTime $start = null;
|
||||||
|
|
||||||
|
public ?\DateTime $end = null;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->itemCode = new NullItemAttributeValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getId() : int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toArray() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function jsonSerialize() : mixed
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
98
Models/Tax/TaxCombinationMapper.php
Normal file
98
Models/Tax/TaxCombinationMapper.php
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Karaka
|
||||||
|
*
|
||||||
|
* PHP Version 8.1
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Billing\Models\Tax;
|
||||||
|
|
||||||
|
use Modules\ClientManagement\Models\ClientAttributeValueMapper;
|
||||||
|
use Modules\ItemManagement\Models\ItemAttributeValueMapper;
|
||||||
|
use Modules\SupplierManagement\Models\SupplierAttributeValueMapper;
|
||||||
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Billing mapper class.
|
||||||
|
*
|
||||||
|
* @package Modules\Billing\Models\Tax
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://jingga.app
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class TaxCombinationMapper extends DataMapperFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Columns.
|
||||||
|
*
|
||||||
|
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const COLUMNS = [
|
||||||
|
'billing_tax_id' => ['name' => 'billing_tax_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
|
'billing_tax_client_code' => ['name' => 'billing_tax_client_code', 'type' => 'int', 'internal' => 'clientCode'],
|
||||||
|
'billing_tax_supplier_code' => ['name' => 'billing_tax_supplier_code', 'type' => 'int', 'internal' => 'supplierCode'],
|
||||||
|
'billing_tax_item_code' => ['name' => 'billing_tax_item_code', 'type' => 'int', 'internal' => 'itemCode'],
|
||||||
|
'billing_tax_code' => ['name' => 'billing_tax_code', 'type' => 'string', 'internal' => 'taxCode'],
|
||||||
|
'billing_tax_type' => ['name' => 'billing_tax_type', 'type' => 'int', 'internal' => 'taxType'],
|
||||||
|
'billing_tax_account' => ['name' => 'billing_tax_account', 'type' => 'string', 'internal' => 'account'],
|
||||||
|
'billing_tax_refund_account' => ['name' => 'billing_tax_refund_account', 'type' => 'string', 'internal' => 'refundAccount'],
|
||||||
|
'billing_tax_discount_account' => ['name' => 'billing_tax_discount_account', 'type' => 'string', 'internal' => 'discountAccount'],
|
||||||
|
'billing_tax_min_price' => ['name' => 'billing_tax_min_price', 'type' => 'int', 'internal' => 'minPrice'],
|
||||||
|
'billing_tax_max_price' => ['name' => 'billing_tax_max_price', 'type' => 'int', 'internal' => 'maxPrice'],
|
||||||
|
'billing_tax_start' => ['name' => 'billing_tax_start', 'type' => 'DateTime', 'internal' => 'start'],
|
||||||
|
'billing_tax_end' => ['name' => 'billing_tax_end', 'type' => 'DateTime', 'internal' => 'end'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has one relation.
|
||||||
|
*
|
||||||
|
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const OWNS_ONE = [
|
||||||
|
'clientCode' => [
|
||||||
|
'mapper' => ClientAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_tax_client_code',
|
||||||
|
],
|
||||||
|
'supplierCode' => [
|
||||||
|
'mapper' => SupplierAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_tax_supplier_code',
|
||||||
|
],
|
||||||
|
'itemCode' => [
|
||||||
|
'mapper' => ItemAttributeValueMapper::class,
|
||||||
|
'external' => 'billing_tax_item_code',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model to use by the mapper.
|
||||||
|
*
|
||||||
|
* @var class-string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const MODEL = TaxCombination::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const TABLE = 'billing_tax';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary field name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public const PRIMARYFIELD = 'billing_tax_id';
|
||||||
|
}
|
||||||
106
Models/billIdentifier.json
Normal file
106
Models/billIdentifier.json
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
{
|
||||||
|
"type": {
|
||||||
|
"purchase_invoice": {
|
||||||
|
"en": [
|
||||||
|
"Invoice"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"Rechnung"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"purchase_credit_note": {
|
||||||
|
"en": [
|
||||||
|
"Credit Note"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"Rechnungskorrektur",
|
||||||
|
"Gutschrift"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"purchase_delivery_note": {
|
||||||
|
"en": [
|
||||||
|
"Delivery Note"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"Lieferschein"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"purchase_order_confirmation": {
|
||||||
|
"en": [
|
||||||
|
"Order Confirmation"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"Auftragsbestätigung"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"purchase_reverse_invoice": {
|
||||||
|
"en": [
|
||||||
|
"Credit Note"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"Gutschrift"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"date_format": [
|
||||||
|
"Y-m-d",
|
||||||
|
"Y.m.d",
|
||||||
|
"Y/m/d",
|
||||||
|
"d-m-Y",
|
||||||
|
"d.m.Y",
|
||||||
|
"d/m/Y",
|
||||||
|
"m-d-Y",
|
||||||
|
"m.d.Y",
|
||||||
|
"m/d/Y",
|
||||||
|
"M. d.Y",
|
||||||
|
"M. d. Y",
|
||||||
|
"M. d Y",
|
||||||
|
"M. d,Y",
|
||||||
|
"M. d, Y",
|
||||||
|
"M d.Y",
|
||||||
|
"M d. Y",
|
||||||
|
"M d Y",
|
||||||
|
"M d,Y",
|
||||||
|
"M d, Y",
|
||||||
|
"M, d.Y",
|
||||||
|
"M, d. Y",
|
||||||
|
"M, d Y",
|
||||||
|
"M, d,Y",
|
||||||
|
"M, d, Y"
|
||||||
|
],
|
||||||
|
"bill_no": {
|
||||||
|
"en": [
|
||||||
|
"/(inv.*?)(no|\\s|,|:|\\.|#)+(?<bill_no>.*?)( |$)/i",
|
||||||
|
"/(#)(?<bill_no>.*?)( |$)/i"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"/(rechnungsn.*?|beleg.*?)(?<bill_no>.*?)( |$)/i"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bill_date": {
|
||||||
|
"en": [
|
||||||
|
"/(inv.*?)(date.*?)(\\s|,|:|\\.)+(?<bill_date>.*?)( |$)/i",
|
||||||
|
"/(date.*?)(\\s|,|:|\\.)+(?<bill_date>.*?)( |$)/i"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"/(rechnungsdat.*?|belegdat.*?)(\\s|,|:|\\.)+(?<bill_date>.*?)( |$)/i"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bill_due": {
|
||||||
|
"en": [
|
||||||
|
"/(due date.*?)(\\s|,|:|\\.)+(?<bill_due>.*?)( |$)/i",
|
||||||
|
"/(due.*?)(\\s|,|:|\\.)+(?<bill_due>.*?)( |$)/i"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"/(fällig.*?)(\\s|,|:|\\.)+(?<bill_due>.*?)( |$)/i"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"total_gross": {
|
||||||
|
"en": [
|
||||||
|
"/(total.*?|gross.*?)(?<total_gross>([0-9]+,*\\.*)+)/i"
|
||||||
|
],
|
||||||
|
"de": [
|
||||||
|
"/(betrag.*?|gesamt.*?|brutto.*?)(?<total_gross>([0-9]+,*\\.*)+)/i"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,4 +17,5 @@ return ['Navigation' => [
|
||||||
'Archive' => 'Archive',
|
'Archive' => 'Archive',
|
||||||
'Bill' => 'Bill',
|
'Bill' => 'Bill',
|
||||||
'Billing' => 'Billing',
|
'Billing' => 'Billing',
|
||||||
|
'Upload' => 'Upload',
|
||||||
]];
|
]];
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ return ['Billing' => [
|
||||||
'Type' => 'Type',
|
'Type' => 'Type',
|
||||||
'Types' => 'Types',
|
'Types' => 'Types',
|
||||||
'Upload' => 'Upload',
|
'Upload' => 'Upload',
|
||||||
|
'Original' => 'Original',
|
||||||
'Value' => 'Value',
|
'Value' => 'Value',
|
||||||
'Variation' => 'Variation',
|
'Variation' => 'Variation',
|
||||||
'Zip' => 'Zip',
|
'Zip' => 'Zip',
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use phpOMS\Localization\ISO3166NameEnum;
|
||||||
|
use phpOMS\Localization\ISO3166TwoEnum;
|
||||||
use phpOMS\Uri\UriFactory;
|
use phpOMS\Uri\UriFactory;
|
||||||
|
|
||||||
$bills = $this->getData('bills') ?? [];
|
$bills = $this->getData('bills') ?? [];
|
||||||
|
|
@ -126,7 +128,7 @@ echo $this->getData('nav')->render(); ?>
|
||||||
<label>
|
<label>
|
||||||
<i class="filter fa fa-filter"></i>
|
<i class="filter fa fa-filter"></i>
|
||||||
</label>
|
</label>
|
||||||
<td><?= $this->getHtml('Net'); ?>
|
<td><?= $this->getHtml('Gross'); ?>
|
||||||
<label for="billList-sort-7">
|
<label for="billList-sort-7">
|
||||||
<input type="radio" name="billList-sort" id="billList-sort-7">
|
<input type="radio" name="billList-sort" id="billList-sort-7">
|
||||||
<i class="sort-asc fa fa-chevron-up"></i>
|
<i class="sort-asc fa fa-chevron-up"></i>
|
||||||
|
|
@ -138,7 +140,7 @@ echo $this->getData('nav')->render(); ?>
|
||||||
<label>
|
<label>
|
||||||
<i class="filter fa fa-filter"></i>
|
<i class="filter fa fa-filter"></i>
|
||||||
</label>
|
</label>
|
||||||
<td><?= $this->getHtml('Created'); ?>
|
<td><?= $this->getHtml('Date'); ?>
|
||||||
<label for="billList-sort-23">
|
<label for="billList-sort-23">
|
||||||
<input type="radio" name="billList-sort" id="billList-sort-23">
|
<input type="radio" name="billList-sort" id="billList-sort-23">
|
||||||
<i class="sort-asc fa fa-chevron-up"></i>
|
<i class="sort-asc fa fa-chevron-up"></i>
|
||||||
|
|
@ -169,9 +171,13 @@ echo $this->getData('nav')->render(); ?>
|
||||||
?>"><?= $value->billAddress; ?></a>
|
?>"><?= $value->billAddress; ?></a>
|
||||||
<td><a href="<?= $url; ?>"><?= $value->billZip; ?></a>
|
<td><a href="<?= $url; ?>"><?= $value->billZip; ?></a>
|
||||||
<td><a href="<?= $url; ?>"><?= $value->billCity; ?></a>
|
<td><a href="<?= $url; ?>"><?= $value->billCity; ?></a>
|
||||||
<td><a href="<?= $url; ?>"><?= $value->billCountry; ?></a>
|
<td><a href="<?= $url; ?>"><?= !empty($value->billCountry)
|
||||||
<td><a href="<?= $url; ?>"><?= $value->netSales->getCurrency(); ?></a>
|
? ISO3166NameEnum::getByName(
|
||||||
<td><a href="<?= $url; ?>"><?= $value->createdAt->format('Y-m-d'); ?></a>
|
ISO3166TwoEnum::getName($value->billCountry)
|
||||||
|
)
|
||||||
|
: ''; ?></a>
|
||||||
|
<td><a href="<?= $url; ?>"><?= $value->grossCosts->getAmount(); ?></a>
|
||||||
|
<td><a href="<?= $url; ?>"><?= $value->billDate?->format('Y-m-d'); ?></a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php if ($count === 0) : ?>
|
<?php if ($count === 0) : ?>
|
||||||
<tr><td colspan="12" class="empty"><?= $this->getHtml('Empty', '0', '0'); ?>
|
<tr><td colspan="12" class="empty"><?= $this->getHtml('Empty', '0', '0'); ?>
|
||||||
|
|
|
||||||
0
Theme/Cli/Lang/en.lang.php
Normal file
0
Theme/Cli/Lang/en.lang.php
Normal file
3
Theme/Cli/bill-parsed.tpl.php
Normal file
3
Theme/Cli/bill-parsed.tpl.php
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
echo \json_encode($this->getData('bill') ?? null, \JSON_PRETTY_PRINT);
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "karaka/module",
|
"name": "karaka/module",
|
||||||
"description": "Module for Karaka.",
|
"description": "Module for Jingga.",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Dennis Eichhorn",
|
"name": "Dennis Eichhorn",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user