diff --git a/Admin/Install/types.json b/Admin/Install/types.json index 4f1da66..a60675a 100644 --- a/Admin/Install/types.json +++ b/Admin/Install/types.json @@ -6,6 +6,13 @@ "de": "Standard" } }, + { + "name": "virtual", + "l11n": { + "en": "Virtual", + "de": "Virtuell" + } + }, { "name": "incoming", "l11n": { @@ -47,5 +54,19 @@ "en": "Retention sample", "de": "Rückstellmuster" } + }, + { + "name": "consignment", + "l11n": { + "en": "Consignment stock", + "de": "Konsignationslager" + } + }, + { + "name": "duty_free", + "l11n": { + "en": "Duty-free", + "de": "Zollfreilager" + } } ] \ No newline at end of file diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php index 8fd3d8b..6a013b7 100755 --- a/Admin/Routes/Web/Backend.php +++ b/Admin/Routes/Web/Backend.php @@ -29,7 +29,7 @@ return [ ], ], ], - '^/warehouse/stock(\?.*)?$' => [ + '^/warehouse/stock/view(\?.*)?$' => [ [ 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStock', 'verb' => RouteVerb::GET, @@ -40,6 +40,17 @@ return [ ], ], ], + '^/warehouse/stock/create(\?.*)?$' => [ + [ + 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockCreate', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::CREATE, + 'state' => PermissionCategory::STOCK, + ], + ], + ], '^/warehouse/stock/type/list(\?.*$|$)' => [ [ 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockTypeList', @@ -51,7 +62,7 @@ return [ ], ], ], - '^/warehouse/stock/type(\?.*)?$' => [ + '^/warehouse/stock/type/view(\?.*)?$' => [ [ 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockType', 'verb' => RouteVerb::GET, @@ -62,6 +73,17 @@ return [ ], ], ], + '^/warehouse/stock/type/create(\?.*)?$' => [ + [ + 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockTypeCreate', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::CREATE, + 'state' => PermissionCategory::STOCK, + ], + ], + ], '^/warehouse/stock/location/list(\?.*$|$)' => [ [ 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockLocationList', @@ -73,7 +95,7 @@ return [ ], ], ], - '^/warehouse/stock/location(\?.*)?$' => [ + '^/warehouse/stock/location/view(\?.*)?$' => [ [ 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockLocation', 'verb' => RouteVerb::GET, @@ -84,4 +106,15 @@ return [ ], ], ], + '^/warehouse/stock/location/create(\?.*)?$' => [ + [ + 'dest' => '\Modules\WarehouseManagement\Controller\BackendController:viewStockLocationCreate', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::STOCK_LOCATION, + ], + ], + ], ]; diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 02b102f..ecf24f0 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -21,6 +21,7 @@ use Modules\Billing\Models\BillTransferType; use Modules\ClientManagement\Models\NullClient; use Modules\ItemManagement\Models\StockIdentifierType; use Modules\SupplierManagement\Models\NullSupplier; +use Modules\WarehouseManagement\Models\NullStockType; use Modules\WarehouseManagement\Models\Stock; use Modules\WarehouseManagement\Models\StockDistribution; use Modules\WarehouseManagement\Models\StockDistributionMapper; @@ -186,6 +187,8 @@ final class ApiController extends Controller $location->name = $request->getDataString('name') ?? ''; $location->stock = $request->getDataInt('stock') ?? 1; + $location->type = $request->hasData('type') ? new NullStockType((int) $request->getDataInt('type')) : null; + return $location; } @@ -434,7 +437,7 @@ final class ApiController extends Controller /** @var \Modules\WarehouseManagement\Models\StockTransaction[] $transactions */ $transactions = StockTransactionMapper::getAll() ->where('billElement', $new->id) - ->execute(); + ->executeGetArray(); /* if ($new->item === $old->item) { @@ -463,7 +466,7 @@ final class ApiController extends Controller /** @var \Modules\WarehouseManagement\Models\StockTransaction[] $transactions */ $transactions = StockTransactionMapper::getAll() ->where('billElement', $new->id) - ->execute(); + ->executeGetArray(); StockTransactionMapper::delete()->execute($transactions); } elseif ($trigger === 'Billing-bill-delete') { @@ -471,7 +474,7 @@ final class ApiController extends Controller /** @var \Modules\WarehouseManagement\Models\StockTransaction[] $transactions */ $transactions = StockTransactionMapper::getAll() ->where('billElement', $element->id) - ->execute(); + ->executeGetArray(); StockTransactionMapper::delete()->execute($transactions); // @todo consider not to delete but mark as deleted? @@ -491,7 +494,7 @@ final class ApiController extends Controller /** @var \Modules\WarehouseManagement\Models\StockTransaction[] $transactions */ $transactions = StockTransactionMapper::getAll() ->where('billElement', $element->id) - ->execute(); + ->executeGetArray(); foreach ($transactions as $transaction) { $transaction->state = StockTransactionState::TRANSIT; // @todo change to more specific diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 571acd3..63b203a 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -70,7 +70,7 @@ final class BackendController extends Controller ->with('l11n') ->where('l11n/language', $response->header->l11n->language) ->limit(25) - ->execute(); + ->executeGetArray(); } return $view; @@ -106,7 +106,7 @@ final class BackendController extends Controller } else { $view->data['stocks'] = StockMapper::getAll() ->limit(25) - ->execute(); + ->executeGetArray(); } return $view; @@ -128,10 +128,21 @@ final class BackendController extends Controller { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/WarehouseManagement/Theme/Backend/stock'); + $view->setTemplate('/Modules/WarehouseManagement/Theme/Backend/stock-view'); $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1001302001, $request, $response); - $view->data['stock'] = StockMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $view->data['stock'] = StockMapper::get() + ->with('locations') + ->with('locations/type') + ->with('locations/type/l11n') + ->where('id', (int) $request->getData('id')) + ->where('locations/type/l11n/language', [$request->header->l11n->language, null]) + ->execute(); + + $view->data['types'] = StockTypeMapper::getAll() + ->with('l11n') + ->where('l11n/language', $request->header->l11n->language) + ->executeGetArray(); return $view; } @@ -155,13 +166,15 @@ final class BackendController extends Controller $view->setTemplate('/Modules/WarehouseManagement/Theme/Backend/stock-type-view'); $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1001302001, $request, $response); - $view->data['type'] = StockMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $view->data['type'] = StockMapper::get() + ->where('id', (int) $request->getData('id'))->execute(); $l11nValues = StockTypeL11nMapper::getAll() ->with('type') ->where('ref', $view->data['type']->id) - ->execute(); + ->executeGetArray(); + $view->data['l11nView'] = new \Web\Backend\Views\L11nView($this->app->l11nManager, $request, $response); $view->data['l11nValues'] = $l11nValues; return $view; @@ -186,22 +199,13 @@ final class BackendController extends Controller $view->setTemplate('/Modules/WarehouseManagement/Theme/Backend/stock-location-list'); $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1001302001, $request, $response); - if ($request->getData('ptype') === 'p') { - $view->data['locations'] = StockLocationMapper::getAll() - ->with('stock') - ->limit(25) - ->execute(); - } elseif ($request->getData('ptype') === 'n') { - $view->data['locations'] = StockLocationMapper::getAll() - ->with('stock') - ->limit(25) - ->execute(); - } else { - $view->data['locations'] = StockLocationMapper::getAll() - ->with('stock') - ->limit(25) - ->execute(); - } + $view->data['locations'] = StockLocationMapper::getAll() + ->with('stock') + ->with('type') + ->with('type/l11n') + ->where('type/l11n/language', [$request->header->l11n->language, null]) + ->limit(25) + ->executeGetArray(); return $view; } @@ -222,10 +226,22 @@ final class BackendController extends Controller { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/WarehouseManagement/Theme/Backend/stock-location'); + $view->setTemplate('/Modules/WarehouseManagement/Theme/Backend/stock-location-view'); $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1001302001, $request, $response); - $view->data['location'] = StockLocationMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $view->data['location'] = StockLocationMapper::get() + ->with('stock') + ->with('shelfs') + ->with('type') + ->with('type/l11n') + ->where('type/l11n/language', [$request->header->l11n->language, null]) + ->where('id', (int) $request->getData('id')) + ->execute(); + + $view->data['types'] = StockTypeMapper::getAll() + ->with('l11n') + ->where('l11n/language', $request->header->l11n->language) + ->executeGetArray(); return $view; } diff --git a/Models/NullStockType.php b/Models/NullStockType.php new file mode 100644 index 0000000..e5e891c --- /dev/null +++ b/Models/NullStockType.php @@ -0,0 +1,46 @@ +id = $id; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : mixed + { + return ['id' => $this->id]; + } +} diff --git a/Models/Stock.php b/Models/Stock.php index 6962e10..2fbad9e 100755 --- a/Models/Stock.php +++ b/Models/Stock.php @@ -59,6 +59,8 @@ class Stock public bool $inventory = false; + public array $locations = []; + /** * Constructor. * diff --git a/Models/StockDistribution.php b/Models/StockDistribution.php index dc09a69..c00bf67 100644 --- a/Models/StockDistribution.php +++ b/Models/StockDistribution.php @@ -41,4 +41,6 @@ class StockDistribution public int $stock = 0; public int $stockType = 0; + + // @remark We don't care about the location because that is just an internal thing and not all companies really care about that. } diff --git a/Models/StockLocation.php b/Models/StockLocation.php index 3c93ec1..2af015c 100755 --- a/Models/StockLocation.php +++ b/Models/StockLocation.php @@ -36,7 +36,7 @@ class StockLocation public int | Stock $stock = 0; - public ?int $type = null; + public ?StockType $type = null; public int $x = 0; @@ -44,6 +44,8 @@ class StockLocation public int $z = 0; + public array $shelfs = []; + /** * Constructor. * diff --git a/Models/StockLocationMapper.php b/Models/StockLocationMapper.php index fabb0d8..6e4a15a 100755 --- a/Models/StockLocationMapper.php +++ b/Models/StockLocationMapper.php @@ -58,6 +58,34 @@ final class StockLocationMapper extends DataMapperFactory ], ]; + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + public const OWNS_ONE = [ + 'type' => [ + 'mapper' => StockTypeMapper::class, + 'external' => 'warehousemgmt_stocklocation_type', + ], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'shelfs' => [ + 'mapper' => StockShelfMapper::class, + 'table' => 'warehousemgmt_stockshelf', + 'self' => 'warehousemgmt_stockshelf_location', + 'external' => null, + ], + ]; + /** * Primary table. * diff --git a/Models/StockMapper.php b/Models/StockMapper.php index c02bda3..e7d8d69 100755 --- a/Models/StockMapper.php +++ b/Models/StockMapper.php @@ -80,6 +80,21 @@ final class StockMapper extends DataMapperFactory ], ]; + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'locations' => [ + 'mapper' => StockLocationMapper::class, + 'table' => 'warehousemgmt_stocklocation', + 'self' => 'warehousemgmt_stocklocation_stock', + 'external' => null, + ], + ]; + /** * Primary table. * @@ -125,7 +140,7 @@ final class StockMapper extends DataMapperFactory /** @var \Modules\WarehouseManagement\Models\StockDistribution[] $temp */ $temp = StockDistributionMapper::getAll() ->where('item', $items, 'IN') - ->execute(); + ->executeGetArray(); foreach ($temp as $t) { if (!isset($dists[$t->item])) { diff --git a/Theme/Backend/Lang/de.lang.php b/Theme/Backend/Lang/de.lang.php index 39a3bb6..5e7f755 100755 --- a/Theme/Backend/Lang/de.lang.php +++ b/Theme/Backend/Lang/de.lang.php @@ -13,12 +13,12 @@ declare(strict_types=1); return ['WarehouseManagement' => [ - 'Language' => '', - 'Localization' => '', - 'Localizations' => '', - 'Locations' => '', - 'Name' => 'Name', - 'Stock' => 'Aktie', - 'Stocks' => '', - 'Type' => 'Typ', + 'Locations' => 'Lagerplätze', + 'Name' => 'Name', + 'Stock' => 'Lager', + 'Stocks' => 'Lager', + 'Shelfs' => 'Fächer', + 'Shelf' => 'Fach', + 'Type' => 'Typ', + 'Location' => 'Lagerplatz', ]]; diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 2c9e098..96d91d8 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -13,12 +13,12 @@ declare(strict_types=1); return ['WarehouseManagement' => [ - 'Language' => '', - 'Localization' => '', - 'Localizations' => '', - 'Locations' => 'Locations', - 'Name' => 'Name', - 'Stock' => 'Stock', - 'Stocks' => 'Stocks', - 'Type' => 'Type', + 'Locations' => 'Locations', + 'Name' => 'Name', + 'Stock' => 'Stock', + 'Stocks' => 'Stocks', + 'Shelfs' => 'Shelfs', + 'Shelf' => 'Shelf', + 'Type' => 'Type', + 'Location' => 'Location', ]]; diff --git a/Theme/Backend/stock-list.tpl.php b/Theme/Backend/stock-list.tpl.php index 702a5c8..cdcbc71 100755 --- a/Theme/Backend/stock-list.tpl.php +++ b/Theme/Backend/stock-list.tpl.php @@ -21,7 +21,11 @@ echo $this->data['nav']->render(); ?>
-
getHtml('Stocks'); ?>download
+
+ getHtml('Stocks'); ?> + download + getHtml('New', '0', '0'); ?> +
@@ -31,7 +35,7 @@ echo $this->data['nav']->render(); ?> $value) : ++$count; - $url = UriFactory::build('{/base}/warehouse/stock?{?}&id=' . $value->id); + $url = UriFactory::build('{/base}/warehouse/stock/view?{?}&id=' . $value->id); ?> $value) : ++$count; - $url = UriFactory::build('{/base}/warehouse/stock/location?{?}&id=' . $value->id); + $url = UriFactory::build('{/base}/warehouse/stock/location/view?{?}&id=' . $value->id); ?>
id; ?> diff --git a/Theme/Backend/stock-location-list.tpl.php b/Theme/Backend/stock-location-list.tpl.php index cfb31c5..42e11b0 100755 --- a/Theme/Backend/stock-location-list.tpl.php +++ b/Theme/Backend/stock-location-list.tpl.php @@ -29,15 +29,17 @@ echo $this->data['nav']->render(); ?> getHtml('ID', '0', '0'); ?> getHtml('Stock'); ?> getHtml('Name'); ?> + getHtml('Type'); ?>
id; ?> stock->name; ?> name; ?> + printHtml($value->type->getL11n()); ?>
getHtml('Empty', '0', '0'); ?> diff --git a/Theme/Backend/stock-location-view.tpl.php b/Theme/Backend/stock-location-view.tpl.php new file mode 100644 index 0000000..e1ba979 --- /dev/null +++ b/Theme/Backend/stock-location-view.tpl.php @@ -0,0 +1,153 @@ +data['location'] ?? new NullStockLocation(); +$isNew = $location->id === 0; + +echo $this->data['nav']->render(); +?> + +
+
+
+
+
getHtml('Location'); ?>
+
+
+ + +
+ +
+ + > +
+ +
+ + +
+ +
+ + +
+
+
+ + + + + + +
+
+
+
+
+ + +
+
+
+
+
getHtml('Shelf'); ?>
+
+
+ + +
+ +
+ + +
+ + +
+
+ + + +
+
+
+
+ +
+
+
getHtml('Shelfs'); ?>download
+
+ + + + + + shelfs as $key => $value) : + ++$c; + $url = UriFactory::build('{/base}/warehouse/stock/location/shelf/view?id=' . $value->id); + ?> + + +
+ getHtml('ID', '0', '0'); ?> + getHtml('Name', '0', '0'); ?> +
+ settings + + + + + + + id; ?> + name; ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
+
+ \ No newline at end of file diff --git a/Theme/Backend/stock-location.tpl.php b/Theme/Backend/stock-location.tpl.php deleted file mode 100755 index 07ab020..0000000 --- a/Theme/Backend/stock-location.tpl.php +++ /dev/null @@ -1,26 +0,0 @@ -data['location']; - -echo $this->data['nav']->render(); -?> -
-
-
-
printHtml($location->name); ?>
-
-
-
-
\ No newline at end of file diff --git a/Theme/Backend/stock-type-list.tpl.php b/Theme/Backend/stock-type-list.tpl.php index 9967cd1..b54842c 100644 --- a/Theme/Backend/stock-type-list.tpl.php +++ b/Theme/Backend/stock-type-list.tpl.php @@ -21,7 +21,11 @@ echo $this->data['nav']->render(); ?>
-
getHtml('Stocks'); ?>download
+
+ getHtml('Stocks'); ?> + download + getHtml('New', '0', '0'); ?> +
@@ -31,7 +35,7 @@ echo $this->data['nav']->render(); ?> $value) : ++$count; - $url = UriFactory::build('{/base}/warehouse/stock/type?id=' . $value->id); + $url = UriFactory::build('{/base}/warehouse/stock/type/view?id=' . $value->id); ?>
id; ?> diff --git a/Theme/Backend/stock-type-view.tpl.php b/Theme/Backend/stock-type-view.tpl.php index d697a6d..abf3418 100644 --- a/Theme/Backend/stock-type-view.tpl.php +++ b/Theme/Backend/stock-type-view.tpl.php @@ -12,82 +12,42 @@ */ declare(strict_types=1); -$type = $this->data['type']; +use Modules\WarehouseManagement\Models\NullStockType; +use phpOMS\Uri\UriFactory; + +$type = $this->data['type'] ?? new NullStockType(); +$isNew = $type->id === 0; echo $this->data['nav']->render(); ?>
-
+
+
getHtml('Type'); ?>
+
+ + +
+
- + >
-
-
- -
-
-
getHtml('Localizations'); ?>download
-
- - - - - - data['l11nValues']; - foreach ($itemL11n as $value) : ++$c; ?> - - -
- getHtml('ID', '0', '0'); ?> - getHtml('Name'); ?>expand_lessexpand_more - getHtml('Language'); ?>expand_lessexpand_more - getHtml('Localization'); ?>expand_lessexpand_more -
- settings - type->isRequired) : ?> - - - - - - - - id; ?> - printHtml($value->type->title); ?> - printHtml($value->language); ?> - printHtml(\substr($value->content, 0, 100))); ?> - - -
getHtml('Empty', '0', '0'); ?> - -
-
+
+ + +
+ data['l11nView']->render( + $this->data['l11nValues'], + [], + '{/api}warehouse/stock/type/l11n?csrf={$CSRF}' + ); + ?> +
+ diff --git a/Theme/Backend/stock-view.tpl.php b/Theme/Backend/stock-view.tpl.php new file mode 100644 index 0000000..9f65ceb --- /dev/null +++ b/Theme/Backend/stock-view.tpl.php @@ -0,0 +1,150 @@ +data['stock'] ?? new NullStock(); +$isNew = $stock->id === 0; + +echo $this->data['nav']->render(); +?> +
+
+
+
+
getHtml('Stock'); ?>
+
+
+ + +
+ +
+ + +
+
+
+ + + + + + +
+
+ +
+
+ + +
+
+
+
+
getHtml('Location'); ?>
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+ + + +
+
+
+
+ +
+
+
getHtml('Locations'); ?>download
+
+ + + + + + locations as $key => $value) : + ++$c; + $url = UriFactory::build('{/base}/warehouse/stock/location/view?id=' . $value->id); + ?> + + +
+ getHtml('ID', '0', '0'); ?> + getHtml('Type', '0', '0'); ?> + getHtml('Name', '0', '0'); ?> +
+ settings + + + + + + + id; ?> + printHtml($value->type->getL11n()); ?> + name; ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
+
+ \ No newline at end of file diff --git a/Theme/Backend/stock.tpl.php b/Theme/Backend/stock.tpl.php deleted file mode 100755 index 3b07a3f..0000000 --- a/Theme/Backend/stock.tpl.php +++ /dev/null @@ -1,31 +0,0 @@ -data['stock']; - -echo $this->data['nav']->render(); -?> -
-
-
-
getHtml('Stock'); ?>
-
-
- - -
-
-
-
-
\ No newline at end of file