This commit is contained in:
Dennis Eichhorn 2024-01-02 23:34:17 +00:00
parent e106dd436b
commit 47159f80c1
17 changed files with 417 additions and 153 deletions

View File

@ -0,0 +1,10 @@
[
{
"description": "Default item segmentation (segment, section, sales group, product group)",
"type": "setting",
"name": "1004800001",
"content": "[\"segment\":1, \"section\":1, \"sales_group\":1, \"product_group\":1]",
"pattern": "",
"module": "ItemManagement"
}
]

43
Admin/Install/Admin.php Normal file
View File

@ -0,0 +1,43 @@
<?php
/**
* Jingga
*
* PHP Version 8.1
*
* @package Modules\ItemManagement\Admin\Install
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\ItemManagement\Admin\Install;
use phpOMS\Application\ApplicationAbstract;
/**
* Admin class.
*
* @package Modules\ItemManagement\Admin\Install
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Admin
{
/**
* Install Admin providing
*
* @param ApplicationAbstract $app Application
* @param string $path Module path
*
* @return void
*
* @since 1.0.0
*/
public static function install(ApplicationAbstract $app, string $path) : void
{
\Modules\Admin\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Admin.install.json']);
}
}

View File

@ -135,6 +135,27 @@
}
]
},
{
"name": "sales_group",
"l11n": {
"en": "Sales Group",
"de": "Umsatzgruppe"
},
"value_type": 1,
"is_custom_allowed": false,
"validation_pattern": "",
"is_required": true,
"default_value": "",
"values": [
{
"value": 1,
"l11n": {
"en": "Sales Group 1",
"de": "Umsatzgruppe 1"
}
}
]
},
{
"name": "product_group",
"l11n": {
@ -150,8 +171,8 @@
{
"value": 1,
"l11n": {
"en": "Group 1",
"de": "Gruppe 1"
"en": "Product Group 1",
"de": "Produktgruppe 1"
}
}
]

View File

@ -29,7 +29,7 @@ return [
],
],
],
'^.*/item/attribute.*$' => [
'^.*/item/attribute$' => [
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeCreate',
'verb' => RouteVerb::PUT,
@ -49,6 +49,86 @@ return [
],
],
],
'^.*/item/attribute/type$' => [
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeTypeCreate',
'verb' => RouteVerb::PUT,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeTypeUpdate',
'verb' => RouteVerb::SET,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
],
'^.*/item/attribute/type/l11n$' => [
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeTypeL11nCreate',
'verb' => RouteVerb::PUT,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeTypeL11nUpdate',
'verb' => RouteVerb::SET,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
],
'^.*/item/attribute/value$' => [
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeValueCreate',
'verb' => RouteVerb::PUT,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeValueUpdate',
'verb' => RouteVerb::SET,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
],
'^.*/item/attribute/value$' => [
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeValueL11nCreate',
'verb' => RouteVerb::PUT,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
[
'dest' => '\Modules\ItemManagement\Controller\ApiAttributeController:apiItemAttributeValueL11nUpdate',
'verb' => RouteVerb::SET,
'permission' => [
'module' => ApiController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_ITEM,
],
],
],
'^.*/item/l11n$' => [
[
'dest' => '\Modules\ItemManagement\Controller\ApiController:apiItemL11nCreate',

View File

@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Modules\ItemManagement\Controller;
use Modules\Admin\Models\NullAccount;
use Modules\ItemManagement\Models\Attribute\ItemAttributeTypeMapper;
use Modules\ItemManagement\Models\Item;
use Modules\ItemManagement\Models\ItemL11nMapper;
use Modules\ItemManagement\Models\ItemL11nTypeMapper;
@ -24,11 +25,14 @@ use Modules\ItemManagement\Models\ItemPriceStatus;
use Modules\ItemManagement\Models\ItemRelationType;
use Modules\ItemManagement\Models\ItemRelationTypeMapper;
use Modules\ItemManagement\Models\ItemStatus;
use Modules\ItemManagement\Models\PermissionCategory;
use Modules\ItemManagement\Models\SettingsEnum as ItemSettingsEnum;
use Modules\Media\Models\Collection;
use Modules\Media\Models\CollectionMapper;
use Modules\Media\Models\MediaMapper;
use Modules\Media\Models\MediaTypeMapper;
use Modules\Media\Models\PathSettings;
use phpOMS\Account\PermissionType;
use phpOMS\Localization\BaseStringL11n;
use phpOMS\Localization\BaseStringL11nType;
use phpOMS\Localization\ISO4217CharEnum;
@ -36,6 +40,7 @@ use phpOMS\Localization\NullBaseStringL11nType;
use phpOMS\Message\Http\HttpRequest;
use phpOMS\Message\Http\HttpResponse;
use phpOMS\Message\Http\RequestStatusCode;
use phpOMS\Message\NotificationLevel;
use phpOMS\Message\RequestAbstract;
use phpOMS\Message\ResponseAbstract;
use phpOMS\Model\Message\FormValidation;
@ -215,9 +220,40 @@ final class ApiController extends Controller
);
}
$this->createItemSegmentation($request, $response, $item);
$this->createStandardCreateResponse($request, $response, $item);
}
private function createItemSegmentation(RequestAbstract $request, ResponseAbstract $response, Item $item) : void
{
/** @var \Model\Setting $settings */
$settings = $this->app->appSettings->get(null, [
ItemSettingsEnum::DEFAULT_SEGMENTATION,
]);
$segmentation = \json_decode($settings->content, true);
if ($segmentation === false) {
return;
}
$types = ItemAttributeTypeMapper::get()
->where('name', \array_keys($segmentation), 'IN')
->execute();
foreach ($types as $type) {
$internalResponse = clone $response;
$internalRequest = new HttpRequest(new HttpUri(''));
$internalRequest->header->account = $request->header->account;
$internalRequest->setData('ref', $item->id);
$internalRequest->setData('type', $type->id);
$internalRequest->setData('value_id', $segmentation[$type->name]);
$this->app->moduleManager->get('ItemManagement', 'ApiAttribute')->apiItemAttributeCreate($internalRequest, $internalResponse);
}
}
/**
* Create directory for an account
*
@ -797,4 +833,60 @@ final class ApiController extends Controller
return [];
}
/**
* Api method to update Note
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param array $data Generic data
*
* @return void
*
* @api
*
* @since 1.0.0
*/
public function apiNoteUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{
$accountId = $request->header->account;
if (!$this->app->accountManager->get($accountId)->hasPermission(
PermissionType::MODIFY, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::NOTE, $request->getDataInt('id'))
) {
$this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []);
$response->header->status = RequestStatusCode::R_403;
return;
}
$this->app->moduleManager->get('Editor', 'Api')->apiEditorUpdate($request, $response, $data);
}
/**
* Api method to delete Note
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param array $data Generic data
*
* @return void
*
* @api
*
* @since 1.0.0
*/
public function apiNoteDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{
$accountId = $request->header->account;
if (!$this->app->accountManager->get($accountId)->hasPermission(
PermissionType::DELETE, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::NOTE, $request->getDataInt('id'))
) {
$this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []);
$response->header->status = RequestStatusCode::R_403;
return;
}
$this->app->moduleManager->get('Editor', 'Api')->apiEditorDelete($request, $response, $data);
}
}

