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"])): ?>
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">
+
+
+ {{price.title}}: {{(price.price)}} €
+
+
+
{{(row.cheapestPurchasePrice * row.sellPriceMultiplier).toFixed(2)}} €
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: `
+
+
+
+
+
+
+ {{item.amount + 'x '}}{{articles.find(article => article.value === item.id).text}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+ Menge {{item.amount}} | Artikel {{articles.find(article => article.value === item.id).text}}
+
+
+
+
+ Keine Artikel hinzugefügt
+
+
+
+
+
+
+ `, 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', {
+
+ {{ row.calculatedSellPrice.toFixed(2) }} €
+ {{ JSON.parse(row.cheapestSellPrice).find(price => price.title === 'Energie Steiermark').price.toFixed(2) }} €
+
+
-
+
-
+
@@ -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'}"
/>
+
@@ -85,7 +88,6 @@ Vue.component('tt-autocomplete', {
watch: {
value(newValue) {
const selectedItem = this.displayingItems.find(item => item.value === newValue);
- console.log(selectedItem);
this.displayValue = selectedItem ? selectedItem.text : '';
},
apiUrl() {
@@ -136,7 +138,7 @@ Vue.component('tt-autocomplete', {
this.fetchSuggestionsDebounceTimer = setTimeout(() => {
// Simulate the API call
setTimeout(async () => {
- const response = await axios.get(`${this.apiUrl}&autocomplete=1&q=${this.displayValue}`);
+ const response = await axios.get(`${this.apiUrl}&autocomplete=1&q=${encodeURIComponent(this.displayValue)}`);
if (response.data?.status === 'error') {
this.displayingItems = [];
} else {
@@ -154,5 +156,9 @@ Vue.component('tt-autocomplete', {
this.displayValue = item.text;
this.showSuggestions = false;
},
+ clear() {
+ this.displayValue = '';
+ this.$emit('input', '');
+ }
},
});
diff --git a/public/plugins/vue/tt-components/tt-checkbox.js b/public/plugins/vue/tt-components/tt-checkbox.js
index 53247e9d2..764684b02 100644
--- a/public/plugins/vue/tt-components/tt-checkbox.js
+++ b/public/plugins/vue/tt-components/tt-checkbox.js
@@ -18,6 +18,9 @@ Vue.component('tt-checkbox', {
this.checkedValue = val;
}
},
+ mounted() {
+ this.$emit('input', this.checkedValue);
+ },
template: `
diff --git a/public/plugins/vue/tt-components/tt-table-crud.js b/public/plugins/vue/tt-components/tt-table-crud.js
index 1749faab6..9d3f212e6 100644
--- a/public/plugins/vue/tt-components/tt-table-crud.js
+++ b/public/plugins/vue/tt-components/tt-table-crud.js
@@ -51,14 +51,17 @@ Vue.component('tt-table-crud', {
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+