diff --git a/Layout/default/User/Form.php b/Layout/default/User/Form.php index 3bc72f040..48e1d99c5 100644 --- a/Layout/default/User/Form.php +++ b/Layout/default/User/Form.php @@ -225,6 +225,31 @@ + +

Lager

+ +
+
+
+ can("WarehouseAdmin")) ? "checked='checked'" : ""?> /> + +
+
+ +
+
+ can("WarehouseUser")) ? "checked='checked'" : ""?> /> + +
+
+ +
+
+ can("WarehouseEShop")) ? "checked='checked'" : ""?> /> + +
+
+

Zusatzberechtigungen

diff --git a/Layout/default/menu.php b/Layout/default/menu.php index d717c8a77..12e8c53c7 100644 --- a/Layout/default/menu.php +++ b/Layout/default/menu.php @@ -130,23 +130,28 @@ - is(["Admin"])&& isset($_GET['warehouse'])): ?> + can(["WarehouseAdmin", "WarehouseUser", "WarehouseEShop"])): ?>
  • - Lager
    + can("WarehouseEShop") && !($me->can("WarehouseAdmin") || $me->can("WarehouseUser"))): ?> + E-Shop
    + can("WarehouseAdmin") || $me->can("WarehouseUser")): ?> + Lager
    +
  • diff --git a/application/User/User.php b/application/User/User.php index b4cdc27e1..2cb02d3ca 100644 --- a/application/User/User.php +++ b/application/User/User.php @@ -261,10 +261,9 @@ class User extends mfBaseModel { if(!is_array($what)) { $what = [$what]; } - - //ob_end_clean();var_dump($what, $this->permissions);exit; + foreach($what as $w) { - $perm = ucfirst(strtolower($w)); + $perm = ucfirst(($w)); if(is_object($this->permissions) && property_exists($this->permissions->data, "can$perm")) { if($this->permissions->{"can$perm"} === "true") { return true; diff --git a/application/User/UserController.php b/application/User/UserController.php index d239ce342..bc65ba9bb 100644 --- a/application/User/UserController.php +++ b/application/User/UserController.php @@ -235,6 +235,9 @@ class UserController extends mfBaseController $user->permissions->canBilling = "false"; $user->permissions->canFibu = "false"; $user->permissions->canStatistics = "false"; + $user->permissions->canWarehouseAdmin = "false"; + $user->permissions->canWarehouseEShop = "false"; + $user->permissions->canWarehouseUser = "false"; if($r->get("can") && is_array($r->can)) { foreach($r->can as $key => $can) { diff --git a/application/WarehouseArticle/WarehouseArticleController.php b/application/WarehouseArticle/WarehouseArticleController.php index 73d2734bf..a3df585bd 100644 --- a/application/WarehouseArticle/WarehouseArticleController.php +++ b/application/WarehouseArticle/WarehouseArticleController.php @@ -9,11 +9,15 @@ class WarehouseArticleController extends TTCrud { ['key' => 'title', 'text' => 'Titel', 'required' => true, 'table' => ['priority' => 9]], ['key' => 'description', 'text' => 'Beschreibung', 'required' => true, 'table' => false], ['key' => 'category', 'text' => 'Kategorie', 'required' => true], + ['key' => 'unit', 'text' => 'Einheit', 'required' => true,'table' => false], // Boolean value + ['key' => 'defaultSellMultiplier', 'text' => 'Standard Multiplikator','regex' => '/^[0-9]*$/' , 'required' => true,'modal' => ['type' => 'number'], 'table' => false], // Boolean value + ['key' => 'revenueAccount', 'text' => 'Erlöskonto', 'required' => true,'modal' => ['type' => 'number'], 'table' => false], // Boolean value ['key' => 'cheapestPurchasePrice', 'text' => 'Einkauf', 'modal' => false, 'table' => ['class' => 'text-center', 'suffix' => ' €']], ['key' => 'cheapestSellPrice', 'text' => 'Verkauf', 'modal' => false, 'table' => ['class' => 'text-center', 'suffix' => ' €']], - ['key' => 'warningAmount', 'text' => 'Warnmenge', 'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related - ['key' => 'criticalAmount', 'text' => 'Kritische Menge', 'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related - ['key' => 'isEShop', 'text' => 'Ist E-Shop', 'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value + ['key' => 'warningAmount', 'text' => 'Warnmenge', 'required' => true,'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related + ['key' => 'criticalAmount', 'text' => 'Kritische Menge', 'required' => true,'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related + ['key' => 'isSerialDocumentation', 'text' => 'Seriennummern', 'required' => true,'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value + ['key' => 'isEShop', 'text' => 'Ist E-Shop', 'required' => true,'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 8]] ]; @@ -43,6 +47,7 @@ class WarehouseArticleController extends TTCrud { $cheapestPurchasePrice = WarehouseArticleDistributorModel::getAll(['articleId' => $articleId], 1, 0, ['key' => 'purchasePrice', 'order' => 'ASC'])[0]->purchasePrice; + $article = WarehouseArticleModel::get($articleId); if (!$article instanceof WarehouseArticleModel) { @@ -53,13 +58,59 @@ class WarehouseArticleController extends TTCrud { // $cheapestSellPrice = $article->sellPriceOverride ?? $article->sellPriceMultiplier * $cheapestPurchasePrice; if ($article->cheapestPurchasePrice != $cheapestPurchasePrice) { - WarehouseArticleModel::update([...get_object_vars($article), // Unpack properties into an array - 'cheapestPurchasePrice' => $cheapestPurchasePrice]); + try { + WarehouseArticleModel::update([...get_object_vars($article), // Unpack properties into an array + 'cheapestPurchasePrice' => $cheapestPurchasePrice]); + } catch (Exception $e) { + print_r($article); + echo PHP_EOL; + die("WarehouseArticleController::updateCheapestPurchasePrice: " . $e->getMessage()); + } } + + //TODO: start update cheapestSellPrice for each PriceType + + $priceTypes = WarehouseArticlePriceTypeModel::getAll(); + $articlePriceTypes = WarehouseArticlePriceModel::getAll(['articleId' => $articleId]); + //priceType has id, title + + $cheapestSellPrices = []; + + foreach ($priceTypes as $priceType) { + // check if priceType exists in articlePriceTypes else use $article->defaultSellMultiplier for price type + $articlePriceType = array_filter($articlePriceTypes, function ($articlePriceType) use ($priceType) { + return $articlePriceType->articlePriceTypeId == $priceType->id; + }); + + if (empty($articlePriceType)) { + $sellPrice = $article->defaultSellMultiplier * $cheapestPurchasePrice; + } else { + $articlePriceType = $articlePriceType[0]; + + if ($articlePriceType->priceOverride) { + $sellPrice = $articlePriceType->priceOverride; + } else { + $sellPrice = $articlePriceType->priceMultiplier * $cheapestPurchasePrice; + } + } + $cheapestSellPrices[] = [ + 'title' => $priceType->title, + 'price' => $sellPrice, + ]; + } + + // save cheapestSellPrices column on article + + $article->cheapestSellPrice = json_encode($cheapestSellPrices); + WarehouseArticleModel::update([...get_object_vars($article)]); } - protected function afterCreate($postData) { - self::updateCheapestPurchasePrice($postData['id']); + protected function afterCreate() { + $last5Articles = WarehouseArticleModel::getAll([], 5, 0, ['key' => 'id', 'order' => 'DESC']); + + foreach ($last5Articles as $article) { + self::updateCheapestPurchasePrice($article->id); + } } protected function updateAllCheapestPurchasePricesAction() { diff --git a/application/WarehouseArticle/WarehouseArticleModel.php b/application/WarehouseArticle/WarehouseArticleModel.php index 30634f526..90d4c13d0 100644 --- a/application/WarehouseArticle/WarehouseArticleModel.php +++ b/application/WarehouseArticle/WarehouseArticleModel.php @@ -6,10 +6,14 @@ class WarehouseArticleModel extends TTCrudBaseModel { public string $description; public string $category; public ?float $cheapestPurchasePrice; - public ?float $cheapestSellPrice; + public ?string $cheapestSellPrice; public int $warningAmount; public int $criticalAmount; public int $isEShop; + public float $defaultSellMultiplier; + public string $unit; + public int $isSerialDocumentation; + public int $revenueAccount; } \ No newline at end of file diff --git a/application/WarehouseArticleDistributor/WarehouseArticleDistributorController.php b/application/WarehouseArticleDistributor/WarehouseArticleDistributorController.php index db8fa6e84..3c7fe4503 100644 --- a/application/WarehouseArticleDistributor/WarehouseArticleDistributorController.php +++ b/application/WarehouseArticleDistributor/WarehouseArticleDistributorController.php @@ -20,8 +20,8 @@ class WarehouseArticleDistributorController extends TTCrud { 'delete' => 'Lieferanteintrag wurde gelöscht', 'noChanges' => 'Keine Änderungen',]; - protected function checkExistingThresholdEntry($postData): bool { - $count = WarehouseLocationThresholdOverrideModel::count(['articleId' => $postData['articleId'], + protected function checkExistingDistributorEntry($postData): bool { + $count = WarehouseArticleDistributorModel::count(['articleId' => $postData['articleId'], 'distributorId' => $postData['distributorId']]); if ($count > 0) { @@ -34,7 +34,7 @@ class WarehouseArticleDistributorController extends TTCrud { } protected function beforeCreate($postData): bool { - return $this->checkExistingThresholdEntry($postData); + return $this->checkExistingDistributorEntry($postData); } protected function afterCreate($postData) { @@ -42,7 +42,7 @@ class WarehouseArticleDistributorController extends TTCrud { } protected function beforeUpdate($postData): bool { - $existing = $this->checkExistingThresholdEntry($postData); + $existing = $this->checkExistingDistributorEntry($postData); if (!$existing) { return false; diff --git a/application/WarehouseArticlePacket/WarehouseArticlePacket.php b/application/WarehouseArticlePacket/WarehouseArticlePacket.php new file mode 100644 index 000000000..7b4d60ff1 --- /dev/null +++ b/application/WarehouseArticlePacket/WarehouseArticlePacket.php @@ -0,0 +1,9 @@ + 'title', 'text' => 'Titel', 'required' => true], + ['key' => 'description', 'text' => 'Beschreibung', 'required' => true], + ['key' => 'category', 'text' => 'Kategorie', 'required' => true], + ['key' => 'overrideSellPrice', 'text' => 'Überschriebener Verkaufspreis', 'required' => false, 'modal' => ['type' => 'number'], 'table' => false], + ['key' => 'calculatedSellPrice', 'text' => 'Verkaufspreis', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false]], + ['key' => 'subItems', 'text' => 'Unterartikel', 'required' => true], + ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 10]], + ]; + // @formatter:on + + protected array $infoMessages = ['create' => 'Artikel-Paket wurde erstellt', + 'update' => 'Artikel-Paket wurde aktualisiert', + 'delete' => 'Artikel-Paket wurde gelöscht', + 'noChanges' => 'Keine Änderungen']; + + protected function prepareCrudConfig() { + $articles = array_map(function ($article) { + return ['value' => $article->id, 'text' => $article->title]; + }, WarehouseArticleModel::getAll( + ['isEShop' => 1], + )); + + $this->columns[5]['modal']['items'] = $articles; + } + + //TODO: make this so it does not update all packets at the same time + protected function updatePacketPricesAction() { + $packets = WarehouseArticlePacketModel::getAll(); + $articles = WarehouseArticleModel::getAll(['isEShop' => 1]); + + // packet has $calculatedSellPrice for this but when overrideSellPrice is set, it should be used + + foreach ($packets as $packet) { + if ($packet->overrideSellPrice) { + $calculatedSellPrice = $packet->overrideSellPrice; + } else { + $subItems = json_decode($packet->subItems); + $calculatedSellPrice = 0; + + foreach ($subItems as $subItem) { + $article = WarehouseArticleModel::get($subItem->id); + $cheapestSellPrices = json_decode($article->cheapestSellPrice); + // find in array cheapestSellPrices by title === 'Energie Steiermark' and get the price + $articlePrice = array_values(array_filter($cheapestSellPrices, function ($cheapestSellPrice) { + return $cheapestSellPrice->title === 'Energie Steiermark'; + }))[0]->price; + + $calculatedSellPrice += $subItem->amount * $articlePrice; + } + } + + WarehouseArticlePacketModel::update([...get_object_vars($packet), // Unpack properties into an array + 'calculatedSellPrice' => $calculatedSellPrice]); + } + + return true; + } + + protected function afterUpdate(): bool { + return $this->updatePacketPricesAction(); + } + + protected function afterCreate(): bool { + return $this->updatePacketPricesAction(); + } + + protected function beforeUpdate($postData): bool { + (new WarehouseHistoryController)->create($postData, $this->mod); + + return true; + } + + protected function getHistoryAction() { + $history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod); + + $history = array_map(function ($item) { + $item = (array) $item; + + $item['columnHeader'] = $this->columns[array_search($item['key'], array_column($this->columns, 'key'))]['text']; + return $item; + }, $history); + + self::returnJson($history); + } + +} \ No newline at end of file diff --git a/application/WarehouseArticlePacket/WarehouseArticlePacketModel.php b/application/WarehouseArticlePacket/WarehouseArticlePacketModel.php new file mode 100644 index 000000000..fce43e62f --- /dev/null +++ b/application/WarehouseArticlePacket/WarehouseArticlePacketModel.php @@ -0,0 +1,11 @@ + false, diff --git a/application/WarehouseArticlePriceType/WarehouseArticlePriceTypeController.php b/application/WarehouseArticlePriceType/WarehouseArticlePriceTypeController.php index b8cfbd12f..affb82be4 100644 --- a/application/WarehouseArticlePriceType/WarehouseArticlePriceTypeController.php +++ b/application/WarehouseArticlePriceType/WarehouseArticlePriceTypeController.php @@ -51,6 +51,15 @@ class WarehouseArticlePriceTypeController extends TTCrud { return true; } + protected function afterUpdate($postData) { + WarehouseArticleController::updateCheapestPurchasePrice($postData['articleId']); + } + + protected function afterCreate($postData) { + //TODO: fix this + WarehouseArticleController::updateCheapestPurchasePrice($postData['articleId']); + } + protected function getHistoryAction() { $history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod); diff --git a/application/WarehouseEShop/WarehouseEShopController.php b/application/WarehouseEShop/WarehouseEShopController.php index 7f23a26a9..bc90ecc02 100644 --- a/application/WarehouseEShop/WarehouseEShopController.php +++ b/application/WarehouseEShop/WarehouseEShopController.php @@ -5,8 +5,9 @@ class WarehouseEShopController extends TTCrud { protected bool $createText = false; protected array $columns = [ - ['key' => 'title', 'text' => 'Titel'], - ['key' => 'category', 'text' => 'Kategorie'], + ['key' => 'title', 'text' => 'Artikel'], + ['key' => 'category', 'text' => 'Kategorie', 'table' => false], + ['key' => 'price', 'text' => 'Preis', 'table' => ['filter' => false,'sortable' => false,'class' => 'text-right']], ['key' => 'amount', 'text' => 'Menge', 'table' => ['filter' => false,'sortable' => false,'class' => 'p-0 width-80']], ['key' => 'add', 'text' => 'Hinzufügen', 'table' => ['filter' => false,'sortable' => false, 'class' => 'width-120 text-center']] ]; @@ -18,6 +19,10 @@ class WarehouseEShopController extends TTCrud { 'noChanges' => 'Keine Änderungen', ]; + public function permissionCheck(): bool { + return $this->user->can(["WarehouseEShop"]); + } + public function getAction() { $filter = $this->postData['filters'] ?? []; $order = $this->postData['order'] ?? ['key' => null, 'order' => 'ASC']; @@ -30,6 +35,10 @@ class WarehouseEShopController extends TTCrud { $filteredAvailable = WarehouseArticleModel::count($filter); $totalRows = WarehouseArticleModel::count(['isEShop' => 1]); + $packetRows = WarehouseArticlePacketModel::getAll(); + + $rows = [...$rows, ...$packetRows]; + self::returnJson(["rows" => $rows, "pagination" => ["page" => $page, "total_pages" => ceil($filteredAvailable / $perPage), diff --git a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php index 6a5702b05..e767dbea2 100644 --- a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php +++ b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php @@ -9,7 +9,7 @@ class WarehouseEShopOrderController extends TTCrud { ['key' => 'status', 'text' => 'Status', 'required' => true], ['key' => 'deliveryMode', 'text' => 'Liefermodus', 'required' => true, 'modal' => ['type' => 'select', 'items' => [ ['value' => 'singleAddress', 'text' => 'Einzelne Adresse'], - ['value' => 'multipleAddresses', 'text' => 'Mehrere Adressen'], +// ['value' => 'multipleAddresses', 'text' => 'Mehrere Adressen'], ]]], ['key' => 'deliveryAddressName', 'text' => 'Lieferadresse Name', 'required' => true, 'table' => false], ['key' => 'deliveryAddressLine', 'text' => 'Lieferadresse', 'required' => true, 'required_length' => 4], @@ -31,6 +31,10 @@ class WarehouseEShopOrderController extends TTCrud { 'noChanges' => 'Keine Änderungen', ]; + public function permissionCheck(): bool { + return $this->user->can(["WarehouseEShop"]); + } + protected function prepareCrudConfig() { $users = array_map(function($user) { return ['value' => intval($user->id), 'text' => $user->name]; @@ -67,11 +71,24 @@ class WarehouseEShopOrderController extends TTCrud { // now create WarehouseEShopOrderItems for each item in the shopping cart foreach ($shoppingCart as $item) { - WarehouseEShopOrderItemModel::create([ - 'orderId' => $id, - 'articleId' => $item['itemId'], - 'quantity' => intval($item['amount']), - ]); + // itemId can either be P-[PACKETID] or I-[ARTICLEID] + // parse this and either fill articleId or articlePacketId for warehouseEShopOrderItem + if (strpos($item['itemId'], 'P-') === 0) { + WarehouseEShopOrderItemModel::create([ + 'orderId' => $id, + 'articlePacketId' => intval(substr($item['itemId'], 2)), + 'quantity' => intval($item['amount']), + ]); + } else if (strpos($item['itemId'], 'I-') === 0) { + WarehouseEShopOrderItemModel::create([ + 'orderId' => $id, + 'articleId' => intval(substr($item['itemId'], 2)), + 'quantity' => intval($item['amount']), + ]); + } else { + self::returnJson(['success' => false, 'message' => 'Invalid item id']); + die(); + } } self::returnJson(['success' => true, diff --git a/application/WarehouseEShopOrderItem/WarehouseEShopOrderItemModel.php b/application/WarehouseEShopOrderItem/WarehouseEShopOrderItemModel.php index 9fcc6627e..6bbf0cd56 100644 --- a/application/WarehouseEShopOrderItem/WarehouseEShopOrderItemModel.php +++ b/application/WarehouseEShopOrderItem/WarehouseEShopOrderItemModel.php @@ -9,6 +9,7 @@ class WarehouseEShopOrderItemModel extends TTCrudBaseModel { public int $id; public int $orderId; - public int $articleId; + public ?int $articleId; + public ?int $articlePacketId; public int $quantity; } \ No newline at end of file diff --git a/application/WarehouseRevenueAccount/WarehouseRevenueAccount.php b/application/WarehouseRevenueAccount/WarehouseRevenueAccount.php new file mode 100644 index 000000000..8077d5496 --- /dev/null +++ b/application/WarehouseRevenueAccount/WarehouseRevenueAccount.php @@ -0,0 +1,9 @@ + 'title', 'text' => 'Titel', 'required' => true], + ['key' => 'revenueAccountNumber', 'text' => 'Erlöskonto Nummer', 'required' => true, 'modal' => ['type' => 'number']], + ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 10]], + ]; + // @formatter:on + + protected array $infoMessages = ['create' => 'Erlöskonto wurde erstellt', + 'update' => 'Erlöskonto wurde aktualisiert', + 'delete' => 'Erlöskonto wurde gelöscht', + 'noChanges' => 'Keine Änderungen']; + + protected function beforeUpdate($postData): bool { + (new WarehouseHistoryController)->create($postData, $this->mod); + + return true; + } + + protected function getHistoryAction() { + $history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod); + + $history = array_map(function ($item) { + $item = (array) $item; + + $item['columnHeader'] = $this->columns[array_search($item['key'], array_column($this->columns, 'key'))]['text']; + return $item; + }, $history); + + self::returnJson($history); + } + +} \ No newline at end of file diff --git a/application/WarehouseRevenueAccount/WarehouseRevenueAccountModel.php b/application/WarehouseRevenueAccount/WarehouseRevenueAccountModel.php new file mode 100644 index 000000000..2113d4b9f --- /dev/null +++ b/application/WarehouseRevenueAccount/WarehouseRevenueAccountModel.php @@ -0,0 +1,7 @@ +getEnvironment() == "thetool") { + $table = $this->table("WorkerPermission"); + $table->addColumn("canWarehouseAdmin", "enum", ["null" => false, "values" => 'false,true', "default" => "false", "after" => "canSuperexpert"]); + $table->addColumn("canWarehouseUser", "enum", ["null" => false, "values" => 'false,true', "default" => "false", "after" => "canSuperexpert"]); + $table->addColumn("canWarehouseEShop", "enum", ["null" => false, "values" => 'false,true', "default" => "false", "after" => "canSuperexpert"]); + $table->update(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $table = $this->table("WorkerPermission"); + $table->removeColumn("canWarehouseAdmin"); + $table->removeColumn("canWarehouseUser"); + $table->removeColumn("canWarehouseEShop"); + $table->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240724143300_update_warehouse_tables.php b/db/migrations/20240724143300_update_warehouse_tables.php new file mode 100644 index 000000000..39c824e41 --- /dev/null +++ b/db/migrations/20240724143300_update_warehouse_tables.php @@ -0,0 +1,62 @@ +getEnvironment() == "thetool") { + $WarehouseArticle = $this->table("WarehouseArticle"); + $WarehouseArticle->changeColumn("cheapestSellPrice", "text", ["null" => false]); + $WarehouseArticle->addColumn("defaultSellMultiplier", "float", ["null" => false, "default" => 1]); + $WarehouseArticle->addColumn("unit", "string", ["null" => false]); + $WarehouseArticle->addColumn("isSerialDocumentation", "integer", ["null" => false]); + $WarehouseArticle->addColumn("revenueAccount", "integer", ["null" => false]); + $WarehouseArticle->update(); + + $WarehouseArticlePacket = $this->table("WarehouseArticlePacket", ["signed" => true]); + $WarehouseArticlePacket->addColumn("title", "string", ["null" => false]); + $WarehouseArticlePacket->addColumn("description", "text", ["null" => false]); + $WarehouseArticlePacket->addColumn("category", "string", ["null" => false]); + $WarehouseArticlePacket->addColumn("overrideSellPrice", "float", ["null" => true]); + $WarehouseArticlePacket->addColumn("calculatedSellPrice", "float", ["null" => true]); + $WarehouseArticlePacket->addColumn("subItems", "text", ["null" => false]); + $WarehouseArticlePacket->create(); + + $WarehouseEShopOrderItem = $this->table("WarehouseEShopOrderItem"); + $WarehouseEShopOrderItem->changeColumn("articleId", "integer", ["null" => true]); + $WarehouseEShopOrderItem->addColumn("articlePacketId", "integer", ["null" => true]); + $WarehouseEShopOrderItem->update(); + + $WarehouseRevenueAccount = $this->table("WarehouseRevenueAccount", ["signed" => true]); + $WarehouseRevenueAccount->addColumn("revenueAccountNumber", "integer", ["null" => false]); + $WarehouseRevenueAccount->addColumn("title", "string", ["null" => false]); + $WarehouseRevenueAccount->create(); + + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $WarehouseArticle = $this->table("WarehouseArticle"); + $WarehouseArticle->changeColumn("cheapestSellPrice", "float", ["null" => false]); + $WarehouseArticle->removeColumn("defaultSellMultiplier"); + $WarehouseArticle->removeColumn("unit"); + $WarehouseArticle->removeColumn("isSerialDocumentation"); + $WarehouseArticle->removeColumn("revenueAccount"); + $WarehouseArticle->update(); + + $WarehouseArticlePacket = $this->table("WarehouseArticlePacket"); + $WarehouseArticlePacket->drop()->save(); + + $WarehouseEShopOrderItem = $this->table("WarehouseEShopOrderItem"); + $WarehouseEShopOrderItem->changeColumn("articleId", "integer", ["null" => false]); + $WarehouseEShopOrderItem->removeColumn("articlePacketId"); + $WarehouseEShopOrderItem->update(); + + $WarehouseRevenueAccount = $this->table("WarehouseRevenueAccount"); + $WarehouseRevenueAccount->drop()->save(); + + } + } +} diff --git a/lib/Helper/Helper.php b/lib/Helper/Helper.php index 2feba1cbb..da0c37603 100644 --- a/lib/Helper/Helper.php +++ b/lib/Helper/Helper.php @@ -61,6 +61,11 @@ class Helper { $value = $data[$key] ?? null; $title = $rules['title'] ?? $key; + //TODO: fix this, skip arrays for now + if (is_array($value)) { + continue; + } + // Apply default values for missing rules $rules = array_merge([ diff --git a/lib/TTCrud/TTCrud.php b/lib/TTCrud/TTCrud.php index a53f0aa3d..22be1fda7 100644 --- a/lib/TTCrud/TTCrud.php +++ b/lib/TTCrud/TTCrud.php @@ -23,7 +23,12 @@ class TTCrud extends mfBaseController { $this->user = $me; $this->layout()->set('me', $me); - if (!$me->is(["Admin"])) { + if (method_exists($this, 'permissionCheck')) { + $allowed = $this->permissionCheck(); + if (!$allowed) { + $this->redirect("Dashboard"); + } + } else if (!$me->is(["Admin"])) { $this->redirect("Dashboard"); } diff --git a/lib/TTCrudBaseModel/TTCrudBaseModel.php b/lib/TTCrudBaseModel/TTCrudBaseModel.php index 9f7039f32..c296fd258 100644 --- a/lib/TTCrudBaseModel/TTCrudBaseModel.php +++ b/lib/TTCrudBaseModel/TTCrudBaseModel.php @@ -68,12 +68,17 @@ class TTCrudBaseModel { } - public static function get($id): TTCrudBaseModel { + public static function get($id, $die= false): TTCrudBaseModel { $FronkDB = FronkDB::singleton(); $db = $FronkDB->link; $id = $db->real_escape_string($id); $table = self::getTable(); $sql = "SELECT * FROM `$table` WHERE `id` = $id"; + + if($die) { + die($sql); + } + $result = $db->query($sql); // as TTCRudBaseModel is abstract, we need to get the class name of the child class $class = get_called_class(); @@ -148,6 +153,13 @@ class TTCrudBaseModel { if ($field === "id") { continue; } + // TODO: make this cleaner + if ($value === "" && (new ReflectionProperty(get_called_class(), $field))->getType()->getName() === "float") { + $value = null; + } + if ($value === "" && (new ReflectionProperty(get_called_class(), $field))->getType()->getName() === "int") { + $value = null; + } $values[] = $value === null ? "`$field` = NULL" : "`$field` = '" . $db->real_escape_string($value) . "'"; } diff --git a/public/js/pages/WarehouseArticle/WarehouseArticle.js b/public/js/pages/WarehouseArticle/WarehouseArticle.js index 96f2a781f..34149983b 100644 --- a/public/js/pages/WarehouseArticle/WarehouseArticle.js +++ b/public/js/pages/WarehouseArticle/WarehouseArticle.js @@ -256,6 +256,12 @@ Vue.component('warehouse-article', { @editPricesEntries="priceModal = true; priceModalId = $event.id" @editThresholdEntries="thresholdModal = true; thresholdModalId = $event.id"> + + diff --git a/public/js/pages/WarehouseArticlePacket/WarehouseArticlePacket.js b/public/js/pages/WarehouseArticlePacket/WarehouseArticlePacket.js new file mode 100644 index 000000000..1ef35a8d7 --- /dev/null +++ b/public/js/pages/WarehouseArticlePacket/WarehouseArticlePacket.js @@ -0,0 +1,90 @@ +Vue.component('WarehouseArticlePacket', { + //language=Vue + template: ` + + + + + + + + + + + `, data() { + return { + window: window, + historyModal: false, + historyModalId: null, + subItemsAutocomplete: '', + articles: [], + updateCounter: 0, + newSubItemAmount: 1, + subItems: [] + } + }, beforeMount() { + this.articles = window['TT_CONFIG']['CRUD_CONFIG'].columns.find(column => column.key === 'subItems').modal.items; + }, methods: { + updateCrudModalData() { + const ref = this.$refs.WarehouseArticlePacketCrud; + ref.$set(ref.crudModalData, 'subItems', JSON.stringify(this.subItems)); + this.updateCounter++; + }, removeSubItem(item) { + this.subItems = this.subItems.filter(subItem => subItem !== item); + this.updateCrudModalData(); + }, addSubItem() { + // only continue if id and amount are set else use window.notify('error', 'Bitte Artikel und Menge auswählen'); + if (this.subItemsAutocomplete === '' || this.newSubItemAmount === '') { + window.notify('error', 'Bitte Artikel und Menge auswählen'); + return; + } + + this.subItems.push({id: this.subItemsAutocomplete, amount: this.newSubItemAmount}); + this.updateCrudModalData(); + this.$refs.subItemsAutocomplete.clear(); + this.newSubItemAmount = 1; + } + }, mounted() { + this.$watch(() => { + return this.$refs.WarehouseArticlePacketCrud.crudModal + }, () => { + // check if this.$refs.WarehouseArticlePacketCrud.crudModalData.subItems is defined + if (typeof this.$refs.WarehouseArticlePacketCrud.crudModalData.subItems === 'undefined') { + this.$set(this.$refs.WarehouseArticlePacketCrud.crudModalData, 'subItems', JSON.stringify([])); + } + this.subItems = JSON.parse(this.$refs.WarehouseArticlePacketCrud.crudModalData.subItems); + }) + + } +}) diff --git a/public/js/pages/WarehouseEShop/WarehouseEShop.js b/public/js/pages/WarehouseEShop/WarehouseEShop.js index e27989598..02a8579ad 100644 --- a/public/js/pages/WarehouseEShop/WarehouseEShop.js +++ b/public/js/pages/WarehouseEShop/WarehouseEShop.js @@ -63,13 +63,18 @@ Vue.component('warehouse-e-shop', { + + @@ -110,12 +115,16 @@ Vue.component('warehouse-e-shop', { 'Ein Fehler ist aufgetreten'); } }, - addToCart(row) { + addToCart(row, type) { + row = JSON.parse(JSON.stringify(row)); + row.id = `${type}-${row.id}`; if (!this.itemAmounts[row.id] || this.itemAmounts[row.id] === 0) { window.notify('error', 'Bitte geben Sie eine Menge ein.'); return; } + console.log(this.shoppingCart, row) + // Check if Article is already in the shopping cart if (this.shoppingCart.some(item => item.itemId === row.id)) { window.notify('warning', `${row.title} ist bereits im Warenkorb.`); diff --git a/public/plugins/vue/tt-components/css/tt-table.css b/public/plugins/vue/tt-components/css/tt-table.css index 76d83e178..c82bb660c 100644 --- a/public/plugins/vue/tt-components/css/tt-table.css +++ b/public/plugins/vue/tt-components/css/tt-table.css @@ -261,7 +261,7 @@ td { .expanded { width: 500px; /* Expanded width */ height: 600px; /* Expanded height */ - z-index: 1000; + z-index: 999999999999999; } .toggle-button { diff --git a/public/plugins/vue/tt-components/tt-autocomplete.js b/public/plugins/vue/tt-components/tt-autocomplete.js index 84712f01c..099b1ef2a 100644 --- a/public/plugins/vue/tt-components/tt-autocomplete.js +++ b/public/plugins/vue/tt-components/tt-autocomplete.js @@ -17,6 +17,9 @@ Vue.component('tt-autocomplete', { :style="{'padding-right': $slots.append ? '30px' : '0'}" /> +