table = 'Preorder'; // Set a primary table if needed, though most methods define their own } /** * Checks if an origin has rights for a given cluster and returns the campaign. * @param int $clusterId The 'adb_netzgebiet_id' from the thetool.Network table. * @param string|null $origin The requesting origin (e.g., https://www.example.com). * @return array|null The campaign data if valid, otherwise null. */ public function getCampaignByClusterIdAndOrigin(int $clusterId, ?string $origin): ?array { // A null origin is not allowed for security reasons if (!$origin) { return null; } $query = " SELECT pc.* FROM thetool.Preordercampaign pc JOIN thetool.Network n ON pc.Network_id = n.id WHERE n.adb_netzgebiet_id = ? "; $res = $this->db->query($query, [$clusterId]); $campaign = $this->db->fetch_assoc($res); if (!$campaign || empty($campaign['iframe_origins'])) { return null; } $allowedOrigins = json_decode($campaign['iframe_origins'], true); if (is_array($allowedOrigins) && in_array($origin, $allowedOrigins)) { return $campaign; } return null; } public function getClusters($frame_referrer): array { $query = " SELECT n.adb_netzgebiet_id as id, ng.name FROM thetool.Preordercampaign pc JOIN thetool.Network n ON pc.Network_id = n.id JOIN addressdb.Netzgebiet ng ON n.adb_netzgebiet_id = ng.id WHERE JSON_SEARCH(pc.iframe_origins, 'one', '" . $this->db->escape($frame_referrer) . "') IS NOT NULL GROUP BY n.adb_netzgebiet_id, ng.name ORDER BY ng.name ASC "; $res = $this->db->query($query); return $this->db->fetch_all_assoc($res); } public function findCities(string $zip, int $adb_network_id): array { $query = " SELECT DISTINCT o.name FROM addressdb.Plz p JOIN addressdb.Ortschaft o ON p.gemeinde_id = o.gemeinde_id JOIN addressdb.Gemeinde g ON o.gemeinde_id = g.id JOIN addressdb.GemeindeNetzgebiet gn ON g.id = gn.gemeinde_id WHERE p.plzstring = " . $this->db->escape($zip) . " AND gn.netzgebiet_id = " . intval($adb_network_id) . " ORDER BY o.name ASC "; $res = $this->db->query($query); $cities = $this->db->fetch_all_assoc($res); return array_column($cities, 'name'); } /** * Finds streets for a given ZIP, city, and cluster. * @param string $zip * @param string $city * @param int $clusterId * @return array */ public function findStreets(string $zip, string $city, int $clusterId): array { $query = " SELECT DISTINCT s.name FROM addressdb.Strasse s JOIN addressdb.Gemeinde g ON s.gemeinde_id = g.id JOIN addressdb.Ortschaft o ON o.gemeinde_id = g.id AND o.name = '" . $this->db->escape($city) . "' JOIN addressdb.GemeindeNetzgebiet gn ON g.id = gn.gemeinde_id WHERE gn.netzgebiet_id = " . intval($clusterId) . " AND EXISTS ( SELECT 1 FROM addressdb.Plz p WHERE p.plzstring = " . $this->db->escape($zip) . " AND p.gemeinde_id = o.gemeinde_id ) ORDER BY s.name ASC "; $res = $this->db->query($query); $streets = $this->db->fetch_all_assoc($res); return array_column($streets, 'name'); } public function findAddresses(array $params): array { $query = " SELECT h.oaid, h.hausnummer, s.name as street, p.plzstring as zip, o.name as city, h.id as hausnummer_id, w.id as wohneinheit_id, h.stiege, h.unit_count as building_unit_count, h.tool_building_type as building_type, w.oaid as unit_oaid, w.stock, w.tuer, w.zusatz FROM addressdb.Hausnummer h JOIN addressdb.Strasse s ON h.strasse_id = s.id JOIN addressdb.Plz p ON h.plz_id = p.id JOIN addressdb.Ortschaft o ON s.gemeinde_id = o.gemeinde_id LEFT JOIN addressdb.Wohneinheit w ON w.hausnummer_id = h.id WHERE h.netzgebiet_id = " . intval($params['cluster_id']) . " AND p.plzstring = " . $this->db->escape($params['zip']) . " AND o.name = '" . $this->db->escape($params['city']) . "' AND s.name = '" . $this->db->escape($params['street']) . "' AND h.hausnummer = '" . $this->db->escape($params['housenumber']) . "' "; $results = $this->db->fetch_all_assoc($this->db->query($query)); if (empty($results)) return []; $addresses = []; $topCounter = 1; if (count($results) > 1) { foreach ($results as $row) { $showText = $this->buildShowText($row, $topCounter++); $addresses[] = [ 'oaid' => $row['unit_oaid'], 'street' => $row['street'], 'housenumber' => $row['hausnummer'], 'hausnummer_id' => $row['hausnummer_id'], 'wohneinheit_id' => $row['wohneinheit_id'], 'building_type' => intval($row['building_type']), 'zip' => $row['zip'], 'city' => $row['city'], 'stiege' => $row['stiege'], 'stock' => $row['stock'], 'tuer' => $row['tuer'], 'zusatz' => $row['zusatz'], 'building_unit_count' => $row['building_unit_count'], 'showText' => $showText, 'preorderTypes' => ['order'] ]; } } else { $row = $results[0]; $addresses[] = [ 'oaid' => $row['oaid'], 'street' => $row['street'], 'housenumber' => $row['hausnummer'], 'hausnummer_id' => $row['hausnummer_id'], 'wohneinheit_id' => $row['wohneinheit_id'], 'building_type' => intval($row['building_type']), 'zip' => $row['zip'], 'city' => $row['city'], 'stiege' => $row['stiege'], 'stock' => $row['stock'], 'tuer' => $row['tuer'], 'zusatz' => $row['zusatz'], 'building_unit_count' => $row['building_unit_count'], 'showText' => $this->buildShowText($row, 1), 'preorderTypes' => ['order'] ]; } return $addresses; } private function buildShowText(array $row, int $counter): string { $parts = array_filter([ $row['stiege'] ? "Stiege {$row['stiege']}" : null, $row['stock'] ? "Stock {$row['stock']}" : null, $row['tuer'] ? "Tür {$row['tuer']}" : null, $row['zusatz'] ?: null ]); return $parts ? implode(', ', $parts) : "Top {$counter}"; } /** * Creates a new preorder record in the database. * @param array $data The validated preorder data from the form. * @param int $campaignId The ID of the associated preorder campaign. * @return array The result containing the new order code. */ public function createPreorder(array $data, int $campaignId): array { $customer = $data['customer']; $address = $data['address']; // Generate a unique code for the preorder $ucode = strtoupper(substr(md5(uniqid(rand(), true)), 0, 10)); $preorderData = [ 'ucode' => $ucode, 'thetool.Preordercampaign_id' => $campaignId, 'oaid' => $address['oaid'], 'type' => $data['preorderType'], 'connection_type' => $data['connectionType'], 'contact_type' => $customer['type'], 'firstname' => $customer['firstname'], 'lastname' => $customer['lastname'], 'company' => $customer['company'] ?? null, 'street' => $customer['street'], 'housenumber' => $customer['housenumber'], 'zip' => $customer['zip'], 'city' => $customer['city'], 'phone' => $customer['phone'], 'email' => $customer['email'], 'address_info' => $data['address_info'], 'accept_agb' => $data['acceptAgb'] ? 1 : 0, 'accept_dsgvo' => $data['acceptDsgvo'] ? 1 : 0, 'accept_marketing' => $data['acceptMarketing'] ? 1 : 0, 'accept_withdrawal' => $data['acceptWithdrawal'] ? 1 : 0, 'addon_data' => json_encode($data['additionalData']), 'submit_type' => 'api', 'submit_request' => json_encode($data), 'order_date' => time(), 'create' => time(), 'edit' => time(), 'create_by' => 0, // System user 'edit_by' => 0, // System user ]; $this->db->insert('Preorder', $preorderData); return ['code' => $ucode]; } }