fix demoSetup

This commit is contained in:
Dennis Eichhorn 2023-04-16 01:55:34 +02:00
parent ac6b22c47f
commit 9c5db3832e
20 changed files with 462 additions and 100 deletions

View File

@ -14,8 +14,6 @@ declare(strict_types=1);
namespace Modules\Billing\Admin\Install;
use Model\Setting;
use Model\SettingMapper;
use Modules\Billing\Models\SettingsEnum;
use phpOMS\Application\ApplicationAbstract;
@ -43,29 +41,26 @@ class Media
{
$media = \Modules\Media\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Media.install.json']);
$preivewType = (int) \reset($media['type'][0]);
$originalType = (int) \reset($media['type'][1]);
$setting = new Setting();
SettingMapper::create()->execute(
$setting->with(
0,
SettingsEnum::PREVIEW_MEDIA_TYPE,
(string) $preivewType,
'\\d+',
module: 'Billing'
)
);
$setting = new Setting();
SettingMapper::create()->execute(
$setting->with(
0,
SettingsEnum::ORIGINAL_MEDIA_TYPE,
(string) $originalType,
'\\d+',
module: 'Billing'
)
\Modules\Admin\Admin\Installer::installExternal(
$app,
[
'data' => [
[
'type' => 'setting',
'name' => SettingsEnum::PREVIEW_MEDIA_TYPE,
'content' => (string) $media['type'][0]['id'],
'pattern' => '\\d+',
'module' => 'Billing'
],
[
'type' => 'setting',
'name' => SettingsEnum::ORIGINAL_MEDIA_TYPE,
'content' => (string) $media['type'][1]['id'],
'pattern' => '\\d+',
'module' => 'Billing'
]
]
]
);
}
}

View File

