'id', 'text' => 'LS-Nr.', 'required' => false, 'modal' => false, 'table' => ['class' => 'text-nowrap']], ['key' => 'billingAddressId', 'text' => 'Rechnungsadresse', 'required' => true, 'type' => 'autocomplete', 'table' => ['class' => 'text-nowrap', 'filter' => 'autocomplete'], 'modal' => ['apiUrl' => 'Address/api?do=findAddress', 'items' => '/Address/Api?do=findAddress', 'type' => 'autocomplete']], ['key' => 'deliveryAddressName', 'text' => 'L.-Adr. Name', 'required' => true], ['key' => 'deliveryAddressLine', 'text' => 'L.-Adr.', 'required' => true], ['key' => 'deliveryAddressPLZ', 'text' => 'L.-Adr. PLZ', 'required' => true], ['key' => 'deliveryAddressCity', 'text' => 'L.-Adr. Ort', 'required' => true], ['key' => 'status', 'text' => 'Status', 'required' => true, 'table' => ['filter' => 'select'], 'modal' => ['type' => 'select', 'items' => [['value' => 'new', 'text' => 'Neu'], ['value' => 'accepted', 'text' => 'Akzeptiert'], ['value' => 'invoiced', 'text' => 'In Rechnung gestellt'],]]], ['key' => 'positions', 'text' => 'Positionen', 'required' => true, 'table' => false, 'modal' => false], ['key' => 'create', 'text' => 'Erstellt', 'required' => false, 'modal' => false, 'table' => ['filter' => 'date']], ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'type' => 'autocomplete', 'table' => ['class' => 'text-nowrap', 'filter' => 'select'], 'modal' => ['items' => [], 'type' => 'select',]], ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']],]; protected array $additionalActions = [['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'], ['key' => 'print', 'title' => 'Drucken', 'class' => 'fas fa-print text-primary'], ['key' => 'printWithPrice', 'title' => 'Drucken mit Preis', 'class' => 'fas fa-print text-success'], ]; protected array $infoMessages = ['create' => 'Lieferschein wurde erstellt.', 'update' => 'Lieferschein wurde aktualisiert', 'delete' => 'Lieferschein wurde gelöscht', 'noChanges' => 'Keine Änderungen vorgenommen']; protected function prepareCrudConfig() { $users = array_map(function ($user) { return ['value' => intval($user->id), 'text' => $user->name]; }, UserModel::search()); $this->columns[array_search('createBy', array_column($this->columns, 'key'))]['modal']['items'] = $users; } protected function beforeCreate($postData): bool { // if postdata status is not new we return an error if ($postData['status'] !== 'new') { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Status muss "Neu" sein']); die(); } $postData['positions'] = json_encode($postData['positions']); return true; } protected function customAutoCompleteBillingAddressId($id) { $address = new Address($id); if ($address->id) { $result = ['id' => $address->id, 'title' => str_replace("'", "\\'", str_replace(["\n", "\r"], " ", $address->getCompanyOrName())) . " (" . $address->zip . " " . $address->city . ", " . $address->street . ")" . (($address->customer_number) ? " [" . $address->customer_number . "]" : "")]; return $result; } } protected function beforeUpdate($postData): bool { $postData['positions'] = json_encode($postData['positions']); (new WarehouseHistoryController)->create($postData, $this->mod); return true; } protected function getHistoryAction() { $historyEntries = []; // remove all history elements where key is positions foreach ((new WarehouseHistoryController)->getHistory($this->request->id, $this->mod, $this->columns) as $entry) { if ($entry['key'] !== 'positions') { $historyEntries[] = $entry; } } // $historyEntries = array_filter($historyEntries, function ($entry) { // return $entry['key'] !== 'positions'; // }); self::returnJson($historyEntries); } protected function getArticleAddressPriceAction() { $articleId = $this->request->articleId; $addressId = $this->request->addressId; if (strlen($articleId) < 1) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Keine Artikel ID gefunden']); } if (strlen($addressId) < 1) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Keine Adress ID gefunden']); } //TODO: implement a select to select price category for each address // for now we default with price with name "Verkauf" $prices = WarehouseArticlePriceTypeModel::getAll(['title' => 'Verkauf']); // if array is empty we return an error if (empty($prices)) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Keine Preiskategorie gefunden']); } $priceType = $prices[0]->title; $article = WarehouseArticleModel::get($articleId); $sellPrices = json_decode($article->cheapestSellPrice, true); $sellPrice = array_search($priceType, array_column($sellPrices, 'title')); if (empty($sellPrice)) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Kein Preis gefunden']); } self::returnJson(['success' => true, 'price' => $sellPrices[$sellPrice]['price']]); } protected function getDeliveryAddressesAction() { $billingAddressId = $this->request->billingAddressId; if (strlen($billingAddressId) < 1) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Keine Rechnungsadresse gefunden']); } $deliveryAddresses = WarehouseShippingNoteModel::getAll(['billingAddressId' => $billingAddressId]); // TODO: maybe this should be improved as it is kinda hacky $result = []; foreach ($deliveryAddresses as $deliveryAddress) { $found = false; foreach ($result as $r) { if ($r->deliveryAddressName == $deliveryAddress->deliveryAddressName && $r->deliveryAddressLine == $deliveryAddress->deliveryAddressLine) { $found = true; break; } } if ($found) { continue; } $result[] = $deliveryAddress; } self::returnJson($result); } protected function getAllTextElementsAction() { $textElements = WarehouseShippingNoteTextElementModel::getAll(); self::returnJson($textElements); } protected function createPDFAction() { $id = $this->request->id; if (strlen($id) < 1) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Lieferschein wurde nicht gefunden']); } $shippingNote = WarehouseShippingNoteModel::get($id); $address = AddressModel::getOne($shippingNote->billingAddressId); $positions = []; // loop through all positions and add articleTitle and articleDescription to each position entry foreach (json_decode($shippingNote->positions, true) as $position) { if (isset($position['article'])) { $article = WarehouseArticleModel::get($position['article']); $position['articleTitle'] = $article->title; $position['articleDescription'] = $article->description === $article->title ? "" : $article->description; $position['articleUnit'] = $article->unit; $positions[] = $position; } elseif (isset($position['articlePacket'])) { $articlePacket = WarehouseArticlePacketModel::get($position['articlePacket']); $position['articleTitle'] = $articlePacket->title; $position['articleDescription'] = $articlePacket->description === $articlePacket->title ? "" : $articlePacket->description; $position['articleUnit'] = 'Stk.'; $positions[] = $position; } } $textElements = []; // parse shippingNote.textElements ({"1":true,"2":true}) to array, fetch each text element and put content into array $shippingNoteTextElements = json_decode($shippingNote->textElements, true); foreach ($shippingNoteTextElements as $key => $value) { if ($value) { $textElement = WarehouseShippingNoteTextElementModel::get($key); $textElements[] = $textElement->content; } } if (empty($textElements)) { $textElements = null; } $pdf_vars = ["shippingNote" => $shippingNote, "positions" => $positions, "textElements" => $textElements, "showPrices" => isset($_GET['price']) && $_GET['price'] == "true", "bank_iban" => TT_INVOICE_BANK_IBAN, "bank_bic" => TT_INVOICE_BANK_BIC, "bank_bank" => TT_INVOICE_BANK_BANK, "bank_owner" => TT_INVOICE_BANK_OWNER]; // Replace placeholders in header // create shipping note in this format LS2024-X0001 // pad number on the left side with zeros $shippingNoteNumber = "LS" . date("Y", $shippingNote->create) . "-" . str_pad($shippingNote->id, 4, "0", STR_PAD_LEFT); $headerHtml = file_get_contents(BASEDIR . "/Layout/default/WarehouseShippingNote/PDF_HEADER.html"); $headerHtml = str_replace("{{ basedir }}", BASEDIR, $headerHtml); $headerHtml = str_replace("{{ addressLine_1 }}", $shippingNote->deliveryAddressName, $headerHtml); $headerHtml = str_replace("{{ addressLine_2 }}", $shippingNote->deliveryAddressLine, $headerHtml); $headerHtml = str_replace("{{ addressLine_3 }}", $shippingNote->deliveryAddressPLZ . " " . $shippingNote->deliveryAddressCity, $headerHtml); $headerHtml = str_replace("{{ addressLine_4 }}", "", $headerHtml); $headerHtml = str_replace("{{ addressLine_5 }}", "", $headerHtml); $headerHtml = str_replace("{{ customerNumber }}", $address->customer_number, $headerHtml); $headerHtml = str_replace("{{ shippingNoteNumber }}", $shippingNoteNumber, $headerHtml); $headerHtml = str_replace("{{ shippingNoteDate }}", date("d.m.Y", $shippingNote->create), $headerHtml); $headerFile = BASEDIR . "/var/temp/shipping-note_header-" . date("U") . "-" . rand(1000, 9999) . ".html"; file_put_contents($headerFile, $headerHtml); // Replace placeholders in header $footerHtml = file_get_contents(BASEDIR . "/Layout/default/WarehouseShippingNote/PDF_FOOTER.html"); $footerHtml = str_replace("{{ bank_iban }}", TT_INVOICE_BANK_IBAN_FORMATTED, $footerHtml); $footerHtml = str_replace("{{ bank_bic }}", TT_INVOICE_BANK_BIC, $footerHtml); $footerHtml = str_replace("{{ bank_bank }}", TT_INVOICE_BANK_BANK, $footerHtml); $footerHtml = str_replace("{{ bank_owner }}", TT_INVOICE_BANK_OWNER, $footerHtml); $footerFile = BASEDIR . "/var/temp/shipping-note_header-" . date("U") . "-" . rand(1000, 9999) . ".html"; file_put_contents($footerFile, $footerHtml); $pdf = new PdfForm("WarehouseShippingNote/PDF_MAIN", $pdf_vars); $wkhtmltopdfArgs = "--header-html $headerFile --footer-html $footerFile"; $filename = $pdf->render($wkhtmltopdfArgs); // return the pdf and die so the client sees the pdf not the filename header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="' . $filename . '"'); readfile($filename); } }