mirror of
https://github.com/Karaka-Management/oms-Billing.git
synced 2026-01-11 15:18:42 +00:00
too many changes
This commit is contained in:
parent
ff90dba39e
commit
44b4db558b
|
|
@ -2,83 +2,11 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
class MYPDF extends TCPDF
|
||||
{
|
||||
public string $fontName = '';
|
||||
public int $fontSize = 8;
|
||||
public int $sideMargin = 15;
|
||||
require_once $this->getData('defaultTemplates')
|
||||
->findFile('.pdf.php')
|
||||
->getAbsolutePath();
|
||||
|
||||
//Page header
|
||||
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);
|
||||
$pdf = new DefaultPdf('P', 'mm', 'A4', true, 'UTF-8', false);
|
||||
|
||||
$creator = $this->getData('bill_creator') ?? 'Jingga';
|
||||
$author = 'Jingga';
|
||||
|
|
@ -120,7 +48,6 @@ $terms = $this->getData('bill_terms') ?? 'https://jingga.app/terms';
|
|||
$taxes = $this->getData('bill_taxes') ?? ['19%' => '0.00'];
|
||||
$currency = $this->getData('bill_currency') ?? 'EUR';
|
||||
|
||||
|
||||
// set document information
|
||||
$pdf->SetCreator($creator);
|
||||
$pdf->SetAuthor($author);
|
||||
|
|
@ -128,28 +55,9 @@ $pdf->SetTitle($title);
|
|||
$pdf->SetSubject($subtitle);
|
||||
$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
|
||||
$pdf->SetImageScale(PDF_IMAGE_SCALE_RATIO);
|
||||
|
||||
// add a page
|
||||
$pdf->AddPage();
|
||||
|
||||
$topPos = $pdf->getY();
|
||||
|
||||
// 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": {
|
||||
"name": "billing_prices",
|
||||
"billing_price": {
|
||||
"name": "billing_price",
|
||||
"fields": {
|
||||
"billing_prices_id": {
|
||||
"name": "billing_prices_id",
|
||||
"billing_price_id": {
|
||||
"name": "billing_price_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"billing_prices_name": {
|
||||
"name": "billing_prices_name",
|
||||
"billing_price_name": {
|
||||
"name": "billing_price_name",
|
||||
"type": "VARCHAR(255)",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_promocode": {
|
||||
"name": "billing_prices_promocode",
|
||||
"type": "INT",
|
||||
"billing_price_promocode": {
|
||||
"name": "billing_price_promocode",
|
||||
"type": "VARCHAR(50)",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_item": {
|
||||
"name": "billing_prices_item",
|
||||
"billing_price_item": {
|
||||
"name": "billing_price_item",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "itemmgmt_item",
|
||||
"foreignKey": "itemmgmt_item_id"
|
||||
},
|
||||
"billing_prices_itemgroup": {
|
||||
"name": "billing_prices_itemgroup",
|
||||
"billing_price_itemgroup": {
|
||||
"name": "billing_price_itemgroup",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "itemmgmt_attr_value",
|
||||
"foreignKey": "itemmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_itemsegment": {
|
||||
"name": "billing_prices_itemsegment",
|
||||
"billing_price_itemsegment": {
|
||||
"name": "billing_price_itemsegment",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "itemmgmt_attr_value",
|
||||
"foreignKey": "itemmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_itemsection": {
|
||||
"name": "billing_prices_itemsection",
|
||||
"billing_price_itemsection": {
|
||||
"name": "billing_price_itemsection",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "itemmgmt_attr_value",
|
||||
"foreignKey": "itemmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_itemtype": {
|
||||
"name": "billing_prices_itemtype",
|
||||
"billing_price_itemtype": {
|
||||
"name": "billing_price_itemtype",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "itemmgmt_attr_value",
|
||||
"foreignKey": "itemmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_client": {
|
||||
"name": "billing_prices_client",
|
||||
"billing_price_client": {
|
||||
"name": "billing_price_client",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "clientmgmt_client",
|
||||
"foreignKey": "clientmgmt_client_id"
|
||||
},
|
||||
"billing_prices_clientgroup": {
|
||||
"name": "billing_prices_clientgroup",
|
||||
"billing_price_clientgroup": {
|
||||
"name": "billing_price_clientgroup",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "clientmgmt_attr_value",
|
||||
"foreignKey": "clientmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_clientsegment": {
|
||||
"name": "billing_prices_clientsegment",
|
||||
"billing_price_clientsegment": {
|
||||
"name": "billing_price_clientsegment",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "clientmgmt_attr_value",
|
||||
"foreignKey": "clientmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_clientsection": {
|
||||
"name": "billing_prices_clientsection",
|
||||
"billing_price_clientsection": {
|
||||
"name": "billing_price_clientsection",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "clientmgmt_attr_value",
|
||||
"foreignKey": "clientmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_clienttype": {
|
||||
"name": "billing_prices_clienttype",
|
||||
"billing_price_clienttype": {
|
||||
"name": "billing_price_clienttype",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "clientmgmt_attr_value",
|
||||
"foreignKey": "clientmgmt_attr_value_id"
|
||||
},
|
||||
"billing_prices_clientcountry": {
|
||||
"name": "billing_prices_clientcountry",
|
||||
"billing_price_clientcountry": {
|
||||
"name": "billing_price_clientcountry",
|
||||
"type": "VARCHAR(2)",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "country",
|
||||
"foreignKey": "country_code2"
|
||||
},
|
||||
"billing_prices_supplier": {
|
||||
"name": "billing_prices_supplier",
|
||||
"billing_price_supplier": {
|
||||
"name": "billing_price_supplier",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "suppliermgmt_supplier",
|
||||
"foreignKey": "suppliermgmt_supplier_id"
|
||||
},
|
||||
"billing_prices_unit": {
|
||||
"name": "billing_prices_unit",
|
||||
"billing_price_unit": {
|
||||
"name": "billing_price_unit",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "unit",
|
||||
"foreignKey": "unit_id"
|
||||
"default": null
|
||||
},
|
||||
"billing_prices_type": {
|
||||
"name": "billing_prices_type",
|
||||
"billing_price_type": {
|
||||
"name": "billing_price_type",
|
||||
"type": "TINYINT(1)",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_quantity": {
|
||||
"name": "billing_prices_quantity",
|
||||
"billing_price_quantity": {
|
||||
"name": "billing_price_quantity",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_price": {
|
||||
"name": "billing_prices_price",
|
||||
"billing_price_price": {
|
||||
"name": "billing_price_price",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_discount": {
|
||||
"name": "billing_prices_discount",
|
||||
"billing_price_price_new": {
|
||||
"name": "billing_price_price_new",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_discountp": {
|
||||
"name": "billing_prices_discountp",
|
||||
"billing_price_discount": {
|
||||
"name": "billing_price_discount",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_bonus": {
|
||||
"name": "billing_prices_bonus",
|
||||
"billing_price_discountp": {
|
||||
"name": "billing_price_discountp",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_multiply": {
|
||||
"name": "billing_prices_multiply",
|
||||
"billing_price_bonus": {
|
||||
"name": "billing_price_bonus",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"billing_price_multiply": {
|
||||
"name": "billing_price_multiply",
|
||||
"type": "TINYINT(1)",
|
||||
"null": false
|
||||
},
|
||||
"billing_prices_currency": {
|
||||
"name": "billing_prices_currency",
|
||||
"billing_price_currency": {
|
||||
"name": "billing_price_currency",
|
||||
"type": "VARCHAR(3)",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "currency",
|
||||
"foreignKey": "currency_code"
|
||||
},
|
||||
"billing_prices_start": {
|
||||
"name": "billing_prices_start",
|
||||
"billing_price_start": {
|
||||
"name": "billing_price_start",
|
||||
"type": "DATETIME",
|
||||
"null": true,
|
||||
"default": null
|
||||
},
|
||||
"billing_prices_end": {
|
||||
"name": "billing_prices_end",
|
||||
"billing_price_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",
|
||||
"null": true,
|
||||
"default": null
|
||||
|
|
@ -444,10 +536,17 @@
|
|||
"type": "DATETIME",
|
||||
"null": false
|
||||
},
|
||||
"billing_bill_date": {
|
||||
"name": "billing_bill_date",
|
||||
"type": "DATETIME",
|
||||
"default": null,
|
||||
"null": true
|
||||
},
|
||||
"billing_bill_performance_date": {
|
||||
"name": "billing_bill_performance_date",
|
||||
"type": "DATETIME",
|
||||
"null": false
|
||||
"default": null,
|
||||
"null": true
|
||||
},
|
||||
"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": {
|
||||
"name": "billing_bill_media",
|
||||
"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",
|
||||
"numberFormat": "{y}-{id}",
|
||||
"transferType": 1,
|
||||
"transferType": 2,
|
||||
"transferStock": false,
|
||||
"isTemplate": false,
|
||||
"l11n": {
|
||||
|
|
@ -211,7 +211,7 @@
|
|||
{
|
||||
"name": "purchase_template",
|
||||
"numberFormat": "{y}-{id}",
|
||||
"transferType": 1,
|
||||
"transferType": 2,
|
||||
"transferStock": false,
|
||||
"isTemplate": true,
|
||||
"l11n": {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ declare(strict_types=1);
|
|||
namespace Modules\Billing\Admin;
|
||||
|
||||
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\Config\SettingsInterface;
|
||||
use phpOMS\Message\Http\HttpRequest;
|
||||
|
|
@ -62,6 +65,208 @@ final class Installer extends InstallerAbstract
|
|||
|
||||
$types = \json_decode($fileContent, true);
|
||||
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()
|
||||
->with('elements')
|
||||
->with('media')
|
||||
->with('media/types')
|
||||
->with('notes')
|
||||
->where('id', (int) $request->getData('id'))
|
||||
->execute();
|
||||
|
|
@ -803,6 +804,7 @@ final class BackendController extends Controller
|
|||
$bill = PurchaseBillMapper::get()
|
||||
->with('elements')
|
||||
->with('media')
|
||||
->with('media/types')
|
||||
->with('notes')
|
||||
->where('id', (int) $request->getData('id'))
|
||||
->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\NullAccount;
|
||||
use Modules\Billing\Models\Attribute\BillAttribute;
|
||||
use Modules\ClientManagement\Models\Client;
|
||||
use Modules\Editor\Models\EditorDoc;
|
||||
use Modules\Media\Models\Collection;
|
||||
use Modules\Media\Models\Media;
|
||||
use Modules\Media\Models\NullMedia;
|
||||
use Modules\SupplierManagement\Models\Supplier;
|
||||
use phpOMS\Localization\ISO3166TwoEnum;
|
||||
use phpOMS\Localization\ISO4217CharEnum;
|
||||
use phpOMS\Localization\ISO639x1Enum;
|
||||
use phpOMS\Localization\Money;
|
||||
|
|
@ -89,13 +89,21 @@ class Bill implements \JsonSerializable
|
|||
*/
|
||||
public \DateTimeImmutable $createdAt;
|
||||
|
||||
/**
|
||||
* Bill created at.
|
||||
*
|
||||
* @var null|\DateTime
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public ?\DateTime $billDate = null;
|
||||
|
||||
/**
|
||||
* Bill created at.
|
||||
*
|
||||
* @var \DateTime
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public \DateTime $performanceDate;
|
||||
public ?\DateTime $performanceDate = null;
|
||||
|
||||
/**
|
||||
* Bill send at.
|
||||
|
|
@ -435,6 +443,14 @@ class Bill implements \JsonSerializable
|
|||
*/
|
||||
protected array $media = [];
|
||||
|
||||
/**
|
||||
* Attributes.
|
||||
*
|
||||
* @var BillAttribute[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private array $attributes = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
|
@ -452,7 +468,6 @@ class Bill implements \JsonSerializable
|
|||
$this->grossDiscount = new Money(0);
|
||||
|
||||
$this->createdAt = new \DateTimeImmutable();
|
||||
$this->performanceDate = new \DateTime();
|
||||
$this->createdBy = new NullAccount();
|
||||
$this->referral = new NullAccount();
|
||||
$this->type = new NullBillType();
|
||||
|
|
@ -514,6 +529,52 @@ class Bill implements \JsonSerializable
|
|||
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
|
||||
*
|
||||
|
|
@ -759,7 +820,7 @@ class Bill implements \JsonSerializable
|
|||
public function getFileByType(int $type) : Media
|
||||
{
|
||||
foreach ($this->media as $file) {
|
||||
if ($file->type->getId() === $type) {
|
||||
if ($file->hasMediaTypeId($type)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
|||
namespace Modules\Billing\Models;
|
||||
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
use Modules\Billing\Models\Attribute\BillAttributeMapper;
|
||||
use Modules\ClientManagement\Models\ClientMapper;
|
||||
use Modules\Editor\Models\EditorDocMapper;
|
||||
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_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_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_created_at' => ['name' => 'billing_bill_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
];
|
||||
|
|
@ -153,6 +155,13 @@ class BillMapper extends DataMapperFactory
|
|||
'mapper' => SupplierMapper::class,
|
||||
'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
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const PRIMARYFIELD ='billing_bill_id';
|
||||
public const PRIMARYFIELD = 'billing_bill_id';
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ final class BillTypeL11nMapper extends DataMapperFactory
|
|||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const PRIMARYFIELD ='billing_type_l11n_id';
|
||||
public const PRIMARYFIELD = 'billing_type_l11n_id';
|
||||
|
||||
/**
|
||||
* Model to use by the mapper.
|
||||
|
|
|
|||
|
|
@ -116,5 +116,5 @@ final class BillTypeMapper extends DataMapperFactory
|
|||
* @var string
|
||||
* @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
|
||||
*
|
||||
* @package Modules\Billing\Models
|
||||
* @package Modules\Billing\Models\Price
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
|
|
@ -12,19 +12,19 @@
|
|||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Billing\Models;
|
||||
namespace Modules\Billing\Models\Price;
|
||||
|
||||
use phpOMS\Stdlib\Base\Enum;
|
||||
|
||||
/**
|
||||
* Module settings enum.
|
||||
*
|
||||
* @package Modules\Billing\Models
|
||||
* @package Modules\Billing\Models\Price
|
||||
* @license OMS License 1.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
abstract class PricingType extends Enum
|
||||
abstract class PriceType extends Enum
|
||||
{
|
||||
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',
|
||||
'Bill' => 'Bill',
|
||||
'Billing' => 'Billing',
|
||||
'Upload' => 'Upload',
|
||||
]];
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ return ['Billing' => [
|
|||
'Type' => 'Type',
|
||||
'Types' => 'Types',
|
||||
'Upload' => 'Upload',
|
||||
'Original' => 'Original',
|
||||
'Value' => 'Value',
|
||||
'Variation' => 'Variation',
|
||||
'Zip' => 'Zip',
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use phpOMS\Localization\ISO3166NameEnum;
|
||||
use phpOMS\Localization\ISO3166TwoEnum;
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
$bills = $this->getData('bills') ?? [];
|
||||
|
|
@ -126,7 +128,7 @@ echo $this->getData('nav')->render(); ?>
|
|||
<label>
|
||||
<i class="filter fa fa-filter"></i>
|
||||
</label>
|
||||
<td><?= $this->getHtml('Net'); ?>
|
||||
<td><?= $this->getHtml('Gross'); ?>
|
||||
<label for="billList-sort-7">
|
||||
<input type="radio" name="billList-sort" id="billList-sort-7">
|
||||
<i class="sort-asc fa fa-chevron-up"></i>
|
||||
|
|
@ -138,7 +140,7 @@ echo $this->getData('nav')->render(); ?>
|
|||
<label>
|
||||
<i class="filter fa fa-filter"></i>
|
||||
</label>
|
||||
<td><?= $this->getHtml('Created'); ?>
|
||||
<td><?= $this->getHtml('Date'); ?>
|
||||
<label for="billList-sort-23">
|
||||
<input type="radio" name="billList-sort" id="billList-sort-23">
|
||||
<i class="sort-asc fa fa-chevron-up"></i>
|
||||
|
|
@ -169,9 +171,13 @@ echo $this->getData('nav')->render(); ?>
|
|||
?>"><?= $value->billAddress; ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $value->billZip; ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $value->billCity; ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $value->billCountry; ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $value->netSales->getCurrency(); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $value->createdAt->format('Y-m-d'); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= !empty($value->billCountry)
|
||||
? ISO3166NameEnum::getByName(
|
||||
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 if ($count === 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",
|
||||
"description": "Module for Karaka.",
|
||||
"description": "Module for Jingga.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dennis Eichhorn",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user