'title', 'text' => 'Titel', 'required' => true, 'table' => ['priority' => 9]], ['key' => 'description', 'text' => 'Beschreibung', 'required' => true], ['key' => 'category', 'text' => 'Kategorie', 'required' => true], ['key' => 'unit', 'text' => 'Einheit', 'required' => true,'table' => false], // Boolean value ['key' => 'revenueAccount', 'text' => 'Erlöskonto', 'required' => true,'modal' => ['type' => 'select', 'items' => [['value' => 0, 'text' => 'Dienstleistungen'], ['value' => 1, 'text' => 'Handelswaren']] ], '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', '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' => 'isEShopHide', 'text' => 'E-Shop Versteckt', '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]] ]; protected array $additionalActions = [ ['key' => 'openHistory','title' => 'Historie','class' => 'fas fa-history text-secondary'], ['key' => 'editDistributorEntries','title' => 'Lieferanten','class' => 'fas fa-truck text-cyan'], ['key' => 'editThresholdEntries','title' => 'Schwellenwerte','class' => 'far fa-fw fa-box-full text-orange'], ['key' => 'editPricesEntries','title' => 'Preise','class' => 'fas fa-euro-sign text-green'], ['key' => 'addToCart','title' => 'Zur Bestellung hinzufügen','class' => 'fas fa-shopping-cart text-primary'], ]; // @formatter:on protected array $infoMessages = ['create' => 'Artikel wurde erstellt', 'update' => 'Artikel wurde aktualisiert', 'delete' => 'Artikel wurde gelöscht', 'noChanges' => 'Keine Änderungen',]; protected function beforeUpdate($postData): bool { (new WarehouseHistoryController)->create($postData, $this->mod); return true; } protected function afterUpdate($postData) { self::updateCheapestPurchasePrice($postData['id']); } /** * Updates the cheapest purchase price for a given article from WarehouseArticleDistributorModel prices. * * @param int $articleId The ID of the article to update. * @return void * @throws Exception If the article is not an instance of WarehouseArticleModel. */ public static function updateCheapestPurchasePrice(int $articleId): void { $article = WarehouseArticleModel::get($articleId); if (!$article instanceof WarehouseArticleModel) { throw new Exception("Article is not an instance of WarehouseArticleModel"); } $order = ['key' => 'purchasePrice', 'order' => 'ASC']; $cheapestDistributorEntry = WarehouseArticleDistributorModel::getAll(['articleId' => $articleId], 1, 0, $order); if (empty($cheapestDistributorEntry)) return; $cheapestPurchasePrice = $cheapestDistributorEntry[0]->purchasePrice; if ($article->cheapestPurchasePrice == $cheapestPurchasePrice) return; WarehouseArticleModel::update(array_merge(get_object_vars($article), ['cheapestPurchasePrice' => $cheapestPurchasePrice])); } protected function afterCreate($postData) { self::updateCheapestPurchasePrice($postData['id']); self::updateSellPrices($postData['id']); } /** * Updates the sell prices for a given article. * * @param int $articleId The ID of the article to update. * @return void * @throws Exception If the article is not an instance of WarehouseArticleModel. */ public static function updateSellPrices(int $articleId) { $article = WarehouseArticleModel::get($articleId); if (!$article instanceof WarehouseArticleModel) { throw new Exception("Article is not an instance of WarehouseArticleModel"); } $priceTypes = WarehouseArticlePriceTypeModel::getAll(); $articlePriceTypes = WarehouseArticlePriceModel::getAll(['articleId' => $articleId]); $cheapestSellPrices = []; // Calculate sell prices for each price type, use default sell multiplier if no specific price is set foreach ($priceTypes as $priceType) { $articlePriceType = null; foreach ($articlePriceTypes as $apt) { if ($apt->articlePriceTypeId == $priceType->id) { $articlePriceType = $apt; break; } } $sellPrice = $priceType->defaultPriceFactor * $article->cheapestPurchasePrice; if ($articlePriceType !== null) { $sellPrice = $articlePriceType->priceOverride ?: $articlePriceType->priceMultiplier * $article->cheapestPurchasePrice; } $cheapestSellPrices[$priceType->id] = ['title' => $priceType->title, 'price' => round($sellPrice, 2)]; } $article->cheapestSellPrice = json_encode($cheapestSellPrices); WarehouseArticleModel::update(get_object_vars($article)); } public function updatePricesAction() { foreach (WarehouseArticleModel::getAll() as $article) { self::updateCheapestPurchasePrice($article->id); self::updateSellPrices($article->id); } self::returnJson(['success' => true, 'message' => 'Preise wurden aktualisiert']); } protected function getHistoryAction() { self::returnJson((new WarehouseHistoryController)->getHistory($this->request->id, $this->mod, $this->columns)); } protected function importAction() { error_reporting(E_ALL); ini_set('display_errors', 1); // read import.json from directory of this file $json = fopen(dirname(__FILE__) . '/import.json', 'r') or die('Unable to open file!'); // read file content $data = fread($json, filesize(dirname(__FILE__) . '/import.json')); // decode json $data = json_decode($data, true); // close file fclose($json); // die with data length // loop through data echo 'Importing ' . count($data) . ' items' . PHP_EOL; $count = 0; foreach ($data as $item) { // echo count + 1 echo ++$count . PHP_EOL; // Check if Distributor exists $distributor = WarehouseDistributorModel::getAll(['name' => $item['Lieferant']]); if (empty($distributor)) { $distributorId = WarehouseDistributorModel::create(['name' => $item['Lieferant'], 'address' => 'Missing', 'plz' => 'Missing', 'city' => 'Missing', 'countryId' => 1, 'email' => 'Missing', 'phone' => 'Missing', 'contactPerson' => 'Missing',]); } else { $distributorId = $distributor[0]->id; } // only continue if PRODUKT 1.ZEILE and PRODUKT 2.ZEILE and ARTIKEL GRUPPE and VK and EK and Lieferant/ Hersteller Artikelnr: are set if (!isset($item['PRODUKT 1.ZEILE'])) { echo 'Missing data for ' . $item['PRODUKT 1.ZEILE'] . PHP_EOL; continue; } if (empty($item['VK'])) { $item['VK'] = 0; $calcSellPriceMultiplier = 0; } else { $item['VK'] = floatval(str_replace(',', '', $item['VK'])); } if (empty($item['EK'])) { $item['EK'] = 0; $calcSellPriceMultiplier = 0; $purchasePrice = 0; } else { $item['EK'] = floatval(str_replace(',', '', $item['EK'])); } if (!empty($item['VK']) && !empty($item['EK'])) { $calcSellPriceMultiplier = $item['VK'] / $item['EK']; // if calcSellPriceMultiplier has more than 2 decimal places assign $calcSellPriceOverride echo strlen(substr(strrchr($calcSellPriceMultiplier, "."), 1)) . PHP_EOL; if (strlen(substr(strrchr($calcSellPriceMultiplier, "."), 1)) > 2) { $calcSellPriceOverride = $item['VK']; } $purchasePrice = str_replace(',', '', $item['EK']); } if (!isset($calcSellPriceMultiplier) && !isset($calcSellPriceOverride) || !isset($purchasePrice)) { echo 'Missing data for ' . $item['PRODUKT 1.ZEILE'] . PHP_EOL; continue; } // Check if Article exists $article = WarehouseArticleModel::getAll(['title' => ['exact' => $item['PRODUKT 1.ZEILE']]]); if (empty($article)) { $articleCreateData = ['title' => $item['PRODUKT 1.ZEILE'], 'description' => $item['PRODUKT 2. ZEILE'], 'category' => $item['ARTIKEL GRUPPE'], 'cheapestPurchasePrice' => 0, 'warningAmount' => 25, 'criticalAmount' => 10, 'isEShop' => 0,]; // if calcSellPriceOverride is set, add it to the $articleCreateData array if (isset($calcSellPriceOverride)) { $articleCreateData['sellPriceOverride'] = $calcSellPriceOverride; } else if (isset($calcSellPriceMultiplier)) { $articleCreateData['sellPriceMultiplier'] = $calcSellPriceMultiplier; } $articleId = WarehouseArticleModel::create($articleCreateData); } else { echo 'Article already exists with title ' . $item['PRODUKT 1.ZEILE'] . PHP_EOL; $articleId = $article[0]->id; } // Check if ArticleDistributor exists $articleDistributor = WarehouseArticleDistributorModel::getAll(['articleId' => $articleId, 'distributorId' => $distributorId]); if (empty($articleDistributor)) { WarehouseArticleDistributorModel::create(['articleId' => $articleId, 'distributorId' => $distributorId, 'purchasePrice' => $purchasePrice, 'externalArticleNumber' => $item['Lieferant/ Hersteller Artikelnr:'],]); } } } protected function prepareOrderAction() { // inside post json it will look like // [ // { // "amount": "5", // "itemId": 441, // "title": "RT-FB-7590AX" // }, // { // "amount": "5", // "itemId": 421, // "title": "RT-FB-7590" // } //] // get the json from the post request // then create a array containing each order we need to make, so search through WarehouseArticleDistributorModel to get the distributorId and purchasePrice (use lowest purchasePrice) // then get the WarehouseDistributorModel and then create a summary of the orders we need to make for each distributor $postData = json_decode(file_get_contents('php://input'), true); $orders = []; foreach ($postData as $order) { $articleDistributors = WarehouseArticleDistributorModel::getAll(['articleId' => $order['itemId']]); $cheapestArticleDistributor = $articleDistributors[0]; foreach ($articleDistributors as $articleDistributor) { if ($articleDistributor->purchasePrice < $cheapestArticleDistributor->purchasePrice) { $cheapestArticleDistributor = $articleDistributor; } } $distributor = WarehouseDistributorModel::get($cheapestArticleDistributor->distributorId); if (!isset($orders[$distributor->id])) { $orders[$distributor->id] = ['distributor' => array($distributor), 'orderAmount' => 0, 'orders' => []]; } $orders[$distributor->id]['orders'][] = ['articleId' => $order['itemId'], 'amount' => $order['amount'], 'sum' => $order['amount'] * $cheapestArticleDistributor->purchasePrice, 'purchasePrice' => $cheapestArticleDistributor->purchasePrice, 'externalArticleNumber' => $cheapestArticleDistributor->externalArticleNumber, 'title' => $order['title'],]; $orders[$distributor->id]['orderAmount'] += $order['amount'] * $cheapestArticleDistributor->purchasePrice; } self::returnJson($orders); } }