View File

@ -29,6 +29,7 @@ use Modules\ItemManagement\Models\ItemL11nTypeMapper;
use Modules\ItemManagement\Models\ItemMapper;
use Modules\Media\Models\MediaMapper;
use Modules\Media\Models\MediaTypeMapper;
use Modules\Organization\Models\Attribute\UnitAttributeMapper;
use Modules\Organization\Models\UnitMapper;
use phpOMS\Asset\AssetType;
use phpOMS\Contract\RenderableInterface;
@ -55,7 +56,7 @@ use phpOMS\Views\View;
final class BackendController extends Controller
{
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -84,7 +85,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -113,7 +114,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -148,7 +149,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -178,7 +179,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -213,7 +214,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -230,7 +231,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -247,7 +248,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -264,7 +265,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -281,7 +282,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -302,7 +303,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -323,7 +324,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -344,7 +345,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -417,6 +418,15 @@ final class BackendController extends Controller
$view->data['itemImage'] = $itemImage;
$businessStart = UnitAttributeMapper::get()
->with('type')
->with('value')
->where('ref', $this->app->unitId)
->where('type/name', 'business_year_start')
->execute();
$view->data['business_start'] = $businessStart->id === 0 ? 1 : $businessStart->value->getValue();
// @todo this one should already be loaded in the backend application no?????????
/** @var \Model\Setting $settings */
$settings = $this->app->appSettings->get(null, [
@ -469,9 +479,11 @@ final class BackendController extends Controller
$audits = AuditMapper::getAll()
->where('type', StringUtils::intHash(ItemMapper::class))
->where('module', 'ItemManagement')
->where('ref', $item->id)
->where('ref', (string) $item->id)
->execute();
// @todo join audit with files, attributes, localization, prices, notes, ...
$view->data['audits'] = $audits;
/** @var \Modules\Media\Models\Media[] $files */
@ -483,61 +495,16 @@ final class BackendController extends Controller
$view->data['files'] = $files;
$mediaListView = new \Modules\Media\Theme\Backend\Components\Media\ListView($this->app->l11nManager, $request, $response);
$mediaListView->setTemplate('/Modules/Media/Theme/Backend/Components/Media/list');
$view->data['medialist'] = $mediaListView;
$view->data['media-upload'] = new \Modules\Media\Theme\Backend\Components\Upload\BaseView($this->app->l11nManager, $request, $response);
$view->data['note'] = new \Modules\Editor\Theme\Backend\Components\Note\BaseView($this->app->l11nManager, $request, $response);
// stats
if ($this->app->moduleManager->isActive('Billing')) {
$ytd = SalesBillMapper::getSalesByItemId($item->id, new SmartDateTime('Y-01-01'), new SmartDateTime('now'));
$mtd = SalesBillMapper::getSalesByItemId($item->id, new SmartDateTime('Y-m-01'), new SmartDateTime('now'));
$avg = SalesBillMapper::getAvgSalesPriceByItemId($item->id, (new SmartDateTime('now'))->smartModify(-1), new SmartDateTime('now'));
$lastOrder = SalesBillMapper::getLastOrderDateByItemId($item->id);
$newestInvoices = SalesBillMapper::getAll()
->with('type')
->with('type/l11n')
->where('type/transferType', BillTransferType::SALES)
->where('type/l11n/language', $response->header->l11n->language)
->sort('id', OrderType::DESC)
->limit(5)
->execute();
$topCustomers = SalesBillMapper::getItemTopClients($item->id, new SmartDateTime('Y-01-01'), new SmartDateTime('now'), 5);
$allInvoices = SalesBillMapper::getItemBills($item->id, new SmartDateTime('Y-01-01'), new SmartDateTime('now'));
$regionSales = [];
$countrySales = SalesBillMapper::getItemCountrySales($item->id, new SmartDateTime('Y-01-01'), new SmartDateTime('now'), 5);
$monthlySalesCosts = SalesBillMapper::getItemMonthlySalesCosts($item->id, (new SmartDateTime('now'))->createModify(-1), new SmartDateTime('now'));
} else {
$ytd = new Money();
$mtd = new Money();
$avg = new Money();
$lastOrder = null;
$newestInvoices = [];
$allInvoices = [];
$topCustomers = [];
$regionSales = [];
$countrySales = [];
$monthlySalesCosts = [];
}
$view->data['ytd'] = $ytd;
$view->data['mtd'] = $mtd;
$view->data['avg'] = $avg;
$view->data['lastOrder'] = $lastOrder;
$view->data['newestInvoices'] = $newestInvoices;
$view->data['allInvoices'] = $allInvoices;
$view->data['topCustomers'] = $topCustomers;
$view->data['regionSales'] = $regionSales;
$view->data['countrySales'] = $countrySales;
$view->data['monthlySalesCosts'] = $monthlySalesCosts;
$view->data['hasBilling'] = $this->app->moduleManager->isActive('Billing');
return $view;
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -554,7 +521,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -571,7 +538,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -588,7 +555,7 @@ final class BackendController extends Controller
}
/**
* Routing end-point for application behaviour.
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response

View File

@ -59,6 +59,7 @@ final class ItemAttributeValueMapper extends DataMapperFactory
'mapper' => ItemAttributeValueL11nMapper::class,
'table' => 'itemmgmt_attr_value_l11n',
'self' => 'itemmgmt_attr_value_l11n_value',
'column' => 'content',
'external' => null,
],
];

View File

@ -20,8 +20,10 @@ use Modules\Media\Models\Media;
use Modules\Media\Models\MediaMapper;
use Modules\Media\Models\MediaType;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
use phpOMS\DataStorage\Database\Query\Builder;
use phpOMS\Localization\BaseStringL11n;
use phpOMS\Localization\BaseStringL11nType;
use phpOMS\Stdlib\Base\FloatInt;
/**
* Item mapper class.

View File

@ -17,7 +17,7 @@ namespace Modules\ItemManagement\Models;
use phpOMS\Stdlib\Base\Enum;
/**
* Permision state enum.
* Permission category enum.
*
* @package Modules\ItemManagement\Models
* @license OMS License 2.0
@ -33,4 +33,6 @@ abstract class PermissionCategory extends Enum
public const STOCK_ITEM = 3;
public const ATTRIBUTE = 4;
public const NOTE = 4;
}

30
Models/SettingsEnum.php Normal file
View File

@ -0,0 +1,30 @@
<?php
/**
* Jingga
*
* PHP Version 8.1
*
* @package Modules\ItemManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\ItemManagement\Models;
use phpOMS\Stdlib\Base\Enum;
/**
* Default settings enum.
*
* @package Modules\ItemManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
abstract class SettingsEnum extends Enum
{
public const DEFAULT_SEGMENTATION = '1004800001';
}

View File

@ -118,7 +118,7 @@ return ['ItemManagement' => [
'QA' => 'QA.',
'QM' => 'Qm.',
'Quantity' => 'Antal',
'QuantityUnit' => 'Mængden af mængde',
'QuantityUnit' => "Mængden af \u{200b}\u{200b}mængde",
'RecentInvoices' => '',
'ReorderLevel' => 'Ombestillingsniveau',
'Reserved' => 'Reserveret',

View File

@ -113,7 +113,7 @@ return ['ItemManagement' => [
'Properties' => 'Propriétés',
'Property' => 'Propriété',
'Purchase' => 'Acheter',
'PurchasePrice' => 'Prix d\'achat',
'PurchasePrice' => "Prix \u{200b}\u{200b}d'achat",
'Purchasing' => 'Achat',
'QA' => 'Qa',
'QM' => 'Qm',
@ -124,7 +124,7 @@ return ['ItemManagement' => [
'Reserved' => 'Réservé',
'SN' => 'Sn',
'Sales' => 'Ventes',
'SalesPrice' => 'Prix de vente',
'SalesPrice' => "Prix \u{200b}\u{200b}de vente",
'SalesPricing' => '',
'Segment' => 'Segment',
'ShelfLife' => 'Durée de vie',

View File

@ -49,7 +49,7 @@ echo $this->data['nav']->render(); ?>
<div class="form-group">
<label for="iPattern"><?= $this->getHtml('Pattern', 'Attribute', 'Backend'); ?></label>
<input id="iPattern" type="text" value="<?= $this->printHtml($attribute->validationPAttern); ?>">
<input id="iPattern" type="text" value="<?= $this->printHtml($attribute->validationPattern); ?>">
</div>
<div class="form-group">
@ -74,7 +74,7 @@ echo $this->data['nav']->render(); ?>
<div class="col-xs-12 col-md-6">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('Language', '0', '0'); ?><i class="g-icon download btn end-xs">download</i></div>
<table class="default">
<table class="default sticky">
<thead>
<tr>
<td>

View File

@ -593,7 +593,7 @@ echo $this->data['nav']->render(); ?>
$footerView->setPage(1);
?>
<div class="box w-100">
<table class="default">
<table class="default sticky">
<caption><?= $this->getHtml('Logs'); ?><i class="g-icon end-xs download btn">download</i></caption>
<thead>
<tr>

View File

@ -12,28 +12,26 @@
*/
declare(strict_types=1);
use Modules\Billing\Models\BillTransferType;
use Modules\Billing\Models\SalesBillMapper;
use Modules\Media\Models\NullMedia;
use phpOMS\DataStorage\Database\Query\OrderType;
use phpOMS\Localization\ISO639Enum;
use phpOMS\Localization\Money;
use phpOMS\Localization\NullLocalization;
use phpOMS\Message\Http\HttpHeader;
use phpOMS\Stdlib\Base\SmartDateTime;
use phpOMS\Uri\UriFactory;
/** @var \Modules\ItemManagement\Models\Item $item */
$item = $this->data['item'];
$attribute = $item->attributes;
$notes = $item->notes;
$files = $item->files;
$itemImage = $this->getData('itemImage') ?? new NullMedia();
$newestInvoices = $this->data['newestInvoices'] ?? [];
$allInvoices = $this->data['allInvoices'] ?? [];
$topCustomers = $this->getData('topCustomers') ?? [[], []];
$regionSales = $this->data['regionSales'] ?? [];
$countrySales = $this->data['countrySales'] ?? [];
$monthlySalesCosts = $this->data['monthlySalesCosts'] ?? [];
$attributeView = $this->data['attributeView'];
$l11nView = $this->data['l11nView'];
@ -48,21 +46,21 @@ echo $this->data['nav']->render();
<div class="tabview tab-2">
<div class="box">
<ul class="tab-links">
<li><label for="c-tab-1"><?= $this->getHtml('Profile'); ?></label></li>
<li><label for="c-tab-2"><?= $this->getHtml('Localization'); ?></label></li>
<li><label for="c-tab-3"><?= $this->getHtml('Attributes'); ?></label></li>
<li><label for="c-tab-4"><?= $this->getHtml('SalesPricing'); ?></label></li>
<li><label for="c-tab-5"><?= $this->getHtml('Procurement'); ?></label></li>
<li><label for="c-tab-6"><?= $this->getHtml('Production'); ?></label></li>
<li><label for="c-tab-7"><?= $this->getHtml('QA'); ?></label></li>
<li><label for="c-tab-8"><?= $this->getHtml('Packaging'); ?></label></li>
<li><label for="c-tab-9"><?= $this->getHtml('Accounting'); ?></label></li>
<li><label for="c-tab-10"><?= $this->getHtml('Stock'); ?></label></li>
<li><label for="c-tab-11"><?= $this->getHtml('Disposal'); ?></label></li>
<li><label for="c-tab-12"><?= $this->getHtml('Notes'); ?></label></li>
<li><label for="c-tab-13"><?= $this->getHtml('Media'); ?></label></li>
<li><label for="c-tab-14"><?= $this->getHtml('Bills'); ?></label></li>
<li><label for="c-tab-15"><?= $this->getHtml('Logs'); ?></label></li>
<li><label for="c-tab-1"><?= $this->getHtml('Profile'); ?></label>
<li><label for="c-tab-2"><?= $this->getHtml('Localization'); ?></label>
<li><label for="c-tab-3"><?= $this->getHtml('Attributes'); ?></label>
<li><label for="c-tab-4"><?= $this->getHtml('SalesPricing'); ?></label>
<li><label for="c-tab-5"><?= $this->getHtml('Procurement'); ?></label>
<li><label for="c-tab-6"><?= $this->getHtml('Production'); ?></label>
<li><label for="c-tab-7"><?= $this->getHtml('QA'); ?></label>
<li><label for="c-tab-8"><?= $this->getHtml('Packaging'); ?></label>
<li><label for="c-tab-9"><?= $this->getHtml('Accounting'); ?></label>
<li><label for="c-tab-10"><?= $this->getHtml('Stock'); ?></label>
<li><label for="c-tab-11"><?= $this->getHtml('Disposal'); ?></label>
<li><label for="c-tab-12"><?= $this->getHtml('Notes'); ?></label>
<li><label for="c-tab-13"><?= $this->getHtml('Media'); ?></label>
<li><label for="c-tab-14"><?= $this->getHtml('Bills'); ?></label>
<li><label for="c-tab-15"><?= $this->getHtml('Logs'); ?></label>
</ul>
</div>
<div class="tab-content">
@ -118,19 +116,18 @@ echo $this->data['nav']->render();
</section>
</div>
<div class="col-xs-12 col-lg-9 plain-grid">
<?php if ($this->data['hasBilling']) : ?>
<div class="row">
<div class="col-xs-12 col-lg-4">
<section class="portlet highlight-7">
<div class="portlet-body">
<table class="wf-100">
<tr><td><?= $this->getHtml('YTDSales'); ?>:
<td><?= $this->getCurrency($this->getData('ytd')); ?>
<td><?= $this->getCurrency(SalesBillMapper::getItemNetSales($item->id, SmartDateTime::startOfYear($this->data['business_start']), new \DateTime('now')), format: 'medium'); ?>
<tr><td><?= $this->getHtml('MTDSales'); ?>:
<td><?= $this->getCurrency($this->getData('mtd')); ?>
<td><?= $this->getCurrency(SalesBillMapper::getItemNetSales($item->id, SmartDateTime::startOfMonth(), new \DateTime('now')), format: 'medium'); ?>
<tr><td><?= $this->getHtml('ILV'); ?>:
<td>
<tr><td><?= $this->getHtml('MRR'); ?>:
<td>
<td><?= $this->getCurrency(SalesBillMapper::getILVHistoric($item->id), format: 'medium'); ?>
</table>
</div>
</section>
@ -141,13 +138,11 @@ echo $this->data['nav']->render();
<div class="portlet-body">
<table class="wf-100">
<tr><td><?= $this->getHtml('LastOrder'); ?>:
<td><?= $this->getData('lastOrder') !== null ? $this->getData('lastOrder')->format('Y-m-d H:i') : ''; ?>
<td><?= SalesBillMapper::getItemLastOrder($item->id)?->format('Y-m-d'); ?>
<tr><td><?= $this->getHtml('PriceChange'); ?>:
<td>
<tr><td><?= $this->getHtml('Created'); ?>:
<td><?= $item->createdAt->format('Y-m-d H:i'); ?>
<tr><td><?= $this->getHtml('Modified'); ?>:
<td>
</table>
</div>
</section>
@ -160,7 +155,7 @@ echo $this->data['nav']->render();
<tr><td><?= $this->getHtml('SalesPrice'); ?>:
<td><?= $this->getCurrency($item->salesPrice, format: 'medium'); ?>
<tr><td><?= $this->getHtml('PurchasePrice'); ?>:
<td><?= $this->getCurrency($item->purchasePrice); ?>
<td><?= $this->getCurrency($item->purchasePrice, format: 'medium'); ?>
<tr><td><?= $this->getHtml('Margin'); ?>:
<td><?= $this->getNumeric(
$item->salesPrice->getInt() === 0
@ -168,12 +163,13 @@ echo $this->data['nav']->render();
: ($item->salesPrice->getInt() - $item->purchasePrice->getInt()) / $item->salesPrice->getInt() * 100
, 'short'); ?> %
<tr><td><?= $this->getHtml('AvgPrice'); ?>:
<td><?= $this->getCurrency($this->getData('avg')); ?>
<td><?= $this->getCurrency(SalesBillMapper::getItemAvgSalesPrice($item->id, (new SmartDateTime('now'))->smartModify(-1), new SmartDateTime('now')), format: 'medium'); ?>
</table>
</div>
</section>
</div>
</div>
<?php endif; ?>
<div class="row">
<div class="col-xs-12 col-md-6">
@ -183,7 +179,7 @@ echo $this->data['nav']->render();
<label for="c-tab-12" class="right-xs btn"><i class="g-icon">edit</i></a>
</div>
<div class="slider">
<table id="iNotesItemList" class="default">
<table id="iNotesItemList" class="default sticky">
<thead>
<tr>
<td class="wf-100"><?= $this->getHtml('Title'); ?>
@ -208,7 +204,7 @@ echo $this->data['nav']->render();
<label for="c-tab-13" class="right-xs btn"><i class="g-icon">edit</i></a>
</div>
<div class="slider">
<table id="iFilesItemList" class="default">
<table id="iFilesItemList" class="default sticky">
<thead>
<tr>
<td class="wf-100"><?= $this->getHtml('Title'); ?>
@ -229,12 +225,13 @@ echo $this->data['nav']->render();
</div>
</div>
<?php if ($this->data['hasBilling']) : ?>
<div class="row">
<div class="col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('RecentInvoices'); ?></div>
<div class="slider">
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td><?= $this->getHtml('Number'); ?>
@ -244,6 +241,15 @@ echo $this->data['nav']->render();
<td><?= $this->getHtml('Date'); ?>
<tbody>
<?php
$newestInvoices = SalesBillMapper::getAll()
->with('type')
->with('type/l11n')
->where('type/transferType', BillTransferType::SALES)
->where('type/l11n/language', $this->response->header->l11n->language)
->sort('id', OrderType::DESC)
->limit(5)
->execute();
/** @var \Modules\Billing\Models\Bill $invoice */
foreach ($newestInvoices as $invoice) :
$url = UriFactory::build('{/base}/sales/bill?{?}&id=' . $invoice->id);
@ -260,13 +266,17 @@ echo $this->data['nav']->render();
</section>
</div>
</div>
<?php endif; ?>
<?php if ($this->data['hasBilling']) :
$topCustomers = SalesBillMapper::getItemTopClients($item->id, SmartDateTime::startOfYear($this->data['business_start']), new SmartDateTime('now'), 5);
?>
<div class="row">
<?php if (!empty($topCustomers[0])) : ?>
<div class="col-xs-12 col-lg-6">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('TopCustomers'); ?></div>
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td><?= $this->getHtml('Number'); ?>
@ -288,7 +298,9 @@ echo $this->data['nav']->render();
</div>
<?php endif; ?>
<?php if (!empty($monthlySalesCosts)) : ?>
<?php
$monthlySalesCosts = SalesBillMapper::getItemMonthlySalesCosts($item->id, (new SmartDateTime('now'))->createModify(-1), new SmartDateTime('now'));
if (!empty($monthlySalesCosts)) : ?>
<div class="col-xs-12 col-lg-6">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Sales'); ?></div>
@ -377,7 +389,9 @@ echo $this->data['nav']->render();
</div>
<div class="row">
<?php if (!empty($regionSales)) : ?>
<?php
$regionSales = [];
if (!empty($regionSales)) : ?>
<div class="col-xs-12 col-lg-6">
<section class="portlet">
<div class="portlet-head">Regions</div>
@ -413,7 +427,9 @@ echo $this->data['nav']->render();
</div>
<?php endif; ?>
<?php if (!empty($countrySales)) : ?>
<?php
$countrySales = SalesBillMapper::getItemCountrySales($item->id, SmartDateTime::startOfYear($this->data['business_start']), new SmartDateTime('now'), 5);
if (!empty($countrySales)) : ?>
<div class="col-xs-12 col-lg-6">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Countries'); ?></div>
@ -456,8 +472,8 @@ echo $this->data['nav']->render();
</section>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
@ -472,6 +488,7 @@ echo $this->data['nav']->render();
?>
</div>
</div>
<input type="radio" id="c-tab-3" name="tabular-2" checked>
<div class="tab">
<div class="row">
@ -485,6 +502,7 @@ echo $this->data['nav']->render();
?>
</div>
</div>
<input type="radio" id="c-tab-4" name="tabular-2" checked>
<div class="tab">
<div class="row">
@ -549,7 +567,7 @@ echo $this->data['nav']->render();
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Prices'); ?><i class="g-icon download btn end-xs">download</i></div>
<div class="slider">
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td>
@ -711,7 +729,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Prices'); ?><i class="g-icon download btn end-xs">download</i></div>
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td>
@ -920,18 +938,13 @@ echo $this->data['nav']->render();
</div>
<input type="radio" id="c-tab-12" name="tabular-2" checked>
<div class="tab">
<div class="row">
</div>
<div class="tab col-simple">
<?= $this->data['note']->render('item-note', 'notes', $item->notes); ?>
</div>
<input type="radio" id="c-tab-13" name="tabular-2" checked>
<div class="tab">
<div class="row">
<div class="col-xs-12">
<?= $this->getData('medialist')->render($this->getData('files')); ?>
</div>
</div>
<div class="tab col-simple">
<?= $this->data['media-upload']->render('item-file', 'files', '', $this->data['files']); ?>
</div>
<input type="radio" id="c-tab-14" name="tabular-2" checked>
@ -940,7 +953,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('RecentInvoices'); ?></div>
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td><?= $this->getHtml('Number'); ?>
@ -950,6 +963,8 @@ echo $this->data['nav']->render();
<td><?= $this->getHtml('Date'); ?>
<tbody>
<?php
$allInvoices = SalesBillMapper::getItemBills($item->id, SmartDateTime::startOfYear($this->data['business_start']), new SmartDateTime('now'));
/** @var \Modules\Billing\Models\Bill $invoice */
foreach ($allInvoices as $invoice) :
$url = UriFactory::build('{/base}/sales/bill?{?}&id=' . $invoice->id);
@ -974,7 +989,7 @@ echo $this->data['nav']->render();
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('Audits', 'Auditor'); ?><i class="g-icon download btn end-xs">download</i></div>
<div class="slider">
<table class="default">
<table class="default sticky">
<colgroup>
<col style="width: 75px">
<col style="width: 150px">

View File

@ -44,21 +44,21 @@ echo $this->data['nav']->render();
<div class="tabview tab-2">
<div class="box">
<ul class="tab-links">
<li><label for="c-tab-1"><?= $this->getHtml('Profile'); ?></label></li>
<li><label for="c-tab-2"><?= $this->getHtml('Address'); ?></label></li>
<li><label for="c-tab-3"><?= $this->getHtml('Localization'); ?></label></li>
<li><label for="c-tab-4"><?= $this->getHtml('Attributes'); ?></label></li>
<li><label for="c-tab-5"><?= $this->getHtml('Sales'); ?></label></li>
<li><label for="c-tab-6"><?= $this->getHtml('Purchasing'); ?></label></li>
<li><label for="c-tab-7"><?= $this->getHtml('Production'); ?></label></li>
<li><label for="c-tab-8"><?= $this->getHtml('QA'); ?></label></li>
<li><label for="c-tab-9"><?= $this->getHtml('Packaging'); ?></label></li>
<li><label for="c-tab-10"><?= $this->getHtml('Accounting'); ?></label></li>
<li><label for="c-tab-11"><?= $this->getHtml('Stock'); ?></label></li>
<li><label for="c-tab-12"><?= $this->getHtml('Disposal'); ?></label></li>
<li><label for="c-tab-13"><?= $this->getHtml('Media'); ?></label></li>
<li><label for="c-tab-14"><?= $this->getHtml('Bills'); ?></label></li>
<li><label for="c-tab-15"><?= $this->getHtml('Logs'); ?></label></li>
<li><label for="c-tab-1"><?= $this->getHtml('Profile'); ?></label>
<li><label for="c-tab-2"><?= $this->getHtml('Address'); ?></label>
<li><label for="c-tab-3"><?= $this->getHtml('Localization'); ?></label>
<li><label for="c-tab-4"><?= $this->getHtml('Attributes'); ?></label>
<li><label for="c-tab-5"><?= $this->getHtml('Sales'); ?></label>
<li><label for="c-tab-6"><?= $this->getHtml('Purchasing'); ?></label>
<li><label for="c-tab-7"><?= $this->getHtml('Production'); ?></label>
<li><label for="c-tab-8"><?= $this->getHtml('QA'); ?></label>
<li><label for="c-tab-9"><?= $this->getHtml('Packaging'); ?></label>
<li><label for="c-tab-10"><?= $this->getHtml('Accounting'); ?></label>
<li><label for="c-tab-11"><?= $this->getHtml('Stock'); ?></label>
<li><label for="c-tab-12"><?= $this->getHtml('Disposal'); ?></label>
<li><label for="c-tab-13"><?= $this->getHtml('Media'); ?></label>
<li><label for="c-tab-14"><?= $this->getHtml('Bills'); ?></label>
<li><label for="c-tab-15"><?= $this->getHtml('Logs'); ?></label>
</ul>
</div>
<div class="tab-content">
@ -163,7 +163,7 @@ echo $this->data['nav']->render();
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Notes'); ?></div>
<div class="slider">
<table id="iNotesItemList" class="default">
<table id="iNotesItemList" class="default sticky">
<thead>
<tr>
<td class="wf-100"><?= $this->getHtml('Title'); ?>
@ -185,7 +185,7 @@ echo $this->data['nav']->render();
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Documents'); ?></div>
<div class="slider">
<table id="iFilesItemList" class="default">
<table id="iFilesItemList" class="default sticky">
<thead>
<tr>
<td class="wf-100"><?= $this->getHtml('Title'); ?>
@ -211,7 +211,7 @@ echo $this->data['nav']->render();
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('RecentInvoices'); ?></div>
<div class="slider">
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td><?= $this->getHtml('Number'); ?>
@ -242,7 +242,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12 col-lg-6">
<section class="portlet">
<div class="portlet-head">Top Customers</div>
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td><?= $this->getHtml('Number'); ?>
@ -459,7 +459,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12 col-md-6">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Localizations'); ?><i class="g-icon download btn end-xs">download</i></div>
<table id="groupTable" class="default">
<table id="groupTable" class="default sticky">
<thead>
<tr>
<td>
@ -537,7 +537,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12 col-md-6">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Groups'); ?><i class="g-icon download btn end-xs">download</i></div>
<table id="groupTable" class="default">
<table id="groupTable" class="default sticky">
<thead>
<tr>
<td>
@ -619,7 +619,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12 col-md-6">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Prices'); ?><i class="g-icon download btn end-xs">download</i></div>
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td>
@ -919,7 +919,7 @@ echo $this->data['nav']->render();
<div class="col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('RecentInvoices'); ?></div>
<table id="iSalesItemList" class="default">
<table id="iSalesItemList" class="default sticky">
<thead>
<tr>
<td><?= $this->getHtml('Number'); ?>
@ -950,7 +950,7 @@ echo $this->data['nav']->render();
<div class="tab">
<div class="row">
<div class="col-xs-12">
<table class="default">
<table class="default sticky">
<caption><?= $this->getHtml('Logs'); ?><i class="g-icon end-xs download btn">download</i></caption>
<thead>
<tr>

View File

@ -23,7 +23,8 @@
"providing": {
"Navigation": "*",
"Editor": "*",
"Media": "*"
"Media": "*",
"Admin": "*"
},
"load": [
{