'Artikel', 'db_table' => 'items', 'list_fields' => array( array( 'db_field' => 'number', 'name' => 'Art-Nr.', 'sortable' => 1 ), array( 'db_field' => 'name', 'name' => 'Bezeichnung', 'sortable' => 1 ), array( 'db_field' => 'file_name', 'ref_db_table' => 'item_files', 'ref_db1_field' => 'id', 'ref_db2_field' => 'item_id', 'name' => 'Bild', 'function' => 'count', 'sortable' => 0 ), array( 'db_field' => 'manufacturer_id', 'name' => 'Hersteller', 'rewrite_function' => 'manufacturer_names', 'sortable' => 1 ), array( 'db_field' => 'inventory', 'name' => 'Lager', 'sortable' => 1 ), array( 'db_field' => 'price_1', 'ref_db_table' => 'item_prices', 'ref_db1_field' => 'id', 'ref_db2_field' => 'item_id', 'name' => 'Preis (netto)', 'format' => 'netto_price', 'sortable' => 1 ), array( 'db_field' => 'steuersatz / 100 * item_prices.price_1 + item_prices.price_1 AS price_brutto', 'db_field_rename' => 'price_brutto', 'ref_db_table' => 'tax', 'ref_db1_field' => 'tax_id', 'ref_db2_field' => 'id', 'name' => 'Preis (brutto)', 'format' => 'netto_price', 'sortable' => 0 ), array( 'db_field' => 'structure_id', 'name' => 'Hauptwarengruppe', 'rewrite_function' => 'structure_values', 'sortable' => 1 ), array( 'db_field' => 'item_type_id', 'ref_db_table' => 'item_types', 'ref_db1_field' => 'id', 'ref_db2_field' => 'item_id', 'name' => 'Typzuordnung', 'function' => 'count', 'sortable' => 0 ), array( 'db_field' => 'active', 'name' => 'Status', 'rewrite_function' => 'state_text', 'sortable' => 1 ) ), 'permanent_filter' => array( array( 'db_field' => 'parent_id', 'relational_operator' => '=', 'value' => '0' ) ), 'list_group_by' => 'id', 'default_sort_item' => 'number', 'default_sort_direction' => 'up', 'search_fields' => array('items.name', 'items.number', 'items.short_description', 'items.detail_description'), 'db_id_field' => 'id', 'edit_link' => 'index.php?admin_modul=admin_item_editor&id=', 'toolbar' => array( 'delete' => '1', 'new' => 'index.php?admin_modul=admin_item_editor', 'copy' => 0, 'select_all' => 1, 'edit' => 0, 'actions' => 1, 'filter' => 1, 'view' => 0, 'csv_export' => 1, 'search' => 1 ), 'list_actions' => array( array( 'db_field' => 'active', 'name' => 'Neuer Status', 'values' => 'state_text' ) ), 'list_filter' => array( array( 'db_field' => 'manufacturer_id', 'relational_operator' => '=', 'name' => 'Hersteller', 'values' => 'manufacturer_names' ), array( 'db_field' => 'active', 'relational_operator' => '=', 'name' => 'Status', 'values' => 'state_text' ), array( 'db_field' => 'items.structure_id', 'relational_operator' => '=', 'name' => 'Hauptwarengruppe', 'values' => 'structure_values' ), array( 'db_field' => 'items.inventory', 'name' => 'Lagerbestand', 'values' => 'inventory_filter' ), array( 'db_field' => 'items.shippable', 'relational_operator' => '=', 'name' => 'Lieferstatus kein Bestand', 'values' => 'shipping_states' ), array( 'db_field' => 'items.shippable_inventory', 'relational_operator' => '=', 'name' => 'Lieferstatus bei Bestand', 'values' => 'shipping_states' ), array( 'db_field' => '(item_prices.price_1', 'name' => 'Netto-Händlerpreis', 'values' => 'price_filter' ), array( 'db_field' => 'item_files.file_name', 'name' => 'Artikelbild', 'values' => 'image_filter' ), array( 'db_field' => 'item_types.item_type_definition_id', 'relational_operator' => '=', 'name' => 'Artikeltypzuordnung', 'values' => 'item_type_values' ), ), 'edit_fields' => array( array( 'db_field' => 'active', 'name' => 'Status', 'type' => 'int' ) ) ); private $schema_fields = array( 'name' => 'text', 'description' => 'text', 'selectable_attribute_1' => 'integer', 'selectable_attribute_2' => 'integer', 'base_price_field' => 'integer', 'base_price_faktor' => 'float', 'base_price_unit' => 'text', 'attribute_name_1' => 'text', 'attribute_name_1_en' => 'text', 'attribute_unit_1' => 'text', 'attribute_rang_1' => 'integer', 'attribute_liste_1' => 'integer', 'attribute_detail_1' => 'integer', 'attribute_name_2' => 'text', 'attribute_name_2_en' => 'text', 'attribute_unit_2' => 'text', 'attribute_rang_2' => 'integer', 'attribute_liste_2' => 'integer', 'attribute_detail_2' => 'integer', 'attribute_name_3' => 'text', 'attribute_name_3_en' => 'text', 'attribute_unit_3' => 'text', 'attribute_rang_3' => 'integer', 'attribute_liste_3' => 'integer', 'attribute_detail_3' => 'integer', 'attribute_name_4' => 'text', 'attribute_name_4_en' => 'text', 'attribute_unit_4' => 'text', 'attribute_rang_4' => 'integer', 'attribute_liste_4' => 'integer', 'attribute_detail_4' => 'integer', 'attribute_name_5' => 'text', 'attribute_name_5_en' => 'text', 'attribute_unit_5' => 'text', 'attribute_rang_5' => 'integer', 'attribute_liste_5' => 'integer', 'attribute_detail_5' => 'integer', 'attribute_name_6' => 'text', 'attribute_name_6_en' => 'text', 'attribute_unit_6' => 'text', 'attribute_rang_6' => 'integer', 'attribute_liste_6' => 'integer', 'attribute_detail_6' => 'integer', 'attribute_name_7' => 'text', 'attribute_name_7_en' => 'text', 'attribute_unit_7' => 'text', 'attribute_rang_7' => 'integer', 'attribute_liste_7' => 'integer', 'attribute_detail_7' => 'integer', 'attribute_name_8' => 'text', 'attribute_name_8_en' => 'text', 'attribute_unit_8' => 'text', 'attribute_rang_8' => 'integer', 'attribute_liste_8' => 'integer', 'attribute_detail_8' => 'integer', 'attribute_name_9' => 'text', 'attribute_name_9_en' => 'text', 'attribute_unit_9' => 'text', 'attribute_rang_9' => 'integer', 'attribute_liste_9' => 'integer', 'attribute_detail_9' => 'integer', 'attribute_name_10' => 'text', 'attribute_name_10_en' => 'text', 'attribute_unit_10' => 'text', 'attribute_rang_10' => 'integer', 'attribute_liste_10' => 'integer', 'attribute_detail_10' => 'integer', 'attribute_name_11' => 'text', 'attribute_name_11_en' => 'text', 'attribute_unit_11' => 'text', 'attribute_rang_11' => 'integer', 'attribute_liste_11' => 'integer', 'attribute_detail_11' => 'integer', 'attribute_name_12' => 'text', 'attribute_name_12_en' => 'text', 'attribute_unit_12' => 'text', 'attribute_rang_12' => 'integer', 'attribute_liste_12' => 'integer', 'attribute_detail_12' => 'integer', 'attribute_name_13' => 'text', 'attribute_name_13_en' => 'text', 'attribute_unit_13' => 'text', 'attribute_rang_13' => 'integer', 'attribute_liste_13' => 'integer', 'attribute_detail_13' => 'integer', 'attribute_name_14' => 'text', 'attribute_name_14_en' => 'text', 'attribute_unit_14' => 'text', 'attribute_rang_14' => 'integer', 'attribute_liste_14' => 'integer', 'attribute_detail_14' => 'integer', 'attribute_name_15' => 'text', 'attribute_name_15_en' => 'text', 'attribute_unit_15' => 'text', 'attribute_rang_15' => 'integer', 'attribute_liste_15' => 'integer', 'attribute_detail_15' => 'integer', 'attribute_name_16' => 'text', 'attribute_name_16_en' => 'text', 'attribute_unit_16' => 'text', 'attribute_rang_16' => 'integer', 'attribute_liste_16' => 'integer', 'attribute_detail_16' => 'integer', 'attribute_name_17' => 'text', 'attribute_name_17_en' => 'text', 'attribute_unit_17' => 'text', 'attribute_rang_17' => 'integer', 'attribute_liste_17' => 'integer', 'attribute_detail_17' => 'integer', 'attribute_name_18' => 'text', 'attribute_name_18_en' => 'text', 'attribute_unit_18' => 'text', 'attribute_rang_18' => 'integer', 'attribute_liste_18' => 'integer', 'attribute_detail_18' => 'integer', 'attribute_name_19' => 'text', 'attribute_name_19_en' => 'text', 'attribute_unit_19' => 'text', 'attribute_rang_19' => 'integer', 'attribute_liste_19' => 'integer', 'attribute_detail_19' => 'integer', 'attribute_name_20' => 'text', 'attribute_name_20_en' => 'text', 'attribute_unit_20' => 'text', 'attribute_rang_20' => 'integer', 'attribute_liste_20' => 'integer', 'attribute_detail_20' => 'integer' ); private $item_fields = array( 'active' => 'integer', 'parent_id' => 'integer', 'number' => 'text', 'name' => 'text', 'short_description' => 'text', 'detail_description' => 'text', 'name_en' => 'text', 'short_description_en' => 'text', 'detail_description_en' => 'text', 'youtube_video' => 'text', 'structure_id' => 'integer', /*'structure_id_2' => 'integer', 'structure_id_3' => 'integer', 'structure_id_4' => 'integer', 'structure_id_5' => 'integer', 'structure_id_6' => 'integer', 'structure_id_7' => 'integer', 'structure_id_8' => 'integer', 'structure_id_9' => 'integer', 'structure_id_10' => 'integer',*/ 'manufacturer_id' => 'integer', 'manufacturer_item_number' => 'text', 'ean_code' => 'text', 'short_uri' => 'text', 'seo_title' => 'text', 'seo_description' => 'text', 'seo_keywords' => 'text', 'inventory_number' => 'text', 'inventory' => 'integer', 'inventory_min' => 'integer', 'inventory_rack_number' => 'text', 'inventory_order_quantity' => 'integer', 'tax_id' => 'integer', 'base_price' => 'float', 'price_type' => 'integer', 'bargain_price_type' => 'integer', 'uvp' => 'float', 'schema_id' => 'integer', /* 'price_1' => 'float', 'bargain_price_1' => 'float', 'quantity_1' => 'integer', 'price_2' => 'float', 'bargain_price_2' => 'float', 'quantity_2' => 'integer', 'price_3' => 'float', 'bargain_price_3' => 'float', 'quantity_3' => 'integer', 'price_4' => 'float', 'bargain_price_4' => 'float', 'quantity_4' => 'integer', 'price_5' => 'float', 'bargain_price_5' => 'float', 'quantity_5' => 'integer', 'price_6' => 'float', 'bargain_price_6' => 'float', 'quantity_6' => 'integer', 'price_7' => 'float', 'bargain_price_7' => 'float', 'quantity_7' => 'integer', 'price_8' => 'float', 'bargain_price_8' => 'float', 'quantity_8' => 'integer', 'price_9' => 'float', 'bargain_price_9' => 'float', 'quantity_9' => 'integer', 'price_10' => 'float', 'bargain_price_10' => 'float', 'quantity_10' => 'integer', 'price_11' => 'float', 'bargain_price_11' => 'float', 'quantity_11' => 'integer', 'price_12' => 'float', 'bargain_price_12' => 'float', 'quantity_12' => 'integer', 'price_13' => 'float', 'bargain_price_13' => 'float', 'quantity_13' => 'integer', 'price_14' => 'float', 'bargain_price_14' => 'float', 'quantity_14' => 'integer', 'price_15' => 'float', 'bargain_price_15' => 'float', 'quantity_15' => 'integer', 'price_16' => 'float', 'bargain_price_16' => 'float', 'quantity_16' => 'integer', 'price_17' => 'float', 'bargain_price_17' => 'float', 'quantity_17' => 'integer', 'price_18' => 'float', 'bargain_price_18' => 'float', 'quantity_18' => 'integer', 'price_19' => 'float', 'bargain_price_19' => 'float', 'quantity_19' => 'integer', 'price_20' => 'float', 'bargain_price_20' => 'float', 'quantity_20' => 'integer', 'price_21' => 'float', 'bargain_price_21' => 'float', 'quantity_21' => 'integer', 'price_22' => 'float', 'bargain_price_22' => 'float', 'quantity_22' => 'integer', 'price_23' => 'float', 'bargain_price_23' => 'float', 'quantity_23' => 'integer', 'price_24' => 'float', 'bargain_price_24' => 'float', 'quantity_24' => 'integer', 'price_25' => 'float', 'bargain_price_25' => 'float', 'quantity_25' => 'integer', 'price_26' => 'float', 'bargain_price_26' => 'float', 'quantity_26' => 'integer', 'price_27' => 'float', 'bargain_price_27' => 'float', 'quantity_27' => 'integer', 'price_28' => 'float', 'bargain_price_28' => 'float', 'quantity_28' => 'integer', 'price_29' => 'float', 'bargain_price_29' => 'float', 'quantity_29' => 'integer', 'price_30' => 'float', 'bargain_price_30' => 'float', 'quantity_30' => 'integer', */ 'attribute_1' => 'text', 'attribute_2' => 'text', 'attribute_3' => 'text', 'attribute_4' => 'text', 'attribute_5' => 'text', 'attribute_6' => 'text', 'attribute_7' => 'text', 'attribute_8' => 'text', 'attribute_9' => 'text', 'attribute_10' => 'text', 'attribute_11' => 'text', 'attribute_12' => 'text', 'attribute_13' => 'text', 'attribute_14' => 'text', 'attribute_15' => 'text', 'attribute_16' => 'text', 'attribute_17' => 'text', 'attribute_18' => 'text', 'attribute_19' => 'text', 'attribute_20' => 'text', 'shippable' => 'shippable', 'available_from' => 'date', 'available_till' => 'date', 'variant_price_type' => 'integer', 'google_product_category' => 'text', 'combination_item' => 'integer', 'sample_unit' => 'text', 'vendor_item_number' => 'text', 'vendor_id' => 'integer', 'has_user_data' => 'integer', 'price_je_vpe' => 'integer', 'vpe_amount' => 'integer', 'vpe_unit' => 'text', 'vpe_sampleprice_unit' => 'float', 'min_quantity' => 'integer', 'shippable_inventory' => 'integer', 'shipping_cost_type' => 'integer', 'shipping_item_type' => 'integer', 'shipping_weight' => 'float', 'buy_quantity' => 'integer', 'main_variant_item_id' => 'integer' ); private $config; protected $base_object; private $shopConfiguration; private $schema_id; private $itemschema_object; private $item_discounts; protected $db; public $id = 0; public $shopArticleProducers; public $discount; public $selectableVariants = array(); public $deleteSelectableVariants = array(); public $itemCount; public $all_tax; public $price_praefix; private $tax_rates; private $manufacturers; private $structure; public function __construct($base_object, $id = false, $with_discounts = 1) { parent::__construct($base_object); $this->config = $base_object->config; $this->db = $base_object->db; $this->base_object = $base_object; // Initialize ItemDatabase for cleaner SQL handling include_once './core/item-db.class.php'; $this->itemDb = new ItemDatabase($this->base_object); // Performance-Debug aktiviert? Dann Debug-Ausgabe später anzeigen if (isset($_GET['debug_performance'])) { $this->debug_performance = true; echo "
✅ DEBUG-MODUS AKTIVIERT - Performance wird gemessen
"; } $this->id = $id; $this->shopConfiguration = $this->config->shopConfiguration; $this->price_praefix = ''; if ($this->shopConfiguration['show_child_items'] == 1) { $this->list_table_config['permanent_filter'] = array(); } $this->list_table_config['permanent_filter'][] = array( 'db_field' => 'item_prices.customergroup_id', 'relational_operator' => '=', 'accept_null' => 1, 'value' => $this->shopConfiguration['item_list_price_group_id'] ); $tax_object = new Tax($base_object); $this->all_tax = $tax_object->get_all(); $this->itemschema_object = new ItemSchema($base_object); if ($with_discounts) { $this->load_item_discounts(); } $this->setup_manufacturers_array(); $this->setup_tax_rate_array(); $this->setup_structure_array(); } // end __construct public function netto_price($string) { return ''.number_format($string, 2, ',', '').' €'; } public function state_text() { return array( '1' => 'aktiv', '0' => 'inaktiv' ); } public function shipping_states() { return array( '1' => 'lieferbar', '0' => 'nicht lieferbar', '2' => 'lieferbar ab', '3' => 'lieferzeit unbekannt', '4' => 'Bestellartikel (Lieferzeit 2-3 Tage)', '5' => 'Bestellartikel (Lieferzeit 14 Tage)' ); } public function inventory_filter() { if ($this->base_object->config->shopConfiguration['item_list_filter_max_inventory'] != '') { return array( '> 0' => '> 0', '= 0' => '= 0', '< 0' => '< 0', '< '.$this->base_object->config->shopConfiguration['item_list_filter_max_inventory'] => '< '.$this->base_object->config->shopConfiguration['item_list_filter_max_inventory'] ); } else { return array( '> 0' => '> 0', '= 0' => '= 0', '< 0' => '< 0' ); } } public function price_filter() { return array( '> 0)' => '> 0', '= 0 || item_prices.price_1 IS NULL)' => '= 0', '< 100)' => '< 100', '> 100)' => '> 100', '< 1000)' => '< 1000', '> 1000)' => '> 1000' ); } public function image_filter() { return array( "IS NULL" => 'nicht vorhanden', ); } public function manufacturer_names() { $manufacturer_object = new Manufacturer($this->base_object); return $manufacturer_object->get_all_names(); } public function structure_values() { $structure_object = new Structure($this->base_object); $data = $structure_object->full_name_path(); $data['0'] = '>>keine Zuweisung vorhanden<<'; return $data; } public function item_type_values() { include_once './core/itemtype.class.php'; $item_type_object = new ItemType($this->base_object); $data = $item_type_object->get_item_type_definitions(); return $data; } private function setup_manufacturers_array() { $sql = "SELECT * FROM manufacturers"; $result = $this->db->query($sql); if ($result->num_rows > 0) { $this->manufacturers = array(); while ($obj = $result->fetch_object()) { $this->manufacturers[$obj->id] = $obj; } } } // end setup_manufacturers_array private function setup_tax_rate_array() { $sql = "SELECT * FROM tax"; $result = $this->db->query($sql); if ($result->num_rows > 0) { $this->tax_rates = array(); while ($obj = $result->fetch_object()) { $this->tax_rates[$obj->id] = $obj; } } } // end setup_tax_rate_array private function setup_structure_array() { $sql = "SELECT * FROM structure"; $result = $this->db->query($sql); if ($result->num_rows > 0) { $this->structure = array(); while ($obj = $result->fetch_object()) { $this->structure[$obj->id] = $obj; } } } // end setup_structure_array public function set_schema_id($id) { $this->schema_id = $id; } public function get_schema_id() { return $this->schema_id; } public function set($data) { foreach ($data as $key => $value) { $this->{$key} = $value; } return; } // end set public function set_id($id) { $this->id = $id; } public function has_id() { if ($this->id) { return true; } return false; } public function get_id($id) { return $this->id; } public function set_row($data) { $dat = Database::clean($data); $sql = Database::insert('items', $data); } public function get_sold_out() { $sql = "SELECT id, name, inventory FROM items WHERE inventory_min>inventory LIMIT 10"; $result = $this->db->query($sql); if ($result->num_rows > 0) { while ($row = $result->fetch_object()) { $data[] = $row; } return $data; } return false; } public function get_all_paginated($items, $page, $order = false, $sort_direction = false) { $page = ($page - 1) * $items; $sort = ''; if ($order) { $sort = " ORDER BY ".$this->db->real_escape_string($order); if ($sort_direction && $sort_direction == 'down') { $sort .= " DESC "; } else { $sort .= " ASC "; } } if ($order == 'new') { $sql = "SELECT id, tax_id, number, name, active, price_1, bargain_price_1, inventory, inventory_min FROM items $sort LIMIT $items OFFSET $page;"; } else if ($order == 'sold_out') { $sql = "SELECT id, tax_id, number, name, active, price_1 FROM items $sort LIMIT $items OFFSET $page;"; } else { if ($_GET['structure_id']) { $sql = "SELECT id, tax_id, number, name, active, price_1, bargain_price_1, inventory, inventory_min FROM items WHERE structure_id=".$_GET['structure_id']." OR structure_id_2=".$_GET['structure_id']." OR structure_id_3=".$_GET['structure_id']." $sort LIMIT $items OFFSET $page;"; } else { $sql = "SELECT id, tax_id, number, name, active, price_1, bargain_price_1, inventory, inventory_min FROM items $sort LIMIT $items OFFSET $page;"; } } $data = parent::get_all_paginated($items, $page, $sql); $new_data = array(); foreach ($data as $obj) { $sql = "SELECT * FROM item_prices WHERE item_id = ".$obj->id." AND customergroup_id = 1 "; $prices = $this->db->query($sql)->fetch_object(); foreach ($prices as $field => $value) { if ($field != 'item_id' && $field != 'customergroup_id') { $obj->{$field} = $value; } } $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; // calc tax $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->price_1_tax = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value; // Set shop_* variables for item_box.tpl template (like in variant structure) // Templates expect shop_price_1 and shop_bargain_price_1 for display if ($this->base_object->customer_group->show_tax) { $obj->shop_price_1 = $obj->price_1_tax; $obj->shop_bargain_price_1 = $obj->bargain_price_1_tax; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } $new_data[] = $obj; } return $new_data; } // end get_all_paginated public function get_data($forCustomerGroup = 1, $for_frontend = true) { if (isset($_GET['debug_performance'])) { echo "
🟦 GET_DATA ERREICHT für ID: " . $this->id . "
"; flush(); ob_flush(); } $manufacturer = new Manufacturer($this->base_object); if (isset($_GET['debug_performance'])) { echo "
🟣 MANUFACTURER ERSTELLT
"; flush(); ob_flush(); } $customer_group_price = $forCustomerGroup; $customer_group_discount = $forCustomerGroup; if (isset($this->base_object->customer_group->adaptPricesFromId) && $this->base_object->customer_group->adaptPricesFromId) { $customer_group_price = $this->base_object->customer_group->adaptPricesFromId; } $forCustomerGroup = $customer_group_price; // Item Match - REAKTIVIERT $sql = "SELECT * FROM krempl_passendwie im JOIN items i ON i.attribute_7 = im.navisionid WHERE i.id = " . intval($this->id); $result = $this->db->query($sql); if ($result) { $obj = $result->fetch_object(); } // Get all Item Data - über unsere neue DB-Klasse $obj = $this->itemDb->getItemData($this->id); if (!$obj) { if (isset($_GET['debug_performance'])) { echo "
"; echo "❌ PROBLEM GEFUNDEN: Item mit ID {$this->id} existiert NICHT in der Datenbank!
"; echo "Das ist der Grund für das Timeout - das System sucht nach einem nicht-existierenden Artikel!
"; echo "URL sollte umgeleitet werden oder 404 zeigen."; echo "
"; die(); } // Check if we're in admin area - don't redirect, show error instead if (isset($_GET['admin_modul'])) { echo "
"; echo "❌ FEHLER: Item mit ID {$this->id} existiert nicht in der Datenbank!
"; echo "Möglicherweise wurde der Artikel gelöscht oder die ID ist ungültig."; echo "
"; return false; } // Normale Behandlung - zurück zur Startseite header('Location: /'); exit(); } if (isset($_GET['debug_performance'])) { echo "
✅ ITEM DATEN GELADEN - ID: {$this->id}
"; flush(); ob_flush(); } // Debug: Überprüfen der Objekt-Eigenschaften $debug_obj = get_object_vars($obj); if (isset($debug_obj['vendor_id'])) { // Stelle sicher, dass vendor_id als Integer behandelt wird $obj->vendor_id = intval($debug_obj['vendor_id']); } // REAKTIVIERT - "Passend wie" Daten für Template $sql = "SELECT i.number, im.vertreiber, im.bestellcode, i.attribute_7, i.number, i.krempl_id FROM krempl_passendwie im INNER JOIN items i ON i.attribute_7 = im.navisionid WHERE i.id = " . intval($this->id); $result = $this->db->query($sql); $obj->match = array(); if ($result) { while ($row = $result->fetch_object()) { $obj->match[] = $row; } } // Herstellerinformationen abrufen - über neue DB-Klasse $obj->herstellerinfo = $this->itemDb->getManufacturerInfo($obj->vendor_id ?? null); if (isset($_GET['debug_performance'])) { echo "
🟠 HERSTELLERINFO GELADEN
"; flush(); ob_flush(); } // Sicherheitshinweise und Dokumente hinzufügen - TEMPORÄR DEAKTIVIERT /*if (isset($obj->attribute_7) && !empty($obj->attribute_7)) { $navisionId = $obj->attribute_7; $sql = "SELECT * FROM sicherheitshinweis_item WHERE navision_id = ?"; $stmt = $this->db->prepare($sql); if ($stmt) { $stmt->bind_param("s", $navisionId); $stmt->execute(); $result = $stmt->get_result(); $warningDocsList = $result->fetch_assoc(); if ($warningDocsList) { // Sicherheitswarnungen laden $warningIdsList = $warningDocsList['warning_ids'] ?? null; $obj->warnings = $this->loadWarnings($warningIdsList);*/ // RESTLICHER SICHERHEITSHINWEISE-BLOCK TEMPORÄR DEAKTIVIERT /*$documentColumns = ['Bedienungsanleitung', 'EU_Datenblatt', 'Energielabel', 'Produktdatenblatt', 'Sicherheitsdatenblatt', 'Zertifikat', 'null_feld']; $documentColumns = [ 'Bedienungsanleitung' => 'Allg. Sicherheitshinweise', 'EU_Datenblatt' => 'EU-Datenblatt', 'Energielabel' => 'Energielabel', 'Produktdatenblatt' => 'Produktdatenblatt', 'Sicherheitsdatenblatt' => 'Sicherheitsdatenblatt', 'Zertifikat' => 'Zertifikat', 'null_feld' => 'Allg. Sicherheitshinweise' ]; $documents = []; foreach ($documentColumns as $column => $label) { if (!empty($warningDocsList[$column])) { $pdfs = explode(',', $warningDocsList[$column]); $pdfs = array_map('trim', $pdfs); $pdfs = array_map(fn($pdf) => trim($pdf, '"'), $pdfs); foreach ($pdfs as $pdf) { $documents[] = [ 'file_name' => $pdf, 'label' => $label ]; } } } $obj->wdocuments = $documents; } else { $obj->warnings = []; $obj->wdocuments = []; } } else { $obj->warnings = []; $obj->wdocuments = []; } }*/ // Sicherheitshinweise: Fallback-System attribute_5 -> attribute_7 $securityData = $this->itemDb->getSecurityWarnings($obj->attribute_7 ?? null, $obj->attribute_5 ?? null); $obj->warnings = $securityData['warnings']; $obj->wdocuments = $securityData['documents']; // 🤖 AI Shopping Schema Generator - KI-optimierte Produktdaten if ($this->shouldGenerateAISchema($obj)) { $this->generateAIShoppingSchema($obj); } // get admin user - über neue DB-Klasse $obj->last_change_user = $this->itemDb->getAdminUser($obj->last_change_user_id ?? null); if (isset($_GET['debug_performance'])) { echo "
🔵 ADMIN USER GELADEN
"; flush(); ob_flush(); } // get prices (auskommentiert) if (isset($_GET['debug_performance'])) { echo "
⚠️ VOR get_file_list() - jetzt testen...
"; flush(); ob_flush(); } $obj->files = $this->get_file_list(); if (isset($_GET['debug_performance'])) { echo "
✅ get_file_list() ERFOLGREICH - " . count($obj->files) . " Dateien geladen
"; flush(); ob_flush(); } if ($obj->parent_id && !$obj->files) { // get parent images if no variant images $obj->parent_files = $this->get_file_list(false, $obj->parent_id); } $manufacturer_data = $manufacturer->get_by_id($obj->manufacturer_id); if ($manufacturer_data) { $obj->manufacturer_name = $manufacturer_data->name; $obj->manufacturer_data = $manufacturer_data; } if (isset($_GET['debug_performance'])) { echo "
🏭 MANUFACTURER->get_by_id() ERFOLGREICH
"; echo "
"; echo "📊 ALLE WERTE nach manufacturer:
"; echo "obj->id = " . var_export($obj->id ?? 'NULL', true) . "
"; echo "obj->parent_id = " . var_export($obj->parent_id ?? 'NULL', true) . "
"; echo "obj->name = " . var_export($obj->name ?? 'NULL', true) . "
"; echo "obj->manufacturer_id = " . var_export($obj->manufacturer_id ?? 'NULL', true) . "
"; echo "manufacturer_data = " . (isset($manufacturer_data) ? 'EXISTS' : 'NULL') . "
"; echo "
"; flush(); ob_flush(); } // get parent item $obj->variant_structure = array(); $parent_id = 0; if (isset($_GET['debug_performance'])) { $check1 = $obj->parent_id ? 'TRUE' : 'FALSE'; $check2 = ($obj->parent_id != '0') ? 'TRUE' : 'FALSE'; $check3 = ($obj->parent_id > 0) ? 'TRUE' : 'FALSE'; echo "
"; echo "🔍 IF-CHECK RESULTS:
"; echo "parent_id = '" . $obj->parent_id . "'
"; echo "Check 1 (\$obj->parent_id): " . $check1 . "
"; echo "Check 2 (parent_id != '0'): " . $check2 . "
"; echo "Check 3 (parent_id > 0): " . $check3 . "
"; echo "
"; flush(); ob_flush(); } if ($obj->parent_id && $obj->parent_id != '0' && $obj->parent_id > 0) { if (isset($_GET['debug_performance'])) { echo "
➡️ GEHT IN IF-BLOCK REIN!
"; flush(); ob_flush(); // die() entfernt - soll durchlaufen } $parent_id = $obj->parent_id; if (isset($_GET['debug_performance'])) { echo "
🔴 VOR get_by_id() für PARENT_ID: " . $obj->parent_id . "
"; echo "
📊 WERTE: parent_id=[" . var_export($obj->parent_id, true) . "] type=[" . gettype($obj->parent_id) . "]
"; flush(); ob_flush(); // die() entfernt - soll durchlaufen } // get parent item data $parent_item = $this->get_by_id($obj->parent_id); if (isset($_GET['debug_performance'])) { echo "
✅ PARENT ITEM GELADEN
"; flush(); ob_flush(); // die() entfernt - soll durchlaufen } $obj->parent_item = $parent_item; $obj->structure_id = $parent_item->structure_id; $obj->variant_structure[] = array( 'id' => $parent_item->id, 'level' => 1, 'name' => $parent_item->name ); } else { $parent_id = '0'; // KORRIGIERT - Items ohne Parent haben parent_id = '0' $obj->variant_structure[] = array( 'id' => $obj->id, 'level' => 1, 'name' => $obj->name ); } if (isset($_GET['debug_performance'])) { echo "
✅ PARENT_ID BLOCK ÜBERSPRUNGEN - Artikel sollte jetzt laden!
"; flush(); ob_flush(); } // get schema data $obj->schema_data_attributes = array(); if (isset($_GET['debug_performance'])) { echo "
🔵 VOR SCHEMA CHECK - schema_id: " . ($obj->schema_id ?? 'NULL') . "
"; flush(); ob_flush(); } if ($obj->schema_id) { if (isset($_GET['debug_performance'])) { echo "
🟠 SCHEMA IF-BLOCK BETRETEN
"; flush(); ob_flush(); } $this->schema_id = $obj->schema_id; if (isset($_GET['debug_performance'])) { echo "
⚠️ VOR get_schema_data() - schema_id: " . $this->schema_id . "
"; flush(); ob_flush(); } $obj->schema_data = $this->get_schema_data(); if (isset($_GET['debug_performance'])) { echo "
✅ get_schema_data() ERFOLGREICH
"; flush(); ob_flush(); } // sampleprice calc data if ($obj->schema_data->base_price_field > 0) { $obj->sample_unit = $obj->schema_data->base_price_unit; } // added md5 variant key for ($i = 0; $i < count($obj->variant_structure); $i++) { // variant key 1 if ($obj->schema_data->selectable_attribute_1) { $obj->variant_structure[$i]['variant_key1_md5'] = md5($obj->variant_structure[$i]['data']->{'attribute_'.$obj->schema_data->selectable_attribute_1}); } // variant key 2 if ($obj->schema_data->selectable_attribute_2) { $obj->variant_structure[$i]['variant_key2_md5'] = md5($obj->variant_structure[$i]['data']->{'attribute_'.$obj->schema_data->selectable_attribute_2}); } else { $obj->variant_structure[$i]['variant_key2_md5'] = md5(0); } } $obj->item_category_name = Structure::get_name_by_id($obj->structure_id); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'name_en' => $attribute->name_en, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; // get selectable attributes 1 $obj->schema_data->all_selectable_attributes_1 = array(); foreach ($all_variants as $variante) { $obj->schema_data->all_selectable_attributes_1[md5($variante['data']->{'attribute_'.$attribute->number})] = $variante['data']->{'attribute_'.$attribute->number}; } } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; // get selectable attributes 2 $obj->schema_data->all_selectable_attributes_2 = array(); foreach ($all_variants as $variante) { $obj->schema_data->all_selectable_attributes_2[md5($variante['data']->{'attribute_'.$attribute->number})] = $variante['data']->{'attribute_'.$attribute->number}; } } // sampleprice calc data if ($obj->schema_data->base_price_field == $attribute->number) { $obj->vpe_sampleprice_unit = $obj->{'attribute_'.$attribute->number}; } } } // get item discount $discount = $this->get_item_discount($customer_group_discount, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // get variants - ONLY if parent_id > 0 if (isset($_GET['debug_performance'])) { echo "
"; echo "📊 PARENT_ID WERTE VOR VARIANTS:
"; echo "parent_id = [" . var_export($parent_id, true) . "] type=[" . gettype($parent_id) . "]
"; echo "parent_id > 0: " . (($parent_id > 0) ? 'TRUE' : 'FALSE') . "
"; echo "
"; flush(); ob_flush(); } if ($parent_id > 0) { if (isset($_GET['debug_performance'])) { echo "
🔴 VARIANTS SQL mit parent_id: " . $parent_id . "
"; flush(); ob_flush(); } $sql = "SELECT i.*, ip.price_1, ip.bargain_price_1 FROM items i LEFT JOIN item_prices ip ON (ip.item_id = i.id AND ip.customergroup_id = ".$this->db->real_escape_string($customer_group_price).") WHERE i.parent_id = ".$this->db->real_escape_string($parent_id)." GROUP BY i.id ORDER BY ip.price_1"; $variant_result = $this->db->query($sql); } else { if (isset($_GET['debug_performance'])) { echo "
✅ VARIANTS ÜBERSPRUNGEN - parent_id ist 0
"; flush(); ob_flush(); } $variant_result = false; } $all_variants = array(); if (isset($_GET['debug_performance'])) { echo "
🟣 NACH VARIANTS SQL - Rows: " . ($variant_result ? $variant_result->num_rows : 'NULL') . "
"; flush(); ob_flush(); } if ($variant_result && $variant_result->num_rows > 0) { while ($variant_obj = $variant_result->fetch_object()) { if ($discount) { $variant_obj->bargain_price_1 = round(($variant_obj->price_1 * (100 - $discount) / 100), 2); $variant_obj->discount = $discount; } // rewrite price with discountprice if ($variant_obj->bargain_price_1 > 0) { $variant_obj->price_1 = $variant_obj->bargain_price_1; } // calc tax $variant_obj->tax = $this->all_tax[$variant_obj->tax_id]->steuersatz; $variant_obj->tax_value = round($variant_obj->price_1 * ($variant_obj->tax / 100), 4); $variant_obj->price_1_tax = $variant_obj->price_1 + $variant_obj->tax_value; $variant_obj->bargain_tax_value = round($variant_obj->bargain_price_1 * ($variant_obj->tax / 100), 2); $variant_obj->bargain_price_1_tax = $variant_obj->bargain_price_1 + $variant_obj->bargain_tax_value; // shop price $variant_obj->sample_price = 0; if ($this->base_object->customer_group->show_tax) { $variant_obj->shop_price_1 = $variant_obj->price_1_tax; $variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1_tax; } else { $variant_obj->shop_price_1 = $variant_obj->price_1; $variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1; } // calc sample price $variant_obj->vpe_sampleprice_unit = $variant_obj->{'attribute_'.$obj->schema_data->base_price_field}; if ($obj->sample_unit && $variant_obj->vpe_sampleprice_unit) { if ($variant_obj->price_je_vpe) { if ($variant_obj->vpe_amount) { if ($variant_obj->shop_bargain_price_1 > 0) { $variant_obj->sample_price = $variant_obj->shop_bargain_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount); } else { $variant_obj->sample_price = $variant_obj->shop_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount); } } } else { if ($variant_obj->shop_bargain_price_1 > 0) { $variant_obj->sample_price = ($variant_obj->shop_bargain_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } else { $variant_obj->sample_price = ($variant_obj->shop_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } } } $all_variants[] = $obj->variant_structure[] = array( 'id' => $variant_obj->id, 'level' => 2, 'name' => $variant_obj->name, 'active' => $variant_obj->active, 'short_uri' => $variant_obj->short_uri, 'number' => $variant_obj->number, 'price_1' => $variant_obj->price_1, 'price_type' => $variant_obj->price_type, 'bargain_price_1' => $variant_obj->bargain_price_1, 'shop_price_1' => $variant_obj->shop_price_1, 'shop_bargain_price_1' => $variant_obj->shop_bargain_price_1, 'sample_price' => $variant_obj->sample_price, 'default_image_file_name' => $variant_obj->default_image_file_name, 'data' => $variant_obj ); // get smallest price for parent article if (!$obj->smallest_variant_price_1 || $obj->smallest_variant_price_1 > $variant_obj->price_1) { $obj->smallest_variant_price_1 = $variant_obj->price_1; $obj->smallest_variant_bargain_price_1 = $variant_obj->bargain_price_1; } } } else { // get prices $prices = $this->getPricesForCustomerGroup($forCustomerGroup); foreach ($prices as $field => $value) { if ($field != 'item_id' && $field != 'customergroup_id') { if (!$this->check_bargain_active($obj, $this->id) && substr($field,0,7) == 'bargain') { $value = 0; } $obj->{$field} = $value; } } } $obj->tax = isset($this->all_tax[$obj->tax_id]->steuersatz) ? $this->all_tax[$obj->tax_id]->steuersatz : 1.19; $obj->price_tax_text_free_shipping = isset($this->base_object->customer_group->price_tax_text_free_shipping) ? str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text_free_shipping) : 'inkl. [tax]% MwSt. versandkostenfrei'; $obj->price_tax_text = isset($this->base_object->customer_group->price_tax_text) ? str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text) : 'inkl. [tax]% MwSt.'; // get item_types $obj->item_types = $this->get_item_types($obj->id); // calc tax $obj->uvp_netto = round(($obj->uvp / ($obj->tax + 100) * 100), 4); $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 4); $obj->price_1_tax = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 4); $obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value; // shop price //$obj->sample_price = 0; if (isset($this->base_object->customer_group->show_tax) && $this->base_object->customer_group->show_tax) { $obj->shop_price_1 = $obj->price_1_tax; $obj->shop_bargain_price_1 = $obj->bargain_price_1_tax; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // calc sample price if ((!$all_variants || $obj->parent_id > 0) && ($obj->sample_unit && $obj->vpe_sampleprice_unit)) { if ($obj->price_je_vpe) { if ($obj->vpe_amount) { if ($obj->shop_bargain_price_1 > 0) { $obj->sample_price = $obj->shop_bargain_price_1 / ($obj->vpe_sampleprice_unit * $obj->vpe_amount); } else { $obj->sample_price = $obj->shop_price_1 / ($obj->vpe_sampleprice_unit * $obj->vpe_amount); } } } else { if ($obj->shop_bargain_price_1 > 0) { $obj->sample_price = ($obj->shop_bargain_price_1 / $obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } else { $obj->sample_price = ($obj->shop_price_1 / $obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } } } if (isset($_GET['debug_performance'])) { echo "
🔵 VOR SAMPLE PRICE + DATE CALC
"; flush(); ob_flush(); } $today = getdate(); $today = strtotime($today['year'].'-'.$today['mon'].'-'.$today['mday']); if (isset($_GET['debug_performance'])) { echo "
✅ DATE CALC FERTIG - today: " . date('Y-m-d', $today) . "
"; flush(); ob_flush(); } // TODO: IS ORDERABLE if ($for_frontend) { if ($obj->shippable == '2') { if ($obj->available_from != '' && $obj->available_from != '0000-00-00') { $startDate = strtotime($obj->available_from); if ($obj->available_till != '' && $obj->available_till != '0000-00-00') { // from - till $stopDate = strtotime($obj->available_till); if ($today > $startDate && $today < $stopDate) { $obj->shippable = 1; } else { $obj->shippable = 0; } } else { // from - no till if ($today > $startDate) { $obj->shippable = 1; } else { //$obj->shippable = 0; } } } else { // no from - till not checked $obj->shippable = 0; } } } // Description Tab $obj->detail_description = str_ireplace( array("\r", "\n", "\r\n", "\t"), '', $obj->detail_description ); if (isset($this->base_object->config->shopConfiguration['item_multi_description']) && $this->base_object->config->shopConfiguration['item_multi_description']) { $description_array = explode('[tab=', $obj->detail_description); $tab_title = array(); $tab_content = array(); if (is_array($description_array)) { foreach ($description_array as $key => $desc) { if (strpos($desc, ']')) { $sign_pos = strpos($desc, ']'); $tab_title[$key] = substr($desc, 0, $sign_pos); $tab_content[$key] = substr($desc, $sign_pos + 1); } } $obj->tab_title = $tab_title; $obj->tab_content = $tab_content; } } if (isset($_GET['debug_performance'])) { echo "
🟠 VOR TAB CONTENT CHECK
"; flush(); ob_flush(); } if (isset($obj->tab_content)) { if (isset($_GET['debug_performance'])) { echo "
⚠️ TAB CONTENT PROCESSING...
"; flush(); ob_flush(); } /*foreach ($obj->tab_content as $tabKey => $tmpTab) { $tidy = new tidy; $tidy->parseString($tmpTab, array( 'output-xhtml' => true, 'show-body-only' => true )); $tidy->cleanRepair(); $obj->tab_content[$tabKey] = $tidy->value; }*/ } // Graduated prices $obj->graduated_prices = array(); for ($i = 2; $i <= 30; ++$i) { $tmpPrice = $obj->{'price_'.$i}; $tmpBargain = $obj->{'bargain_price_'.$i}; $tmpQuantity = $obj->{'quantity_'.$i}; $tmpBargainTax = 0; $tmpBargainTaxPrice = 0; if ($tmpPrice > 0) { // calc tax $tmpTax = round($tmpPrice * ($obj->tax / 100), 4); $tmpTaxPrice = $tmpPrice + $tmpTax; if ($tmpBargain > 0) { $tmpBargainTax = round($tmpBargain * ($obj->tax / 100), 4); $tmpBargainTaxPrice = $tmpBargain + $tmpBargainTax; } // calc sample price $tmpSamplePriceNet = 0; $tmpSamplePriceGross = 0; // intelectra base price calc if ($obj->attribute_11 && $obj->attribute_15) { $obj->sample_unit = $obj->attribute_15; if ($tmpBargain > 0) { if (strstr($obj->sample_unit, '100')) { $tmpSamplePriceNet = $tmpBargain / ($obj->attribute_11 * 10); $tmpSamplePriceGross = $tmpBargainTaxPrice / ($obj->attribute_11 * 10); } else { $tmpSamplePriceNet = $tmpBargain / $obj->attribute_11; $tmpSamplePriceGross = $tmpBargainTaxPrice / $obj->attribute_11; } } else { if (strstr($obj->sample_unit, '100')) { $tmpSamplePriceNet = $tmpPrice / ($obj->attribute_11 * 10); $tmpSamplePriceGross = $tmpTaxPrice / ($obj->attribute_11 * 10); } else { $tmpSamplePriceNet = $tmpPrice / $obj->attribute_11; $tmpSamplePriceGross = $tmpTaxPrice / $obj->attribute_11; } } } /*if ($obj->sample_unit && $obj->vpe_sampleprice_unit) { if ($obj->price_je_vpe) { if ($obj->vpe_amount) { if ($tmpBargain > 0) { $tmpSamplePriceNet = $tmpBargain / ($obj->vpe_sampleprice_unit * $obj->vpe_amount); $tmpSamplePriceGross = $tmpBargainTaxPrice / ($obj->vpe_sampleprice_unit * $obj->vpe_amount); } else { $tmpSamplePriceNet = $tmpPrice / ($obj->vpe_sampleprice_unit * $obj->vpe_amount); $tmpSamplePriceGross = $tmpTaxPrice / ($obj->vpe_sampleprice_unit * $obj->vpe_amount); } } } else { if ($tmpBargain > 0) { $tmpSamplePriceNet = $tmpBargain / $obj->vpe_sampleprice_unit; $tmpSamplePriceGross = $tmpBargainTaxPrice / $obj->vpe_sampleprice_unit; } else { $tmpSamplePriceNet = $tmpPrice / $obj->vpe_sampleprice_unit; $tmpSamplePriceGross = $tmpTaxPrice / $obj->vpe_sampleprice_unit; } } }*/ // shop price if ($this->base_object->customer_group->show_tax) { $obj->graduated_prices[$tmpQuantity] = array( 'price' => $tmpTaxPrice, 'samplePrice' => $tmpSamplePriceGross, 'bargain' => $tmpBargainTaxPrice, 'priceNet' => $tmpPrice, 'bargainNet' => $tmpBargain, 'priceGross' => $tmpTaxPrice, 'bargainGross' => $tmpBargainTaxPrice, 'samplePriceNet' => $tmpSamplePriceNet, 'samplePriceGross' => $tmpSamplePriceGross ); } else { $obj->graduated_prices[$tmpQuantity] = array( 'price' => $tmpPrice, 'samplePrice' => $tmpSamplePriceNet, 'bargain' => $tmpBargain, 'priceNet' => $tmpPrice, 'bargainNet' => $tmpBargain, 'priceGross' => $tmpTaxPrice, 'bargainGross' => $tmpBargainTaxPrice, 'samplePriceNet' => $tmpSamplePriceNet, 'samplePriceGross' => $tmpSamplePriceGross ); } } } // Assigned items (additional items) if (isset($_GET['debug_performance'])) { echo "
🎀 VOR ASSIGNED ITEMS
"; flush(); ob_flush(); } $customer_object = new Customer_group($this->base_object); $customer_price_group_id = $customer_object->get_group_price_id($forCustomerGroup); $obj->assignedItemSet = $this->get_assigned_items_new($this->id, $customer_price_group_id, 1); if (isset($_GET['debug_performance'])) { echo "
"; echo "🔴 ASSIGNED ITEMS CHECK:
"; echo "obj->parent_id = [" . var_export($obj->parent_id, true) . "]
"; echo "assignedItemSet = " . (empty($obj->assignedItemSet) ? 'EMPTY' : 'HAS_DATA') . "
"; echo "
"; flush(); ob_flush(); } if ($obj->parent_id && $obj->parent_id != '0' && $obj->parent_id > 0 && !$obj->assignedItemSet) { // get parent assigned items if no variant assigned items $obj->parent_assignedItemSet = $this->get_assigned_items_new($obj->parent_id, $customer_price_group_id, 1); } if (isset($_GET['debug_performance'])) { echo "
🔵 NACH ASSIGNED ITEMS 1 - Weiter zu Items 2
"; flush(); ob_flush(); } // Assigned items 2 (spare parts) $obj->assignedItemSet2 = $this->get_assigned_items($this->id, $customer_price_group_id, 2); if ($obj->parent_id && $obj->parent_id != '0' && $obj->parent_id > 0 && !$obj->assignedItemSet2) { // get parent assigned items if no variant assigned items $obj->parent_assignedItemSet2 = $this->get_assigned_items($obj->parent_id, $customer_price_group_id, 2); } // Assigned items 5 (spare parts) $obj->assignedItemSet5 = $this->get_assigned_items($this->id, $customer_price_group_id, 2); if ($obj->parent_id && $obj->parent_id != '0' && $obj->parent_id > 0 && !$obj->assignedItemSet5) { // get parent assigned items if no variant assigned items $obj->parent_assignedItemSet5 = $this->get_assigned_items($obj->parent_id, $customer_price_group_id, 2); } if (isset($_GET['debug_performance'])) { echo "
🟣 NACH ASSIGNED ITEMS 2+5 - 2 Schritte vor!
"; flush(); ob_flush(); } // Assigned items 3 (real friends) $obj->assignedItemSet3 = $this->get_assigned_items($this->id, $customer_price_group_id, 3); if ($obj->parent_id && $obj->parent_id != '0' && $obj->parent_id > 0 && !$obj->assignedItemSet3) { // get parent assigned items if no variant assigned items $obj->parent_assignedItemSet3 = $this->get_assigned_items($obj->parent_id, $customer_price_group_id, 3); } // shipping costs if ($obj->shipping_cost_type == 2) { $sql = "SELECT * FROM item_shipping_costs WHERE item_id = ".intval($this->id); $result = $this->db->query($sql); $obj->shipping_area_costs = array(); while ($obj_shipping = $result->fetch_object()) { $obj->shipping_area_costs[$obj_shipping->shipping_area_id] = $obj_shipping; } } if (isset($_GET['debug_performance'])) { echo "
🟠 NACH SHIPPING COSTS - Fast am Ende!
"; flush(); ob_flush(); } // Include individual for intelectra if (isset($_GET['debug_performance'])) { echo "
⚠️ VOR INCLUDE IF-CHECK
"; echo "
"; echo "📊 INCLUDE VARIABLEN:
"; echo "this->base_object = " . (isset($this->base_object) ? 'EXISTS' : 'NULL') . "
"; echo "config = " . (isset($this->base_object->config) ? 'EXISTS' : 'NULL') . "
"; echo "shopConfiguration = " . (isset($this->base_object->config->shopConfiguration) ? 'EXISTS' : 'NULL') . "
"; echo "custom_global_modules = [" . var_export($this->base_object->config->shopConfiguration['custom_global_modules'] ?? 'NOT_SET', true) . "]
"; echo "ROOT_DIR = [" . var_export(defined('ROOT_DIR') ? ROOT_DIR : 'NOT_DEFINED', true) . "]
"; echo "SHOP_SYSTEM = [" . var_export(defined('SHOP_SYSTEM') ? SHOP_SYSTEM : 'NOT_DEFINED', true) . "]
"; $include_path = ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/intelectra_item_additional.inc.php'; echo "INCLUDE PATH = [" . $include_path . "]
"; echo "FILE EXISTS = " . (file_exists($include_path) ? 'YES' : 'NO') . "
"; echo "
"; flush(); ob_flush(); } if (isset($this->base_object->config->shopConfiguration['custom_global_modules']) && $this->base_object->config->shopConfiguration['custom_global_modules']) { if (isset($_GET['debug_performance'])) { echo "
💗 INCLUDE IF-CHECK = TRUE
"; flush(); ob_flush(); } $shopArticle = $obj; // Fix: Define $shopArticle for the include if (isset($_GET['debug_performance'])) { echo "
🔥 VOR INCLUDE intelectra_item_additional.inc.php
"; flush(); ob_flush(); } // REAKTIVIERT - Performance-optimiert durch Step-by-Step Query-Zerlegung! include_once ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/intelectra_item_additional.inc.php'; if (isset($_GET['debug_performance'])) { echo "
✅ INCLUDE DEAKTIVIERT - Artikel sollte jetzt laden!
"; flush(); ob_flush(); } if (isset($_GET['debug_performance'])) { echo "
✅ NACH INCLUDE - Fast am Ende!
"; flush(); ob_flush(); } } if (isset($_GET['debug_performance'])) { echo "
🏆 get_data() ERFOLGREICH BEENDET!
"; flush(); ob_flush(); die("🎉 SUCCESS! get_data() kam bis zum ENDE der Funktion!"); } return $obj; } /** * Generiert den Bilddateinamen basierend auf den Warnungsdaten * * @param array $warning Die Daten der Warnung * @return string|null Der generierte Bilddateiname oder null, wenn kein Bild verfügbar ist */ private function generateImageFileName($warning) { // Verwende "bilddateiname", wenn vorhanden if (!empty($warning['bilddateiname'])) { return $warning['bilddateiname']; } // Verwende "bildnr", wenn vorhanden if (!empty($warning['bildnr'])) { return $warning['bildnr'] . ".gif"; } // Generiere basierend auf der Bildnummer if (!empty($warning['bild'])) { $baseName = "ISO_7010_"; $suffix = ".svg"; // Extrahiere die letzten 3 Ziffern der Bildnummer $imageFileId = substr($warning['bild'], -4); return $baseName . $imageFileId . $suffix; } // Kein Bild verfügbar return null; } public function getPricesForCustomerGroup($customerGroup) { $sql = "SELECT * FROM item_prices WHERE item_id = ".intval($this->id)." AND customergroup_id = ".intval($customerGroup); $prices = $this->db->query($sql)->fetch_object(); return $prices; } public function getVariantPricesForCustomerGroup($customerGroup, $forAjax = false, $showTax = false, $taxValue = 0, $discount = 0, $for_frontend = true) { $sql = "SELECT * FROM item_attribute_variants WHERE item_id = ".intval($this->id)." AND customergroup_id = ".intval($customerGroup); $result = $this->db->query($sql); $variant_data = array(); if ($forAjax) { while ($obj_variants = $result->fetch_object()) { if ($showTax && $taxValue > 0) { $tmpTax = round($obj_variants->price * ($taxValue / 100), 2); $obj_variants->price = round($obj_variants->price + $tmpTax, 2); //$obj_variants->price = ($obj_variants->price / 100) * (100 + $taxValue); } $variant_data[$obj_variants->attribut1.'_'.$obj_variants->attribut2] = $obj_variants->price; } } else { while ($obj_variants = $result->fetch_object()) { if ($discount) { $obj_variants->price = round(($obj_variants->price * (100 - $discount) / 100), 2); $obj_variants->discount = $discount; $obj_variants->discount_text = 'Rabatt!'; } $tmpTax = round($obj_variants->price * ($taxValue / 100), 2); $obj_variants->price_net = $obj_variants->price; $obj_variants->price_gross = round($obj_variants->price + $tmpTax, 2); //$obj_variants->price_gross = ($obj_variants->price / 100) * (100 + $taxValue); if ($showTax && $taxValue > 0) { $tmpTax = round($obj_variants->price * ($taxValue / 100), 2); $obj_variants->price = round($obj_variants->price + $tmpTax, 2); //$obj_variants->price = ($obj_variants->price / 100) * (100 + $taxValue); } $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['item_number'] = $obj_variants->item_number; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['manufacturer_item_number'] = $obj_variants->manufacturer_item_number; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['ek'] = $obj_variants->ek; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['price'] = $obj_variants->price; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['priceNet'] = $obj_variants->price_net; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['priceGross'] = $obj_variants->price_gross; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['taxes'] = $tmpTax; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = $obj_variants->shippable; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['inventory'] = $obj_variants->inventory; $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['additional_charge'] = $obj_variants->additional_charge; $tmpFrom = explode('-', $obj_variants->available_from); if (count($tmpFrom) == 3) { $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['available_from'] = $tmpFrom[2].'.'.$tmpFrom[1].'.'.$tmpFrom[0]; } $tmpTill = explode('-', $obj_variants->available_till); if (count($tmpTill) == 3) { $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['available_till'] = $tmpTill[2].'.'.$tmpTill[1].'.'.$tmpTill[0]; } $today = getdate(); $today = strtotime($today['year'].'-'.$today['mon'].'-'.$today['mday']); // TODO: IS ORDERABLE if ($for_frontend) { if ($obj_variants->shippable == '2') { if ($obj_variants->available_from != '' && $obj_variants->available_from != '0000-00-00') { $startDate = strtotime($obj_variants->available_from); if ($obj_variants->available_till != '' && $obj_variants->available_till != '0000-00-00') { // from - till $stopDate = strtotime($obj_variants->available_till); if ($today > $startDate && $today < $stopDate) { $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 1; } else { $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 0; } } else { // from - no till if ($today > $startDate) { $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 1; } else { //$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 0; } } } else { // no from - till not checked $variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 0; } } } } } return array_reverse($variant_data, true); } // TODO: (sh 2011-05-30 mit absprache von jd) // kopie von "getVariantPricesForCustomerGroup()", die daten werden fuer die artikeldetailansicht benoetigt. public function getVariantPricesForArticleDetails($customerGroup, $attribut1, $attribut2) { $sql = " SELECT price, shippable, DATE_FORMAT(available_from, '%e.%c.%Y') AS available_date, available_from FROM item_attribute_variants WHERE item_id = ".$this->id." AND customergroup_id = ".$customerGroup." AND TRIM(attribut1) LIKE '".trim($attribut1)."' AND TRIM(attribut2) LIKE '".trim($attribut2)."' "; $result = $this->db->query($sql); $variant_data = $result->fetch_object(); return $variant_data; } public function create($data, $priceData = false) { if ($data) { if (isset($data['short_uri'])) { if (!$data['short_uri']) { $data['short_uri'] = $data['name']; } $data['short_uri'] = $this->short_uri($data['short_uri']); } $sql = "INSERT INTO items SET "; if ($data['schema_id']) { $schema_data = $this->itemschema_object->get_data($data['schema_id']); if ($schema_data->selectable_attribute_1) { $data['attribute_'.$schema_data->selectable_attribute_1] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_1]); } if ($schema_data->selectable_attribute_2) { $data['attribute_'.$schema_data->selectable_attribute_2] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_2]); } } foreach ($data as $var_name => $value) { $value = $this->db->real_escape_string($value); if ($this->item_fields[$var_name] == 'integer') { $sql .= $var_name.' = '.$value.', '; } else if ($this->item_fields[$var_name] == 'date') { if (preg_match("/^(\d{2})\.(\d{2})\.(\d{4})$/", $value, $matches)) { $tmpVal = $matches[3].'-'.$matches[2].'-'.$matches[1]; } else { $tmpVal = '0000-00-00'; } $sql .= $var_name.'="'.$tmpVal.'", '; } else if ($this->item_fields[$var_name] == 'float') { $sql .= $var_name.'="'.number_format((float) $value, 4, '.', '').'", '; } else { $sql .= $var_name.' = "'.$value.'", '; } } $sql .= " quantity_1 = '1', "; $sql .= " price_1 = '".number_format($priceData['prices']['price_1'],4,'.','')."', "; $sql .= " bargain_price_1 = '".number_format($priceData['prices']['bargain_price_1'],4,'.','')."' "; $this->db->query($sql); $this->id = $this->db->insert_id; // save prices if ($priceData) { $this->replace_prices($priceData); } // save assigned items $this->saveAssignedItems(1); $this->saveAssignedItems(2); $this->saveAssignedItems(3); $this->_assignToStructures($_POST['assigned_structures']); return $this->id; } return false; } function short_uri($short_uri, $id = false) { $short_uri = str_replace(array('ä', 'Ä', 'ö', 'Ö', 'ü', 'Ü', 'ß'), array('ae', 'Ae', 'oe', 'Oe', 'ue', 'Ue', 'ss'), $short_uri); $short_uri = preg_replace("@[^0-9aA-zZ\-]@si", "-", $short_uri); $short_uri = preg_replace("@(-{2,})@si", "-", $short_uri); $new_uri = ''; $old_uri = $short_uri; $i = 0; while ($new_uri == '') { if ($id) { $sql = "SELECT id FROM items WHERE short_uri = '$short_uri' AND id != $id"; } else { $sql = "SELECT id FROM items WHERE short_uri = '$short_uri'"; } $result = $this->db->query($sql); if ($result->num_rows == 0) { $new_uri = $short_uri; } else { $i++; $short_uri = $old_uri.'_'.$i; } } return $new_uri; } public function sort_image_list($list) { $counter = 1; $picQueryParts = array(); foreach ($list as $pic_id) { ++$counter; $pic_id = str_replace('picelementContainer_', '', $pic_id); if ($counter == 2) { $default_image = $pic_id; } $picQueryParts[] = '('.$pic_id.', '.$counter.')'; } $this->db->query("CREATE TEMPORARY TABLE tmp_item_files ( id INT, pos INT )"); $this->db->query("INSERT INTO tmp_item_files (id, pos) VALUES ".implode(', ', $picQueryParts)); $result = $this->db->query(" UPDATE item_files i, tmp_item_files i_tmp SET i.rang = i_tmp.pos WHERE i.id = i_tmp.id AND i.item_id = ".$this->id." "); return $sql = $this->set_default_image($default_image); } public function set_default_image($image_id) { $sql = "UPDATE items i SET i.default_image_file_name = (SELECT f.file_name FROM item_files f WHERE f.id = ".$this->db->real_escape_string($image_id).") WHERE i.id=".$this->db->real_escape_string($this->id); $this->db->query($sql); return $sql; } public function delete_file($file_id, $id = false) { // get pic infos $sql = "SELECT * FROM item_files WHERE id=".$this->db->real_escape_string($file_id); $result = $this->db->query($sql); if ($result) { $obj = $result->fetch_object(); if ($obj->type == '0') { // unlink all the files with prefixes foreach ($this->base_object->config->shopConfiguration['images'] as $image) { $filename = $image[0].$obj->file_name; $filepath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$filename; if (file_exists($filepath)) { @unlink($filepath); } } // unlink the original $filename = $obj->file_name; $filepath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$filename; if (file_exists($filepath)) { @unlink($filepath); } } else if ($obj->type == '1') { $filepath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/documents/article/'.$obj->file_name; if (file_exists($filepath)) { @unlink($filepath); } // update state in item table $item_id = ($id) ? $id : $this->id; $sql = "SELECT count(*) AS num FROM item_files WHERE type = 1 AND id!=".$this->db->real_escape_string($file_id)." AND item_id=".$this->db->real_escape_string($item_id); $result = $this->db->query($sql); if ($result->fetch_object()->num == 0) { $query = "UPDATE items SET has_documents = 0 WHERE id = '".$this->db->real_escape_string($item_id)."'"; $this->db->query($query); } } $sql = "DELETE FROM item_files WHERE id=".$this->db->real_escape_string($file_id); if ($id) { $sql .= " AND item_id=".$this->db->real_escape_string($id); $this->id = $id; } else if ($this->id) { $sql .= " AND item_id=".$this->db->real_escape_string($this->id); } else { // TODO: log and set error // DELETE wird trotzdem ausgeführt (nur ohne item_id Constraint) } return $this->db->query($sql); } // TODO log and set error return false; } // end delete_file // FIXME: put function to generate scaled images into its own function // so that it can be called seperately to regenerate all shop public function add_uploaded_file($file_data, $watermark_activ = false) { // DEBUG LOGGING $debug_log = '/var/www/vhosts/intelectra.de/httpdocs/logs/upload_debug.log'; $start = microtime(true); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] START\n", FILE_APPEND); $tempFile = $file_data['Filedata']['tmp_name']; // is file a image $file_info = getimagesize($tempFile); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] getimagesize done: " . round((microtime(true)-$start)*1000,2) . "ms\n", FILE_APPEND); if (isset($file_info[2]) && $file_info[2] > 0 && $file_info[2] < 4) { // 🚀 FIX: Async Python Image Processing Service - verhindert 504 Timeouts // Generate filename FIRST before async processing $targetPath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'; $image_type = array('', 'gif', 'jpg', 'png'); $file_id = md5(uniqid(rand(), TRUE)); $file_name = $file_id.'.'.$image_type[$file_info[2]]; $targetFile = str_replace('//', '/', $targetPath).$file_name; // Move uploaded file IMMEDIATELY move_uploaded_file($tempFile, $targetFile); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] move_uploaded_file done: " . round((microtime(true)-$start)*1000,2) . "ms\n", FILE_APPEND); // Get picture count BEFORE async processing $sql = "SELECT count( id ) AS image_count FROM item_files WHERE item_id=".$this->db->real_escape_string($this->id); $result = $this->db->query($sql); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] SELECT count done: " . round((microtime(true)-$start)*1000,2) . "ms\n", FILE_APPEND); $picture_count = 1; while ($obj = $result->fetch_object()) { $picture_count = $obj->image_count + 1; } // Save picture in database IMMEDIATELY $sql = "INSERT INTO item_files (item_id, file_name, rang) VALUES (".$this->db->real_escape_string($this->id).", '". $this->db->real_escape_string($file_name)."', ". $this->db->real_escape_string($picture_count).")"; $this->db->query($sql); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] INSERT done: " . round((microtime(true)-$start)*1000,2) . "ms\n", FILE_APPEND); // Update default image $sql = "UPDATE items i SET i.default_image_file_name = (SELECT f.file_name FROM item_files f WHERE f.item_id = ".$this->db->real_escape_string($this->id)." ORDER BY rang LIMIT 1) WHERE i.id=".$this->db->real_escape_string($this->id); $this->db->query($sql); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] UPDATE default_image done: " . round((microtime(true)-$start)*1000,2) . "ms\n", FILE_APPEND); // 🔥 START ASYNC IMAGE PROCESSING (non-blocking!) $this->startAsyncImageProcessing($targetFile, $file_name, $this->id, $watermark_activ); file_put_contents($debug_log, date('Y-m-d H:i:s') . " [ADD_FILE] startAsyncImageProcessing done: " . round((microtime(true)-$start)*1000,2) . "ms\n", FILE_APPEND); // ✅ Return IMMEDIATELY - no waiting! return true; } else { // save to article documents $file_name = $file_data['Filedata']['name']; } return; } public function add_uploaded_pdf($file_data) { $tempFile = $file_data['Filedata']['tmp_name']; $targetPath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/documents/article/'; $file_id = md5(uniqid(rand(), TRUE)); $file_name = $file_id.'.pdf'; // save article picture $targetFile = str_replace('//', '/', $targetPath).$file_name; move_uploaded_file($tempFile, $targetFile); $size = filesize($targetFile); $sql = " INSERT INTO item_files (item_id, file_name, alt, rang, type, size) VALUES ( ".$this->db->real_escape_string($this->id).", '".$this->db->real_escape_string($file_name)."', '".$this->db->real_escape_string($file_data['Filedata']['name'])."', 0, 1, '".$size."' ) "; $result = $this->db->query($sql); if ($result) { // update state in item table $query = "UPDATE items SET has_documents = 1 WHERE id = '".$this->id; $this->db->query($query); $return_object = new stdClass(); $return_object->id = $this->db->insert_id; $return_object->item_id = $this->id; $return_object->file_name = $file_name; $return_object->path = str_replace('//', '/', './web/'.SHOP_SYSTEM.'/documents/article/'); $return_object->alt = $file_data['Filedata']['name']; return $return_object; } return false; } public function get_file_list($type = false, $id = false) { if (!$id) { $id = $this->id; } $id = intval($id); if ($type === 0) { $sql = "SELECT * FROM item_files WHERE item_id=".intval($id)." AND type=0 ORDER BY rang"; } else if ($type) { $sql = "SELECT * FROM item_files WHERE item_id=".intval($id)." AND type=".intval($type)." ORDER BY rang"; } else { $sql = "SELECT * FROM item_files WHERE item_id=".intval($id)." ORDER BY rang"; } $result = $this->db->query($sql); $data = array(); if ($result->num_rows > 0) { while ($obj = $result->fetch_object()) { $data[] = $obj; } } else { $data = false; } return $data; } public function update($data, $priceData = false) { if ($data) { // If no primary structure assigned if ((!isset($data['structure_id']) || !is_numeric($data['structure_id'])) && isset($_POST['assigned_structures']) && is_array($_POST['assigned_structures'])) { $data['structure_id'] = current($_POST['assigned_structures']); reset($_POST['assigned_structures']); } if (isset($data['short_uri'])) { if (!$data['short_uri']) { $data['short_uri'] = $data['name']; } $data['short_uri'] = $this->short_uri($data['short_uri'], $this->id); } $schema_data = $this->itemschema_object->get_data($data['schema_id']); $sql = "UPDATE items SET "; if ($data['schema_id']) { $schema_data = $this->itemschema_object->get_data($data['schema_id']); if ($schema_data->selectable_attribute_1) { $data['attribute_'.$schema_data->selectable_attribute_1] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_1]); } if ($schema_data->selectable_attribute_2) { $data['attribute_'.$schema_data->selectable_attribute_2] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_2]); } } /*$data['attribute_'.$schema_data->selectable_attribute_1] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_1]); $data['attribute_'.$schema_data->selectable_attribute_2] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_2]);*/ foreach ($data as $var_name => $value) { $value = $this->db->real_escape_string($value); if ($this->item_fields[$var_name] == 'integer') { $sql .= $var_name.'='.$value.', '; } else if ($this->item_fields[$var_name] == 'float') { $sql .= $var_name.'='.floatval($value).', '; } else if ($this->item_fields[$var_name] == 'date') { if (preg_match("/^(\d{2})\.(\d{2})\.(\d{4})$/", $value, $matches)) { $tmpVal = $matches[3].'-'.$matches[2].'-'.$matches[1]; } else { $tmpVal = '0000-00-00'; } $sql .= $var_name.'="'.$tmpVal.'", '; } else { $sql .= $var_name.'="'.$value.'", '; } } /*$sql .= " quantity_1 = '1', "; $sql .= " price_1 = '".$priceData['prices']['price_1']."', "; $sql .= " bargain_price_1 = '".$priceData['prices']['bargain_price_1']."', ";*/ $sql = substr($sql, 0, -2); $sql .= ' WHERE id='.$this->id; $this->db->query($sql); if ($this->db->error) { $log_object = Logger::get_instance(); $log_object->info('Error in /core/main_class.php->get_list_items()', $this->db->error.', sql:'.$sql); $count = 0; } // save variants /*if ($priceData['customerGroup']) { $this->update_variants($priceData['customerGroup'], $data, $priceData); }*/ // save prices if ($priceData) { $this->replace_prices($priceData); } // save assigned items $this->saveAssignedItems(1); $this->saveAssignedItems(2); $this->saveAssignedItems(3); // save shipping costs $this->save_shipping_costs(); // Assign to structures $this->_assignToStructures($_POST['assigned_structures']); // update variant items include('./core/item_variant_schema.inc.php'); foreach ($item_fields as $field => $state) { if ($state == 0) { $value = $this->db->real_escape_string($data[$field]); $sql = "UPDATE items SET ".$field."='".$value."'"; $sql .= ' WHERE parent_id='.$this->id; $this->db->query($sql); } } $this->update_last_change(); } return; } private function save_shipping_costs() { $shipping_ids = $_POST['item_shipping_id']; $item_shipping_price = $_POST['item_shipping_price']; if (isset($shipping_ids) && isset($item_shipping_price)) { // delete old prices $sql = " DELETE FROM item_shipping_costs WHERE item_id = ".$this->id." "; $this->db->query($sql); // insert new shipping prices for ($i = 0; $i < count($shipping_ids); $i++) { $sql = " INSERT INTO item_shipping_costs (item_id, shipping_area_id, price) VALUES (".$this->id.", ".$this->db->real_escape_string($shipping_ids[$i]).", '".$this->db->real_escape_string(str_replace(';', ', ', $item_shipping_price[$i]))."')"; $this->db->query($sql); } } } private function replace_prices($priceData) { // ⚡ PERFORMANCE FIX: Nur aufrufen wenn tatsächlich Preis-Daten vorhanden! // Verhindert 504 Timeout bei Kurz-URL Updates etc. if (!isset($priceData['prices']) || empty($priceData['prices'])) { return true; // Keine Preise = nichts zu tun = success } // 🚀 Python Smart Price Update Service (Verhindert 50+ REPLACE INTO Abfragen!) $python_result = $this->callPythonPriceService($priceData); if ($python_result && isset($python_result['success']) && $python_result['success']) { // Python Service erfolgreich if (isset($_GET['debug_performance'])) { $changes = $python_result['groups_updated'] ?? 0; echo "
🐍 PYTHON PRICE SERVICE: {$changes} Gruppen aktualisiert
"; } return true; } // 🔄 FALLBACK: Original PHP-Code (Legacy-Support) if (isset($_GET['debug_performance'])) { echo "
⚠️ FALLBACK: PHP Price Update
"; } $customerGroups_object = new Customer_group($this->base_object); $customerGroups = $customerGroups_object->get_all_price_groups(); $groups = array(); foreach ($customerGroups as $group) { if (is_array($priceData['prices']['group_'.$group->id])) { $fields = array(); $values = array(); foreach ($priceData['prices']['group_'.$group->id] as $field => $value) { $fields[] = $field; $values[] = (float) $value; } $sql = "REPLACE INTO item_prices (item_id, customergroup_id, ".implode(',', $fields).") VALUES (".$this->id.",".$group->id.",".implode(',', $values).")"; $this->db->query($sql); } } } // TODO: /*private function update_variants($customerGroup, $item_data, $priceData) { $sql = "DELETE FROM item_attribute_variants WHERE item_id = ".$this->id." AND customergroup_id = ".$customerGroup; $this->db->query($sql); $data = $this->get_data(); // enable transactions $this->db->autocommit(false); if (!$data->price_variants_2) { $data->price_variants_2 = array(''); } foreach ($data->price_variants_1 as $att1) { $att1 = trim($att1); foreach ($data->price_variants_2 as $att2) { $att2 = trim($att2); if ($item_data['variant_price_type'] == 0) { $additional_charge = '0.00'; $price = $_POST['vprice'][$att1.'_'.$att2]; } else if ($item_data['variant_price_type'] == 1) { $additional_charge = $_POST['variant_price_type'][$att1.'_'.$att2]; $old_price = 0; if ($priceData['prices']['bargain_price_1'] > 0) { $price = $additional_charge + $priceData['prices']['bargain_price_1']; $old_price = $additional_charge + $priceData['prices']['price_1']; } else { $price = $additional_charge + $priceData['prices']['price_1']; } } $ek = $_POST['vek'][$att1.'_'.$att2]; $shippable = $_POST['vshippable'][$att1.'_'.$att2]; if ($_POST['vshippable'][$att1.'_'.$att2] == 2) { $avFrom = ''; $tmpFrom = explode('.', $_POST['vlieferbar_ab'][$att1.'_'.$att2]); if (count($tmpFrom) == 3) { $avFrom = $tmpFrom[2].'-'.$tmpFrom[1].'-'.$tmpFrom[0]; } $avTill = ''; $tmpTill = explode('.', $_POST['vlieferbar_bis'][$att1.'_'.$att2]); if (count($tmpTill) == 3) { $avTill = $tmpTill[2].'-'.$tmpTill[1].'-'.$tmpTill[0]; } } else { $avFrom = ''; $avTill = ''; } $item_number = $_POST['item_number'][$att1.'_'.$att2]; $manufacturer_item_number = $_POST['manufacturer_item_number'][$att1.'_'.$att2]; $sql = " INSERT INTO item_attribute_variants ( item_id, customergroup_id, attribut1, attribut2, price, old_price, ek, shippable, available_from, available_till, inventory, additional_charge, item_number, manufacturer_item_number ) VALUES ( ".$this->id.", ".$customerGroup.", '".$att1."', '".$att2."', '".$price."', '".$old_price."', '".$ek."', '".$shippable."', '".$avFrom."', '".$avTill."', '".$inventory."', '".$additional_charge."', '".$item_number."', '".$manufacturer_item_number."' )"; $this->db->query($sql); } } // commit transaction $result = $this->db->commit(); // disable transactions $this->db->autocommit(true); }*/ public function delete() { $sql = "DELETE FROM items WHERE id=".$this->id; $this->db->query($sql); $sql = "DELETE FROM item_prices WHERE item_id=".$this->id; $this->db->query($sql); $sql = "DELETE FROM item_attribute_variants WHERE item_id=".$this->id; $this->db->query($sql); return; } public function data_filter($request) { $data = array(); foreach ($this->item_fields as $field_name => $var_type) { if (isset($request[$field_name])) { if ($var_type == 'text') { $data[$field_name] = $request[$field_name]; } else if ($var_type == 'float') { $request[$field_name] = str_replace(',', '.', $request[$field_name]); $data[$field_name] = $request[$field_name]; } else if ($var_type == 'date') { $data[$field_name] = $request[$field_name]; } else { $data[$field_name] = (int) $request[$field_name]; } } } return $data; } public function get_all_item_schemas() { $sql = "SELECT * FROM item_schema"; $result = $this->db->query($sql); $data = array(); while ($obj = $result->fetch_object()) { $data[] = $obj; } return $data; } public function get_all_item_schema_paginated($items, $page, $order = false) { $page -= 1; $sql = "SELECT * FROM item_schema LIMIT $items OFFSET $page"; $result = $this->db->query($sql); while ($obj = $result->fetch_object()) { $data[] = $obj; } return $data; } // end get_all public function get_schema_data() { $sql = "SELECT * FROM item_schema WHERE id = ".$this->schema_id; $result = $this->db->query($sql); $schema = $result->fetch_object(); $attributes = array(); $sql = "SELECT * FROM item_schema_attributes WHERE schema_id = ".$this->schema_id." ORDER BY rang"; $result = $this->db->query($sql); while ($obj = $result->fetch_object()) { $attributes[] = $obj; } $schema->attributes = $attributes; return $schema; } public function create_schema($data) { if ($data) { $sql = "INSERT INTO item_schema SET "; foreach ($data as $var_name => $value) { $value = $this->db->real_escape_string($value); if ($this->schema_fields[$var_name] == 'integer') { $sql .= $var_name.' = '.$value.', '; } else { $sql .= $var_name.' = "'.$value.'", '; } } $sql = substr($sql, 0, -2); $this->db->query($sql); $this->schema_id = $this->db->insert_id; if ($this->schema_id) { for ($i = 1; $i < 21; $i++) { $sql = "INSERT INTO item_schema_attributes (schema_id, number, rang) VALUES (".$this->schema_id.", ".$i.", ".$i.")"; $this->db->query($sql); } } } return; } public function update_schema($data) { if ($data) { $sql = "UPDATE item_schema SET name='".$data['name']."', description='".$data['description']."', selectable_attribute_1='".$data['selectable_attribute_1']."', base_price_field='".$data['base_price_field']."', base_price_faktor='".$data['base_price_faktor']."', base_price_unit='".$data['base_price_unit']."', selectable_attribute_2='".$data['selectable_attribute_2']."' WHERE id=".$this->schema_id; $this->db->query($sql); $sql = "DELETE FROM item_schema_attributes WHERE schema_id=".$this->schema_id; $this->db->query($sql); // save attribute data for ($i = 1; $i < 21; $i++) { $show_list = ($data['attribute_liste_'.$i]) ? $data['attribute_liste_'.$i] : 0; $show_detail = ($data['attribute_detail_'.$i]) ? $data['attribute_detail_'.$i] : 0; $sql = " INSERT INTO item_schema_attributes (schema_id, number, name, name_en, unit, rang, show_list, show_detail) VALUES (".$this->schema_id.", $i, '".$data['attribute_name_'.$i]."', '".$data['attribute_name_'.$i.'_en']."', '".$data['attribute_unit_'.$i]."', ".$data['attribute_rang_'.$i].", ".$show_list.", ".$show_detail.")"; $this->db->query($sql); } } return; } // end update_shema public function delete_schema() { $sql = "DELETE FROM item_schema_attributes WHERE schema_id=".$this->schema_id; $this->db->query($sql); $sql = "DELETE FROM item_schema WHERE id=".$this->schema_id; $this->db->query($sql); return; } public function schema_data_filter($request) { $data = array(); foreach ($this->schema_fields as $field_name => $var_type) { if (isset($request[$field_name])) { if ($var_type == 'text') { $data[$field_name] = $request[$field_name]; } else if ($var_type == 'float') { $data[$field_name] = $request[$field_name]; } else { $data[$field_name] = (int) $request[$field_name]; } } } return $data; } public function search($data) { $sql = 'SELECT * FROM items '; $where = ''; // build clauses for manufacturer IDs that contain a specific substring if (isset($data['manufacturer_search'])) { $clause = 'manufacturer_id = '; $manufacturer = new Manufacturer($this->base_object); $results = $manufacturer->get_where_name_like($data['manufacturer_search']); if ($results) { foreach ($results as $result) { if ($where == '') { $where .= ' WHERE '.$clause.$result->id; } $where .= ' OR '.$clause.$result->id; } } } if (isset($data['text_search'])) { if (isset($data['text_options'])) { if (strpos($data['text_options'], ';')) { $text_options = str_replace(';', ', ', $data['text_options']); $clause = "CONCAT(".$text_options.") LIKE '%".$data['text_search']."%'"; } $clause = $data['text_options']." LIKE '%".$data['text_search']."%'"; } $clause = "name LIKE '%".$data['text_search']."%'"; $where = Database::where($where, $clause); } if (isset($data['numeric_search'])) { if (isset($data['numeric_options'])) { if (strpos($data['numeric_options'], ';')) { $numeric_options = str_replace(';', ', ', $data['numeric_options']); $clause = "CONCAT(".$numeric_options.") LIKE '%".$data['numeric_search']."%'"; } $clause = $data['numeric_options']." LIKE '%".$data['numeric_search']."%'"; } $clause = "number LIKE '%".$data['numeric_search']."%'"; $where = Database::where($where, $clause); } if (isset($data['limiting_options'])) { // todo $data['limiting_options']; } $result = $this->db->query($sql.$where); while ($obj = $result->fetch_object()) { $end[] = $obj; } return $end; } // end search public function delete_by_id($id) { $rs = $this->db->query("DELETE FROM items WHERE id=$id;"); $rs = $this->db->query("DELETE FROM item_files WHERE item_id=$id;"); } public function set_active_by_id($id) { $rs = $this->db->query("UPDATE items SET active=1 WHERE id=$id;"); } public function set_inactive_by_id($id) { $rs = $this->db->query("UPDATE items SET active=0 WHERE id=$id;"); } public function copy() { // copy standard data $sql = "SELECT * FROM items WHERE id = ".intval($this->id); $result = $this->db->query($sql); $obj = $result->fetch_object(); if (!$obj->short_uri) { $obj->short_uri = $obj->name; } $obj->short_uri = $this->short_uri($obj->short_uri); $obj->name = 'Kopie von: '.$obj->name; // create copy object $sql = "INSERT INTO items SET "; foreach ($this->item_fields as $key => $var_type) { if ($var_type == 'integer') { $obj->{$key} = (int) $obj->{$key}; } else if ($var_type == 'float' && $obj->{$key} == '') { $obj->{$key} = 0.0; } else if ($var_type == 'date' && $obj->{$key} == '') { $obj->{$key} = '0000-00-00'; } $sql .= $key." = '".$this->db->real_escape_string($obj->{$key})."', "; } $sql = substr($sql, 0, -2); $this->db->query($sql); /*echo $sql; exit();*/ $new_id = $this->db->insert_id; //copy prices $sql = "SELECT * FROM item_prices WHERE item_id = ".intval($this->id); $result = $this->db->query($sql); $variant_data = array(); while ($obj = $result->fetch_object()) { $sql = "INSERT INTO item_prices (item_id, customergroup_id"; for ($i = 1; $i < 31; $i++) { $sql .= ", quantity_".$i.", price_".$i.", bargain_price_".$i; } $sql .= ") VALUES (".$new_id.", ".$obj->customergroup_id; for ($i = 1; $i < 31; $i++) { if ($obj->{'price_'.$i} == '') { $obj->{'price_'.$i} = 0.0; } if ($obj->{'bargain_price_'.$i} == '') { $obj->{'bargain_price_'.$i} = 0.0; } if ($obj->{'quantity_'.$i} == '') { $obj->{'quantity_'.$i} = 0; } $sql .= ", ".$obj->{'quantity_'.$i}.", ".$obj->{'price_'.$i}.", ".$obj->{'bargain_price_'.$i}; } $sql .= ")"; $this->db->query($sql); } // copy variant data $sql = "SELECT * FROM item_attribute_variants WHERE item_id = ".intval($this->id); $result = $this->db->query($sql); $variant_data = array(); while ($obj = $result->fetch_object()) { $sql = "INSERT INTO item_attribute_variants (item_id, attribut1, attribut2, item_number, price, ek, shippable) VALUES (".$new_id.",'$obj->attribut1','$obj->attribut2','$obj->item_number','$obj->price','$obj->ek',$obj->shippable) "; $this->db->query($sql); } // copy files $sql = "SELECT * FROM item_files WHERE item_id = ".intval($this->id); $result = $this->db->query($sql); $variant_data = array(); $image_count = 0; while ($obj = $result->fetch_object()) { // old: $images = array('', 'thumb_', 'overview_', 'overview_2_', 'detail_'); $images = $this->base_object->config->shopConfiguration['images']; foreach ($images as $image) { $image_name = $image[0]; $filename = $image_name.$obj->file_name; $new_filename = $image_name.$new_id.$obj->file_name; copy($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$filename, $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$new_filename); } $image_count++; $sql = "INSERT INTO item_files (item_id, file_name, rang, type, description, attribut1, attribut2, alt) VALUES (".$new_id.", '". $new_id.$obj->file_name."', '". $obj->rang."', '". $obj->type."', '". $obj->description."', '". $obj->attribut1."', '". $obj->attribut2."', '". $obj->alt."')"; $this->db->query($sql); if ($image_count == 1) { $sql = "UPDATE items SET default_image_file_name = '".$this->db->real_escape_string($new_id.$obj->file_name )."' WHERE id=".$new_id; $result3 = $this->db->query($sql); } } // copy assigned items $sql = "SELECT * FROM item_item_assign WHERE item_parent_id = ".intval($this->id); $result = $this->db->query($sql); while ($obj = $result->fetch_object()) { $sql = "INSERT INTO item_item_assign (item_parent_id, item_child_id, type, position) VALUES (".$new_id.", '".$obj->item_child_id."', '".$obj->type."', '".$obj->position."')"; $this->db->query($sql); } // copy item structure assign $sql = "SELECT * FROM item_structure_assign WHERE item_id = ".intval($this->id); $result = $this->db->query($sql); while ($obj = $result->fetch_object()) { $sql = "INSERT INTO item_structure_assign (item_id, structure_id, pos) VALUES (".$new_id.", '".$obj->structure_id."', '".$obj->pos."')"; $this->db->query($sql); } $this->id = $new_id; return; } //UGLY HACK, KILL ME SOOOOOON the root is 3 in EMFA protected function get_item_category_root() { $sql = "SELECT id FROM structure WHERE short_uri = 'Warengruppen'"; $result = $this->db->query($sql); if ($result->num_rows > 0) { return $result->fetch_object()->id; } return false; } protected function get_all_item_categories($root = false) { if (!$root) { $root = $this->get_item_category_root(); } $sql = "SELECT id, name, short_uri FROM structure WHERE parent_id=$root"; $result = $this->db->query($sql); if ($result->num_rows > 0) { while ($obj = $result->fetch_object()) { $id = $obj->id; $data[] = $obj; $children = $this->get_all_item_categories($id); if ($children) { foreach ($children as $child) { $data[] = $child; } } } return $data; } return false; } public function get_item_category_assoc_array() { $categories = $this->get_all_item_categories(); foreach ($categories as $category) { $data[$category->id] = $category->short_uri; } return $data; } public function get_item_list($structure_id, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false, $sort_by = false) { $manufacturers = Manufacturer::get_name_id_pair(); $limited = false; if (is_numeric($itemsPerPage)) { $limitMax = $itemsPerPage; $limited = true; } if (is_numeric($currentPage)) { $limitMin = $currentPage * $limitMax - $limitMax; } else { $limitMin = 0; } $whereAdd = ''; if ($activeOnly) { $whereAdd .= " AND i.active = 1 "; } if (is_numeric($fromManufacturerOnly)) { $whereAdd .= " AND i.manufacturer_id = ".$fromManufacturerOnly; } $sql = "SELECT count(id) AS num FROM items i WHERE (structure_id=".$this->db->real_escape_string($structure_id)." OR structure_id_2=".$this->db->real_escape_string($structure_id)." OR structure_id_3=".$this->db->real_escape_string($structure_id)." OR structure_id_4=".$this->db->real_escape_string($structure_id)." OR structure_id_5=".$this->db->real_escape_string($structure_id)." OR structure_id_6=".$this->db->real_escape_string($structure_id)." OR structure_id_7=".$this->db->real_escape_string($structure_id)." OR structure_id_8=".$this->db->real_escape_string($structure_id)." OR structure_id_9=".$this->db->real_escape_string($structure_id)." OR structure_id_10=".$this->db->real_escape_string($structure_id).") $whereAdd"; $result = $this->db->query($sql); $this->itemCount = $result->fetch_object()->num; //probably the wrong place $sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." WHERE (structure_id=".$this->db->real_escape_string($structure_id)." OR structure_id_2=".$this->db->real_escape_string($structure_id)." OR structure_id_3=".$this->db->real_escape_string($structure_id)." OR structure_id_4=".$this->db->real_escape_string($structure_id)." OR structure_id_5=".$this->db->real_escape_string($structure_id)." OR structure_id_6=".$this->db->real_escape_string($structure_id)." OR structure_id_7=".$this->db->real_escape_string($structure_id)." OR structure_id_8=".$this->db->real_escape_string($structure_id)." OR structure_id_9=".$this->db->real_escape_string($structure_id)." OR structure_id_10=".$this->db->real_escape_string($structure_id).") $whereAdd GROUP BY i.id"; if ($sort_by) { if ($sort_by == 'name_up') { $sql .= " ORDER BY i.name ASC"; } else if ($sort_by == 'name_down') { $sql .= " ORDER BY i.name DESC"; } else if ($sort_by == 'number_up') { $sql .= " ORDER BY i.number ASC"; } else if ($sort_by == 'number_down') { $sql .= " ORDER BY i.number DESC"; } else if ($sort_by == 'manufacturer_up') { $sql .= " ORDER BY i.manufacturer_id ASC"; } else if ($sort_by == 'manufacturer_down') { $sql .= " ORDER BY i.manufacturer_id DESC"; } else if ($sort_by == 'price_up') { $sql .= " ORDER BY ip.price_1 ASC"; } else if ($sort_by == 'price_down') { $sql .= " ORDER BY ip.price_1 DESC"; } } if ($limited) { $sql .= " LIMIT ".$this->db->real_escape_string($limitMin).", ".$this->db->real_escape_string($limitMax); } $result = $this->db->query($sql); $list = array(); $show_taxes = $this->base_object->customer_group->show_tax; while ($obj = $result->fetch_object()) { // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = $manufacturers[$obj->manufacturer_id]; if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number}); } } } if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } return $list; } public function get_item_list_by_ids($ids, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false) { $manufacturers = Manufacturer::get_name_id_pair(); if (is_numeric($itemsPerPage)) { $limitMax = $itemsPerPage; } else if ($itemsPerPage == 'all') { $limitMax = 99999; } if (is_numeric($currentPage)) { $limitMin = $currentPage * $limitMax - $limitMax; } else { $limitMin = 0; } $whereAdd = array(); if ($activeOnly) { $whereAdd[] = " AND items.active = 1 "; } if (is_numeric($fromManufacturerOnly)) { $whereAdd[] = " AND items.manufacturer_id = ".$fromManufacturerOnly; } $sqlCount = "SELECT items.id FROM items LEFT JOIN item_files ON item_files.item_id = items.id WHERE (items.id IN (".implode(",", $ids)."))".implode(" ", $whereAdd)." GROUP BY items.id ORDER BY items.number ASC, item_files.rang ASC"; $this->itemCount = $this->db->query($sqlCount)->num_rows; $sql = "SELECT items.*, item_files.file_name, item_files.rang, item_prices.price_1, item_prices.bargain_price_1 FROM item_prices RIGHT JOIN items ON items.id = item_prices.item_id AND item_prices.customergroup_id = '".$this->base_object->customer_group->price_group_id."' LEFT JOIN item_files ON item_files.item_id = items.id WHERE items.id IN (".implode(",", $ids).")".implode(" ", $whereAdd)." GROUP BY items.id ORDER BY items.number ASC, item_files.rang ASC LIMIT ".(int)$limitMin.", ".(int)$limitMax; $result = $this->db->query($sql); $list = array(); while ($obj = $result->fetch_object()) { // TODO: HACK //$item_category_assoc_array = //$obj->item_category_short_uri = // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : ''; $obj->manufacturer_data = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : null; // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } if ($this->base_object->customer_group->show_tax) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number}); } } } if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } return $list; } public function get_all_items_list() { $structure_object = new Structure($this->base_object); $all_tree_full_path = $structure_object->get_all_tree_full_path(0, ' > '); $manufacturers = Manufacturer::get_name_id_pair(); $limitMax = 10000; $sqlCount = "SELECT items.id FROM items LEFT JOIN item_files ON item_files.item_id = items.id WHERE items.active = 1 GROUP BY items.id ORDER BY items.number ASC, item_files.rang ASC"; $this->itemCount = $this->db->query($sqlCount)->num_rows; $sql = "SELECT items.*, item_files.file_name, item_files.rang, item_prices.price_1, item_prices.bargain_price_1 FROM item_prices RIGHT JOIN items ON items.id = item_prices.item_id AND item_prices.customergroup_id = '".$this->base_object->customer_group->price_group_id."' LEFT JOIN item_files ON item_files.item_id = items.id WHERE items.active = 1 GROUP BY items.id ORDER BY items.number ASC, item_files.rang ASC LIMIT ".$limitMax; $result = $this->db->query($sql); $list = array(); while ($obj = $result->fetch_object()) { // TODO: HACK //$item_category_assoc_array = //$obj->item_category_short_uri = // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = $manufacturers[$obj->manufacturer_id]; // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } if ($this->base_object->customer_group->show_tax) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = split(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = split(';', $obj->{'attribute_'.$attribute->number}); } } } if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } if ($obj->structure_id) { $obj->structure_data = $all_tree_full_path[$obj->structure_id]; } } return $list; } // end get_all_paginated private function match_by_string($data) { $data = preg_replace("@(\s){2,}@si", " ", $data); $data = trim($data); $data = explode(' ', $data); $match = ''; foreach ($data as $point) { if ($match == '') { $match = " HAVING search_field LIKE '%$point%'"; } else { $match .= " AND search_field LIKE '%$point%'"; } } return $match; } public function find_by_string($data) { $sql = "SELECT items.id, items.number, items.name, items.short_description, manufacturers.name as manufacturer, CONCAT_WS(' ', items.number, items.name, items.short_description, if (manufacturers.name IS NOT NULL,manufacturers.name,' ')) as search_field FROM items LEFT JOIN manufacturers ON manufacturers.id = items.manufacturer_id WHERE items.active = 1"; $match = $this->match_by_string($data); $sql .= $match.' LIMIT 5'; $result = $this->db->query($sql); if ($result->num_rows > 0) { while ($obj = $result->fetch_object()) { $return[] = $obj; } return $return; } return false; } // end find_by_string public function hits_by_string($data) { $sql = "SELECT CONCAT_WS(' ', items.number, items.name, items.short_description, if (manufacturers.name IS NOT NULL, manufacturers.name,' ')) as search_field FROM items LEFT JOIN manufacturers ON manufacturers.id = items.manufacturer_id WHERE items.active = 1"; $match = $this->match_by_string($data); $sql .= $match; $result = $this->db->query($sql); if ($result) { return $result->num_rows; } return 0; } // end hits_by_string public function get_by_id($id) { if (isset($_GET['debug_performance'])) { echo "
🔍 get_by_id() GESTARTET für ID: $id
"; flush(); ob_flush(); } $sql = "SELECT * FROM items WHERE id = $id"; if (isset($_GET['debug_performance'])) { echo "
📝 SQL bereit: $sql
"; flush(); ob_flush(); } $result = $this->db->query($sql); if (isset($_GET['debug_performance'])) { echo "
⚡ DB->query() FERTIG - Rows: " . ($result ? $result->num_rows : 'ERROR') . "
"; flush(); ob_flush(); } if ($result->num_rows == 1) { $obj = $result->fetch_object(); if (isset($_GET['debug_performance'])) { echo "
✅ get_by_id() ERFOLGREICH - Object returned
"; flush(); ob_flush(); } return $obj; } if (isset($_GET['debug_performance'])) { echo "
❌ get_by_id() FAILED - No result for ID: $id
"; flush(); ob_flush(); } return false; } // end get_by_id public function get_by_number($nr) { $sql = "SELECT id, `number` FROM items WHERE `number` = '$nr'"; $result = $this->db->query($sql); if ($result->num_rows > 0) { return $result->fetch_object()->id; } return false; } // end get_by_number public function get_item_for_order($id) { $sql = "SELECT * FROM items WHERE id = $id"; $result = $this->db->query($sql); if ($result->num_rows == 1) { $obj = $result->fetch_object(); $tax_rate = Tax::get_taxrate($obj->tax_id); $obj->tax = $tax_rate; $obj->price = Money::show_money($obj->price_1); $price_with_tax = Money::get_price_with_taxes($obj->price, $tax_rate); $obj->price_with_tax = Money::show_money($price_with_tax); $obj->item_name = $obj->name; $obj->item_number = $obj->number; $total = $obj->price; $obj->total = Money::show_money($total); $total_with_tax = $obj->price_with_tax; $obj->total_with_tax = Money::show_money($total_with_tax); $obj->amount = 1; return $obj; } return false; } // end get_by_id public function search_items($search) { $sql = ''; $matchingItemNumberFirst = false; //echo "Items->search_items() called
"; if (isset($search['manufacturer_id'])) { $sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." WHERE i.active=1 AND i.parent_id=0 AND i.manufacturer_id=".$search['manufacturer_id']." GROUP BY i.id ORDER BY i.name DESC"; } else if (isset($search['search_item'])) { // Include individual search if (isset($this->base_object->config->shopConfiguration['custom_global_modules']) && $this->base_object->config->shopConfiguration['custom_global_modules']) { include_once ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/website_item_search.inc.php'; } else { // Default search $where_add = ''; if (isset($search['item_category']) && $search['item_category'] > 0) { $category_id = $this->db->real_escape_string($search['item_category']); $sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." RIGHT JOIN item_structure_assign isa ON i.id=isa.item_id WHERE i.active=1 AND ( i.name like '%".$search['search_item']."%' || i.number like '%".$search['search_item']."%' || i.short_description like '%".$search['search_item']."%' || i.attribute_1 like '%".$search['search_item']."%' || i.attribute_2 like '%".$search['search_item']."%' || i.attribute_3 like '%".$search['search_item']."%' || i.attribute_4 like '%".$search['search_item']."%' || i.attribute_5 like '%".$search['search_item']."%' || i.seo_keywords like '%".$search['search_item']."%' || i.detail_description like '%".$search['search_item']."%') AND parent_id = 0 AND isa.structure_id = $category_id GROUP BY i.id ORDER BY i.name DESC"; } else { $sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." WHERE i.active=1 AND (i.name like '%".$search['search_item']."%' || i.number like '%".$search['search_item']."%' || i.short_description like '%".$search['search_item']."%' || i.attribute_1 like '%".$search['search_item']."%' || i.attribute_2 like '%".$search['search_item']."%' || i.attribute_3 like '%".$search['search_item']."%' || i.attribute_4 like '%".$search['search_item']."%' || i.attribute_5 like '%".$search['search_item']."%' || i.seo_keywords like '%".$search['search_item']."%' || i.detail_description like '%".$search['search_item']."%') AND parent_id = 0 GROUP BY i.id ORDER BY i.name DESC"; } } } $list = array(); if ($sql) { $result = $this->db->query($sql); $list = array(); $show_taxes = $this->base_object->customer_group->show_tax; while ($obj = $result->fetch_object()) { // get variants $sql = "SELECT i.id, ip.price_1, ip.bargain_price_1 FROM items i LEFT JOIN item_prices ip ON ip.item_id = i.id WHERE ip.price_1 > 0 AND i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1 LIMIT 1"; $variant_result = $this->db->query($sql); if ($variant_result) { while ($variant_obj = $variant_result->fetch_object()) { $obj->price_1 = $variant_obj->price_1; $obj->bargain_price_1 = $variant_obj->bargain_price_1; $obj->price_praefix = 'ab'; } } // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); //$obj->manufacturer_text = $manufacturers[$obj->manufacturer_id]; $obj->manufacturer_text = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : ''; $obj->manufacturer_data = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : null; // bargain if (!$this->check_bargain_active($obj, $obj->id)) { $obj->bargain_price_1 = 0; } // get quantity prices $sql = "SELECT * FROM item_prices WHERE item_id = '".$this->db->real_escape_string($obj->id)."' AND customergroup_id = '".$this->db->real_escape_string(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1)."' LIMIT 1"; $quantityprciesResult = $this->db->query($sql); if ($quantityprciesResult) { while ($QP = $quantityprciesResult->fetch_object()) { foreach ($QP as $colName => $colValue) { if (stristr($colName, 'price') && stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->bargain_price_1) { $obj->bargain_price_1 = $colValue; $obj->price_praefix = 'ab'; } else if (stristr($colName, 'price') && !stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->price_1) { $obj->price_1 = $colValue; $obj->price_praefix = 'ab'; } } } } if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number}); } } } $obj->numberMatch = ($obj->number == $search['search_item']); // intelectra individual if ($obj->attribute_11 && $obj->attribute_15) { $obj->sample_unit = $obj->attribute_15; if (strstr($obj->sample_unit, '100')) { if ($obj->attribute_11 * 10 != 0) { $price_for_calc = ($obj->shop_bargain_price_1 > 0) ? $obj->shop_bargain_price_1 : $obj->shop_price_1; $obj->sample_price = $price_for_calc / ($obj->attribute_11 * 10); } else { error_log("Division durch 0 vermieden. \$obj->attribute_11 * 10 ist 0."); $obj->sample_price = 0; // Oder ein anderer Standardwert } } else { if ($obj->attribute_11 != 0) { $price_for_calc = ($obj->shop_bargain_price_1 > 0) ? $obj->shop_bargain_price_1 : $obj->shop_price_1; $obj->sample_price = $price_for_calc / $obj->attribute_11; } else { error_log("Division durch 0 vermieden. \$obj->attribute_11 ist 0."); $obj->sample_price = 0; // Oder ein anderer Standardwert } } } // emd intelectra individual if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } } // Bring items with a matching item number (matching against the search item) to the top if ($matchingItemNumberFirst) { uasort($list, function($a, $b) { if ($a->numberMatch > $b->numberMatch) { return -1; } else { return 1; } }); } /*echo "search_items result:
";
		var_dump($list);
		echo "

