needlogin = true; $me = new User(); $me->loadMe(); $this->me = $me; $this->layout()->set("me", $me); if (!$me->is(["Preorderlogistics"])) { $this->redirect("Dashboard"); } } protected function indexAction() { $my_campaigns = []; $user_network_ids = json_decode($this->me->getFlag("preorder_networks")->value() ?: '[]', true); if (is_array($user_network_ids) && count($user_network_ids)) { $campaign_objects = PreordercampaignModel::search(['network_id' => $user_network_ids]); if(is_array($campaign_objects)){ foreach($campaign_objects as $campaign) { $my_campaigns[] = ['value' => $campaign->id, 'text' => $campaign->name]; } } } $js_variables = [ 'CRUD_CONFIG' => [ 'CAMPAIGNS' => $my_campaigns, ] ]; Helper::renderVue($this, 'PreorderLogistics', 'Versandlogistik', $js_variables); } protected function getPreordersAction() { $postData = json_decode(file_get_contents('php://input'), true); $filter = $this->getPreparedFilter($postData['filters'] ?? []); $pagination = $postData['pagination'] ?? ['page' => 1, 'per_page' => 25]; // The 'order' parameter is received but not passed to searchWithLogistics, as it's not supported by the custom model method. // $order = $postData['order'] ?? ['key' => 'id', 'order' => 'DESC']; $my_campaign_ids = $this->getUserCampaignIds(); if (empty($my_campaign_ids)) { self::returnJson(['rows' => [], 'pagination' => ['total_rows' => 0]]); return; } if (empty($filter['preordercampaign_id'])) { $filter['preordercampaign_id'] = $my_campaign_ids; } else { // Ensure the filtered campaign is one the user has access to are arrays and if not allowed dont push it to the filter $preordercampaign_ids = is_array($filter['preordercampaign_id']) ? $filter['preordercampaign_id'] : [$filter['preordercampaign_id']]; $new_allowed_ids = array_intersect($preordercampaign_ids, $my_campaign_ids); if (empty($new_allowed_ids)) { self::returnJson(['rows' => [], 'pagination' => ['total_rows' => 0]]); return; } } $totalCount = PreorderModel::countWithLogistics($filter); // FIX: Removed the $order parameter from the call, as the custom model method does not support it. $preorders = PreorderModel::searchWithLogistics($filter, ['start' => ($pagination['page'] - 1) * $pagination['per_page'], 'count' => $pagination['per_page']]); $rows = []; if (is_array($preorders)) { foreach ($preorders as $preorder) { // Ensure we are working with an object, as expected by relation accessors if (!is_object($preorder)) continue; $row = (array)$preorder->data; // FIX: Added null-safe checks for related properties to prevent warnings $row['status_code'] = $preorder->status ? $preorder->status->code : null; $row['display_address'] = $this->getFormattedAddress($preorder); $row['sent'] = ($preorder->logistics && $preorder->logistics->sent); $row['id'] = $preorder->id; // Ensure ID is included $rows[] = $row; } } self::returnJson([ 'rows' => $rows, 'pagination' => [ 'page' => $pagination['page'], 'per_page' => $pagination['per_page'], 'total_rows' => intval($totalCount), 'total_pages' => ceil($totalCount / $pagination['per_page']), 'filtered_available' => intval($totalCount) ] ]); } protected function getFCPsForCampaignAction() { if (empty($this->request->campaign_id)) { self::returnJson([]); return; } if (is_array($this->request->campaign_id)) { if (count($this->request->campaign_id) !== 1) { self::returnJson([]); return; } $this->request->campaign_id = $this->request->campaign_id[0]; } $campaign = new Preordercampaign($this->request->campaign_id); if (!$campaign->id) self::sendError("Kampagne nicht gefunden"); self::returnJson(array_map( fn($fcp) => ["real_id" => $fcp->id, "id" => $fcp->name ?? null, "text" => $fcp->name ?? null, 'lat' => $fcp->gps_lat ?? null, 'lng' => $fcp->gps_long ?? null], ADBRimoFcp::getAll(["netzgebiet_id" => intval($campaign->network->adb_netzgebiet_id)]) ?? [] )); } protected function saveSentAction() { $postData = json_decode(file_get_contents('php://input'), true); $this->saveSentStatus($postData['id'], $postData['sent']); self::returnJson(['success' => true]); } protected function printAction() { $this->layout()->setTemplate("Preorderlogistics/Print.template"); $id = $this->request->id; if (!is_numeric($id) || $id < 1) { $this->layout()->setFlash("Vorbestellung nicht gefunden", "error"); $this->redirect("Preorderlogistics"); } $preorder = new Preorder($id); if (!$preorder->id || !$this->isUserAllowedForPreorder($preorder)) { $this->layout()->setFlash("Vorbestellung nicht gefunden oder keine Berechtigung", "error"); $this->redirect("Preorderlogistics"); } if (!$preorder->cifurl) { $preorder->createCiftoken(); $preorder->cifurl = $preorder->generateCifUrl(); $preorder->cifcableurl = $preorder->generateCifCableUrl(); $preorder->save(); } $qr = QRCode::init($preorder->cifurl); $this->layout()->set("qr_url", $qr->base64()); $this->layout()->set("preorder", $preorder); } protected function printAllAction() { $preorders = $this->getFilteredPreordersFromRequest(); $combinedHtml = ''; foreach ($preorders as $preorder) { ob_start(); $this->printActionContent($preorder->id); $combinedHtml .= ob_get_clean();// . '
'; } echo $combinedHtml; exit; } protected function csvExportAction() { $preorders = $this->getFilteredPreordersFromRequest(); $this->generateAndDownloadCsv($preorders, "export-versand.csv"); } protected function csvExportAndMarkAsSentAction() { $preorders = $this->getFilteredPreordersFromRequest(); foreach ($preorders as $preorder) $this->saveSentStatus($preorder->id, true); $this->generateAndDownloadCsv($preorders, "export-versand-markiert.csv"); } private function getFilteredPreordersFromRequest() { $postData = json_decode(file_get_contents('php://input'), true); $filter = $this->getPreparedFilter($postData['filters'] ?? []); $my_campaign_ids = $this->getUserCampaignIds(); if (empty($my_campaign_ids)) return []; if (empty($filter['preordercampaign_id'])) { $filter['preordercampaign_id'] = $my_campaign_ids; } else { // Ensure the filtered campaign is one the user has access to are arrays and if not allowed dont push it to the filter $preordercampaign_ids = is_array($filter['preordercampaign_id']) ? $filter['preordercampaign_id'] : [$filter['preordercampaign_id']]; $new_allowed_ids = array_intersect($preordercampaign_ids, $my_campaign_ids); if (empty($new_allowed_ids)) { self::returnJson(['rows' => [], 'pagination' => ['total_rows' => 0]]); return; } } // Return objects for methods that expect them return PreorderModel::searchWithLogistics($filter, []); } private function generateAndDownloadCsv($preorders, $filename) { header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=' . $filename); $output = fopen('php://output', 'w'); fputcsv($output, ["ucode", "oaid", "addr_name", "addr_street", "addr_zip", "addr_city", "phone", "email"], ";"); foreach ($preorders as $preorder) { fputcsv($output, [ $preorder->ucode, $preorder->oaid, $preorder->company ?: "{$preorder->firstname} {$preorder->lastname}", $preorder->adb_hausnummer_id && $preorder->adb_hausnummer && $preorder->adb_hausnummer->strasse ? "{$preorder->adb_hausnummer->strasse->name} {$preorder->adb_hausnummer->hausnummer}" : trim("{$preorder->street} {$preorder->housenumber}"), $preorder->adb_hausnummer_id && $preorder->adb_hausnummer && $preorder->adb_hausnummer->plz ? $preorder->adb_hausnummer->plz->plz : $preorder->zip, $preorder->adb_hausnummer_id && $preorder->adb_hausnummer && $preorder->adb_hausnummer->ortschaft ? $preorder->adb_hausnummer->ortschaft->name : $preorder->city, $preorder->phone, $preorder->email ], ";"); } fclose($output); exit; } private function printActionContent($id) { $preorder = new Preorder($id); if (!$preorder->id) return; if (!$preorder->cifurl) { $preorder->createCiftoken(); $preorder->cifurl = $preorder->generateCifUrl(); $preorder->cifcableurl = $preorder->generateCifCableUrl(); $preorder->save(); } $qr = QRCode::init($preorder->cifurl); $layout = new mfLayout(); $layout->setTemplate("Preorderlogistics/Print.template"); $layout->set("qr_url", $qr->base64()); $layout->set("preorder", $preorder); echo $layout->render(false); } private function saveSentStatus($preorder_id, $isSent) { if (!is_numeric($preorder_id) || $preorder_id < 1) return false; $preorder = new Preorder($preorder_id); if (!$preorder->id || !$this->isUserAllowedForPreorder($preorder)) return false; $installation_kit_status_flag = PreorderStatusflagModel::getFirst(["code" => "145"]); if (!$installation_kit_status_flag) return false; $flagvalue = PreorderStatusflagValueModel::getFirst(["preorder_id" => $preorder_id, "flag_id" => $installation_kit_status_flag->id]); if (!$flagvalue) { $flagvalue = PreorderStatusflagValueModel::create([ "preorder_id" => $preorder_id, "flag_id" => $installation_kit_status_flag->id ]); } $flagvalue->value = $isSent ? 1 : 0; $flagvalue->save(); $plog = PreorderlogisticsModel::getFirst(["preorder_id" => $preorder->id]); if (!$plog) { $plog = PreorderlogisticsModel::create(["preorder_id" => $preorder->id]); } $plog->sent = $isSent ? time() : 0; $plog->sent_by = $isSent ? $this->me->id : null; return $plog->save(); } private function getFormattedAddress(Preorder $preorder) { if ($preorder->adb_hausnummer_id && $preorder->adb_hausnummer) { $address = $preorder->company ? htmlspecialchars($preorder->company) . "
" . htmlspecialchars(trim("{$preorder->firstname} {$preorder->lastname}")) : htmlspecialchars(trim("{$preorder->firstname} {$preorder->lastname}")); if ($preorder->adb_hausnummer->strasse) { $address .= "
" . htmlspecialchars($preorder->adb_hausnummer->strasse->name) . " " . htmlspecialchars($preorder->adb_hausnummer->hausnummer); } $address .= ($preorder->adb_wohneinheit_id && $preorder->adb_wohneinheit && (string)$preorder->adb_wohneinheit) ? "
" . htmlspecialchars((string)$preorder->adb_wohneinheit) : ""; if ($preorder->adb_hausnummer->plz && $preorder->adb_hausnummer->ortschaft) { $address .= "
" . htmlspecialchars($preorder->adb_hausnummer->plz->plz) . " " . htmlspecialchars($preorder->adb_hausnummer->ortschaft->name); } if ($preorder->adb_hausnummer->strasse && $preorder->adb_hausnummer->strasse->gemeinde) { $address .= "
" . htmlspecialchars($preorder->adb_hausnummer->strasse->gemeinde->name); } } else { $address = htmlspecialchars($preorder->company ?: "{$preorder->firstname} {$preorder->lastname}"); $address .= "
" . htmlspecialchars(trim("{$preorder->street} {$preorder->housenumber}")); $address .= "
" . htmlspecialchars($preorder->zip) . " " . htmlspecialchars($preorder->city); } return $address; } private function getUserCampaignIds() { $user_network_ids = json_decode($this->me->getFlag("preorder_networks")->value() ?: '[]', true); if (!is_array($user_network_ids) || count($user_network_ids) === 0) return []; $campaigns = PreordercampaignModel::search(['network_id' => $user_network_ids]); if(!is_array($campaigns)) return []; return array_map(fn($c) => $c->id, $campaigns); } private function isUserAllowedForPreorder(Preorder $preorder) { $user_campaign_ids = $this->getUserCampaignIds(); return in_array($preorder->preordercampaign_id, $user_campaign_ids); } private function getPreparedFilter($filter) { $new_filter = ['add-where' => ""]; if (!empty($filter['ucode'])) $new_filter['ucode%'] = "%" . $filter['ucode'] . "%"; if (!empty($filter['oaid'])) $new_filter['oaid%'] = "%" . $filter['oaid'] . "%"; if (!empty($filter['preordercampaign_id'])) $new_filter['preordercampaign_id'] = $filter['preordercampaign_id']; // FIX: Corrected filter key for FCP if (!empty($filter['fcp'])) $new_filter['fcp_id'] = $filter['fcp']; if(!empty($filter['address'])) { $address = $this->db()->escape($filter['address']); $new_filter['add-where'] .= " AND (adb_hausnummer.gemeinde like '%$address%' OR adb_hausnummer.plz like '%$address%' OR adb_hausnummer.strasse like '%$address%' OR adb_hausnummer.hausnummer like '%$address%' OR CONCAT(adb_hausnummer.strasse, ' ', adb_hausnummer.hausnummer) like '%$address%')"; } if(!empty($filter['kunde'])) { $kunde = $this->db()->escape($filter['kunde']); $new_filter['add-where'] .= " AND (company like '%$kunde%' OR firstname like '%$kunde%' OR lastname like '%$kunde%' OR concat(firstname, ' ', lastname) like '%$kunde%' OR concat(lastname, ' ', firstname) like '%$kunde%')"; } $installation_kit_status_flag = PreorderStatusflagModel::getFirst(["code" => "145"]); if ($installation_kit_status_flag) { $installation_kit_status_flag_id = $installation_kit_status_flag->id; if (isset($filter['sent'])) { if ($filter['sent'] == "yes") $new_filter["preorder_status_flags_enabled"] = [$installation_kit_status_flag_id]; if ($filter['sent'] == "no") $new_filter["preorder_status_flags_disabled"] = [$installation_kit_status_flag_id]; // if 'all', do nothing to apply no filter for sent status } else { // Default to 'not sent' if filter is not set $new_filter["preorder_status_flags_disabled"] = [$installation_kit_status_flag_id]; } } // Date filter for sent date (Versanddatum range) if (!empty($filter['sent_date']) && is_array($filter['sent_date'])) { if (!empty($filter['sent_date']['from'])) { $new_filter['add-where'] .= " AND Preorderlogistics.sent >= " . intval($filter['sent_date']['from']); } if (!empty($filter['sent_date']['to'])) { $new_filter['add-where'] .= " AND Preorderlogistics.sent <= " . intval($filter['sent_date']['to']); } } $new_filter["status_code"] = 140; $new_filter["deleted"] = 0; $new_filter["unit_count<="] = 2; return $new_filter; } }