diff --git a/Admin/Install/Media.install.json b/Admin/Install/Media.install.json
index b57a11d..5cd95c7 100755
--- a/Admin/Install/Media.install.json
+++ b/Admin/Install/Media.install.json
@@ -9,7 +9,7 @@
{
"type": "collection",
"create_directory": true,
- "name": "Articles",
+ "name": "Items",
"virtualPath": "/Modules/ItemManagement",
"user": 1
},
diff --git a/Admin/Install/Navigation.install.json b/Admin/Install/Navigation.install.json
index 9bc633d..cb23dac 100755
--- a/Admin/Install/Navigation.install.json
+++ b/Admin/Install/Navigation.install.json
@@ -8,7 +8,7 @@
"uri": null,
"target": "self",
"icon": "fa fa-usd",
- "order": 20,
+ "order": 35,
"from": "ItemManagement",
"permission": { "permission": 2, "category": null, "element": null },
"parent": 0,
@@ -22,8 +22,8 @@
"uri": "{/lang}/{/app}/item/attribute/type/list?{?}",
"target": "self",
"icon": null,
- "order": 15,
- "from": "Sales",
+ "order": 5,
+ "from": "ItemManagement",
"permission": { "permission": 2, "category": null, "element": null },
"parent": 1004801001,
"children": [
@@ -36,8 +36,8 @@
"uri": "{/lang}/{/app}/item/attribute/type/list?{?}",
"target": "self",
"icon": null,
- "order": 15,
- "from": "Sales",
+ "order": 5,
+ "from": "ItemManagement",
"permission": { "permission": 2, "category": null, "element": null },
"parent": 1004802001,
"children": []
@@ -51,13 +51,75 @@
"uri": "{/lang}/{/app}/item/attribute/value/list?{?}",
"target": "self",
"icon": null,
- "order": 15,
- "from": "Sales",
+ "order": 10,
+ "from": "ItemManagement",
"permission": { "permission": 2, "category": null, "element": null },
"parent": 1004802001,
"children": []
}
]
+ },
+ {
+ "id": 1004803001,
+ "pid": "/",
+ "type": 2,
+ "subtype": 1,
+ "name": "Items",
+ "uri": "{/lang}/{/app}/item/list",
+ "target": "self",
+ "icon": null,
+ "order": 10,
+ "from": "ItemManagement",
+ "permission": { "permission": 2, "category": null, "element": null },
+ "parent": 1004801001,
+ "children": [
+ {
+ "id": 1004803002,
+ "pid": "/item",
+ "type": 3,
+ "subtype": 1,
+ "name": "List",
+ "uri": "{/lang}/{/app}/item/list",
+ "target": "self",
+ "icon": null,
+ "order": 1,
+ "from": "ItemManagement",
+ "permission": { "permission": 2, "category": null, "element": null },
+ "parent": 1004803001,
+ "children": [
+ {
+ "id": 1004803003,
+ "pid": "/item",
+ "type": 3,
+ "subtype": 1,
+ "name": "Item",
+ "uri": "{/lang}/{/app}/item/profile?{?}",
+ "target": "self",
+ "icon": null,
+ "order": 1,
+ "from": "ItemManagement",
+ "permission": { "permission": 2, "category": null, "element": null },
+ "parent": 1004803002,
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": 1004803004,
+ "pid": "/item",
+ "type": 3,
+ "subtype": 1,
+ "name": "Create",
+ "uri": "{/lang}/{/app}/item/create?{?}",
+ "target": "self",
+ "icon": null,
+ "order": 5,
+ "from": "ItemManagement",
+ "permission": { "permission": 4, "category": null, "element": null },
+ "parent": 1004803001,
+ "children": []
+ }
+ ]
}
]
},
@@ -66,7 +128,7 @@
"pid": "/",
"type": 2,
"subtype": 1,
- "name": "Articles",
+ "name": "Items",
"uri": "{/lang}/{/app}/sales/item/list",
"target": "self",
"icon": null,
@@ -94,7 +156,7 @@
"pid": "/sales/item",
"type": 3,
"subtype": 1,
- "name": "Article",
+ "name": "Item",
"uri": "{/lang}/{/app}/sales/item/single?{?}",
"target": "self",
"icon": null,
@@ -128,7 +190,7 @@
"pid": "/",
"type": 2,
"subtype": 1,
- "name": "Articles",
+ "name": "Items",
"uri": "{/lang}/{/app}/purchase/item/list",
"target": "self",
"icon": null,
@@ -156,7 +218,7 @@
"pid": "/purchase/item",
"type": 3,
"subtype": 1,
- "name": "Article",
+ "name": "Item",
"uri": "{/lang}/{/app}/purchase/item/single?{?}",
"target": "self",
"icon": null,
@@ -190,7 +252,7 @@
"pid": "/",
"type": 2,
"subtype": 1,
- "name": "Articles",
+ "name": "Items",
"uri": "{/lang}/{/app}/warehouse/item/list",
"target": "self",
"icon": null,
@@ -218,7 +280,7 @@
"pid": "/warehouse/item",
"type": 3,
"subtype": 1,
- "name": "Article",
+ "name": "Item",
"uri": "{/lang}/{/app}/warehouse/item/single?{?}",
"target": "self",
"icon": null,
@@ -252,7 +314,7 @@
"pid": "/",
"type": 2,
"subtype": 1,
- "name": "Articles",
+ "name": "Items",
"uri": "{/lang}/{/app}/production/item/list",
"target": "self",
"icon": null,
@@ -280,7 +342,7 @@
"pid": "ac2ed3d0212c51b3ba19a5c862eca728c3cb9d18",
"type": 3,
"subtype": 1,
- "name": "Article",
+ "name": "Item",
"uri": "{/lang}/{/app}/production/item/single?{?}",
"target": "self",
"icon": null,
@@ -314,7 +376,7 @@
"pid": "/sales/analysis",
"type": 3,
"subtype": 1,
- "name": "Article",
+ "name": "Item",
"uri": "{/lang}/{/app}/sales/analysis/item",
"target": "self",
"icon": null,
@@ -329,7 +391,7 @@
"pid": "/purchase/analysis",
"type": 3,
"subtype": 1,
- "name": "Article",
+ "name": "Item",
"uri": "{/lang}/{/app}/purchase/analysis/item",
"target": "self",
"icon": null,
diff --git a/Admin/Installer.php b/Admin/Installer.php
index a3e0126..6d97f40 100755
--- a/Admin/Installer.php
+++ b/Admin/Installer.php
@@ -128,11 +128,17 @@ final class Installer extends InstallerAbstract
$request->setData('number', (string) $item['number']);
$module->apiItemCreate($request, $response);
- $itemId = $response->get('')['response']->getId();
- $itemArray[] = !\is_array($response['response'])
- ? $response['response']->toArray()
- : $response['response'];
+ $responseData = $response->get('');
+ if (!\is_array($responseData)) {
+ continue;
+ }
+
+ $itemId = $responseData['response']->getId();
+
+ $itemArray[] = !\is_array($responseData['response'])
+ ? $responseData['response']->toArray()
+ : $responseData['response'];
foreach ($item['l11ns'] as $name => $l11ns) {
$l11nType = $l11nTypes[$name];
diff --git a/Admin/Routes/Web/Api.php b/Admin/Routes/Web/Api.php
new file mode 100644
index 0000000..2f40a0d
--- /dev/null
+++ b/Admin/Routes/Web/Api.php
@@ -0,0 +1,32 @@
+ [
+ [
+ 'dest' => '\Modules\ItemManagement\Controller\ApiController:apiItemFind',
+ 'verb' => RouteVerb::GET,
+ 'permission' => [
+ 'module' => ApiController::NAME,
+ 'type' => PermissionType::READ,
+ 'state' => PermissionCategory::SALES_ITEM,
+ ],
+ ],
+ ],
+];
diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php
index a3b41f1..d374f3e 100755
--- a/Admin/Routes/Web/Backend.php
+++ b/Admin/Routes/Web/Backend.php
@@ -51,9 +51,9 @@ return [
],
],
],
- '^.*/sales/item/list.*$' => [
+ '^/item/list.*$' => [
[
- 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementSalesList',
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementItemList',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::NAME,
@@ -62,25 +62,37 @@ return [
],
],
],
- '^.*/purchase/item/list.*$' => [
+ '^/item/create.*$' => [
[
- 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementPurchaseList',
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementItemCreate',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::NAME,
- 'type' => PermissionType::READ,
- 'state' => PermissionCategory::PURCHASE_ITEM,
+ 'type' => PermissionType::CREATE,
+ 'state' => PermissionCategory::SALES_ITEM,
],
],
],
- '^.*/warehouse/item/list.*$' => [
+ '^/item/profile.*$' => [
[
- 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementWarehousingList',
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementItemItem',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
- 'state' => PermissionCategory::STOCK_ITEM,
+ 'state' => PermissionCategory::SALES_ITEM,
+ ],
+ ],
+ ],
+
+ '^.*/sales/item/list.*$' => [
+ [
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementSalesList',
+ 'verb' => RouteVerb::GET,
+ 'permission' => [
+ 'module' => BackendController::NAME,
+ 'type' => PermissionType::READ,
+ 'state' => PermissionCategory::SALES_ITEM,
],
],
],
@@ -95,28 +107,6 @@ return [
],
],
],
- '^.*/purchase/item/create.*$' => [
- [
- 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementPurchaseCreate',
- 'verb' => RouteVerb::GET,
- 'permission' => [
- 'module' => BackendController::NAME,
- 'type' => PermissionType::CREATE,
- 'state' => PermissionCategory::PURCHASE_ITEM,
- ],
- ],
- ],
- '.*/warehouse/item/create.*$' => [
- [
- 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementWarehousingCreate',
- 'verb' => RouteVerb::GET,
- 'permission' => [
- 'module' => BackendController::NAME,
- 'type' => PermissionType::CREATE,
- 'state' => PermissionCategory::STOCK_ITEM,
- ],
- ],
- ],
'^.*/sales/item/profile.*$' => [
[
'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementSalesItem',
@@ -128,6 +118,29 @@ return [
],
],
],
+
+ '^.*/purchase/item/list.*$' => [
+ [
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementPurchaseList',
+ 'verb' => RouteVerb::GET,
+ 'permission' => [
+ 'module' => BackendController::NAME,
+ 'type' => PermissionType::READ,
+ 'state' => PermissionCategory::PURCHASE_ITEM,
+ ],
+ ],
+ ],
+ '^.*/purchase/item/create.*$' => [
+ [
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementPurchaseCreate',
+ 'verb' => RouteVerb::GET,
+ 'permission' => [
+ 'module' => BackendController::NAME,
+ 'type' => PermissionType::CREATE,
+ 'state' => PermissionCategory::PURCHASE_ITEM,
+ ],
+ ],
+ ],
'^.*/purchase/item/profile.*$' => [
[
'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementPurchaseItem',
@@ -139,6 +152,29 @@ return [
],
],
],
+
+ '^.*/warehouse/item/list.*$' => [
+ [
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementWarehousingList',
+ 'verb' => RouteVerb::GET,
+ 'permission' => [
+ 'module' => BackendController::NAME,
+ 'type' => PermissionType::READ,
+ 'state' => PermissionCategory::STOCK_ITEM,
+ ],
+ ],
+ ],
+ '.*/warehouse/item/create.*$' => [
+ [
+ 'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementWarehousingCreate',
+ 'verb' => RouteVerb::GET,
+ 'permission' => [
+ 'module' => BackendController::NAME,
+ 'type' => PermissionType::CREATE,
+ 'state' => PermissionCategory::STOCK_ITEM,
+ ],
+ ],
+ ],
'^.*/warehouse/item/profile.*$' => [
[
'dest' => '\Modules\ItemManagement\Controller\BackendController:viewItemManagementWarehouseItem',
diff --git a/Controller/ApiController.php b/Controller/ApiController.php
index 6013303..f01897b 100755
--- a/Controller/ApiController.php
+++ b/Controller/ApiController.php
@@ -14,6 +14,8 @@ declare(strict_types=1);
namespace Modules\ItemManagement\Controller;
+use Modules\Admin\Models\NullAccount;
+use Modules\Billing\Models\PricingMapper;
use Modules\ItemManagement\Models\Item;
use Modules\ItemManagement\Models\ItemAttribute;
use Modules\ItemManagement\Models\ItemAttributeMapper;
@@ -35,7 +37,10 @@ use Modules\ItemManagement\Models\ItemRelationTypeMapper;
use Modules\ItemManagement\Models\NullItemAttributeType;
use Modules\ItemManagement\Models\NullItemAttributeValue;
use Modules\ItemManagement\Models\NullItemL11nType;
+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\Localization\BaseStringL11n;
use phpOMS\Localization\ISO4217CharEnum;
@@ -46,6 +51,7 @@ use phpOMS\Message\NotificationLevel;
use phpOMS\Message\RequestAbstract;
use phpOMS\Message\ResponseAbstract;
use phpOMS\Model\Message\FormValidation;
+use phpOMS\System\MimeType;
/**
* ItemManagement class.
@@ -57,6 +63,64 @@ use phpOMS\Model\Message\FormValidation;
*/
final class ApiController extends Controller
{
+ /**
+ * Api method to find items
+ *
+ * @param RequestAbstract $request Request
+ * @param ResponseAbstract $response Response
+ * @param mixed $data Generic data
+ *
+ * @return void
+ *
+ * @api
+ *
+ * @since 1.0.0
+ */
+ public function apiItemFind(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
+ {
+ $l11n = ItemL11nMapper::getAll()
+ ->with('type')
+ ->where('type/title', ['name1', 'name2', 'name3'], 'IN')
+ ->where('language', $request->getLanguage())
+ ->where('description', '%' . ($request->getData('search') ?? '') . '%', 'LIKE')
+ ->execute();
+
+ $items = [];
+ foreach ($l11n as $item) {
+ $items[] = $item->item;
+ }
+
+ $response->header->set('Content-Type', MimeType::M_JSON, true);
+ $response->set(
+ $request->uri->__toString(),
+ \array_values(
+ ItemMapper::getAll()
+ ->with('l11n')
+ ->with('l11n/type')
+ ->where('id', $items, 'IN')
+ ->where('l11n/type/title', ['name1', 'name2', 'name3'], 'IN')
+ ->where('l11n/language', $request->getLanguage())
+ ->execute()
+ )
+ );
+
+ /*
+ @todo: BIG TODO.
+ This is the query I want to be used internally:
+
+ select itemmgmt_item.itemmgmt_item_no, itemmgmt_item_l11n.itemmgmt_item_l11n_description
+ from itemmgmt_item
+ left join itemmgmt_item_l11n on itemmgmt_item.itemmgmt_item_id = itemmgmt_item_l11n.itemmgmt_item_l11n_item
+ left join itemmgmt_item_l11n_type on itemmgmt_item_l11n.itemmgmt_item_l11n_typeref = itemmgmt_item_l11n_type.itemmgmt_item_l11n_type_id
+ where
+ itemmgmt_item_l11n_type.itemmgmt_item_l11n_type_title IN ("name1", "name2", "name3")
+ AND itemmgmt_item_l11n.itemmgmt_item_l11n_lang = "en"
+ AND itemmgmt_item_l11n.itemmgmt_item_l11n_description LIKE "%Doc%"
+
+ It is not used because they are defined as has many relations and therefore queried as a loop internally. I as the person making the request know its a 1 to 1 result despite the 1 to many db relation.
+ */
+ }
+
/**
* Api method to create item
*
@@ -85,9 +149,74 @@ final class ApiController extends Controller
$this->createModel($request->header->account, $item, ItemMapper::class, 'item', $request->getOrigin());
$this->app->dbPool->get()->con->commit();
+ $this->createMediaDirForItem($item->number, $request->header->account);
+
+ $uploadedFiles = $request->getFile('item_profile_image');
+ if (!empty($uploadedFiles)) {
+ // upload image
+ $uploaded = $this->app->moduleManager->get('Media')->uploadFiles(
+ names: [],
+ fileNames: [],
+ files: $uploadedFiles,
+ account: $request->header->account,
+ basePath: __DIR__ . '/../../../Modules/Media/Files/Modules/ItemManagement/Items/' . $item->number,
+ virtualPath: '/Modules/ItemManagement/Items/' . $item->number,
+ pathSettings: PathSettings::FILE_PATH
+ );
+
+ // create type / media relation
+ $profileImageType = MediaTypeMapper::get()
+ ->where('name', 'item_profile_image')
+ ->execute();
+
+ $this->createModelRelation(
+ $request->header->account,
+ $uploaded[0]->getId(),
+ $profileImageType->getId(),
+ MediaMapper::class,
+ 'types',
+ '',
+ $request->getOrigin()
+ );
+
+ // create item relation
+ $this->createModelRelation(
+ $request->header->account,
+ $item->getId(),
+ $uploaded[0]->getId(),
+ ItemMapper::class,
+ 'files',
+ '',
+ $request->getOrigin()
+ );
+ }
+
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Item', 'Item successfully created', $item);
}
+ /**
+ * Create directory for an account
+ *
+ * @param string $number Item number
+ * @param int $createdBy Creator of the directory
+ *
+ * @return Collection
+ *
+ * @since 1.0.0
+ */
+ private function createMediaDirForItem(string $number, int $createdBy) : Collection
+ {
+ $collection = new Collection();
+ $collection->name = $number;
+ $collection->setVirtualPath('/Modules/ItemManagement/Items');
+ $collection->setPath('/Modules/Media/Files/Modules/ItemManagement/Items/' . $number);
+ $collection->createdBy = new NullAccount($createdBy);
+
+ CollectionMapper::create()->execute($collection);
+
+ return $collection;
+ }
+
/**
* Method to create item from request.
*
@@ -104,8 +233,8 @@ final class ApiController extends Controller
$item->salesPrice = new Money($request->getData('salesprice', 'int') ?? 0);
$item->purchasePrice = new Money($request->getData('purchaseprice', 'int') ?? 0);
$item->info = (string) ($request->getData('info') ?? '');
- $item->parent = ($request->getData('parent') !== null) ? (int) $request->getData('parent') : null;
- $item->unit = ($request->getData('unit') !== null) ? (int) $request->getData('unit') : null;
+ $item->parent = $request->getData('parent', 'int');
+ $item->unit = $request->getData('unit', 'int');
return $item;
}
@@ -817,8 +946,8 @@ final class ApiController extends Controller
fileNames: $request->getDataList('filenames'),
files: $uploadedFiles,
account: $request->header->account,
- basePath: __DIR__ . '/../../../Modules/Media/Files/Modules/ItemManagement/Articles/' . ($request->getData('item') ?? '0'),
- virtualPath: '/Modules/ItemManagement/Articles/' . ($request->getData('item') ?? '0'),
+ basePath: __DIR__ . '/../../../Modules/Media/Files/Modules/ItemManagement/Items/' . ($request->getData('item') ?? '0'),
+ virtualPath: '/Modules/ItemManagement/Items/' . ($request->getData('item') ?? '0'),
pathSettings: PathSettings::FILE_PATH
);
@@ -888,7 +1017,7 @@ final class ApiController extends Controller
return;
}
- $request->setData('virtualpath', '/Modules/ItemManagement/Articles/' . $request->getData('id'), true);
+ $request->setData('virtualpath', '/Modules/ItemManagement/Items/' . $request->getData('id'), true);
$this->app->moduleManager->get('Editor')->apiEditorCreate($request, $response, $data);
if ($response->header->status !== RequestStatusCode::R_200) {
diff --git a/Controller/BackendController.php b/Controller/BackendController.php
index 2b27ab3..46e5eda 100755
--- a/Controller/BackendController.php
+++ b/Controller/BackendController.php
@@ -161,6 +161,41 @@ final class BackendController extends Controller
return $view;
}
+ /**
+ * Routing end-point for application behaviour.
+ *
+ * @param RequestAbstract $request Request
+ * @param ResponseAbstract $response Response
+ * @param mixed $data Generic data
+ *
+ * @return RenderableInterface
+ *
+ * @since 1.0.0
+ * @codeCoverageIgnore
+ */
+ public function viewItemManagementItemList(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface
+ {
+ $view = new View($this->app->l11nManager, $request, $response);
+ $view->setTemplate('/Modules/ItemManagement/Theme/Backend/item-list');
+ $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1004801001, $request, $response));
+
+ /** @var \Modules\ItemManagement\Models\Item[] $items */
+ $items = ItemMapper::getAll()
+ ->with('l11n')
+ ->with('l11n/type')
+ ->with('files')
+ ->with('files/types')
+ ->where('l11n/language', $response->getLanguage())
+ ->where('l11n/type/title', ['name1', 'name2', 'name3'], 'IN')
+ ->where('files/types/name', 'item_profile_image')
+ ->limit(25)
+ ->execute();
+
+ $view->addData('items', $items);
+
+ return $view;
+ }
+
/**
* Routing end-point for application behaviour.
*
@@ -239,7 +274,7 @@ final class BackendController extends Controller
public function viewItemManagementWarehousingList(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
- $view->setTemplate('/Modules/ItemManagement/Theme/Backend/stock-list');
+ $view->setTemplate('/Modules/ItemManagement/Theme/Backend/stock-item-list');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1004807001, $request, $response));
$items = ItemMapper::getAll()->execute();
@@ -311,6 +346,99 @@ final class BackendController extends Controller
return $view;
}
+ /**
+ * Routing end-point for application behaviour.
+ *
+ * @param RequestAbstract $request Request
+ * @param ResponseAbstract $response Response
+ * @param mixed $data Generic data
+ *
+ * @return View
+ *
+ * @since 1.0.0
+ * @codeCoverageIgnore
+ */
+ public function viewItemManagementItemItem(RequestAbstract $request, ResponseAbstract $response, $data = null) : View
+ {
+ $head = $response->get('Content')->getData('head');
+ $head->addAsset(AssetType::CSS, 'Resources/chartjs/Chartjs/chart.css');
+ $head->addAsset(AssetType::JSLATE, 'Resources/chartjs/Chartjs/chart.js');
+ $head->addAsset(AssetType::JSLATE, 'Modules/ItemManagement/Controller.js', ['type' => 'module']);
+
+ $view = new View($this->app->l11nManager, $request, $response);
+ $view->setTemplate('/Modules/ItemManagement/Theme/Backend/item-profile');
+ $view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1004803001, $request, $response));
+
+ /** @var \Modules\ItemManagement\Models\Item $item */
+ $item = ItemMapper::get()
+ ->with('l11n')
+ ->with('l11n/type')
+ ->with('files')
+ ->with('files/types')
+ ->with('notes')
+ ->where('id', (int) $request->getData('id'))
+ ->where('l11n/language', $response->getLanguage())
+ ->where('l11n/type/title', ['name1', 'name2', 'name3'], 'IN')
+ ->limit(5, 'files')->sort('files/id', OrderType::DESC) // @todo: limit not working!!!
+ ->limit(5, 'notes')->sort('notes/id', OrderType::DESC)
+ ->execute();
+
+ $view->addData('item', $item);
+
+ /** @var \Model\Setting $settings */
+ $settings = $this->app->appSettings->get(null, [
+ SettingsEnum::DEFAULT_LOCALIZATION,
+ ]);
+
+ $view->setData('defaultlocalization', LocalizationMapper::get()->where('id', (int) $settings->getId())->execute());
+
+ // stats
+ if ($this->app->moduleManager->isActive('Billing')) {
+ $ytd = SalesBillMapper::getSalesByItemId($item->getId(), new SmartDateTime('Y-01-01'), new SmartDateTime('now'));
+ $mtd = SalesBillMapper::getSalesByItemId($item->getId(), new SmartDateTime('Y-m-01'), new SmartDateTime('now'));
+ $avg = SalesBillMapper::getAvgSalesPriceByItemId($item->getId(), (new SmartDateTime('now'))->smartModify(-1), new SmartDateTime('now'));
+
+ $lastOrder = SalesBillMapper::getLastOrderDateByItemId($item->getId());
+
+ $newestInvoices = SalesBillMapper::getAll()
+ ->with('type')
+ ->where('type/transferType', BillTransferType::SALES)
+ ->sort('id', OrderType::DESC)
+ ->limit(5)
+ ->execute();
+
+ $topCustomers = [];
+ $allInvoices = SalesBillMapper::getItemBills($item->getId(), new SmartDateTime('Y-01-01'), new SmartDateTime('now'));
+ $regionSales = SalesBillMapper::getItemRegionSales($item->getId(), new SmartDateTime('Y-01-01'), new SmartDateTime('now'));
+ $countrySales = SalesBillMapper::getItemCountrySales($item->getId(), new SmartDateTime('Y-01-01'), new SmartDateTime('now'), 5);
+ $monthlySalesCosts = SalesBillMapper::getItemMonthlySalesCosts($item->getId(), (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->addData('ytd', $ytd);
+ $view->addData('mtd', $mtd);
+ $view->addData('avg', $avg);
+ $view->addData('lastOrder', $lastOrder);
+ $view->addData('newestInvoices', $newestInvoices);
+ $view->addData('allInvoices', $allInvoices);
+ $view->addData('topCustomers', $topCustomers);
+ $view->addData('regionSales', $regionSales);
+ $view->addData('countrySales', $countrySales);
+ $view->addData('monthlySalesCosts', $monthlySalesCosts);
+
+ return $view;
+ }
+
/**
* Routing end-point for application behaviour.
*
diff --git a/Models/Item.php b/Models/Item.php
index 8018dfa..3095f65 100755
--- a/Models/Item.php
+++ b/Models/Item.php
@@ -27,7 +27,7 @@ use phpOMS\Localization\Money;
* @link https://jingga.app
* @since 1.0.0
*/
-class Item
+class Item implements \JsonSerializable
{
/**
* ID.
@@ -374,6 +374,7 @@ class Item
'number' => $this->number,
'status' => $this->status,
'info' => $this->info,
+ 'l11n' => $this->l11n,
];
}
diff --git a/Theme/Backend/Lang/Navigation.en.lang.php b/Theme/Backend/Lang/Navigation.en.lang.php
index 1f3c37a..c3a973c 100755
--- a/Theme/Backend/Lang/Navigation.en.lang.php
+++ b/Theme/Backend/Lang/Navigation.en.lang.php
@@ -14,7 +14,7 @@ declare(strict_types=1);
return ['Navigation' => [
'Analyze' => 'Analyze',
- 'Article' => 'Article',
+ 'Items' => 'Items',
'Attributes' => 'Attributes',
'Create' => 'Create',
'ItemManagement' => 'Item Management',
diff --git a/Theme/Backend/item-list.tpl.php b/Theme/Backend/item-list.tpl.php
new file mode 100755
index 0000000..cda26db
--- /dev/null
+++ b/Theme/Backend/item-list.tpl.php
@@ -0,0 +1,156 @@
+getData('items') ?? [];
+
+echo $this->getData('nav')->render(); ?>
+
+
+
+
+ = $this->getHtml('Items'); ?>
+
+
+
+
diff --git a/Theme/Backend/item-profile.tpl.php b/Theme/Backend/item-profile.tpl.php
new file mode 100644
index 0000000..295637a
--- /dev/null
+++ b/Theme/Backend/item-profile.tpl.php
@@ -0,0 +1,980 @@
+getData('item');
+
+$itemL11n = $item->getL11ns();
+$itemAttribute = $item->getAttributes();
+
+$notes = $item->getNotes();
+$files = $item->getFiles();
+
+$newestInvoices = $this->getData('newestInvoices') ?? [];
+$allInvoices = $this->getData('allInvoices') ?? [];
+$topCustomers = $this->getData('topCustomers') ?? [];
+$regionSales = $this->getData('regionSales') ?? [];
+$countrySales = $this->getData('countrySales') ?? [];
+$monthlySalesCosts = $this->getData('monthlySalesCosts') ?? [];
+
+$languages = ISO639Enum::getConstants();
+
+/** @var \phpOMS\Localization\Localization $l11n */
+$l11n = $this->getData('defaultlocalization') ?? new NullLocalization();
+
+echo $this->getData('nav')->render();
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
request->uri->fragment === 'c-tab-1' ? ' checked' : ''; ?>>
+
+
+
+
+
+ getFileByTypeName('item_profile_image'); ?>
+
+
+
); ?>)
+
+
+
+
+
+
+
+
+
+
+
+ | = $this->getHtml('YTDSales'); ?>:
+ | = $this->getData('ytd')->getCurrency(); ?>
+ |
| = $this->getHtml('MTDSales'); ?>:
+ | = $this->getData('mtd')->getCurrency(); ?>
+ |
| = $this->getHtml('ILV'); ?>:
+ |
+ |
| = $this->getHtml('MRR'); ?>:
+ |
+ |
+
+
+
+
+
+
+
+
+ | = $this->getHtml('LastOrder'); ?>:
+ | = $this->getData('lastOrder') !== null ? $this->getData('lastOrder')->format('Y-m-d H:i') : ''; ?>
+ |
| = $this->getHtml('PriceChange'); ?>:
+ |
+ |
| = $this->getHtml('Created'); ?>:
+ | = $item->createdAt->format('Y-m-d H:i'); ?>
+ |
| = $this->getHtml('Modified'); ?>:
+ |
+ |
+
+
+
+
+
+
+
+
+ | = $this->getHtml('SalesPrice'); ?>:
+ | = $item->salesPrice->getCurrency(); ?>
+ |
| = $this->getHtml('PurchasePrice'); ?>:
+ | = $item->purchasePrice->getCurrency(); ?>
+ |
| = $this->getHtml('Margin'); ?>:
+ | = \round(
+ $item->salesPrice->getInt() === 0
+ ? 0
+ : ($item->salesPrice->getInt() - $item->purchasePrice->getInt()) / $item->salesPrice->getInt() * 100, 2
+ ); ?> %
+ |
| = $this->getHtml('AvgPrice'); ?>:
+ | = $this->getData('avg')->getCurrency(); ?>
+ |
+
+
+
+
+
+
+
+
+ = $this->getHtml('Notes'); ?>
+
+
+
+
+
+
+ = $this->getHtml('Documents'); ?>
+
+
+
+
+
+
+
+
+ = $this->getHtml('RecentInvoices'); ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('Sales'); ?>
+
+
+
+
+
+
+
+
+
+
+ Regions
+
+
+
+
+
+
+
+
+ = $this->getHtml('Countries'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('Localizations'); ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('Attribute'); ?>
+
+
+
+
+
+
+ = $this->getHtml('Groups'); ?>
+
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('Pricing'); ?>
+
+
+
+
+
+
+
+ = $this->getHtml('Prices'); ?>
+
+
+
+ |
+ | = $this->getHtml('ID', '0', '0'); ?>
+ | = $this->getHtml('Name'); ?>
+ |
+ $value) : ++$c;
+ $url = UriFactory::build('{/lang}/{/app}/admin/group/settings?{?}&id=' . $value->getId()); ?>
+
+ |
+ | = $value->getId(); ?>
+ | = $this->printHtml($value->name); ?>
+
+
+ |
+ | = $this->getHtml('Empty', '0', '0'); ?>
+
+ |
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('Purchase'); ?>
+
+
+
+
+
+
+
+
+ = $this->getHtml('Supplier'); ?>
+
+
+
+
+
+
+
+ = $this->getHtml('Prices'); ?>
+
+
+ |
+ | = $this->getHtml('ID', '0', '0'); ?>
+ | = $this->getHtml('Name'); ?>
+ |
+ $value) : ++$c;
+ $url = UriFactory::build('{/lang}/{/app}/admin/group/settings?{?}&id=' . $value->getId()); ?>
+
+ |
+ | = $value->getId(); ?>
+ | = $this->printHtml($value->name); ?>
+
+
+ |
+ | = $this->getHtml('Empty', '0', '0'); ?>
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('General'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('General'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('RecentInvoices'); ?>
+
+
+
+
+
+
+
+
+
+
+
+ = $this->getHtml('Logs'); ?>
+
+
+ | IP
+ | = $this->getHtml('ID', '0', '0'); ?>
+ | = $this->getHtml('Name'); ?>
+ | = $this->getHtml('Log'); ?>
+ | = $this->getHtml('Date'); ?>
+ |
+
+ |
+ |
+
+ | = $this->printHtml($this->request->getOrigin()); ?>
+ | = $this->printHtml((string) $this->request->header->account); ?>
+ | = $this->printHtml((string) $this->request->header->account); ?>
+ | Creating item
+ | = $this->printHtml((new \DateTime('now'))->format('Y-m-d H:i:s')); ?>
+ |
+
+
+
+
+
\ No newline at end of file
diff --git a/Theme/Backend/stock-item-list.tpl.php b/Theme/Backend/stock-item-list.tpl.php
new file mode 100755
index 0000000..c78f812
--- /dev/null
+++ b/Theme/Backend/stock-item-list.tpl.php
@@ -0,0 +1,143 @@
+getData('items') ?? [];
+
+echo $this->getData('nav')->render(); ?>
+
+
+
+
+ = $this->getHtml('Items'); ?>
+
+
+
+
diff --git a/Theme/Backend/stock-list.tpl.php b/Theme/Backend/stock-list.tpl.php
deleted file mode 100755
index 9ba9720..0000000
--- a/Theme/Backend/stock-list.tpl.php
+++ /dev/null
@@ -1,78 +0,0 @@
-getData('items');
-
-echo $this->getData('nav')->render(); ?>
-
-
-
-
- = $this->getHtml('Items'); ?>
-
-
-
-