diff --git a/Admin/Install/Media.php b/Admin/Install/Media.php index 0cdee03..503da26 100755 --- a/Admin/Install/Media.php +++ b/Admin/Install/Media.php @@ -14,7 +14,6 @@ declare(strict_types=1); namespace Modules\Billing\Admin\Install; -use Modules\Billing\Models\SettingsEnum; use phpOMS\Application\ApplicationAbstract; /** diff --git a/Admin/Install/Taxes/taxes.json b/Admin/Install/Taxes/taxes.json index 340a123..e83dac9 100644 --- a/Admin/Install/Taxes/taxes.json +++ b/Admin/Install/Taxes/taxes.json @@ -80,6 +80,13 @@ "tax_code": "DE_M19", "account": "8400" }, + { + "type": 1, + "item_code": "REDUCED", + "account_code": "DE", + "tax_code": "DE_M7", + "account": "8300" + }, { "type": 2, "item_code": "GENERAL", @@ -94,6 +101,20 @@ "tax_code": "SBIZ_0", "account": "8195" }, + { + "type": 2, + "item_code": "REDUCED", + "account_code": "DE", + "tax_code": "DE_V7", + "account": "3060" + }, + { + "type": 1, + "item_code": "REDUCED", + "account_code": "DE_S", + "tax_code": "SBIZ_0", + "account": "8195" + }, { "type": 2, "item_code": "GENERAL", diff --git a/Admin/Install/db.json b/Admin/Install/db.json index a927ec7..c6d51d5 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -10,14 +10,14 @@ "autoincrement": true }, "billing_payment_term_code": { - "description": "In days", + "comment": "In days", "name": "billing_payment_term_code", "type": "VARCHAR(100)", "null": false, "unique": true }, "billing_payment_term_due": { - "description": "In days", + "comment": "In days", "name": "billing_payment_term_due", "type": "INT", "null": false @@ -67,7 +67,7 @@ "autoincrement": true }, "billing_shipping_term_code": { - "description": "In days", + "comment": "In days", "name": "billing_shipping_term_code", "type": "VARCHAR(100)", "null": false, @@ -338,13 +338,13 @@ "foreignKey": "itemmgmt_attr_value_id" }, "billing_tax_code": { - "description": "tax abbr. code", + "comment": "tax abbr. code", "name": "billing_tax_code", "type": "VARCHAR(10)", "null": false }, "billing_tax_type": { - "description": "sales/purchase", + "comment": "sales/purchase", "name": "billing_tax_type", "type": "TINYINT", "null": false @@ -444,7 +444,7 @@ "null": false }, "billing_type_transfer_type": { - "description": "What kind of bill is it?", + "comment": "What kind of bill is it?", "name": "billing_type_transfer_type", "type": "TINYINT", "null": false @@ -458,25 +458,25 @@ "foreignKey": "media_id" }, "billing_type_transfer_stock": { - "description": "Does this bill type move stock?", + "comment": "Does this bill type move stock?", "name": "billing_type_transfer_stock", "type": "TINYINT(1)", "null": false }, "billing_type_accounting": { - "description": "Is this bill relevant for accounting", + "comment": "Is this bill relevant for accounting", "name": "billing_type_accounting", "type": "TINYINT(1)", "null": false }, "billing_type_sign": { - "description": "1 = from->to direction, -1 = to->from direction = credit note", + "comment": "1 = from->to direction, -1 = to->from direction = credit note", "name": "billing_type_sign", "type": "TINYINT(1)", "null": false }, "billing_type_email": { - "description": "send email on archive", + "comment": "send email on archive", "name": "billing_type_email", "type": "TINYINT(1)", "null": false @@ -487,7 +487,7 @@ "null": false }, "billing_type_is_template": { - "description": "What kind of bill is it?", + "comment": "What kind of bill is it?", "name": "billing_type_is_template", "type": "TINYINT(1)", "null": false @@ -834,35 +834,35 @@ "null": false }, "billing_bill_accsegment": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_accsegment", "type": "INT", "null": true, "default": null }, "billing_bill_accsection": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_accsection", "type": "INT", "null": true, "default": null }, "billing_bill_accgroup": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_accgroup", "type": "INT", "null": true, "default": null }, "billing_bill_acctype": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_acctype", "type": "INT", "null": true, "default": null }, "billing_bill_payment": { - "description": "should this handle the dues?", + "comment": "should this handle the dues?", "name": "billing_bill_payment", "type": "INT", "null": false @@ -911,7 +911,7 @@ } }, "billing_subscription": { - "description": "https://learn.microsoft.com/en-us/graph/outlook-schedule-recurring-events", + "comment": "https://learn.microsoft.com/en-us/graph/outlook-schedule-recurring-events", "name": "billing_subscription", "fields": { "billing_subscription_id": { @@ -1201,7 +1201,7 @@ "default": null }, "billing_bill_element_segment": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_element_segment", "type": "INT", "null": true, @@ -1210,7 +1210,7 @@ "foreignKey": "itemmgmt_attr_value_id" }, "billing_bill_element_section": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_element_section", "type": "INT", "null": true, @@ -1219,7 +1219,7 @@ "foreignKey": "itemmgmt_attr_value_id" }, "billing_bill_element_salesgroup": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_element_salesgroup", "type": "INT", "null": true, @@ -1228,7 +1228,7 @@ "foreignKey": "itemmgmt_attr_value_id" }, "billing_bill_element_productgroup": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_element_productgroup", "type": "INT", "null": true, @@ -1237,7 +1237,7 @@ "foreignKey": "itemmgmt_attr_value_id" }, "billing_bill_element_itemtype": { - "description": "attribute values", + "comment": "attribute values", "name": "billing_bill_element_itemtype", "type": "INT", "null": true, @@ -1323,13 +1323,13 @@ "null": false }, "billing_attr_type_required": { - "description": "Every item must have this attribute type if set to true.", + "comment": "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.", + "comment": "This is a regex validation pattern.", "name": "billing_attr_type_pattern", "type": "VARCHAR(255)", "null": false diff --git a/Admin/Installer.php b/Admin/Installer.php index 4cd261e..d169c1d 100755 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -208,6 +208,10 @@ final class Installer extends InstallerAbstract $module = $app->moduleManager->get('Billing', 'ApiAttribute'); foreach ($attributes as $attribute) { + if (!isset($attribute['values'])) { + continue; + } + $billAttrValue[$attribute['name']] = []; /** @var array $value */ diff --git a/Controller/ApiBillController.php b/Controller/ApiBillController.php index b404132..075e539 100755 --- a/Controller/ApiBillController.php +++ b/Controller/ApiBillController.php @@ -44,6 +44,7 @@ use Modules\Media\Models\NullCollection; use Modules\Media\Models\PathSettings; use Modules\Media\Models\UploadStatus; use Modules\Messages\Models\EmailMapper; +use Modules\Sales\Models\NullSalesRep; use Modules\SupplierManagement\Models\NullSupplier; use Modules\SupplierManagement\Models\Supplier; use Modules\SupplierManagement\Models\SupplierMapper; @@ -263,7 +264,14 @@ final class ApiBillController extends Controller // Create final pdf $this->apiBillPdfArchiveCreate($request, $response, $data); - $media = $response->getDataArray($request->uri->__toString())['response']; + $media = $response->getDataArray($request->uri->__toString())['response'] ?? null; + + if ($media === null) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $media); + + return; + } $this->app->eventManager->triggerSimilar('PRE:Module:' . self::NAME . '-bill-finalize', '', [ $request->header->account, @@ -469,7 +477,7 @@ final class ApiBillController extends Controller $bill->accSection = empty($temp = $bill->client->getAttribute('section')->value->id) ? null : $temp; $bill->accGroup = empty($temp = $bill->client->getAttribute('client_group')->value->id) ? null : $temp; $bill->accType = empty($temp = $bill->client->getAttribute('client_type')->value->id) ? null : $temp; - $bill->rep = $request->getDataInt('rep') ?? $account->rep; + $bill->rep = $request->hasData('rep') ? new NullSalesRep((int) $request->getData('rep')) : $account->rep; } else { $bill->supplier = $account; $bill->accTaxCode = empty($temp = $bill->supplier->getAttribute('purchase_tax_code')->value->id) ? null : $temp; @@ -1576,11 +1584,21 @@ final class ApiBillController extends Controller $this->app->moduleManager->get('Editor', 'Api')->apiEditorCreate($request, $response, $data); if ($response->header->status !== RequestStatusCode::R_200) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, null); + return; } /** @var \Modules\Editor\Models\EditorDoc $model */ - $model = $response->getDataArray($request->uri->__toString())['response']; + $model = $response->getDataArray($request->uri->__toString())['response'] ?? null; + if ($model === null) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $model); + + return; + } + $this->createModelRelation($request->header->account, $request->getDataInt('id'), $model->id, BillMapper::class, 'notes', '', $request->getOrigin()); } diff --git a/Controller/ApiPriceController.php b/Controller/ApiPriceController.php index 435bc45..0b2f1e1 100755 --- a/Controller/ApiPriceController.php +++ b/Controller/ApiPriceController.php @@ -79,11 +79,11 @@ final class ApiPriceController extends Controller 'price:' . $item->id . ':' . $client->id . ':' . $supplier->id . ':' . ($request->getDataInt('price_quantity') ?? '') ); - if (!empty($json)) { + if (!empty($json) && \is_array($json)) { $json['bestActualPrice'] = FloatInt::fromJson($json['bestActualPrice']); $json['discountPercent'] = FloatInt::fromJson($json['discountPercent']); - $json['discountAmount'] = FloatInt::fromJson($json['discountAmount']); - $json['bonus'] = FloatInt::fromJson($json['bonus']); + $json['discountAmount'] = FloatInt::fromJson($json['discountAmount']); + $json['bonus'] = FloatInt::fromJson($json['bonus']); return $json; } diff --git a/Controller/ApiPurchaseController.php b/Controller/ApiPurchaseController.php index 1fcf1e4..cdd85a3 100755 --- a/Controller/ApiPurchaseController.php +++ b/Controller/ApiPurchaseController.php @@ -159,8 +159,12 @@ final class ApiPurchaseController extends Controller $this->app->moduleManager->get('Billing', 'ApiBill')->apiBillCreate($billRequest, $billResponse, $data); - $billId = $billResponse->getDataArray('')['response']->id; - $bills[] = $billId; + $bill = $billResponse->getDataArray('')['response'] ?? null; + if ($bill === null) { + continue; + } + + $bills[] = $bill->id; // Upload and assign document to bill $mediaResponse = new HttpResponse(); @@ -177,14 +181,14 @@ final class ApiPurchaseController extends Controller $mediaRequest->setData('media', \json_encode($file)); } - $mediaRequest->setData('bill', $billId); + $mediaRequest->setData('bill', $bill->id); $mediaRequest->setData('tag', $tag->id); $mediaRequest->setData('parse_content', true, true); $this->app->moduleManager->get('Billing', 'ApiBill')->apiMediaAddToBill($mediaRequest, $mediaResponse, $data); if (\is_array($file)) { /** @var \Modules\Media\Models\Media[] $uploaded */ - $uploaded = $mediaResponse->getDataArray('')['response']['upload']; + $uploaded = $mediaResponse->getDataArray('')['response']['upload'] ?? []; if (empty($uploaded)) { return []; } @@ -195,8 +199,8 @@ final class ApiPurchaseController extends Controller } } - $request->setData('id', $billId, true); - $request->setData('bill', $billId, true); + $request->setData('id', $bill->id, true); + $request->setData('bill', $bill->id, true); $this->apiInvoiceParse($request, $response, $data); } diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 9a294ba..758fc0a 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -256,6 +256,16 @@ final class BackendController extends Controller ->where('l11n/language', $request->header->l11n->language) ->executeGetArray(); + $view->data['paymentterms'] = PaymentTermMapper::getAll() + ->with('l11n') + ->where('l11n/language', $request->header->l11n->language) + ->executeGetArray(); + + $view->data['shippingterms'] = ShippingTermMapper::getAll() + ->with('l11n') + ->where('l11n/language', $request->header->l11n->language) + ->executeGetArray(); + $logs = []; if ($this->app->accountManager->get($request->header->account)->hasPermission( PermissionType::READ, diff --git a/Controller/CliController.php b/Controller/CliController.php index 23b03e7..0ad2d65 100755 --- a/Controller/CliController.php +++ b/Controller/CliController.php @@ -20,7 +20,7 @@ use Modules\Billing\Models\BillMapper; use Modules\Billing\Models\BillTypeMapper; use Modules\Billing\Models\InvoiceRecognition; use Modules\Billing\Models\NullBillType; -use Modules\Billing\Models\SettingsEnum; +use Modules\ItemManagement\Models\NullItem; use Modules\Payment\Models\PaymentType; use Modules\SupplierManagement\Models\NullSupplier; use Modules\SupplierManagement\Models\Supplier; @@ -325,7 +325,7 @@ final class CliController extends Controller $internalResponse->header->l11n->language = $bill->language; $this->app->moduleManager->get('ItemManagement', 'Api')->apiItemFind($internalRequest, $internalResponse); - $item = $internalResponse->getDataArray('')[0]; + $item = $internalResponse->getDataArray('')[0] ?? new NullItem(); $billElement->itemName = $key; diff --git a/Docs/Dev/en/structure.md b/Docs/Dev/en/structure.md deleted file mode 100755 index c408307..0000000 --- a/Docs/Dev/en/structure.md +++ /dev/null @@ -1,5 +0,0 @@ -# Structure - -## ER - -![ER](Modules/Billing/Docs/Dev/img/er.png) \ No newline at end of file diff --git a/Docs/Dev/img/er.png b/Docs/Dev/img/er.png deleted file mode 100644 index d076e15..0000000 Binary files a/Docs/Dev/img/er.png and /dev/null differ diff --git a/Docs/Help/en/SUMMARY.md b/Docs/Help/en/SUMMARY.md new file mode 100644 index 0000000..40ade73 --- /dev/null +++ b/Docs/Help/en/SUMMARY.md @@ -0,0 +1,5 @@ +# User Content + +* [Bill]({%}&page=Help/bill) +* [Bill Types]({%}&page=Help/bill_types) +* [Taxes]({%}&page=Help/taxes) diff --git a/Docs/Help/en/bill.md b/Docs/Help/en/bill.md new file mode 100644 index 0000000..4625f40 --- /dev/null +++ b/Docs/Help/en/bill.md @@ -0,0 +1,37 @@ +# Bill + +## General + +In the overview of the bill you can define the general bill information. + +![Bill settings](Modules/Billing/Docs/Help/img/bill/bill_invoice_general.png) + +In the overview of the bill you can define the general terms. + +![Bill settings](Modules/Billing/Docs/Help/img/bill/bill_invoice_terms.png) + +You can also select stored billing and delivery addresses from the client or supplier. Additionally, you can also create a custom billing or delivery address. + +![Bill address](Modules/Billing/Docs/Help/img/bill/bill_invoice_billing_address.png) + +## Items + +In the items tab you can add and modify items in the bill. + +Depending on the settings you can select existing items by number or name or create custom invoice elements. + +Prices, discounts and taxes are automatically calculated based on the information stored in the items, tax codes, clients and suppliers. You can overwrite these information at your own digression. + +![Bill items](Modules/Billing/Docs/Help/img/bill/bill_element_list.png) + +## Preview + +In the preview tab you can preview the finished invoice. You can also change the invoice type in the preview. + +## Archive + +This tab only appears once the invoice is created and saved. This shows how the invoice is saved in the system. + +## Files + +If you want to add files to the invoice you can do this in the Files tab. \ No newline at end of file diff --git a/Docs/Help/en/bill_types.md b/Docs/Help/en/bill_types.md new file mode 100644 index 0000000..5e90258 --- /dev/null +++ b/Docs/Help/en/bill_types.md @@ -0,0 +1,38 @@ +# Bill Types + +The Billing module provides various default bill types that can be used directly after the installation. + +## Sales + +| Name | Effects stock | Accounting relevant | +| ------------------ | ------------- | ------------------- | +| Offer | No | No | +| Order Confirmation | No | No | +| Delivery Note | Yes | No | +| Invoice | No | Yes | +| Proforma Invoice | No | No | +| Credit Note | No | Yes | +| Reverse Invoice | No | Yes | +| Subscription | No | Yes | + +## Purchase + +| Name | Effects stock | Accounting relevant | +| ------------------ | ------------- | ------------------- | +| Offer | No | No | +| Order | No | No | +| Order Confirmation | No | No | +| Delivery Note | Yes | No | +| Invoice | No | Yes | +| Proforma Invoice | No | No | +| Credit Note | No | Yes | +| Reverse Invoice | No | Yes | +| Subscription | No | Yes | + +## Warehouse + +| Name | Effects stock | Accounting relevant | +| -------------- | ------------- | ------------------- | +| Stock Movement | Yes | No | +| Stock Decrease | Yes | No | +| Stock Increase | Yes | No | diff --git a/Docs/Help/en/introduction.md b/Docs/Help/en/introduction.md new file mode 100644 index 0000000..879406b --- /dev/null +++ b/Docs/Help/en/introduction.md @@ -0,0 +1,37 @@ +# Introduction + +The **Billing** module is essential for writing and managing invoices either from a sales or procurement perspective. + +## Target Group + +The target group for this module is the sales and purchase department. + +# Setup + +This module doesn't have any additional setup requirements. + +# Features + +## Payment Terms + +Multiple payment terms to indicate when a invoice becomes due. + +## Shipping Terms + +Multiple shipping terms to indicate how the goods on the invoice are shipped. + +### Billing Types + +Different billing types such as: + +* Invoice +* Delivery note +* Order confirmation +* Offer +* ... more + +# Recommendation + +Other modules that work great with this one together are: + +* [SalesAnalysis]({/}?id=SalesAnalysis) \ No newline at end of file diff --git a/Docs/Help/en/taxes.md b/Docs/Help/en/taxes.md new file mode 100644 index 0000000..e82b81d --- /dev/null +++ b/Docs/Help/en/taxes.md @@ -0,0 +1,79 @@ +# Taxes + +Taxes for cusstomers/suppliers and items are automatically calculated based on specific indicators/tax codes that always work in combination with each other. Visually you can think about it as a matrix where both customer/supplier indicator and item tax code result in the respective taxes. + +**Visualization** + +| | Item sales_tax_code 1 | Item sales_tax_code 2 | Item sales_tax_code 2 | +| ----------------------- | --------------------- | --------------------- | --------------------- | +| Client sales_tax_code 1 | 19 % (domestic) | 7 % (domestic) | 19 % (domestic) | +| Client sales_tax_code 2 | 0 % (intra-community) | 0 % (intra-community) | 0 % (intra-community) | +| Client sales_tax_code 2 | 0 % (third country) | 0 % (third country) | 0 % (third country) | + +These indicators/tax codes are completely custom and you can define them as you see fit. + +## Items + +Every item that you want to sell must have an attribute set called **Sales tax code** (`sales_tax_code`). + +Every item that you want to purchase must have an attribute set called **Purchase tax code** (`purchase_tax_code`). + +You can define these attributes when viewing a item. For more details please refer to the [Item Management]({/}?id=ItemManagement) documentation. + +By default the Item Management module has already defined some sales and purchase tax codes that you can use. Of course you can create additional sales and purchase tax codes as you see fit. + +## Clients + +Every client/customer that you want to create invoices for must have an attribute set called **Sales tax code** (`sales_tax_code`). You can define this attribute when viewing a client. For more details please refer to the [Client Management]({/}?id=ClientManagement) documentation. + +By default the Client Management module has already defined some sales tax codes that you can use. Of course you can create additional sales tax codes as you see fit. However, the default tax codes should be already sufficient to handle your use cases. + +### Germany + +Most German companies only need `DE` for domestic sales, `INT` for third country sales, `EU` for intra-community sales (B2B). + +Most small businesses only need `DE_S` for domestic sales, `INT` for third country sales, `EU_S` for intra-community sales (B2B). + +## Suppliers + +Every supplier that you want to create invoices for must have an attribute set called **Purchase tax code** (`purchase_tax_code`). You can define this attribute when viewing a supplier. For more details please refer to the [Supplier Management]({/}?id=SupplierManagement) documentation. + +By default the Supplier Management module has already defined some purchase tax codes that you can use. Of course you can create additional purchase tax codes as you see fit. + +## Tax Codes + +Tax codes define a single code that specifies how high the taxes are. These tax codes can also be used in accounting when creating a new entry and are therefore managed by the Finance module. + +For more details please refer to the [Finance]({/}?id=Finance) module. + +## Tax Combinations + +After you defined the item sales/purchase tax code and client/purchase tax code you have to create the possible combinations that can occur. The tax combinations can be viewed and edited under `Finance >> Tax Combinations` + +![Tax combination](Modules/Billing/Docs/Help/img/taxes/taxes_combination.png) + +**Example visual representation** + +The following example still follows the same structure as mentioned in the beginning but filled with actual values. + +| | GENERAL | REDUCED | SERVICE | +| --- | ------------------ | ---------------- | ------------------ | +| DE | DE_M19 (= 19% tax) | DE_M7 (= 7% tax) | DE_M19 (= 19% tax) | +| EU | EU_S0 (= 0% tax) | EU_S0 (= 0% tax) | EU_S0 (= 0% tax) | +| INT | S0 (= 0% tax) | S0 (= 0% tax) | S0 (= 0% tax) | + +> Please note that despite effectively the equal tax amount (0 %) for EU and INT you probably have to use different tax codes due to your local tax laws and accounting practices. + +> Sales and purchase combinations are separate, which means if you want to sell and purchase an item you will have to create at least one combination using sales tax codes and one using purchase tax codes. + +### Actual combination + +![Tax combinations](Modules/Billing/Docs/Help/img/taxes/taxes_combinations.png) + +## Steps + +1. Create additional item sales tax codes and purchase tax codes in the Item Management module as you see fit. +2. Create additional sales tax codes in the Client Management module as you see fit. +3. Create additional purchase tax codes in the Supplier Management module as you see fit. +4. Create additional tax codes if necessary in the Finance module. +5. Create additional tax code combinations in the Finance module as you see fit diff --git a/Docs/Help/img/bill/bill_element_list.png b/Docs/Help/img/bill/bill_element_list.png new file mode 100644 index 0000000..9a4c14f Binary files /dev/null and b/Docs/Help/img/bill/bill_element_list.png differ diff --git a/Docs/Help/img/bill/bill_invoice_billing_address.png b/Docs/Help/img/bill/bill_invoice_billing_address.png new file mode 100644 index 0000000..e3465d6 Binary files /dev/null and b/Docs/Help/img/bill/bill_invoice_billing_address.png differ diff --git a/Docs/Help/img/bill/bill_invoice_delivery_address.png b/Docs/Help/img/bill/bill_invoice_delivery_address.png new file mode 100644 index 0000000..30f27f4 Binary files /dev/null and b/Docs/Help/img/bill/bill_invoice_delivery_address.png differ diff --git a/Docs/Help/img/bill/bill_invoice_general.png b/Docs/Help/img/bill/bill_invoice_general.png new file mode 100644 index 0000000..c30ba65 Binary files /dev/null and b/Docs/Help/img/bill/bill_invoice_general.png differ diff --git a/Docs/Help/img/bill/bill_invoice_terms.png b/Docs/Help/img/bill/bill_invoice_terms.png new file mode 100644 index 0000000..1375c93 Binary files /dev/null and b/Docs/Help/img/bill/bill_invoice_terms.png differ diff --git a/Docs/Help/img/taxes/taxes_combination.png b/Docs/Help/img/taxes/taxes_combination.png new file mode 100644 index 0000000..5757dec Binary files /dev/null and b/Docs/Help/img/taxes/taxes_combination.png differ diff --git a/Docs/Help/img/taxes/taxes_combinations.png b/Docs/Help/img/taxes/taxes_combinations.png new file mode 100644 index 0000000..eb1b3bf Binary files /dev/null and b/Docs/Help/img/taxes/taxes_combinations.png differ diff --git a/Docs/img.json b/Docs/img.json new file mode 100644 index 0000000..98bbabe --- /dev/null +++ b/Docs/img.json @@ -0,0 +1,38 @@ +[ + [ + "/finance/tax/combination/list", + "//*[@id=\"content\"]/div[2]/div/section/table/tbody/tr[1]", + "/Billing/Docs/Help/img/taxes/taxes_combinations.png" + ], + [ + "/finance/tax/combination/view?id=1", + "//*[@id=\"content\"]/div[2]/div/section", + "/Billing/Docs/Help/img/taxes/taxes_combination.png" + ], + + [ + "/sales/bill/view?id=1", + "//*[@id=\"content\"]/div[2]/div[2]/div[1]/div/div[1]/section", + "/Billing/Docs/Help/img/bill/bill_invoice_general.png" + ], + [ + "/sales/bill/view?id=1", + "//*[@id=\"content\"]//div[2]/div[2]/div[1]/div/div[1]/section[2]", + "/Billing/Docs/Help/img/bill/bill_invoice_terms.png" + ], + [ + "/sales/bill/view?id=1", + "//*[@id=\"content\"]/div[2]/div[2]/div[1]/div/div[2]/section", + "/Billing/Docs/Help/img/bill/bill_invoice_billing_address.png" + ], + [ + "/sales/bill/view?id=1", + "//*[@id=\"content\"]/div[2]/div[2]/div[1]/div/div[3]/section", + "/Billing/Docs/Help/img/bill/bill_invoice_delivery_address.png" + ], + [ + "/sales/bill/view?id=1#c-tab-2", + "//*[@id=\"content\"]/div[2]/div[2]/div[2]/div/div/section", + "/Billing/Docs/Help/img/bill/bill_element_list.png" + ] +] \ No newline at end of file diff --git a/Models/Bill.php b/Models/Bill.php index 889a5ac..5f9b7b5 100755 --- a/Models/Bill.php +++ b/Models/Bill.php @@ -19,6 +19,7 @@ use Modules\Admin\Models\NullAccount; use Modules\ClientManagement\Models\Client; use Modules\Sales\Models\SalesRep; use Modules\SupplierManagement\Models\Supplier; +use phpOMS\Localization\BaseStringL11nType; use phpOMS\Localization\ISO4217CharEnum; use phpOMS\Localization\ISO639x1Enum; use phpOMS\Stdlib\Base\FloatInt; @@ -354,9 +355,9 @@ class Bill implements \JsonSerializable */ public int $terms = 0; - public ?int $paymentTerms = null; + public ?BaseStringL11nType $paymentTerms = null; - public ?int $shippingTerms = null; + public ?BaseStringL11nType $shippingTerms = null; /** * Terms text. diff --git a/Models/BillMapper.php b/Models/BillMapper.php index 9f6997a..1c7b443 100755 --- a/Models/BillMapper.php +++ b/Models/BillMapper.php @@ -76,7 +76,7 @@ class BillMapper extends DataMapperFactory 'billing_bill_netdiscount' => ['name' => 'billing_bill_netdiscount', 'type' => 'Serializable', 'internal' => 'netDiscount'], 'billing_bill_taxp' => ['name' => 'billing_bill_taxp', 'type' => 'Serializable', 'internal' => 'taxP'], 'billing_bill_fiaccount' => ['name' => 'billing_bill_fiaccount', 'type' => 'string', 'internal' => 'fiAccount'], - 'billing_bill_rep' => ['name' => 'billing_bill_rep', 'type' => 'int', 'internal' => 'rep'], + 'billing_bill_rep' => ['name' => 'billing_bill_rep', 'type' => 'int', 'internal' => 'rep'], 'billing_bill_currency' => ['name' => 'billing_bill_currency', 'type' => 'string', 'internal' => 'currency'], 'billing_bill_language' => ['name' => 'billing_bill_language', 'type' => 'string', 'internal' => 'language'], 'billing_bill_referral' => ['name' => 'billing_bill_referral', 'type' => 'int', 'internal' => 'referral'], @@ -127,6 +127,12 @@ class BillMapper extends DataMapperFactory 'external' => 'billing_bill_note_doc', 'self' => 'billing_bill_note_bill', ], + 'attributes' => [ + 'mapper' => BillAttributeMapper::class, + 'table' => 'billing_bill_attr', + 'self' => 'billing_bill_attr_bill', + 'external' => null, + ], ]; /** @@ -148,6 +154,14 @@ class BillMapper extends DataMapperFactory 'mapper' => SalesRepMapper::class, 'external' => 'billing_bill_rep', ], + 'paymentTerms' => [ + 'mapper' => PaymentTermMapper::class, + 'external' => 'billing_bill_paymentterms', + ], + 'shippingTerms' => [ + 'mapper' => ShippingTermMapper::class, + 'external' => 'shippingTerms', + ], ]; /** @@ -168,14 +182,7 @@ class BillMapper extends DataMapperFactory 'supplier' => [ 'mapper' => SupplierMapper::class, 'external' => 'billing_bill_supplier', - ], - 'attributes' => [ - 'mapper' => BillAttributeMapper::class, - 'table' => 'billing_bill_attr', - 'self' => 'billing_bill_attr_bill', - 'conditional' => true, - 'external' => null, - ], + ] ]; /** diff --git a/Models/BillTypeMapper.php b/Models/BillTypeMapper.php index 46a348c..67cee1c 100755 --- a/Models/BillTypeMapper.php +++ b/Models/BillTypeMapper.php @@ -45,7 +45,7 @@ final class BillTypeMapper extends DataMapperFactory '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_accounting' => ['name' => 'billing_type_accounting', 'type' => 'bool', 'internal' => 'isAccounting'], - 'billing_type_sign' => ['name' => 'billing_type_sign', 'type' => 'int', 'internal' => 'sign'], + 'billing_type_sign' => ['name' => 'billing_type_sign', 'type' => 'int', 'internal' => 'sign'], 'billing_type_email' => ['name' => 'billing_type_email', 'type' => 'bool', 'internal' => 'email'], 'billing_type_is_template' => ['name' => 'billing_type_is_template', 'type' => 'bool', 'internal' => 'isTemplate'], ]; diff --git a/Models/PurchaseBillMapper.php b/Models/PurchaseBillMapper.php index 335055b..e7c9947 100755 --- a/Models/PurchaseBillMapper.php +++ b/Models/PurchaseBillMapper.php @@ -26,6 +26,9 @@ use phpOMS\Stdlib\Base\FloatInt; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @template T of Bill + * @extends BillMapper */ final class PurchaseBillMapper extends BillMapper { @@ -212,7 +215,7 @@ final class PurchaseBillMapper extends BillMapper $query->orderBy(self::TABLE . '_d1.' . self::COLUMNS[self::PRIMARYFIELD]['name'], 'DESC'); } - return self::getAll()->execute($query); + return self::getAll()->executeGetArray($query); } /** @@ -231,7 +234,7 @@ final class PurchaseBillMapper extends BillMapper $query->orderBy(self::TABLE . '_d1.' . self::COLUMNS[self::PRIMARYFIELD]['name'], 'DESC'); } - return self::getAll()->execute($query); + return self::getAll()->executeGetArray($query); } /** diff --git a/Models/SalesBillMapper.php b/Models/SalesBillMapper.php index 4b66001..54583ac 100755 --- a/Models/SalesBillMapper.php +++ b/Models/SalesBillMapper.php @@ -26,6 +26,9 @@ use phpOMS\Stdlib\Base\FloatInt; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @template T of Bill + * @extends BillMapper */ final class SalesBillMapper extends BillMapper { @@ -226,7 +229,7 @@ final class SalesBillMapper extends BillMapper $query->orderBy(self::TABLE . '_d1.' . self::COLUMNS[self::PRIMARYFIELD]['name'], 'DESC'); } - return self::getAll()->execute($query); + return self::getAll()->executeGetArray($query); } /** @@ -246,7 +249,7 @@ final class SalesBillMapper extends BillMapper $query->orderBy(self::TABLE . '_d1.' . self::COLUMNS[self::PRIMARYFIELD]['name'], 'DESC'); } - return self::getAll()->execute($query); + return self::getAll()->executeGetArray($query); } /** @@ -318,7 +321,7 @@ final class SalesBillMapper extends BillMapper ->with('type/l11n') ->sort('id', OrderType::DESC) ->limit($limit) - ->execute($query); + ->executeGetArray($query); } /** diff --git a/Models/StockBillMapper.php b/Models/StockBillMapper.php index 4354417..7ce3e43 100755 --- a/Models/StockBillMapper.php +++ b/Models/StockBillMapper.php @@ -23,6 +23,9 @@ use phpOMS\DataStorage\Database\Query\Builder; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @template T of Bill + * @extends BillMapper */ final class StockBillMapper extends BillMapper { diff --git a/Theme/Backend/Lang/Navigation.de.lang.php b/Theme/Backend/Lang/Navigation.de.lang.php index c7a4b08..39ac363 100755 --- a/Theme/Backend/Lang/Navigation.de.lang.php +++ b/Theme/Backend/Lang/Navigation.de.lang.php @@ -21,5 +21,5 @@ return ['Navigation' => [ 'Upload' => 'Hochladen', 'PaymentTerms' => 'Zahlungsbedingungen', 'ShippingTerms' => 'Lieferbedingungen', - 'TaxCombinations' => 'Tax Combinations', + 'TaxCombinations' => 'Tax Combinations', ]]; diff --git a/Theme/Backend/Lang/Navigation.en.lang.php b/Theme/Backend/Lang/Navigation.en.lang.php index 1d0eff6..27abb42 100755 --- a/Theme/Backend/Lang/Navigation.en.lang.php +++ b/Theme/Backend/Lang/Navigation.en.lang.php @@ -21,5 +21,5 @@ return ['Navigation' => [ 'Upload' => 'Upload', 'PaymentTerms' => 'Payment Terms', 'ShippingTerms' => 'Shipping Terms', - 'TaxCombinations' => 'Tax Combinations', + 'TaxCombinations' => 'Tax Combinations', ]]; diff --git a/Theme/Backend/Lang/de.lang.php b/Theme/Backend/Lang/de.lang.php index b75dc73..9060259 100755 --- a/Theme/Backend/Lang/de.lang.php +++ b/Theme/Backend/Lang/de.lang.php @@ -15,7 +15,10 @@ declare(strict_types=1); return ['Billing' => [ 'Address' => 'Adresse', 'Addresses' => 'Adressen', + 'General' => 'Allgemein', 'AlreadyPaid' => 'Bereits bezahlt', + 'Shipping' => 'Lieferung', + 'Terms' => 'Lieferbedingungen', 'Amount' => 'Betrag', 'Archive' => 'Archiev', 'Internal' => 'Intern', @@ -59,7 +62,6 @@ return ['Billing' => [ 'Original' => 'Original', 'Payment' => 'Zahlung', 'PaymentPlan' => 'Zahlungsplan', - 'Postal' => 'Post', 'Prepaid' => 'Vorausbezahlt', 'Preview' => 'Vorschau', 'Price' => 'Preis', @@ -79,7 +81,7 @@ return ['Billing' => [ 'Type' => 'Typ', 'Types' => 'Typen', 'Upload' => 'Hochladen', - 'Postal' => 'Postal', + 'Postal' => 'Postleitzahl', 'Files' => 'Files', 'TaxCode' => 'Steuerkz.', 'PL' => 'GuV', diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index e34f8b8..ee1780e 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -15,9 +15,12 @@ declare(strict_types=1); return ['Billing' => [ 'Address' => 'Address', 'Addresses' => 'Addresses', + 'General' => 'General', 'AlreadyPaid' => 'Already Paid', 'Amount' => 'Amount', 'Archive' => 'Archive', + 'Shipping' => 'Shipping', + 'Terms' => 'Terms', 'Internal' => 'Internal', 'Error' => 'Error', 'Billing' => 'Billing', @@ -79,7 +82,6 @@ return ['Billing' => [ 'Type' => 'Type', 'Types' => 'Types', 'Upload' => 'Upload', - 'Postal' => 'Postal', 'Files' => 'Files', 'TaxCode' => 'Tax Code', 'PL' => 'PL', diff --git a/Theme/Backend/bill-create.tpl.php b/Theme/Backend/bill-create.tpl.php index 7d1a338..c88342c 100755 --- a/Theme/Backend/bill-create.tpl.php +++ b/Theme/Backend/bill-create.tpl.php @@ -34,7 +34,9 @@ $media = $this->data['media'] ?? []; $bill = $this->getData('bill') ?? new NullBill(); $elements = $bill->elements; -$billTypes = $this->data['billtypes'] ?? []; +$billTypes = $this->data['billtypes'] ?? []; +$paymentTerms = $this->data['paymentterms'] ?? []; +$shippingTerms = $this->data['shippingterms'] ?? []; $archive = $bill->getFileByTagName('internal_bill'); @@ -75,10 +77,10 @@ echo $this->data['nav']->render(); ?> -
+
@@ -163,26 +165,6 @@ echo $this->data['nav']->render(); ?> >
- -
- - > -
- -
- - -
- -
- - -
@@ -191,6 +173,42 @@ echo $this->data['nav']->render(); ?> + +
+
getHtml('Terms'); ?>
+
+
+ + +
+ +
+ + > +
+ +
+ + +
+ +
+ + +
+
+
diff --git a/info.json b/info.json index 7f83ac7..56ba1c9 100755 --- a/info.json +++ b/info.json @@ -12,7 +12,7 @@ }, "creator": { "name": "Jingga", - "website": "jingga.app" + "website": "https://jingga.app" }, "directory": "Billing", "dependencies": {