@ -388,6 +388,15 @@
"primary": true,
"autoincrement": true
},
"billing_bill_sequence": {
"name": "billing_bill_sequence",
"type": "INT",
"null": false,
"multi_autoincrement": [
"billing_bill_unit",
"billing_bill_type"
]
},
"billing_bill_number": {
"name": "billing_bill_number",
"type": "VARCHAR(255)",
@ -664,6 +673,80 @@
"type": "VARCHAR(255)",
"default": null,
"null": true
},
"billing_bill_unit": {
"name": "billing_bill_unit",
"type": "INT",
"null": false,
"foreignTable": "unit",
"foreignKey": "unit_id"
}
}
},
"billing_subscription": {
"description": "https://learn.microsoft.com/en-us/graph/outlook-schedule-recurring-events",
"name": "billing_subscription",
"fields": {
"billing_subscription_id": {
"name": "billing_subscription_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"billing_subscription_status": {
"name": "billing_subscription_status",
"type": "TINYINT(1)",
"null": false
},
"billing_subscription_start": {
"name": "billing_subscription_start",
"type": "DATETIME",
"null": false
},
"billing_subscription_end": {
"name": "billing_subscription_end",
"type": "DATETIME",
"null": true,
"default": null
},
"billing_subscription_price": {
"name": "billing_subscription_price",
"type": "BIGINT",
"null": false
},
"billing_subscription_quantity": {
"name": "billing_subscription_quantity",
"type": "BIGINT",
"null": false
},
"billing_subscription_bill": {
"name": "billing_subscription_bill",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "billing_bill",
"foreignKey": "billing_bill_id"
},
"billing_subscription_item": {
"name": "billing_subscription_item",
"type": "INT",
"null": false,
"foreignTable": "itemmgmt_item",
"foreignKey": "itemmgmt_item_id"
},
"billing_subscription_autorenew": {
"name": "billing_subscription_autorenew",
"type": "TINYINT(1)",
"null": false
},
"billing_subscription_client": {
"name": "billing_subscription_client",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "clientmgmt_client",
"foreignKey": "clientmgmt_client_id"
}
}
},
@ -686,7 +769,17 @@
"name": "billing_bill_element_item",
"type": "INT",
"null": true,
"default": null
"default": null,
"foreignTable": "itemmgmt_item",
"foreignKey": "itemmgmt_item_id"
},
"billing_bill_element_subscription": {
"name": "billing_bill_element_subscription",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "billing_subscription",
"foreignKey": "billing_subscription_id"
},
"billing_bill_element_item_segment": {
"name": "billing_bill_element_item_segment",
@ -1184,46 +1277,6 @@
}
}
},
"billing_bill_subscription": {
"description": "https://learn.microsoft.com/en-us/graph/outlook-schedule-recurring-events",
"name": "billing_bill_subscription",
"fields": {
"billing_bill_subscription_id": {
"name": "billing_bill_subscription_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"billing_bill_subscription_status": {
"name": "billing_bill_subscription_status",
"type": "TINYINT(1)",
"null": false
},
"billing_bill_subscription_bill": {
"name": "billing_bill_subscription_bill",
"type": "INT",
"null": false,
"foreignTable": "billing_bill",
"foreignKey": "billing_bill_id"
},
"billing_bill_subscription_schedule": {
"name": "billing_bill_subscription_schedule",
"type": "INT",
"null": false,
"foreignTable": "schedule",
"foreignKey": "schedule_id"
},
"billing_bill_subscription_account": {
"name": "billing_bill_subscription_account",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "account",
"foreignKey": "account_id"
}
}
},
"billing_bill_responsible": {
"name": "billing_bill_responsible",
"fields": {

View File

@ -0,0 +1,11 @@
CREATE TRIGGER update_billing_bill_sequence
BEFORE INSERT ON billing_bill
FOR EACH ROW BEGIN
SET NEW.billing_bill_sequence = (
SELECT COALESCE(MAX(billing_bill_sequence), 0) + 1
FROM billing_bill
WHERE billing_bill_unit = NEW.billing_bill_unit
AND billing_bill_type = NEW.billing_bill_type
LIMIT 1
);
END;

16
Admin/Install/db.psql.sql Normal file
View File

@ -0,0 +1,16 @@
CREATE SEQUENCE billing_bill_sequence;
CREATE OR REPLACE FUNCTION update_billing_bill_sequence()
RETURNS TRIGGER AS
$$
BEGIN
NEW.billing_bill_sequence = nextval('billing_bill_sequence') WHERE billing_bill_unit = NEW.billing_bill_unit;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER update_sequence_trigger
BEFORE INSERT ON billing_bill
FOR EACH ROW
EXECUTE FUNCTION update_billing_bill_sequence();

View File

@ -17,6 +17,7 @@ namespace Modules\Billing\Admin;
use Modules\Attribute\Models\AttributeTypeMapper;
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;
@ -258,8 +259,8 @@ final class Installer extends InstallerAbstract
/** @var \Modules\Billing\Controller\ApiController $module */
$module = $app->moduleManager->getModuleInstance('Billing');
/** @var \Modules\Attribute\Models\AttributeType $AttributeSales */
$AttributeSales = AttributeTypeMapper::get()
/** @var \Modules\Attribute\Models\ItemAttributeTypeMapper $itemAttributeSales */
$itemAttributeSales = ItemAttributeTypeMapper::get()
->with('defaults')
->where('name', 'sales_tax_code')
->execute();
@ -277,7 +278,7 @@ final class Installer extends InstallerAbstract
->execute();
foreach ($taxes as $tax) {
$itemValue = $AttributeSales->getDefaultByValue($tax['item_code']);
$itemValue = $itemAttributeSales->getDefaultByValue($tax['item_code']);
$accountValue = $tax['type'] === 1
? $clientAttributeSales->getDefaultByValue($tax['account_code'])
: $supplierAttributeSales->getDefaultByValue($tax['account_code']);

View File

@ -168,6 +168,15 @@ final class ApiBillController extends Controller
{
$this->createModel($request->header->account, $bill, BillMapper::class, 'bill', $request->getOrigin());
// We ned to get the bill again since the bill has a trigger which is executed on insert
// @todo: consider to remove the trigger and select the latest bill here and add + 1 to the new sequence since we have to tdo an update anyways
/** @var Bill $bill */
$tmp = BillMapper::get()
->where('id', $bill->getId())
->execute();
$bill->sequence = $tmp->sequence;
$old = clone $bill;
$bill->buildNumber(); // The bill id is part of the number
$this->updateModel($request->header->account, $old, $bill, BillMapper::class, 'bill', $request->getOrigin());
@ -194,6 +203,7 @@ final class ApiBillController extends Controller
// @todo: validate vat before creation
$bill = new Bill();
$bill->createdBy = new NullAccount($request->header->account);
$bill->unit = $client->unit ?? $this->app->unitId;
$bill->billDate = new \DateTime('now'); // @todo: Date of payment
$bill->performanceDate = new \DateTime('now'); // @todo: Date of payment
$bill->accountNumber = $client->number;
@ -279,8 +289,12 @@ final class ApiBillController extends Controller
{
$taxCode = $this->app->moduleManager->get('Billing', 'ApiTax')->getTaxCodeFromClientItem($client, $item, $request->getCountry());
$element = BillElement::fromItem($item, $taxCode, $request->getDataInt('quantity') ?? 1);
$element->bill = $request->getDataInt('bill') ?? 0;
$element = BillElement::fromItem(
$item,
$taxCode,
$request->getDataInt('quantity') ?? 1,
$bill->getId()
);
return $element;
}
@ -327,6 +341,7 @@ final class ApiBillController extends Controller
// @todo: use defaultInvoiceAddress or mainAddress. also consider to use billto1, billto2, billto3 (for multiple lines e.g. name2, fao etc.)
/** @var \Modules\SupplierManagement\Models\Supplier|\Modules\ClientManagement\Models\Client $account */
$bill = new Bill();
$bill->unit = $account->unit ?? $this->app->unitId;
$bill->createdBy = new NullAccount($request->header->account);
$bill->type = $billType;
$bill->billTo = $request->getDataString('billto') ?? (

View File

@ -54,10 +54,10 @@ final class ApiPurchaseController extends Controller
*/
public function apiSupplierBillUpload(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
{
$originalType = $request->getDataInt('type') ?? (int) $this->app->appSettings->get(
$originalType = $request->getDataInt('type') ?? ((int) $this->app->appSettings->get(
names: SettingsEnum::ORIGINAL_MEDIA_TYPE,
module: self::NAME
)->content;
)->content);
/** @var \Modules\Billing\Models\BillType $purchaseTransferType */
$purchaseTransferType = BillTypeMapper::get()

View File

@ -128,11 +128,11 @@ final class BackendController extends Controller
/** @var \Modules\Auditor\Models\Auditor[] $logsBill */
$logsBill = AuditMapper::getAll()
->with('createdBy')
->where('module', 'Billing')
->where('type', StringUtils::intHash(BillMapper::class))
->where('ref', $bill->getId())
->execute();
->with('createdBy')
->where('module', 'Billing')
->where('type', StringUtils::intHash(BillMapper::class))
->where('ref', $bill->getId())
->execute();
/** @var \Modules\Auditor\Models\Auditor[] $logsElements */
$logsElements = AuditMapper::getAll()

View File

@ -45,6 +45,21 @@ class Bill implements \JsonSerializable
*/
protected int $id = 0;
/**
* Sequence.
*
* Incrementing value depending on multiple columns e.g.:
* id & unit
* id & unit & type
* id & unit & year
*
* @var int
* @since 1.0.0
*/
public int $sequence = 0;
public int $unit = 0;
public int $source = 0;
/**
@ -497,6 +512,7 @@ class Bill implements \JsonSerializable
'{m}',
'{d}',
'{id}',
'{sequence}',
'{type}',
],
[
@ -504,6 +520,7 @@ class Bill implements \JsonSerializable
$this->createdAt->format('m'),
$this->createdAt->format('d'),
$this->id,
$this->sequence,
$this->type->getId(),
],
$this->type->numberFormat

View File

@ -50,6 +50,8 @@ class BillElement implements \JsonSerializable
protected int $quantity = 0;
public ?Subscription $subscription = null;
public Money $singleSalesPriceNet;
public Money $singleSalesPriceGross;
@ -227,15 +229,17 @@ class BillElement implements \JsonSerializable
* @param Item $item Item
* @param TaxCode $code Tax code used for gross amount calculation
* @param int $quantity Quantity
* @param int $bill Bill
*
* @return self
*
* @since 1.0.0
*/
public static function fromItem(Item $item, TaxCode $code, int $quantity = 1) : self
public static function fromItem(Item $item, TaxCode $code, int $quantity = 1, int $bill = 0) : self
{
$element = new self();
$element->item = $item->getId();
$element->bill = $bill;
$element->item = empty($item->getId()) ? null : $item->getId();
$element->itemNumber = $item->number;
$element->itemName = $item->getL11n('name1')->description;
$element->itemDescription = $item->getL11n('description_short')->description;
@ -267,6 +271,20 @@ class BillElement implements \JsonSerializable
$element->singleProfitGross->setInt($element->singleSalesPriceGross->getInt() - $element->singlePurchasePriceGross->getInt());
$element->totalProfitGross->setInt($element->quantity * ($element->totalSalesPriceGross->getInt() - $element->totalPurchasePriceGross->getInt()));
if (!empty($element->bill)
&& $item->getAttribute('subscription')?->value->getValue() === 1
) {
$element->subscription = new Subscription();
$element->subscription->bill = $element->bill;
$element->subscription->item = $element->item;
$element->subscription->start = $element->quantity;
$element->subscription->end = $element->quantity;
$element->subscription->quantity = $element->quantity;
$element->subscription->autoRenew = $item->getAttribute('subscription_renewal_type')->value->getValue() === 1
? true
: false;
}
return $element;
}

View File

@ -83,6 +83,19 @@ final class BillElementMapper extends DataMapperFactory
],
];
/**
* 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 = [
'subscription' => [
'mapper' => SubscriptionMapper::class,
'external' => 'billing_bill_element_subscription',
],
];
/**
* Primary field name.
*

View File

@ -44,6 +44,7 @@ class BillMapper extends DataMapperFactory
*/
public const COLUMNS = [
'billing_bill_id' => ['name' => 'billing_bill_id', 'type' => 'int', 'internal' => 'id'],
'billing_bill_sequence' => ['name' => 'billing_bill_sequence', 'type' => 'int', 'internal' => 'sequence'],
'billing_bill_number' => ['name' => 'billing_bill_number', 'type' => 'string', 'internal' => 'number'],
'billing_bill_type' => ['name' => 'billing_bill_type', 'type' => 'int', 'internal' => 'type'],
'billing_bill_template' => ['name' => 'billing_bill_template', 'type' => 'int', 'internal' => 'template'],
@ -90,6 +91,7 @@ class BillMapper extends DataMapperFactory
'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],
'billing_bill_unit' => ['name' => 'billing_bill_unit', 'type' => 'int', 'internal' => 'unit'],
];
/**

View File

@ -0,0 +1,47 @@
<?php
/**
* Karaka
*
* PHP Version 8.1
*
* @package Modules\Billing\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\Billing\Models;
/**
* Null subscription class.
*
* @package Modules\Billing\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullSubscription extends Subscription
{
/**
* 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];
}
}

View File

@ -14,9 +14,9 @@ declare(strict_types=1);
namespace Modules\Billing\Models\Price;
use Modules\Attribute\Models\AttributeValueMapper;
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;
@ -83,19 +83,19 @@ final class PriceMapper extends DataMapperFactory
'external' => 'billing_price_item',
],
'itemgroup' => [
'mapper' => AttributeValueMapper::class,
'mapper' => ItemAttributeValueMapper::class,
'external' => 'billing_price_itemgroup',
],
'itemsegment' => [
'mapper' => AttributeValueMapper::class,
'mapper' => ItemAttributeValueMapper::class,
'external' => 'billing_price_itemsegment',
],
'itemsection' => [
'mapper' => AttributeValueMapper::class,
'mapper' => ItemAttributeValueMapper::class,
'external' => 'billing_price_itemsection',
],
'itemtype' => [
'mapper' => AttributeValueMapper::class,
'mapper' => ItemAttributeValueMapper::class,
'external' => 'billing_price_itemtype',
],
'client' => [

View File

@ -229,22 +229,34 @@ final class SalesBillMapper extends BillMapper
*/
public static function getItemTopClients(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$query = ClientMapper::getQuery();
$query->selectAs('SUM(billing_bill_element_total_netsalesprice)', 'net_sales')
->leftJoin(self::TABLE, self::TABLE . '_d1')
->on(ClientMapper::TABLE . '_d1.clientmgmt_client_id', '=', self::TABLE . '_d1.billing_bill_client')
->leftJoin(BillElementMapper::TABLE, BillElementMapper::TABLE . '_d1')
->on(self::TABLE . '_d1.billing_bill_id', '=', BillElementMapper::TABLE . '_d1.billing_bill_element_bill')
->where(BillElementMapper::TABLE . '_d1.billing_bill_element_item', '=', $id)
->andWhere(self::TABLE . '_d1.billing_bill_performance_date', '>=', $start)
->andWhere(self::TABLE . '_d1.billing_bill_performance_date', '<=', $end)
$query = new Builder(self::$db);
$query->selectAs(ClientMapper::TABLE . '.clientmgmt_client_id', 'client')
->selectAs('SUM(' . BillElementMapper::TABLE . '.billing_bill_element_total_netsalesprice)', 'net_sales')
->from(ClientMapper::TABLE)
->leftJoin( self::TABLE)
->on(ClientMapper::TABLE . '.clientmgmt_client_id', '=', self::TABLE . '.billing_bill_client')
->leftJoin(BillElementMapper::TABLE)
->on(self::TABLE . '.billing_bill_id', '=', BillElementMapper::TABLE . '.billing_bill_element_bill')
->where(BillElementMapper::TABLE . '.billing_bill_element_item', '=', $id)
->andWhere(self::TABLE . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::TABLE . '.billing_bill_performance_date', '<=', $end)
->orderBy('net_sales', 'DESC')
->limit($limit)
->groupBy(ClientMapper::TABLE . '_d1.clientmgmt_client_id');
->groupBy('client');
/** @var \Modules\ClientManagement\Models\Client[] $clients */
$clients = ClientMapper::getAll()->execute($query);
$data = ClientMapper::getRaw()->execute();
$stmt = $query->execute();
$data = $stmt->fetchAll();
$clientIds = [];
foreach ($data as $client) {
$clientIds[] = $client['client'];
}
if (!empty($clientIds)) {
$clients = ClientMapper::getAll()
->where('id', $clientIds, 'IN')
->execute();
}
return [$clients, $data];
}

94
Models/Subscription.php Normal file
View File

@ -0,0 +1,94 @@
<?php
/**
* Karaka
*
* PHP Version 8.1
*
* @package Modules\Billing\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\Billing\Models;
use phpOMS\Stdlib\Base\FloatInt;
/**
* Subscription class.
*
* @package Modules\Billing\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Subscription implements \JsonSerializable
{
/**
* ID.
*
* @var int
* @since 1.0.0
*/
protected int $id = 0;
public int $status = 0;
public \DateTime $start;
public ?\DateTime $end = null;
public FloatInt $price;
public int $bill = 0;
public int $item = 0;
public bool $autoRenew = false;
public int $client = 0;
public int $quantity = 0;
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct()
{
$price = new FloatInt();
}
/**
* 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();
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* Karaka
*
* PHP Version 8.1
*
* @package Modules\Billing\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\Billing\Models;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
* Mapper class.
*
* @package Modules\Billing\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @template T of Subscription
* @extends DataMapperFactory<T>
*/
final class SubscriptionMapper 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_subscription_id' => ['name' => 'billing_subscription_id', 'type' => 'int', 'internal' => 'id'],
'billing_subscription_status' => ['name' => 'billing_subscription_status', 'type' => 'int', 'internal' => 'status'],
'billing_subscription_start' => ['name' => 'billing_subscription_start', 'type' => 'DateTime', 'internal' => 'start'],
'billing_subscription_end' => ['name' => 'billing_subscription_end', 'type' => 'DateTime', 'internal' => 'end'],
'billing_subscription_price' => ['name' => 'billing_subscription_price', 'type' => 'Serializable', 'internal' => 'price'],
'billing_subscription_quantity' => ['name' => 'billing_subscription_quantity', 'type' => 'int', 'internal' => 'quantity'],
'billing_subscription_bill' => ['name' => 'billing_subscription_bill', 'type' => 'int', 'internal' => 'bill'],
'billing_subscription_item' => ['name' => 'billing_subscription_item', 'type' => 'int', 'internal' => 'item'],
'billing_subscription_autorenew' => ['name' => 'billing_subscription_autorenew', 'type' => 'bool', 'internal' => 'autoRenew'],
'billing_subscription_client' => ['name' => 'billing_subscription_client', 'type' => 'int', 'internal' => 'client'],
];
/**
* Primary field name.
*
* @var string
* @since 1.0.0
*/
public const PRIMARYFIELD = 'billing_subscription_id';
/**
* Primary table.
*
* @var string
* @since 1.0.0
*/
public const TABLE = 'billing_subscription';
}

View File

@ -14,8 +14,8 @@ declare(strict_types=1);
namespace Modules\Billing\Models\Tax;
use Modules\Attribute\Models\AttributeValueMapper;
use Modules\ClientManagement\Models\ClientAttributeValueMapper;
use Modules\ItemManagement\Models\ItemAttributeValueMapper;
use Modules\SupplierManagement\Models\SupplierAttributeValueMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
@ -70,7 +70,7 @@ final class TaxCombinationMapper extends DataMapperFactory
'external' => 'billing_tax_supplier_code',
],
'itemCode' => [
'mapper' => AttributeValueMapper::class,
'mapper' => ItemAttributeValueMapper::class,
'external' => 'billing_tax_item_code',
],
];

View File

@ -40,6 +40,7 @@ return ['Billing' => [
'Created' => 'Created',
'CreditCard' => 'CreditCard',
'CreditNote' => 'Credit Note',
'CreateBill' => 'Create Bill',
'Customers' => 'Customers',
'Date' => 'Date',
'Delivery' => 'Delivery',

View File

@ -20,6 +20,7 @@
"Admin": "1.0.0",
"Sales": "1.0.0",
"Media": "1.0.0",
"Finance": "1.0.0",
"Calendar": "1.0.0",
"ItemManagement": "1.0.0",
"ClientManagement": "1.0.0",