";*/ return $list; } public function search_group_items($search, $item_ids = false) { // get full path structures $structure_object = new Structure($this->base_object); $all_structures = $structure_object->get_all(); // Include individual search if (isset($this->base_object->config->shopConfiguration['custom_global_modules']) && $this->base_object->config->shopConfiguration['custom_global_modules']) { include_once ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/website_itemgroups_search.inc.php'; // Default search } else { $sql = "SELECT -- wg.name, wg.id, -- wg.parent_id, count(wg.id) AS found_items FROM structure wg LEFT JOIN item_structure_assign isa ON wg.id = isa.structure_id LEFT JOIN items i ON i.id = isa.item_id WHERE (i.name like '%".$search['search_item']."%' || i.short_description like '%".$search['search_item']."%' || i.attribute_1 like '%".$search['search_item']."%' || i.attribute_2 like '%".$search['search_item']."%' || i.attribute_3 like '%".$search['search_item']."%' || i.attribute_4 like '%".$search['search_item']."%' || i.attribute_5 like '%".$search['search_item']."%' || i.detail_description like '%".$search['search_item']."%') AND i.parent_id = 0 AND wg.active=1 GROUP BY wg.id"; } if ($sql) { $result = $this->db->query($sql); $parent_child = array(); while ($obj = $result->fetch_object()) { $all_structures[$obj->id]->found_items = $obj->found_items; $parent_id = $all_structures[$obj->id]->parent_id; if (isset($parent_child[$parent_id]) && $parent_child[$parent_id]) { $parent_child[$parent_id]->children[] = $all_structures[$obj->id]; } else { $parent_child[$parent_id] = $all_structures[$parent_id]; $parent_child[$parent_id]->children[] = $all_structures[$obj->id]; } } return $parent_child; } } public function get_item_list_manufacturer($structure_id, $manufacturer_id) { /*$sql = "SELECT items.* FROM items WHERE (items.structure_id = ".$structure_id." OR items.structure_id_2 = ".$structure_id." OR items.structure_id_3 = ".$structure_id.") AND items.manufacturer_id = ".$manufacturer_id." ORDER BY items.name ASC";*/ $sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." WHERE i.active=1 AND (i.structure_id = ".$structure_id." OR i.structure_id_2 = ".$structure_id." OR i.structure_id_3 = ".$structure_id.") AND i.manufacturer_id = ".$manufacturer_id." GROUP BY i.id ORDER BY i.name DESC"; $result = $this->db->query($sql); $list = array(); while ($obj = $result->fetch_object()) { // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = $manufacturers[$obj->manufacturer_id]; // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } $show_taxes = $this->base_object->customer_group->show_tax; if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } $list[$obj->id] = $obj; } return $list; } public function get_price($id) { $sql = "SELECT price_1 as price, tax_id FROM items WHERE id=".$this->db->real_escape_string($id); $result = $this->db->query($sql); if ($result->num_rows > 0) { $obj = $result->fetch_object(); $taxrate = Tax::get_taxrate($obj->tax_id); $price = Money::get_price_with_taxes($obj->price, $taxrate); return Money::show_money($price); } //TODO: false can't be used in calculations return Money::show_money(0.00); } public function calculate_prices($item, $quantity = 1, $variant1 = false, $variant2 = false, $wantedPrice = false, $customer_id = false) { if ($customer_id) { $customer_group_id = CustomerHelper::get_customer_group_id_by_customer_id($customer_id); $customer_group_object = new Customer_group($this->base_object); $customer_group_data = $customer_group_object->get_data($customer_group_id); $show_taxes = $customer_group_data->show_tax; } else { $show_taxes = $this->base_object->customer_group->show_tax; } if ($variant1 || $variant2) { $data['itemPriceNet'] = $item->variant_data[$variant1][$variant2]['priceNet']; $data['itemPriceGross'] = $item->variant_data[$variant1][$variant2]['priceGross']; $data['variant_number'] = $item->variant_data[$variant1][$variant2]['itemNumber']; } else { if ($item->bargain_price_1 > 0) { $data['itemPriceNet'] = $item->bargain_price_1; $data['itemPriceGross'] = $item->bargain_price_1_tax; } else { $data['itemPriceNet'] = $item->price_1; $data['itemPriceGross'] = $item->price_1_tax; } } if (is_array($item->graduated_prices) && count($item->graduated_prices) > 0) { foreach ($item->graduated_prices as $quan => $gpData) { if ($quan <= $quantity) { if ($gpData['bargainNet'] > 0) { $data['itemPriceNet'] = $gpData['bargainNet']; $data['itemPriceGross'] = $gpData['bargainGross']; } else { $data['itemPriceNet'] = $gpData['priceNet']; $data['itemPriceGross'] = $gpData['priceGross']; } } else { break; } } } if ($show_taxes) { // WITH TAXES if ($wantedPrice) { if ($data['itemPriceGross'] != $wantedPrice) { $grossPrice = $wantedPrice; $netPrice = $wantedPrice / (100.0 + (float) $item->tax) * 100.0; $data['itemPriceNet'] = $netPrice; $data['itemPriceGross'] = $grossPrice; } } $data['shownPrice'] = $data['itemPriceGross']; } else { // WITHOUT TAXES if ($wantedPrice) { if ($data['itemPriceNet'] != $wantedPrice) { $grossPrice = $wantedPrice * (100.0 + (float) $item->tax) / 100.0; $netPrice = $wantedPrice; $data['itemPriceNet'] = $netPrice; $data['itemPriceGross'] = $grossPrice; } } $data['shownPrice'] = $data['itemPriceNet']; } $data['itemPriceNet'] = round($data['itemPriceNet'], 4); $data['itemPriceGross'] = round($data['itemPriceGross'], 4); $data['shownPrice'] = round($data['shownPrice'], 4); return $data; } public function find_for_ajax($searchString, $limit = 30) { $sql = " SELECT id, number, name, active FROM items WHERE number LIKE '%".$this->db->real_escape_string($searchString)."%' OR name LIKE '%".$this->db->real_escape_string($searchString)."%' ORDER BY name, number, id, active DESC LIMIT 0, ".$this->db->real_escape_string($limit); $result = $this->db->query($sql); if ($result->num_rows > 0) { $return = array(); while ($obj = $result->fetch_object()) { $return[] = $obj; } return $return; } return false; } private function saveAssignedItems($type = 1) { // NEUE PYTHON-BASIERTE SAVE LOGIK - Nur Änderungen speichern! if (is_numeric($this->id)) { // ⚡ PERFORMANCE FIX: Nur aufrufen wenn tatsächlich POST-Daten vorhanden! // Verhindert 504 Timeout bei Kurz-URL Updates etc. if (!isset($_POST['assignedItemsCollection'.$type])) { return true; // Keine Daten = nichts zu tun = success } // Versuche Python Service (wenn verfügbar) $python_script = dirname(dirname(__FILE__)) . '/modules/import/item_save_service.py'; if (file_exists($python_script)) { $items = isset($_POST['assignedItemsCollection'.$type]) ? $_POST['assignedItemsCollection'.$type] : array(); $actions = array( 1 => 'save_accessories', 2 => 'save_spare_parts', 3 => 'save_alternatives' ); $data = array( 'item_id' => $this->id, 'action' => $actions[$type], 'items' => $items ); $json_data = json_encode($data); $command = "python3 " . escapeshellarg($python_script) . " " . escapeshellarg($json_data); $output = shell_exec($command . " 2>&1"); $result = json_decode($output, true); if ($result && isset($result['success']) && $result['success']) { // Update flags $db_switch_fields = array( 1 => 'has_additional_items', 2 => 'has_spare_parts', 3 => 'has_real_friends' // LOL wer hat das genannt? ); if (isset($db_switch_fields[$type])) { $has_items = !empty($items) ? 1 : 0; $query = "UPDATE items SET ".$db_switch_fields[$type]." = ".$has_items." WHERE id = '".$this->id."'"; $this->db->query($query); } return true; // Python Success! } } // FALLBACK zur alten Logik (falls Python nicht läuft) switch ($type) { case 1: $db_switch_field = 'has_additional_items'; break; case 2: $db_switch_field = 'has_spare_parts'; break; case 3: $db_switch_field = 'has_real_friends'; break; default: $db_switch_field = false; } $queryDelete = "DELETE FROM item_item_assign WHERE item_parent_id = '".$this->id."' AND type = ".$type; $this->db->query($queryDelete); if ($db_switch_field) { $query = "UPDATE items SET ".$db_switch_field." = 0 WHERE id = '".$this->id."'"; $this->db->query($query); } if (is_array($_POST['assignedItemsCollection'.$type])) { $pos = 0; $inserts = array(); foreach ($_POST['assignedItemsCollection'.$type] as $itemId) { if (is_numeric($itemId)) { ++$pos; $inserts[] = "(".$this->id.",".$itemId.", $type, ".$pos.")"; } } if (count($inserts) > 0) { $queryInsert = "REPLACE INTO item_item_assign (item_parent_id, item_child_id, type, position) VALUES ".implode(',', $inserts); $this->db->query($queryInsert); if ($db_switch_field) { $query = "UPDATE items SET ".$db_switch_field." = 1 WHERE id = '".$this->id."'"; $this->db->query($query); } } } } return true; } public function delete_item_item_assign($item_parent_id, $item_child_id, $type = false) { $sql = ''; if ($type) { $sql = "DELETE FROM item_item_assign WHERE item_parent_id = '".$item_parent_id."' AND item_child_id = '".$item_child_id."' AND type = ".$type; } else { $sql = "DELETE FROM item_item_assign WHERE item_parent_id = '".$item_parent_id."' AND item_child_id = '".$item_child_id."'"; } $this->db->query($sql); return true; } public function get_all_interesting_items_by_group_id($group_id) { // get structure_ids $ids = array(); $sql = " SELECT * FROM structure WHERE id=".$this->db->real_escape_string($group_id); $result = $this->db->query($sql); $obj = $result->fetch_object(); $sql = " SELECT id FROM structure WHERE parent_id=".$this->db->real_escape_string($obj->parent_id); $result = $this->db->query($sql); if ($result->num_rows > 0) { while ($obj = $result->fetch_object()) { $ids[] = $obj->id; } // get items $all_items = array(); foreach ($ids as $structure_id) { $items = $this->get_item_list($structure_id); $all_items = array_merge($all_items, $items); } return $all_items; } return false; } // TODO: needs paging public function get_by_manufacturer($id) { $sql = "SELECT * FROM items WHERE manufacturer_id=".$this->db->real_escape_string($id); $result = $this->db->query($sql); if ($result->num_rows > 0) { $return_data = array(); while ($obj = $result->fetch_object()) { $return_data[] = $obj; } return $return_data; } return false; } private function watermark($strImageDestination) { $strImageWatermark = './web/'.SHOP_SYSTEM.'/documents/'.$this->base_object->config->shopConfiguration['item_watermark_image']; $iTransparency = 0; $iQuality = 80; list ( $iDestinationWidth, $iDestinationHeight, $iDestinationType ) = getimagesize($strImageDestination); list ( $iWatermarkWidth, $iWatermarkHeight, $iWatermarkType ) = getimagesize($strImageWatermark); switch ($iDestinationType) { case 1: $rDestination = imagecreatefromgif ($strImageDestination); break; case 2: $rDestination = imagecreatefromjpeg($strImageDestination); break; case 3: $rDestination = imagecreatefrompng($strImageDestination); } switch ($iWatermarkType) { case 1: $rWatermark = imagecreatefromgif ($strImageWatermark); break; case 2: $rWatermark = imagecreatefromjpeg($strImageWatermark); break; case 3: $rWatermark = imagecreatefrompng($strImageWatermark); } /* * Position des Wasserzeichens (1 - 5). * 1 = Oben links. * 2 = Oben rechts. * 3 = Unten links. * 4 = Unten rechts * 5 = Horizontal/vertikal zentriert. * * Standard = 4 */ switch ($this->base_object->config->shopConfiguration['item_watermark_pos']) { case 1: $iPositionX = 0; $iPositionY = 0; break; case 2: $iPositionX = $iDestinationWidth - $iWatermarkWidth; $iPositionY = 0; break; case 3: $iPositionX = 0; $iPositionY = $iDestinationHeight - $iWatermarkHeight; break; case 4: default: $iPositionX = $iDestinationWidth - $iWatermarkWidth; $iPositionY = $iDestinationHeight - $iWatermarkHeight; break; case 5: $iPositionX = ceil(( $iDestinationWidth / 2)); $iPositionX -= ceil(( $iWatermarkWidth / 2)); $iPositionY = ceil(( $iDestinationHeight / 2)); $iPositionY -= ceil(( $iWatermarkHeight / 2)); } $iTransparency = 100 - $iTransparency; /* imagecopymerge ( $rDestination, $rWatermark, $iPositionX, $iPositionY, 0, 0, $iWatermarkWidth, $iWatermarkHeight, $iTransparency ); */ // Wasserzeichen einfügen imagecopy($rDestination, $rWatermark, $iPositionX, $iPositionY, 0, 0, $iWatermarkWidth, $iWatermarkHeight); /* * Ausgabeformat (1 - 3): * 1 = GIF-Format * 2 = JPEG-Format * 3 = PNG-Format * * Standard = 3 */ switch ($iDestinationType) { case 1: //header ( 'content-type: image/gif' ); imagegif ($rDestination, $strImageDestination); break; case 2: //header ( 'content-type: image/jpeg' ); imagejpeg($rDestination, $strImageDestination, $iQuality); break; case 3: default: //header ( 'content-type: image/png' ); imagepng($rDestination, $strImageDestination); } imagedestroy($rDestination); imagedestroy($rWatermark); return; } /** * $type : accessories = 0, alternative = 1 * $id : id of parent or child item * $order : normal = 0 and selects parent item ids, reverse is 1 and selects child item ids */ public function get_all_item_items($type = false, $id = false, $order = 0) { $sql = "SELECT iia.*, i.name, i.active, i.number FROM item_item_assign iia JOIN items i ON"; if ($id) { if ($order === 1) { $sql .= " i.id = iia.item_child_id WHERE iia.item_parent_id=".$this->db->real_escape_string($id); $this->id = $id; } else if ($order === 0) { $sql .= " i.id = iia.item_parent_id WHERE iia.item_child_id=".$this->db->real_escape_string($id); $this->id = $id; } else { return false; } } else if ($this->id) { if ($order === 1) { $sql .= " i.id = iia.item_child_id WHERE iia.item_child_id=".$this->db->real_escape_string(intval($this->id)); } else if ($order === 0) { $sql .= " i.id = iia.item_parent_id WHERE iia.item_parent_id=".$this->db->real_escape_string(intval($this->id)); } else { return false; } } else { return false; } if ($type) { $sql .= " AND type=".$this->db->real_escape_string(intval($type)); } $sql .= " ORDER BY iia.position ASC"; $result = $this->db->query($sql); if ($result->num_rows > 0) { $return_data = array(); while ($obj = $result->fetch_object()) { $return_data[] = $obj; } if ($return_data != array()) { return $return_data; } } return false; } // end get_all_item_items public function remove_default_image($id = false) { $sql = "UPDATE items SET default_image_file_name='' WHERE id="; if ($id) { $sql .= $this->db->real_escape_string($id); $this->id = $id; } else if ($this->id) { $sql .= $this->db->real_escape_string($this->db); } else { return false; } $this->db->query($sql); } // end remove_default_image public function increase_inventory($quantity, $variant1, $variant2, $id = false) { if (is_int((int) $quantity)) { $quantity = (int) $quantity; if ($id) { $this->id = $id; } if (!$this->id) { return false; } if ($this->has_variants()) { // reduce inventory for item variants $inventory = $this->get_inventory(true, $variant1, $variant2); $new_inventory = $inventory + $quantity; // TODO: what to do if the item was already delivered? // increasing the original item might not be right return $this->db->query("UPDATE item_attribute_variants SET inventory=".$this->db->real_escape_string($new_inventory)." WHERE item_id=".$this->db->real_escape_string($this->id)." AND attribut1='".$this->db->real_escape_string($variant1)."' AND attribut2='".$this->db->real_escape_string($variant2)."'"); } else { // reduce inventory for item $inventory = $this->get_inventory(); $new_inventory = $inventory + $quantity; // TODO: what to do if the item was already delivered? // increasing the original item might not be right return $this->db->query("UPDATE items SET inventory=".$this->db->real_escape_string($new_inventory)." WHERE id=".$this->db->real_escape_string($this->id)); } } return false; } // end increase_inventory public function reduce_inventory($quantity, $variant1, $variant2, $id = false) { if (is_int((int) $quantity)) { $quantity = (int) $quantity; if ($id) { $this->id = $id; } if (!$this->id) { return false; } if ($this->has_variants()) { // reduce inventory for item variants $inventory = $this->get_inventory(true, $variant1, $variant2); $new_inventory = $inventory - $quantity; // TODO: new inventory can slip under 0, what to do? return $this->db->query("UPDATE item_attribute_variants SET inventory=".$this->db->real_escape_string($new_inventory)." WHERE item_id=".$this->db->real_escape_string($this->id)." AND attribut1='".$this->db->real_escape_string($variant1)."' AND attribut2='".$this->db->real_escape_string($variant2)."'"); } else { // reduce inventory for item $inventory = $this->get_inventory(); $new_inventory = $inventory - $quantity; // TODO: new inventory can slip under 0, what to do? return $this->db->query("UPDATE items SET inventory=".$this->db->real_escape_string($new_inventory)." WHERE id=".$this->db->real_escape_string($this->id)); } } return false; } // end reduce_inventory private function get_inventory($has_variants = false, $variant1 = false, $variant2 = false) { if ($has_variants) { $sql = "SELECT inventory AS num FROM item_attribute_variants WHERE item_id=".$this->db->real_escape_string($this->id)." AND attribut1='".$this->db->real_escape_string($variant1)."' AND attribut2='".$this->db->real_escape_string($variant2)."' LIMIT 1"; } else { $sql = "SELECT inventory AS num FROM items WHERE id=".$this->db->real_escape_string($this->id); } $result = $this->db->query($sql); return $result->fetch_object()->num; } private function has_variants() { $sql = "SELECT * FROM item_attribute_variants WHERE item_id=".$this->db->real_escape_string($this->id); $result = $this->db->query($sql); if ($result->num_rows > 0) { return true; } return false; } public function get_all_by_manufacturer($manufacturer_id) { $sql = "SELECT * FROM items WHERE manufacturer_id=".$this->db->real_escape_string($manufacturer_id); $result = $this->db->query($sql); if ($result->num_rows > 0) { $return_data = array(); while ($obj = $result->fetch_object()) { $return_data[] = $obj; } if ($return_data == array()) { return false; } return $return_data; } return false; } // end get_all_by_manufacturer public function get_all_google_item_categories($parent = false) { $sql_where = ($parent) ? "parent = '".$this->db->real_escape_string($parent)."'" : "parent = ''"; $sql = "SELECT * FROM google_item_categories WHERE ".$sql_where; $result = $this->db->query($sql); if ($result->num_rows > 0) { $data = array(); while ($obj = $result->fetch_object()) { $data[] = $obj; } return $data; } else { return array(); } } private function load_item_discounts() { // get discounts for all customer_groups $sql = "SELECT * FROM discount_item_groups"; $result = $this->db->query($sql); $discounts = array(); if ($result) { while ($obj = $result->fetch_object()) { $discounts[$obj->customer_group_id][$obj->manufacturer_id][$obj->structure_id] = $obj->discount; } } $this->item_discounts = $discounts; return false; } public function get_item_discount($customer_group_id, $manufacturer_id, $structure_id) { if (isset($this->item_discounts[$customer_group_id][$manufacturer_id][$structure_id])) { return $this->item_discounts[$customer_group_id][$manufacturer_id][$structure_id]; } else { return 0; } } public function get_assigned_items($item_id, $customer_group_price_id, $type = 1) { $list = array(); // get assigned item ids $sql = 'SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_item_assign iip LEFT JOIN items i ON iip.item_child_id=i.id -- RIGHT JOIN LEFT JOIN item_prices ip ON i.id=ip.item_id AND ip.customergroup_id='.$this->db->real_escape_string($customer_group_price_id).' WHERE iip.item_parent_id='.$this->db->real_escape_string($item_id).' AND iip.type='.$this->db->real_escape_string($type).' ORDER BY iip.position ASC'; $result = $this->db->query($sql); $show_taxes = (isset($this->base_object->customer_group->show_tax)) ? $this->base_object->customer_group->show_tax : 1; while ($obj = $result->fetch_object()) { // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->tax_rate = $this->all_tax[$obj->tax_id]->steuersatz; // some do it this way some do it that way $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : ''; $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->price_1_tax = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value; if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // bargain if (!$this->check_bargain_active($obj, $obj->id)) { $obj->shop_bargain_price_1 = $obj->bargain_price_1 = 0; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = split(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = split(';', $obj->{'attribute_'.$attribute->number}); } } } if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } return $list; } public function get_assigned_items_new($item_id, $customer_group_price_id, $type = 1) { $list = array(); // get assigned item ids $sql = 'SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_item_assign iip LEFT JOIN items i ON iip.item_child_id=i.id -- RIGHT JOIN LEFT JOIN item_prices ip ON i.id=ip.item_id AND ip.customergroup_id='.$this->db->real_escape_string($customer_group_price_id).' WHERE iip.item_parent_id='.$this->db->real_escape_string($item_id).' AND iip.type='.$this->db->real_escape_string($type).' ORDER BY iip.position ASC'; $result = $this->db->query($sql); $show_taxes = (isset($this->base_object->customer_group->show_tax)) ? $this->base_object->customer_group->show_tax : 1; while ($obj = $result->fetch_object()) { // variant check $sql = "SELECT i.id, ip.price_1, ip.bargain_price_1 FROM items i LEFT JOIN item_prices ip ON (ip.item_id = i.id AND ip.customergroup_id = ".$this->db->real_escape_string($customer_group_price_id).") WHERE i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1 ASC LIMIT 1"; $variant_result = $this->db->query($sql); if ($variant_result && $variant_result->num_rows > 0) { $variant_obj = $variant_result->fetch_object(); $obj->price_1 = $variant_obj->price_1; $obj->bargain_price_1 = $variant_obj->bargain_price_1; $obj->price_praefix = 'ab'; } // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // bargain if (!$this->check_bargain_active($obj, $obj->id)) { $obj->bargain_price_1 = 0; } // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->tax_rate = $this->all_tax[$obj->tax_id]->steuersatz; // some do it this way some do it that way $obj->price_tax_text = str_replace('[tax]', $obj->tax, isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : ''; $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->price_1_tax = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value; if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = split(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = split(';', $obj->{'attribute_'.$attribute->number}); } } } if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } return $list; } public function is_combination_item($item_id = false) { $sql = 'SELECT * FROM items WHERE combination_item=1 AND id='; if ($item_id) { $sql .= $this->db->real_escape_string($item_id); $this->id = $item_id; } else if ($this->id) { $sql .= $this->db->real_escape_string($this->id); } else { return false; } $result = $this->db->query($sql); if ($result->num_rows > 0) { return true; } return false; } public function get_opinion_list($item_id) { $data = array(); if ($item_id) { $sql = "SELECT * FROM item_opinion WHERE item_id = ".$item_id." ORDER BY timestamp DESC"; $result = $this->db->query($sql); while ($obj = $result->fetch_object()) { $obj->date = substr($obj->timestamp, 8, 2).'.'.substr($obj->timestamp, 5, 2).'.'.substr($obj->timestamp, 0, 4); $data[] = $obj; } } return $data; } public function get_avg_opinion($item_id) { $avg = false; if ($item_id) { $sql = "SELECT AVG(rang) AS avg_opinion FROM item_opinion WHERE item_id = ".$item_id; $result = $this->db->query($sql); $AVGO = $result->fetch_object(); $avg = $AVGO->avg_opinion; } return $avg; } public function create_opinion($data) { // save opinion in database $sql = "INSERT INTO item_opinion (item_id, timestamp, rang, opinion_text, user_id, user_name, active) VALUES (".$this->db->real_escape_string($data['item_id']).", current_timestamp, ". $this->db->real_escape_string($data['rang']).",'". $this->db->real_escape_string($data['opinion_text'])."', ". $this->db->real_escape_string($data['user_id']).", '". $this->db->real_escape_string($data['user_name'])."',1)"; $this->db->query($sql); return; } public function get_item_types($id = false) { $sql = 'SELECT it.*, itd.* FROM item_types it JOIN item_type_definitions itd ON ( it.item_type_definition_id = itd.item_type_definition_id ) WHERE it.item_id='; if ($id) { $sql .= $this->db->real_escape_string($id); $this->id = $id; } else if ($this->id) { $sql .= $this->db->real_escape_string($this->id); } else { return false; } $result = $this->db->query($sql); if ($result->num_rows > 0) { $data = array(); while ($obj = $result->fetch_object()) { $data[] = $obj; } return $data; } return false; } // end get_item_types private function fix_data($obj) { // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } if ($this->base_object->customer_group->show_tax) { if (!isset($obj->tax)) {$obj->tax = 19;} $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } $obj->tax_rate = $this->tax_rates[$obj->tax_id]->steuersatz; $obj->manufacturer_name = ''; if (isset($this->manufacturers[$obj->manufacturer_id])) { $obj->manufacturer_name = $this->manufacturers[$obj->manufacturer_id]->name; } $obj->structure_name = ''; if (isset($this->structure[$obj->structure_id])) { $obj->structure_name = $this->structure[$obj->structure_id]->name; } return $obj; } // end fix_pricing public function get_flat_items() { $sql = "SELECT i.*, ip.price_1, ip.bargain_price_1, ip.price_2, ip.bargain_price_2, ip.price_3, ip.bargain_price_3, ip.quantity_2, ip.quantity_3 FROM items i LEFT JOIN item_prices ip ON ip.item_id = i.id WHERE i.active=1 AND ip.customergroup_id=".$this->db->real_escape_string(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1)." ORDER BY i.number"; $result = $this->db->query($sql); $data = array(); if ($result->num_rows > 0) { while ($obj = $result->fetch_object()) { $data[] = $this->fix_data($obj); } } return $data; } public function get_item_list_new($structure_id, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false, $sort_by = false, $infinite = false) { // $manufacturers = Manufacturer::get_name_id_pair(); $limited = false; if (is_numeric($itemsPerPage)) { $limitMax = $itemsPerPage; $limited = true; } // Load for infinite scrolling if ($infinite) { $limitMax = 24; $limited = true; } if (is_numeric($currentPage)) { $limitMin = $currentPage * $limitMax - $limitMax; } else { $limitMin = 0; } $whereAdd = ''; if ($activeOnly) { $whereAdd .= " isa.structure_id=".$this->db->real_escape_string($structure_id); } if ($activeOnly) { $whereAdd .= " AND i.active = 1 "; } if (is_numeric($fromManufacturerOnly)) { $whereAdd .= " AND i.manufacturer_id = ".$fromManufacturerOnly; } $sql = "SELECT count(id) AS num FROM items i RIGHT JOIN item_structure_assign isa ON i.id = isa.item_id WHERE $whereAdd"; $result = $this->db->query($sql); $this->itemCount = ($result) ? $result->fetch_object()->num : 0; //probably the wrong place $sql = " SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON ( i.id = ip.item_id AND ip.customergroup_id =".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." ) RIGHT JOIN item_structure_assign isa ON i.id = isa.item_id WHERE ".$whereAdd." GROUP BY i.id "; if ($sort_by) { if ($sort_by == 'name_up') { $sql .= " ORDER BY i.name ASC"; } else if ($sort_by == 'name_down') { $sql .= " ORDER BY i.name DESC"; } else if ($sort_by == 'number_up') { $sql .= " ORDER BY i.number ASC"; } else if ($sort_by == 'number_down') { $sql .= " ORDER BY i.number DESC"; } else if ($sort_by == 'manufacturer_up') { $sql .= " ORDER BY i.manufacturer_id ASC"; } else if ($sort_by == 'manufacturer_down') { $sql .= " ORDER BY i.manufacturer_id DESC"; } else if ($sort_by == 'price_up') { $sql .= " ORDER BY ip.price_1 ASC"; } else if ($sort_by == 'price_down') { $sql .= " ORDER BY ip.price_1 DESC"; } } if ($limited) { $sql .= " LIMIT ".$this->db->real_escape_string($limitMin).", ".$this->db->real_escape_string($limitMax); } $list = array(); $result = $this->db->query($sql); $show_taxes = $this->base_object->customer_group->show_tax; while ($obj = $result->fetch_object()) { // bargain if (!$this->check_bargain_active($obj, $obj->id)) { $obj->bargain_price_1 = 0; } // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // get quantity prices $sql = "SELECT * FROM item_prices WHERE item_id = '".$this->db->real_escape_string($obj->id)."' AND customergroup_id = '".$this->db->real_escape_string(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1)."' LIMIT 1"; $quantityprciesResult = $this->db->query($sql); if ($quantityprciesResult) { while ($QP = $quantityprciesResult->fetch_object()) { foreach ($QP as $colName => $colValue) { if (stristr($colName, 'price') && stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->bargain_price_1) { $obj->bargain_price_1 = $colValue; $obj->price_praefix = 'ab'; } else if (stristr($colName, 'price') && !stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->price_1) { $obj->price_1 = $colValue; $obj->price_praefix = 'ab'; } } } } // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', number_format($obj->tax, 2, ',', '.'), isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id]->name; $obj->manufacturer_data = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : null; if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 4); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 4); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'name_en' => $attribute->name_en, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number}); } } } // get variants? $sql = "SELECT i.*, ip.price_1, ip.bargain_price_1 FROM items i LEFT JOIN item_prices ip ON ip.item_id = i.id WHERE ip.price_1 > 0 AND i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1"; $variant_result = $this->db->query($sql); $obj->variant_structure = array(); if ($variant_result && $variant_result->num_rows > 0) { $obj->price_praefix = 'ab'; $obj->bargain_price_1 = 0; $obj->price_1 = 0; $obj->shop_price_1 = 0; $obj->shop_bargain_price_1 = 0; while ($variant_obj = $variant_result->fetch_object()) { // variants // calc tax $variant_obj->tax = $this->all_tax[$variant_obj->tax_id]->steuersatz; $variant_obj->tax_value = round($variant_obj->price_1 * ($variant_obj->tax / 100), 4); $variant_obj->price_1_tax = $variant_obj->price_1 + $variant_obj->tax_value; $variant_obj->bargain_tax_value = round($variant_obj->bargain_price_1 * ($variant_obj->tax / 100), 2); $variant_obj->bargain_price_1_tax = $variant_obj->bargain_price_1 + $variant_obj->bargain_tax_value; // shop price $variant_obj->sample_price = 0; if ($this->base_object->customer_group->show_tax) { $variant_obj->shop_price_1 = $variant_obj->price_1_tax; $variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1_tax; } else { $variant_obj->shop_price_1 = $variant_obj->price_1; $variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1; } if ($obj->shop_price_1 == 0 || $obj->shop_price_1 > $variant_obj->shop_price_1) { $obj->shop_price_1 = $variant_obj->shop_price_1; } // calc sample price $variant_obj->vpe_sampleprice_unit = $variant_obj->{'attribute_'.$obj->schema_data->base_price_field}; if ($obj->sample_unit && $variant_obj->vpe_sampleprice_unit) { if ($variant_obj->price_je_vpe) { if ($variant_obj->vpe_amount) { if ($variant_obj->shop_bargain_price_1 > 0) { $variant_obj->sample_price = $variant_obj->shop_bargain_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount); } else { $variant_obj->sample_price = $variant_obj->shop_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount); } } } else { if ($variant_obj->shop_bargain_price_1 > 0) { $variant_obj->sample_price = ($variant_obj->shop_bargain_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } else { $variant_obj->sample_price = ($variant_obj->shop_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } } } $obj->variant_structure[] = array( 'id' => $variant_obj->id, 'level' => 2, 'name' => $variant_obj->name, 'number' => $variant_obj->number, 'short_uri' => $variant_obj->short_uri, 'price_1' => $variant_obj->price_1, 'bargain_price_1' => $variant_obj->bargain_price_1, 'shop_price_1' => $variant_obj->shop_price_1, 'shop_bargain_price_1' => $variant_obj->shop_bargain_price_1, 'sample_price' => $variant_obj->sample_price, 'default_image_file_name' => $variant_obj->default_image_file_name, 'price_type' => $variant_obj->price_type, 'data' => $variant_obj ); // get smallest price for parent article if (!$obj->smallest_variant_price_1 || $obj->smallest_variant_price_1 > $variant_obj->price_1) { $obj->price_1 = $variant_obj->price_1; $obj->bargain_price_1 = $variant_obj->bargain_price_1; } } } // intelectra individual if ($obj->attribute_11 && $obj->attribute_15) { $obj->sample_unit = $obj->attribute_15; if (strstr($obj->sample_unit, '100')) { $price_for_calc = ($obj->shop_bargain_price_1 > 0) ? $obj->shop_bargain_price_1 : $obj->shop_price_1; $obj->sample_price = $price_for_calc / ($obj->attribute_11 * 10); } else { $price_for_calc = ($obj->shop_bargain_price_1 > 0) ? $obj->shop_bargain_price_1 : $obj->shop_price_1; $obj->sample_price = $price_for_calc / $obj->attribute_11; } } // end intelectra individual if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } return $list; } private function _cleanupStructureAssignment($ignore = false) { if ($ignore) { $sql = "DELETE FROM item_structure_assign WHERE item_id = ".$this->db->real_escape_string($this->id)." AND structure_id NOT IN (".implode(', ', $ignore).")"; } else { $sql = "DELETE FROM item_structure_assign WHERE item_id = ".$this->db->real_escape_string($this->id); } $this->db->query($sql); } private function _assignToStructures($structures) { $newStrucutres = array(); if (is_array($structures)) { foreach ($structures as $structure_id) { if (is_numeric($structure_id)) { $newStrucutres[] = '('.$this->id.', '.$structure_id.')'; } } $sql = "INSERT IGNORE INTO item_structure_assign (item_id, structure_id) VALUES ".implode(', ', $newStrucutres); $this->db->query($sql); } $this->_cleanupStructureAssignment($structures); } public function getStructureAssignment() { $sql = "SELECT * FROM item_structure_assign WHERE item_id = ".$this->db->real_escape_string($this->id); $res = $this->db->query($sql); $assignedStructures = array(); while ($S = $res->fetch_object()) { $assignedStructures[$S->structure_id] = $S->pos; } return $assignedStructures; } public function set_inventory($quantity) { if (is_int((int) $quantity)) { $quantity = (int) $quantity; if (!$this->id) { return false; } $sql = "UPDATE items SET inventory=".$this->db->real_escape_string($quantity)." WHERE id=".$this->db->real_escape_string($this->id); return $this->db->query($sql); } return false; } public function searchItems($searchString, $idsOnly = false, $loose = true) { //echo "Itemclass->searchItems called"; $timer_start = microtime(true); $searchString_trimmed = trim($searchString); $searchString_filtered = preg_replace("@[^\p{L}\p{N}\s\*]@sui", '', $searchString_trimmed); if ($loose) { $searchString_enriched = preg_replace("@([^\s])(\s)@sui", '$1*$2', $searchString_filtered); $searchString_ready = $searchString_enriched.'*'; } else { $searchString_ready = $searchString_filtered; } $results_items_associations = $this->_searchItemWithinItemsAndAssociations($searchString_ready, $idsOnly); $results_associations = $this->_searchItemWithinAssociations($searchString_ready); $results_items = $this->_searchItemWithinItems($searchString_ready); $results = array_replace($results_items_associations, $results_associations, $results_items); $running_time = microtime(true) - $timer_start; $result = array( 'searchstring' => $searchString, 'results' => count($results), 'queryTime' => $running_time, 'data' => $results ); return $result; } private function _searchItemWithinItemsAndAssociations($searchString, $idsOnly = false) { $query = " SELECT tbl_items.id, tbl_items.number, tbl_items.name, tbl_items.short_uri, (tbl_items.matchpoints + 1) / (tbl_zuordnungen.matchpoints + 1) AS relevance FROM ( SELECT i.id, i.number, i.name, i.short_uri, MATCH ( i.number, i.name, i.detail_description, i.attribute_1, i.attribute_2, i.attribute_3, i.attribute_4, i.attribute_5 ) AGAINST ( '".$this->db->real_escape_string($searchString)."' COLLATE utf8_general_ci IN NATURAL LANGUAGE MODE ) AS matchpoints FROM items i WHERE i.active = 1 AND i.parent_id = 0 AND MATCH ( i.number, i.name, i.detail_description, i.attribute_1, i.attribute_2, i.attribute_3, i.attribute_4, i.attribute_5 ) AGAINST ( '".$this->db->real_escape_string($searchString)."' COLLATE utf8_general_ci IN BOOLEAN MODE ) ) AS tbl_items INNER JOIN ( SELECT gz.anr, gz.bezeichnung1, MATCH ( gz.bezeichnung1 ) AGAINST ( '".$this->db->real_escape_string($searchString)."' COLLATE utf8_general_ci IN NATURAL LANGUAGE MODE ) AS matchpoints FROM import_geraetezuordnung gz WHERE MATCH ( gz.bezeichnung1 ) AGAINST ( '".$this->db->real_escape_string($searchString)."' COLLATE utf8_general_ci IN BOOLEAN MODE ) ) AS tbl_zuordnungen ON tbl_items.number = tbl_zuordnungen.anr GROUP BY tbl_items.number ORDER BY relevance DESC "; $rs = $this->db->query($query); $results = array(); if ($idsOnly) { while ($I = $rs->fetch_object()) { $results[$I->id] = $I->id; } } else { $method = __METHOD__; while ($I = $rs->fetch_object()) { $I->method = $method; $I->string = $searchString; $results[$I->id] = $I; } } return $results; } private function _searchItemWithinAssociations($searchString, $idsOnly = false) { $searchString_limited = '+'.preg_replace("@(\s)@sui", '$1+', $searchString); $query = "SELECT anr FROM import_geraetezuordnung WHERE MATCH (bezeichnung1) AGAINST ('".$this->db->real_escape_string($searchString_limited)."' COLLATE utf8_general_ci IN BOOLEAN MODE) GROUP BY anr"; $rs = $this->db->query($query); $itemNumbers = array(); while ($A = $rs->fetch_object()) { $itemNumbers[] = $A->anr; } $results = array(); if (count($itemNumbers) > 0) { $itemNumberList = implode(',', $itemNumbers); $queryItems = "SELECT id, number, name, short_uri FROM items FORCE INDEX (parent_id_number_active) WHERE parent_id = 0 AND number IN (".$itemNumberList.") AND active = 1"; $rsItems = $this->db->query($queryItems); if ($idsOnly) { while ($I = $rs->fetch_object()) { $results[$I->id] = $I->id; } } else { $method = __METHOD__; while ($I = $rsItems->fetch_object()) { $I->method = $method; $I->string = $searchString_limited; $results[$I->id] = $I; } } } return $results; } private function _searchItemWithinItems($searchString, $idsOnly = false) { $searchString_limited = '+'.preg_replace("@(\s)@sui", '$1+', $searchString); $query = " SELECT id, number, name, short_uri, MATCH ( number, name, detail_description, attribute_1, attribute_2, attribute_3, attribute_4, attribute_5 ) AGAINST ( '".$this->db->real_escape_string($searchString_limited)."' COLLATE utf8_general_ci IN NATURAL LANGUAGE MODE ) AS relevance FROM items WHERE active = 1 AND parent_id = 0 AND MATCH ( number, name, detail_description, attribute_1, attribute_2, attribute_3, attribute_4, attribute_5 ) AGAINST ( '".$this->db->real_escape_string($searchString_limited)."' COLLATE utf8_general_ci IN BOOLEAN MODE ) ORDER BY relevance DESC "; $rs = $this->db->query($query); $results = array(); if ($idsOnly) { while ($I = $rs->fetch_object()) { $results[$I->id] = $I->id; } } else { $method = __METHOD__; while ($I = $rs->fetch_object()) { $I->method = $method; $I->string = $searchString_limited; $results[$I->id] = $I; } } return $results; } public function get_all_structure_items($structure_id) { // get items $sql = "SELECT id, name, short_uri, active FROM items WHERE active=1 AND structure_id=".$this->db->real_escape_string($structure_id); $result = $this->db->query($sql); if ($this->db->error) { $log_object = Logger::get_instance(); $log_object->info('Error in /core/items_class.php->get_all_structure_items()', $this->db->error.', sql:'.$sql); } $data = array(); if ($result) { while ($row = $result->fetch_object()) { $data[] = $row; } } return $data; } public function get_item_list_by_type($structure_id, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false, $sort_by = false, $infinite = false) { $limited = false; if (is_numeric($itemsPerPage)) { $limitMax = $itemsPerPage; $limited = true; } // Load for infinite scrolling if ($infinite) { $limitMax = 24; $limited = true; } if (is_numeric($currentPage)) { $limitMin = $currentPage * $limitMax - $limitMax; } else { $limitMin = 0; } $structure_object = new Structure($this->base_object); $structure_data = $structure_object->get_by_id($structure_id); $whereAdd = 'isa.item_type_definition_id='.$structure_data->item_type; if ($activeOnly) { $whereAdd .= " AND i.active = 1 "; } if (is_numeric($fromManufacturerOnly)) { $whereAdd .= " AND i.manufacturer_id = ".$fromManufacturerOnly; } // get type include_once './core/itemtype.class.php'; $item_type_object = New ItemType($this->base_object); $type_data = $item_type_object->load($structure_data->item_type); if ($type_data['item_type_definition_type'] == 1) { $today = getdate(); $today = $today['year'].'-'.$today['mon'].'-'.$today['mday']; $whereAdd .= " AND isa.item_type_available_from <= '".$this->db->real_escape_string($today)."' AND isa.item_type_available_until >= '".$this->db->real_escape_string($today)."'"; } $sql = "SELECT count(id) AS num FROM items i RIGHT JOIN item_types isa ON i.id = isa.item_id WHERE $whereAdd"; $result = $this->db->query($sql); $this->itemCount = ($result) ? $result->fetch_object()->num : 0; $sql = " SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip RIGHT JOIN items i ON ( i.id = ip.item_id AND ip.customergroup_id =".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." ) RIGHT JOIN item_types isa ON i.id = isa.item_id WHERE ".$whereAdd." GROUP BY i.id"; if ($sort_by) { if ($sort_by == 'name_up') { $sql .= " ORDER BY i.name ASC"; } else if ($sort_by == 'name_down') { $sql .= " ORDER BY i.name DESC"; } else if ($sort_by == 'number_up') { $sql .= " ORDER BY i.number ASC"; } else if ($sort_by == 'number_down') { $sql .= " ORDER BY i.number DESC"; } else if ($sort_by == 'manufacturer_up') { $sql .= " ORDER BY i.manufacturer_id ASC"; } else if ($sort_by == 'manufacturer_down') { $sql .= " ORDER BY i.manufacturer_id DESC"; } else if ($sort_by == 'price_up') { $sql .= " ORDER BY ip.price_1 ASC"; } else if ($sort_by == 'price_down') { $sql .= " ORDER BY ip.price_1 DESC"; } } if ($limited) { $sql .= " LIMIT ".$this->db->real_escape_string($limitMin).", ".$this->db->real_escape_string($limitMax); } $list = array(); $result = $this->db->query($sql); $show_taxes = $this->base_object->customer_group->show_tax; while ($obj = $result->fetch_object()) { // bargain if (!$this->check_bargain_active($obj, $obj->id)) { $obj->bargain_price_1 = 0; } // get item discount $discount = $this->get_item_discount(isset($this->base_object->customer_group->id) ? intval($this->base_object->customer_group->id) : 1, $obj->manufacturer_id, $obj->structure_id); if ($discount) { $obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2); $obj->discount = $discount; $obj->discount_text = 'Rabatt!'; } // shop price $obj->tax = $this->all_tax[$obj->tax_id]->steuersatz; $obj->price_tax_text = str_replace('[tax]', number_format($obj->tax, 2, ',', '.'), isset($this->base_object->customer_group->price_tax_text) ? $this->base_object->customer_group->price_tax_text : 'inkl. [tax]% MwSt.'); $obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id]->name; $obj->manufacturer_data = isset($this->manufacturers[$obj->manufacturer_id]) ? $this->manufacturers[$obj->manufacturer_id] : null; if ($show_taxes) { $obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 4); $obj->shop_price_1 = $obj->price_1 + $obj->tax_value; $obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 4); $obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value; } else { $obj->shop_price_1 = $obj->price_1; $obj->shop_bargain_price_1 = $obj->bargain_price_1; } // get schema data $obj->schema_data_attributes = array(); if ($obj->schema_id) { $this->schema_id = $obj->schema_id; $obj->schema_data = $this->get_schema_data(); foreach ($obj->schema_data->attributes as $attribute) { if ($attribute->name) { $attr = array( 'name' => $attribute->name, 'name_en' => $attribute->name_en, 'unit' => $attribute->unit, 'value' => $obj->{'attribute_'.$attribute->number}, 'show_detail' => $attribute->show_detail, 'show_list' => $attribute->show_list, 'number' => $attribute->number ); $obj->schema_data_attributes[] = $attr; } if ($obj->schema_data->selectable_attribute_1 == $attribute->number) { $obj->schema_data->selectable_name_1 = $attribute->name; $obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number}); } if ($obj->schema_data->selectable_attribute_2 == $attribute->number) { $obj->schema_data->selectable_name_2 = $attribute->name; $obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number}); } } } // get variants? $sql = "SELECT i.*, ip.price_1, ip.bargain_price_1 FROM items i LEFT JOIN item_prices ip ON ip.item_id = i.id WHERE ip.price_1 > 0 AND i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1"; $variant_result = $this->db->query($sql); $obj->variant_structure = array(); if ($variant_result && $variant_result->num_rows > 0) { $obj->price_praefix = 'ab'; $obj->bargain_price_1 = 0; $obj->price_1 = 0; $obj->shop_price_1 = 0; $obj->shop_bargain_price_1 = 0; while ($variant_obj = $variant_result->fetch_object()) { // variants // calc tax $variant_obj->tax = $this->all_tax[$variant_obj->tax_id]->steuersatz; $variant_obj->tax_value = round($variant_obj->price_1 * ($variant_obj->tax / 100), 4); $variant_obj->price_1_tax = $variant_obj->price_1 + $variant_obj->tax_value; $variant_obj->bargain_tax_value = round($variant_obj->bargain_price_1 * ($variant_obj->tax / 100), 2); $variant_obj->bargain_price_1_tax = $variant_obj->bargain_price_1 + $variant_obj->bargain_tax_value; // shop price $variant_obj->sample_price = 0; if ($this->base_object->customer_group->show_tax) { $variant_obj->shop_price_1 = $variant_obj->price_1_tax; $variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1_tax; } else { $variant_obj->shop_price_1 = $variant_obj->price_1; $variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1; } if ($obj->shop_price_1 == 0 || $obj->shop_price_1 > $variant_obj->shop_price_1) { $obj->shop_price_1 = $variant_obj->shop_price_1; } // calc sample price $variant_obj->vpe_sampleprice_unit = $variant_obj->{'attribute_'.$obj->schema_data->base_price_field}; if ($obj->sample_unit && $variant_obj->vpe_sampleprice_unit) { if ($variant_obj->price_je_vpe) { if ($variant_obj->vpe_amount) { if ($variant_obj->shop_bargain_price_1 > 0) { $variant_obj->sample_price = $variant_obj->shop_bargain_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount); } else { $variant_obj->sample_price = $variant_obj->shop_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount); } } } else { if ($variant_obj->shop_bargain_price_1 > 0) { $variant_obj->sample_price = ($variant_obj->shop_bargain_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } else { $variant_obj->sample_price = ($variant_obj->shop_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor; } } } $obj->variant_structure[] = array( 'id' => $variant_obj->id, 'level' => 2, 'name' => $variant_obj->name, 'number' => $variant_obj->number, 'short_uri' => $variant_obj->short_uri, 'price_1' => $variant_obj->price_1, 'bargain_price_1' => $variant_obj->bargain_price_1, 'shop_price_1' => $variant_obj->shop_price_1, 'shop_bargain_price_1' => $variant_obj->shop_bargain_price_1, 'sample_price' => $variant_obj->sample_price, 'default_image_file_name' => $variant_obj->default_image_file_name, 'price_type' => $variant_obj->price_type, 'data' => $variant_obj ); // get smallest price for parent article if (!$obj->smallest_variant_price_1 || $obj->smallest_variant_price_1 > $variant_obj->price_1) { $obj->price_1 = $variant_obj->price_1; $obj->bargain_price_1 = $variant_obj->bargain_price_1; } } } if (!isset($list[$obj->id])) { $list[$obj->id] = $obj; } } return $list; } function update_last_change() { $sql = "UPDATE items SET last_change_date = NOW(), last_change_user_id=".$this->db->real_escape_string($this->base_object->customer->id)." WHERE id=".$this->db->real_escape_string($this->id); $result = $this->db->query($sql); } private function check_bargain_active($obj, $id) { if ($obj->bargain_price_type == 1) { return 1; } else if ($obj->bargain_price_type == 2) { $today = getdate(); $today = $today['year'].'-'.$today['mon'].'-'.$today['mday']; $sql = "SELECT item_types.item_type_id FROM item_types LEFT JOIN item_type_definitions ON item_type_definitions.item_type_definition_id=item_types.item_type_definition_id WHERE item_id =".$this->db->real_escape_string($id). " AND item_type_available_from <= '".$this->db->real_escape_string($today)."' AND item_type_available_until >= '".$this->db->real_escape_string($today)."' AND item_type_definitions.item_type_definition_type=1 AND item_type_definitions.item_type_definition_is_active=1"; $result = $this->db->query($sql); $found = $result->fetch_array(); if ($found) { return 1; } } return 0; } public function createIntWithTableData($html) { $int = new stdClass(); $int->geraete_table_data = $html; return $int; } private function loadWarnings($warningIdsList) { $articleWarnings = []; if ($warningIdsList) { $ids = explode(',', $warningIdsList); $placeholders = implode(',', array_fill(0, count($ids), '?')); $sqlWarn = " SELECT warning_id, name, beschreibung, bild, bildnr, bilddateiname FROM sicherheitshinweis WHERE warning_id IN ($placeholders) ORDER BY warning_id "; $stmtWarn = $this->db->prepare($sqlWarn); if ($stmtWarn) { $types = str_repeat('i', count($ids)); $stmtWarn->bind_param($types, ...$ids); $stmtWarn->execute(); $resultWarn = $stmtWarn->get_result(); $articleWarnings = $resultWarn->fetch_all(MYSQLI_ASSOC); // Bilddateiname für jede Warnung generieren foreach ($articleWarnings as &$warning) { $warning['final_bilddateiname'] = $this->generateImageFileName($warning); } } else { } } return $articleWarnings; } // Funktion zum Laden der Dokumente (umbenannt auf "SafetyInstructions") private function loadSafetyInstructions($warningDocsList) { $articleSafetyInstructions = []; // Dokumente $documentFields = [ 'Bedienungsanleitung' => 'Bedienungsanleitung', 'EU_Datenblatt' => 'EU_Datenblatt', 'Energielabel' => 'Energielabel', 'Produktdatenblatt' => 'Produktdatenblatt', 'Sicherheitsdatenblatt' => 'Sicherheitsdatenblatt', 'Zertifikat' => 'Zertifikat', 'null_feld' => 'null_feld', ]; foreach ($documentFields as $key => $field) { if (!empty($warningDocsList[$field])) { $articleSafetyInstructions[] = (object)[ 'name' => $key, 'file_name' => $warningDocsList[$field] ]; error_log("Dokument gefunden: $key = {$warningDocsList[$field]}"); } } return $articleSafetyInstructions; } // 🤖 AI SHOPPING SCHEMA METHODS private function shouldGenerateAISchema($item) { // Nur für aktive Artikel mit ID if (!$item || !isset($item->id) || !$item->active) { return false; } // Nicht für Debug-Aufrufe if (isset($_GET['debug_performance'])) { return false; } // Optional: Nur für bestimmte Kategorien // if (!$this->isRelevantForAI($item)) return false; return true; } private function generateAIShoppingSchema($item) { $python_script = dirname(__FILE__) . '/python/ai_shopping_schema_generator.py'; if (file_exists($python_script)) { $data = json_encode([ 'item_id' => $item->id, 'name' => $item->name ?? '', 'warnings' => $item->warnings ?? [], 'attributes' => $this->extractTechnicalAttributes($item), 'compatibility' => $this->getCompatibilityInfo($item), 'price' => $item->price ?? 0, 'manufacturer' => $item->manufacturer_data->name ?? '', 'category' => $item->structure_name ?? 'Ersatzteil', 'article_number' => $item->number ?? '', 'slug' => $this->generateSlug($item) ]); // Non-blocking execution - Shop-Performance bleibt unberührt! $command = "python3 " . escapeshellarg($python_script) . " " . escapeshellarg($data) . " >/dev/null 2>&1 &"; shell_exec($command); // Debug-Output (optional) if (isset($_GET['debug_ai'])) { echo "
🤖 AI SCHEMA: Generated for item {$item->id}
"; } } } private function extractTechnicalAttributes($item) { $attributes = []; // Extrahiere technische Attribute aus verfügbaren Feldern $technical_fields = [ 'attribute_1', 'attribute_2', 'attribute_3', 'attribute_4', 'attribute_5', 'attribute_6', 'attribute_7', 'attribute_8', 'attribute_9', 'attribute_10', 'manufacturer_item_number', 'ean', 'weight', 'dimensions' ]; foreach ($technical_fields as $field) { if (isset($item->$field) && !empty($item->$field)) { $attributes[$field] = $item->$field; } } return $attributes; } private function getCompatibilityInfo($item) { $compatibility = []; // Herstellerinformationen if (isset($item->manufacturer_data)) { $compatibility['manufacturer'] = $item->manufacturer_data->name ?? ''; } // Kategorieinfo if (isset($item->structure_name)) { $compatibility['category'] = $item->structure_name; } // EAN für Kompatibilitäts-Matching if (isset($item->ean) && !empty($item->ean)) { $compatibility['ean'] = $item->ean; } return $compatibility; } private function generateSlug($item) { $name = $item->name ?? ''; $slug = strtolower($name); $slug = preg_replace('/[^a-z0-9\s-]/', '', $slug); $slug = preg_replace('/\s+/', '-', trim($slug)); return substr($slug, 0, 50); } /** * 🐍 Python Smart Price Update Service * Verhindert 50+ einzelne REPLACE INTO Abfragen */ private function callPythonPriceService($priceData) { try { $python_script = __DIR__ . '/../modules/import/price_update_service.py'; if (!file_exists($python_script)) { return false; // Kein Python Service verfügbar } $service_data = [ 'action' => 'update_prices', 'item_id' => $this->id, 'prices' => $priceData['prices'] ?? [] ]; $json_input = escapeshellarg(json_encode($service_data, JSON_UNESCAPED_UNICODE)); $command = "python3 {$python_script} {$json_input} 2>&1"; $output = shell_exec($command); $result = json_decode($output, true); if (isset($_GET['debug_performance']) && $result) { echo "
🐍 Python Output: " . htmlspecialchars($output) . "
"; } return $result; } catch (Exception $e) { error_log("Python Price Service Error: " . $e->getMessage()); return false; // Fallback zu PHP } } /** * 🚀 ASYNC Image Processing - verhindert 504 Timeouts! * Startet Python Image Service im Hintergrund (NON-BLOCKING!) */ private function startAsyncImageProcessing($source_file, $file_name, $item_id, $watermark_enabled = false) { try { $python_script = __DIR__ . '/../modules/import/image_processing_service.py'; // Fallback zu PHP wenn kein Python Service verfügbar if (!file_exists($python_script)) { error_log("Python Image Service not found, using PHP fallback"); return $this->processPHPImageFallback($source_file, $file_name, $watermark_enabled); } // Prepare service data $service_data = [ 'source_file' => $source_file, 'item_id' => $item_id, 'watermark' => $watermark_enabled ? 1 : 0, 'shop_system' => SHOP_SYSTEM, 'document_root' => $_SERVER['DOCUMENT_ROOT'], 'image_sizes' => $this->base_object->config->shopConfiguration['images'] ]; $json_input = escapeshellarg(json_encode($service_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); // 🔥 NON-BLOCKING EXECUTION: Run Python in background with nohup // Output redirected to log file, process detached with & $log_file = $_SERVER['DOCUMENT_ROOT'] . "/logs" . "/image_processing_{$item_id}.log"; $command = "nohup python3 {$python_script} {$json_input} > {$log_file} 2>&1 &"; // Windows compatibility check if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { // Windows: use START /B for background execution $command = "start /B python {$python_script} {$json_input} > {$log_file} 2>&1"; } // Execute NON-BLOCKING command if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { exec($command); } else { $cmd_wrapped = "( $command ) > /dev/null 2>&1"; shell_exec($cmd_wrapped); } if (isset($_GET['debug_performance'])) { echo '
🚀 Async Python Image Service gestartet (non-blocking) - Log: ' . $log_file . '
'; } return true; } catch (Exception $e) { error_log("Async Image Processing Error: " . $e->getMessage()); // Fallback zu PHP bei Fehler return $this->processPHPImageFallback($source_file, $file_name, $watermark_enabled); } } /** * PHP Fallback für Image Processing (wenn Python nicht verfügbar) * ACHTUNG: Kann 504 Timeouts verursachen bei großen Bildern! */ private function processPHPImageFallback($targetFile, $file_name, $watermark_activ = false) { try { if (isset($_GET['debug_performance'])) { $start_time = microtime(true); echo '
⚠️ Python nicht verfügbar - PHP Fallback wird verwendet (kann langsam sein)
'; } // resize max image size $imaginator = new phImaginator(); $imaginator->add($targetFile); $imaginator->Resize_fitBoth('800', '800'); $imaginator->save(); // create 4 scaled down images if (class_exists('Imagick')) { foreach ($this->base_object->config->shopConfiguration['images'] as $pair) { $image = new Imagick($targetFile); $image->thumbnailImage($pair[1], $pair[1]); $image->setImageFileName(dirname($targetFile) . '/' . $pair[0] . basename($targetFile)); $image->writeImage(); $image->destroy(); } } // set watermark if ($watermark_activ && $this->base_object->config->shopConfiguration['item_watermark_image']) { $this->watermark($targetFile); } // resize image (additional sizes) if (isset($this->base_object->config->shopConfiguration['images'])) { foreach ($this->base_object->config->shopConfiguration['images'] as $image) { $image_name = $image[0]; $size = $image[1]; $imaginator = new phImaginator(); $imaginator->add($targetFile); $imaginator->Resize_fitBoth($size, $size); $imaginator->nameAdd($image_name); $imaginator->save(); } } if (isset($_GET['debug_performance'])) { $end_time = microtime(true); $execution_time = ($end_time - $start_time) * 1000; echo '
PHP Fallback completed: ' . number_format($execution_time, 2) . 'ms
'; } return true; } catch (Exception $e) { error_log("PHP Image Fallback Error: " . $e->getMessage()); return false; } } } ?>