diff --git a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php index b09717d9b..ffa8dea7d 100644 --- a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php +++ b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php @@ -12,6 +12,7 @@ class WarehouseEShopOrderController extends TTCrud { 'modal' => ['type' => 'select', 'items' => [['value' => 'new', 'text' => 'Neu'], ['value' => 'accepted', 'text' => 'An Lieferant übergeben'], + ['value' => 'acceptedInternally', 'text' => 'Interne verarbeitung'], ['value' => 'sent', 'text' => 'Gesendet'], ['value' => 'done', 'text' => 'Erledigt'],]], 'table' => ['filter' => 'select']], @@ -26,6 +27,7 @@ class WarehouseEShopOrderController extends TTCrud { ['key' => 'deliveryAddressLine', 'text' => 'Adresse', 'required' => true, 'required_length' => 4], ['key' => 'deliveryAddressPLZ', 'text' => 'PLZ', 'required' => true, 'regex' => '/^\d{4}$/'], ['key' => 'deliveryAddressCity', 'text' => 'Stadt', 'required' => true, 'required_length' => 3], + ['key' => 'trackingNumber', 'text' => 'Trackingnummer', 'required' => false, 'modal' => false], ['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false, 'filter' => 'datetime'], ['key' => 'createBy', 'text' => 'Erstellt von', @@ -39,6 +41,7 @@ class WarehouseEShopOrderController extends TTCrud { 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']],]; protected array $additionalActions = [['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'], + ['key' => 'showTrackingHistory', 'title' => 'Tracking Historie', 'class' => 'fas fa-truck text-primary'], ['key' => 'openSingleOrderEmail', 'title' => 'Bestellbestätigung', 'class' => 'fas fa-envelope text-primary'],]; protected array $infoMessages = ['create' => 'Bestellung wurde erfolgreich erstellt, sie erhalten in Kürze eine Bestätigungsmail', @@ -55,7 +58,7 @@ class WarehouseEShopOrderController extends TTCrud { return ['value' => intval($user->id), 'text' => $user->name]; }, UserModel::search()); - $this->columns[9]['modal']['items'] = $users; + $this->columns[10]['modal']['items'] = $users; } protected function singleOrderEmailAction() { @@ -106,6 +109,8 @@ class WarehouseEShopOrderController extends TTCrud { } } + + protected function CSVExportNewOrdersMarkAcceptedAction($returnCSV = false, $orderIds = []) { $orders = WarehouseEShopOrderModel::getAll(['status' => 'new']); $orders = array_map(function ($order) { @@ -292,4 +297,143 @@ class WarehouseEShopOrderController extends TTCrud { self::returnJson((new WarehouseHistoryController)->getHistory($this->request->id, $this->mod, $this->columns)); } + protected function GLSTrackingApi($trackingNumber, $plz) { + $url = "https://gls-group.eu/app/service/open/rest/AT/de/rstt028/$trackingNumber?postalCode=$plz"; + return file_get_contents($url); + } + + protected function checkAndUpdateTrackingState($tracking, $orderId) { + // check inside the tracking json if data.history[xxx].evtDscr (lowercase) contains "erfolgreich zugestellt" + $tracking = json_decode($tracking, true); + $history = $tracking['history']; + $successfulDelivery = false; + foreach ($history as $entry) { + if (strpos(strtolower($entry['evtDscr']), 'erfolgreich zugestellt') !== false) { + $successfulDelivery = true; + break; + } + } + + if ($successfulDelivery) { + $order = (array) WarehouseEShopOrderModel::get($orderId); + $order['status'] = 'done'; + WarehouseEShopOrderModel::update($order); + } + } + + protected function fetchGLSTrackingAction() { + $orderId = $this->request->id; + + $order = WarehouseEShopOrderModel::get($orderId); + $trackingNumber = $order->trackingNumber; + $plz = $order->deliveryAddressPLZ; + + $tracking = $this->GLSTrackingApi($trackingNumber, $plz); + $this->checkAndUpdateTrackingState($tracking, $orderId); + die($tracking); + } + + protected function readGLSEmailAction() { + $host = '{mail.xinon.at:993/imap/ssl/novalidate-cert}INBOX'; + $mbox = imap_open($host, 'eshop-versand@xinon.at', 'savemanfb545aw'); + $emails = imap_search($mbox, 'ALL'); + + if ($emails) { + // Sort emails from newest to oldest + rsort($emails); + + // Loop through each email + foreach ($emails as $email_number) { + $overview = imap_fetch_overview($mbox, $email_number, 0); + + if (strpos($overview[0]->from, 'gls') === false) { + //continue; + } + + $message = imap_fetchbody($mbox, $email_number, 1); // 1 for plain text part + + // START ADDRESS PARSING + $address = ''; + $lines = explode("\n", $message); + $start = false; + foreach ($lines as $line) { + if (strpos($line, 'ZUSTELLADRESSE') !== false) { + $start = true; + } + if ($start) { + $address .= $line . "\n"; + } + if ($start && preg_match('/[a-zA-Z]/', $line) === 0) { + break; + } + } + + $address = substr($address, strpos($address, "\n") + 1); + + $addressLines = explode("\n", $address); + $addressLine = trim(array_shift($addressLines)); + $plzCity = trim(array_shift($addressLines)); + $plzCityParts = explode(' ', $plzCity); + $plz = $plzCityParts[0]; + $city = $plzCityParts[1]; + // END ADDRESS PARSING + + // START TRACKING NUMBER PARSING + $trackingNumber = ''; + preg_match('/\d{6,}/', $message, $matches); + if (!empty($matches)) { + $trackingNumber = $matches[0]; + } + // END TRACKING NUMBER PARSING + + + $orders = WarehouseEShopOrderModel::getAll(['deliveryAddressLine' => $addressLine, 'deliveryAddressPLZ' => $plz, 'deliveryAddressCity' => $city]); + if (empty($orders)) { + continue; + } + + // now check if the trackingNumber is already set and if not set it and create a history entry + $order = (array) $orders[0]; + // + if ($order['trackingNumber']) { + continue; + } + + $order['trackingNumber'] = $trackingNumber; + WarehouseEShopOrderModel::update($order); + + WarehouseHistoryModel::create(['table' => 'WarehouseEShopOrder', + 'row_id' => $order['id'], + 'key' => 'trackingNumber', + 'old_value' => '', + 'new_value' => $trackingNumber, + 'note' => '', + 'user_id' => 1, + 'create' => date('U')]); + + die(); + + die($address); + + echo "Subject: " . $overview[0]->subject . "\n"; + echo "From: " . $overview[0]->from . "\n"; + echo "Date: " . $overview[0]->date . "\n"; + echo "Message:\n" . $message . "\n\n"; + echo "---------------------------------------\n\n"; + } + } else { + echo "No emails found."; + } + +// Close the IMAP connection + imap_close($mbox); + die(); // do without ssl + $mbox = imap_open("{mail.xino.at:143/novalidate-cert}INBOX", "eshop-versand@xinon.at", "savemanfb545aw"); + // print all mails in mailbox with content + $mails = imap_search($mbox, 'ALL'); + $mails = array_reverse($mails); + $mails = array_slice($mails, 0, 10); + + $result = []; + } } \ No newline at end of file diff --git a/application/WarehouseEShopOrder/WarehouseEShopOrderModel.php b/application/WarehouseEShopOrder/WarehouseEShopOrderModel.php index b8dcdd974..32db2b2ae 100644 --- a/application/WarehouseEShopOrder/WarehouseEShopOrderModel.php +++ b/application/WarehouseEShopOrder/WarehouseEShopOrderModel.php @@ -21,6 +21,7 @@ class WarehouseEShopOrderModel extends TTCrudBaseModel { public string $deliveryAddressLine; public string $deliveryAddressPLZ; public string $deliveryAddressCity; + public string $trackingNumber; public int $create; public int $createBy; } \ No newline at end of file diff --git a/db/migrations/20240920100000_warehouse_add_tracking_support.php b/db/migrations/20240920100000_warehouse_add_tracking_support.php new file mode 100644 index 000000000..5e4c1f345 --- /dev/null +++ b/db/migrations/20240920100000_warehouse_add_tracking_support.php @@ -0,0 +1,24 @@ +getEnvironment() == "thetool") { + $WarehouseEShopOrder = $this->table("WarehouseEShopOrder"); + $WarehouseEShopOrder->addColumn("trackingNumber", "string", ["limit" => 255, "null" => true]); + $WarehouseEShopOrder->changeColumn("status", "enum", ["values" => ["new", "accepted", "acceptedInternally", "sent", "done"], "null" => false]); + $WarehouseEShopOrder->update(); + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $WarehouseEShopOrder = $this->table("WarehouseEShopOrder"); + $WarehouseEShopOrder->removeColumn("trackingNumber"); + $WarehouseEShopOrder->changeColumn("status", "enum", ["values" => ["new", "accepted", "sent", "done"], "null" => false]); + $WarehouseEShopOrder->update(); + } + } +} diff --git a/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js b/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js index c284c63b8..3b06bc382 100644 --- a/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js +++ b/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js @@ -3,8 +3,9 @@ Vue.component('warehouse-e-shop-order', { //language=Vue template: ` - - + - - - +
-

+

- +
- +
- - + + +
+
    +
  • + {{ entry.date }} {{ entry.time }} - {{ entry.evtDscr }} +
  • +
+
+ +
+ +
`, data() { return { - window: window, historyModal: false, historyModalId: null, articleItems: null, openSingleOrderEmailModal: false, singleOrderEmailModalId: null, singleOrderEmailModalText: null + window: window, + historyModal: false, + historyModalId: null, + articleItems: null, + openSingleOrderEmailModal: false, + singleOrderEmailModalId: null, + singleOrderEmailModalText: null, + openTrackingHistoryModal: false, + trackingHistoryModalId: null, + trackingHistoryModalData: null, } - }, - async mounted() { + }, async mounted() { const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/getAllItemsPerOrder`); console.log(response.data); this.articleItems = response.data; - }, - methods: { + }, methods: { async sendSingleOrderEmail() { const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/singleOrderEmail?id=${this.singleOrderEmailModalId}`); if (response.data.message) { @@ -70,8 +94,7 @@ Vue.component('warehouse-e-shop-order', { window.notify('error', 'Ein Fehler ist aufgetreten'); } await this.$refs.table.$refs.table.fetchData(); - }, - async createCSVExportAndMarkAsAccepted() { + }, async createCSVExportAndMarkAsAccepted() { const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/CSVExportNewOrdersMarkAccepted`); if (response.data.message) { @@ -108,8 +131,7 @@ Vue.component('warehouse-e-shop-order', { await this.$refs.table.$refs.table.fetchData(); } - }, - watch: { + }, watch: { singleOrderEmailModalId() { this.openSingleOrderEmailModal = !!this.singleOrderEmailModalId; this.singleOrderEmailModalText = null; @@ -118,6 +140,21 @@ Vue.component('warehouse-e-shop-order', { .then(response => this.singleOrderEmailModalText = response.data) .catch(error => window.notify('error', error.response?.data?.message || 'Ein Fehler ist aufgetreten')); } + }, + async trackingHistoryModalId() { + this.openTrackingHistoryModal = !!this.trackingHistoryModalId; + this.trackingHistoryModalData = null; + if (this.trackingHistoryModalId) { + const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/fetchGLSTracking?id=${this.trackingHistoryModalId}`); + const data = response.data; + // if data is a empty string, show error + if (!data) { + window.notify('error', data.message || 'Keine Daten gefunden'); + return; + } + // if data is not empty, show data + this.$set(this, 'trackingHistoryModalData', data); + } } } })