diff --git a/import-drewmax.php b/import-drewmax.php index 301dec2c..43a839d0 100644 --- a/import-drewmax.php +++ b/import-drewmax.php @@ -8,11 +8,12 @@ include(dirname(__FILE__).'/init.php'); $context = Context::getContext(); // Sprawdzenie trybu działania na podstawie parametrów URL -$modeAdd = (Tools::getValue('add') === 'true'); +$modeAdd = (Tools::getValue('add') === 'true'); $modeUpdate = (Tools::getValue('update') === 'true'); +$modeSynch = (Tools::getValue('synch') === 'true'); -if (!$modeAdd && !$modeUpdate) { - die('Brak akcji. Dodaj do adresu ?add=true lub ?update=true'); +if (!$modeAdd && !$modeUpdate && !$modeSynch) { + die('Brak akcji. Dodaj do adresu ?add=true lub ?update=true lub ?synch=true'); } // Plik logu aktualizacji cen @@ -298,6 +299,18 @@ function getTaxRulesGroupIdForRate($rate, $id_country = null) { return $id ? (int)$id : 0; } +// Zwraca główny produkt z grupy – pierwszy, którego SKU istnieje w PrestaShop +function findMainProductDataFromGroup($products) { + foreach ($products as $p) { + $ref = (string)$p->sku; + if ($ref !== '' && findProductByReference($ref)) { + return $p; // to główny produkt + } + } + return null; +} + + // === GRUPOWANIE PRODUKTÓW PO SYMBOLU === $productsBySymbol = []; foreach ($xml->product as $productData) { @@ -337,13 +350,20 @@ if ($modeUpdate) { $updatedSomething = false; + foreach ($productsBySymbol as $symbol => $products) { if (empty($products)) { continue; } // Główny produkt – referencja z pierwszego elementu grupy - $mainProductData = $products[0]; + // $mainProductData = $products[0]; + // $reference = (string)$mainProductData->sku; + // $key = 'product_'.$reference; + $mainProductData = findMainProductDataFromGroup($products); + if (!$mainProductData) { + continue; // w grupie nie ma produktu, który istnieje w Presta + } $reference = (string)$mainProductData->sku; $key = 'product_'.$reference; @@ -491,157 +511,338 @@ if ($modeUpdate) { // ======================================= // =========== TRYB DODAWANIA ============ // ======================================= +if ($modeAdd) { + $productAdded = false; + $combinationAdded = false; -$productAdded = false; -$combinationAdded = false; - -// Tworzenie lub aktualizacja produktów z kombinacjami (dodawanie) -foreach ($productsBySymbol as $symbol => $products) { - if (empty($products)) { - continue; - } - - // Główny produkt – dane z pierwszego w grupie - $mainProductData = $products[0]; - $mainProduct = findProductByReference((string)$mainProductData->sku); - - // BAZA: najtańszy wariant w grupie (brutto i netto) - list($grossBase, $netPrice) = getBasePricesFromGroup($products); - - if (!$mainProduct) { - // Create a new product if it doesn't exist - $mainProduct = new Product(); - $mainProduct->name = createMultiLangField((string)$mainProductData->title); - - $description = (string)$mainProductData->description; - $description = str_replace("\n", "
", $description); - $mainProduct->description = createMultiLangField($description); - - // Cena BRUTTO z XML -> NETTO (23%) – bazą jest najtańszy wariant - $mainProduct->price = $netPrice > 0 ? $netPrice : 0; - - // VAT 23% jeśli dostępny - if (!empty($idTaxRulesGroup23)) { - $mainProduct->id_tax_rules_group = (int)$idTaxRulesGroup23; + // Tworzenie lub aktualizacja produktów z kombinacjami (dodawanie) + foreach ($productsBySymbol as $symbol => $products) { + if (empty($products)) { + continue; } - // Produkt aktywny + delivery times - $mainProduct->active = 1; - $mainProduct->delivery_in_stock = createMultiLangField('2-7 dni roboczych'); - $mainProduct->delivery_out_stock = createMultiLangField('4-10 tygodni'); + // ===== Filter item_group_id ===== + // $mainProductDataTemp = $products[0]; + // if ((string)$mainProductDataTemp->item_group_id !== '68590') { + // continue; + // } - $mainProduct->reference = (string)$mainProductData->sku; - $mainProduct->id_category_default = 2; // np. Strona główna - $mainProduct->link_rewrite = createLinkRewrite((string)$mainProductData->title); - $mainProduct->add(); - - // Add images to the product - if (!empty($mainProductData->image)) { - addProductImage($mainProduct->id, (string)$mainProductData->image); + // Główny produkt – dane z pierwszego w grupie + // $mainProductData = $products[0]; + // $mainProduct = findProductByReference((string)$mainProductData->sku); + $mainProductData = findMainProductDataFromGroup($products); + if (!$mainProductData) { + $mainProductData = $products[0]; // fallback na etapie dodawania } + $mainProduct = findProductByReference((string)$mainProductData->sku); - for ($i = 1; $i <= 10; $i++) { - $imageUrl = (string)$mainProductData->{'images_' . $i}; - if (!empty($imageUrl)) { - addProductImage($mainProduct->id, $imageUrl); + // BAZA: najtańszy wariant w grupie (brutto i netto) + list($grossBase, $netPrice) = getBasePricesFromGroup($products); + + if (!$mainProduct) { + // Create a new product if it doesn't exist + $mainProduct = new Product(); + $mainProduct->name = createMultiLangField((string)$mainProductData->title); + + $description = (string)$mainProductData->description; + $description = str_replace("\n", "
", $description); + $mainProduct->description = createMultiLangField($description); + + // Cena BRUTTO z XML -> NETTO (23%) – bazą jest najtańszy wariant + $mainProduct->price = $netPrice > 0 ? $netPrice : 0; + + // VAT 23% jeśli dostępny + if (!empty($idTaxRulesGroup23)) { + $mainProduct->id_tax_rules_group = (int)$idTaxRulesGroup23; } - } - $productAdded = true; - } + // Produkt aktywny + delivery times + $mainProduct->active = 1; + $mainProduct->delivery_in_stock = createMultiLangField('2-7 dni roboczych'); + $mainProduct->delivery_out_stock = createMultiLangField('4-10 tygodni'); - // Ensure the product is saved before adding combinations - if (!$mainProduct->id) { - echo "Failed to create or update main product: " . (string)$mainProductData->title . "\n"; - continue; - } + $mainProduct->reference = (string)$mainProductData->sku; + $mainProduct->id_category_default = 107; // np. Meble + $mainProduct->link_rewrite = createLinkRewrite((string)$mainProductData->title); + $mainProduct->add(); - // Ensure the combination set is unique for the product - $addedCombinations = []; + // ===== Poprawne przypisanie kategorii ===== + $id_lang = (int)$context->language->id; + $defaultCategory = new Category($mainProduct->id_category_default, $id_lang); - // Add or update combinations for each product in the group - foreach ($products as $productData) { - $attributes = [ - 'Kolor' => (string)$productData->Kolor, - 'Dlugosc' => (string)$productData->Dlugosc, - 'Szerokosc' => (string)$productData->Szerokosc, - 'Glebokosc' => (string)$productData->Glebokosc, - 'Wysokosc' => (string)$productData->Wysokosc, - ]; + if (Validate::isLoadedObject($defaultCategory) && $defaultCategory->name == 'Strona główna') { + $newCategoryId = 107; // Meble + $mainProduct->id_category_default = (int)$newCategoryId; - $attributeIds = []; - foreach ($attributes as $name => $value) { - if (!empty($value)) { - $attributeGroupId = createAttribute($name, [$value]); - $attribute = findAttributeByName($attributeGroupId, $value); - if ($attribute) { - $attributeIds[] = (int)$attribute->id; + // Podmieniamy kategorie produktu (zachowując inne) + $categories = $mainProduct->getCategories(); + $categories = array_diff($categories, [(int)$defaultCategory->id]); + $categories[] = (int)$newCategoryId; + $categories = array_unique(array_map('intval', $categories)); + $mainProduct->updateCategories($categories); + } + // ===== Koniec ustawienia kategorii ===== + + // Add images to the product + if (!empty($mainProductData->image)) { + addProductImage($mainProduct->id, (string)$mainProductData->image); + } + + for ($i = 1; $i <= 10; $i++) { + $imageUrl = (string)$mainProductData->{'images_' . $i}; + if (!empty($imageUrl)) { + addProductImage($mainProduct->id, $imageUrl); } } + + $productAdded = true; } - // Create a unique key for the attribute set - sort($attributeIds); - $key = implode('-', $attributeIds); + // Ensure the product is saved before adding combinations + if (!$mainProduct->id) { + echo "Failed to create or update main product: " . (string)$mainProductData->title . "\n"; + continue; + } - // Add or update combination if it is unique - if (!empty($attributeIds) && !isset($addedCombinations[$key])) { - $combination = findCombinationByAttributes($mainProduct->id, $attributeIds); - if (!$combination) { - // Create new combination - $combination = new Combination(); - $combination->id_product = (int)$mainProduct->id; - $combination->quantity = 100; // startowo, i tak zaraz nadpiszemy StockAvailable - $combination->reference = (string)$productData->sku; - $combination->add(); - $combination->setAttributes($attributeIds); - $combination->save(); - $combinationAdded = true; - } else { - // Update existing combination quantity if necessary - $combination->quantity = 100; // startowo - $combination->update(); + // Ensure the combination set is unique for the product + $addedCombinations = []; + + // Add or update combinations for each product in the group + foreach ($products as $productData) { + $attributes = [ + 'Kolor' => (string)$productData->Kolor, + 'Dlugosc' => (string)$productData->Dlugosc, + 'Szerokosc' => (string)$productData->Szerokosc, + 'Glebokosc' => (string)$productData->Glebokosc, + 'Wysokosc' => (string)$productData->Wysokosc, + ]; + + $attributeIds = []; + foreach ($attributes as $name => $value) { + if (!empty($value)) { + $attributeGroupId = createAttribute($name, [$value]); + $attribute = findAttributeByName($attributeGroupId, $value); + if ($attribute) { + $attributeIds[] = (int)$attribute->id; + } + } } - // Mark this combination as added - $addedCombinations[$key] = true; + // Create a unique key for the attribute set + sort($attributeIds); + $key = implode('-', $attributeIds); + + // Add or update combination if it is unique + if (!empty($attributeIds) && !isset($addedCombinations[$key])) { + $combination = findCombinationByAttributes($mainProduct->id, $attributeIds); + if (!$combination) { + // Create new combination + $combination = new Combination(); + $combination->id_product = (int)$mainProduct->id; + $combination->quantity = 100; // startowo, i tak zaraz nadpiszemy StockAvailable + $combination->reference = (string)$productData->sku; + $combination->add(); + $combination->setAttributes($attributeIds); + $combination->save(); + $combinationAdded = true; + } else { + // Update existing combination quantity if necessary + $combination->quantity = 100; // startowo + $combination->update(); + } + + // Mark this combination as added + $addedCombinations[$key] = true; + } + + if ($combinationAdded) { + break; // Break if a new combination was added + } } - if ($combinationAdded) { - break; // Break if a new combination was added + // --- STANY MAGAZYNOWE PRODUKTU (ID_PRODUCT_ATTRIBUTE = 0) --- + $mainStatus = (string)$mainProductData->Status_magazynowy; + $mainQty = ($mainStatus === 'instock') ? 100 : 0; + StockAvailable::setQuantity($mainProduct->id, 0, $mainQty); + + // --- STANY MAGAZYNOWE KOMBINACJI --- + foreach ($products as $productDataVariant) { + $variantRef = (string)$productDataVariant->sku; + $variantStatus = (string)$productDataVariant->Status_magazynowy; + $variantQty = ($variantStatus === 'instock') ? 100 : 0; + + $combination = findCombinationByReference($mainProduct->id, $variantRef); + if ($combination) { + StockAvailable::setQuantity($mainProduct->id, $combination->id, $variantQty); + } + } + + // Ensure the product has combinations enabled + $mainProduct->checkDefaultAttributes(); + Product::updateDefaultAttribute($mainProduct->id); + + if ($productAdded || $combinationAdded) { + if ($productAdded) { + echo "

Dodałem produkt: " . htmlspecialchars((string)$mainProductData->title) . "

"; + } + if ($combinationAdded) { + echo "

Dodałem kombinację: " . htmlspecialchars((string)$mainProductData->title) . "

"; + } + break; // Break if a new product or combination was added } } +} - // --- STANY MAGAZYNOWE PRODUKTU (ID_PRODUCT_ATTRIBUTE = 0) --- - $mainStatus = (string)$mainProductData->Status_magazynowy; - $mainQty = ($mainStatus === 'instock') ? 100 : 0; - StockAvailable::setQuantity($mainProduct->id, 0, $mainQty); +// ======================================= +// ========= TRYB SYNCHRONIZACJI ========= +// ======================================= +if ($modeSynch) { + echo '

Rozpoczynam synchronizację produktów...

'; - // --- STANY MAGAZYNOWE KOMBINACJI --- - foreach ($products as $productDataVariant) { - $variantRef = (string)$productDataVariant->sku; - $variantStatus = (string)$productDataVariant->Status_magazynowy; - $variantQty = ($variantStatus === 'instock') ? 100 : 0; + $db = Db::getInstance(); - $combination = findCombinationByReference($mainProduct->id, $variantRef); - if ($combination) { - StockAvailable::setQuantity($mainProduct->id, $combination->id, $variantQty); - } + // 1. Wyczyszczenie tymczasowej tabeli + $db->execute('TRUNCATE TABLE `'._DB_PREFIX_.'drewmax_products_temp`'); + + // 1.1 Wczytywanie SKU z XML i dodawanie do tymczasowej tabeli + $skusInXml = []; + foreach ($xml->product as $productData) { + $sku = trim((string)$productData->sku); + if ($sku === '') continue; + + $skusInXml[] = $sku; + + $db->execute(' + INSERT INTO `'._DB_PREFIX_.'drewmax_products_temp` (`sku`, `date_checked`) + VALUES (\''.pSQL($sku).'\', NOW()) + '); } - // Ensure the product has combinations enabled - $mainProduct->checkDefaultAttributes(); - Product::updateDefaultAttribute($mainProduct->id); + // 2. Praca z historią + if (!empty($skusInXml)) { + // Utworzenie listy SKU dla SQL + $skusList = "'" . implode("','", array_map('pSQL', $skusInXml)) . "'"; - if ($productAdded || $combinationAdded) { - if ($productAdded) { - echo "

Dodałem produkt: " . htmlspecialchars((string)$mainProductData->title) . "

"; - } - if ($combinationAdded) { - echo "

Dodałem kombinację: " . htmlspecialchars((string)$mainProductData->title) . "

"; - } - break; // Break if a new product or combination was added + // 2.1 Dodawanie nowych SKU do historii lub przywracanie aktywności + $sqlInsert = ' + INSERT INTO `'._DB_PREFIX_.'drewmax_products_history` (`sku`, `active`) + SELECT t.sku, 1 + FROM `'._DB_PREFIX_.'drewmax_products_temp` t + LEFT JOIN `'._DB_PREFIX_.'drewmax_products_history` h ON h.sku = t.sku + WHERE h.sku IS NULL + '; + $db->execute($sqlInsert); + + $sqlUpdateActive = ' + UPDATE `'._DB_PREFIX_.'drewmax_products_history` h + JOIN `'._DB_PREFIX_.'drewmax_products_temp` t ON h.sku = t.sku + SET h.active = 1 + WHERE h.active = 0 + '; + $db->execute($sqlUpdateActive); } + + // 2.2 Wykluczanie produktów, których nie ma w temp + $sqlDeactivate = ' + UPDATE `'._DB_PREFIX_.'drewmax_products_history` h + LEFT JOIN `'._DB_PREFIX_.'drewmax_products_temp` t ON h.sku = t.sku + SET h.active = 0 + WHERE t.sku IS NULL AND h.active = 1 + '; + $db->execute($sqlDeactivate); + + // Wyłącz produkty w PrestaShop dla SKU, które mają active=0 + $skusToDisable = $db->executeS(' + SELECT sku FROM `'._DB_PREFIX_.'drewmax_products_history` + WHERE active = 0 + '); + + // 3. Synchronizacja statusu produktów i kombinacji w PrestaShop + // Pobieramy tylko SKU z historii (źródło prawdy) + $allHistory = $db->executeS(' + SELECT sku, active + FROM `'._DB_PREFIX_.'drewmax_products_history` + '); + + foreach ($allHistory as $row) { + $sku = trim($row['sku']); + $activeStatus = (int)$row['active']; + + if ($sku === '') { + continue; + } + + /** + * KROK 3.1 + * Sprawdzenie czy SKU jest GŁÓWNYM PRODUKTEM + * (tylko ps_product.reference) + */ + $idProduct = (int)$db->getValue(' + SELECT id_product + FROM `'._DB_PREFIX_.'product` + WHERE reference = \''.pSQL($sku).'\' + LIMIT 1 + '); + + if ($idProduct > 0) { + // === GŁÓWNY PRODUKT === + $product = new Product($idProduct); + + if (!Validate::isLoadedObject($product)) { + continue; + } + + if ($activeStatus === 0 && (int)$product->active === 1) { + // Wyłącz produkt + $product->active = 0; + $product->update(); + echo "Wyłączono PRODUKT: {$sku}
"; + } + + if ($activeStatus === 1 && (int)$product->active === 0) { + // Włącz produkt + $product->active = 1; + $product->update(); + echo "Włączono PRODUKT: {$sku}
"; + } + + // Główny produkt obsłużony → NIE sprawdzamy kombinacji + continue; + } + + /** + * KROK 3.2 + * Jeśli NIE jest produktem → sprawdzamy czy to KOMBINACJA + */ + $combinationRow = $db->getRow(' + SELECT id_product_attribute, id_product + FROM `'._DB_PREFIX_.'product_attribute` + WHERE reference = \''.pSQL($sku).'\' + LIMIT 1 + '); + + if ($combinationRow) { + // === KOMBINACJA === + if ($activeStatus === 0) { + $idProductAttribute = (int)$combinationRow['id_product_attribute']; + + $combination = new Combination($idProductAttribute); + if (Validate::isLoadedObject($combination)) { + $combination->delete(); + echo "Usunięto KOMBINACJĘ: {$sku} (ID: {$idProductAttribute})
"; + } + } + + // Jeśli active = 1 → NIC NIE ROBIMY (kombinacji się nie aktywuje) + continue; + } + + /** + * KROK 3.3 + * SKU nie istnieje w PrestaShop → ignorujemy + */ + } + echo '

Synchronizacja zakończona.

'; } // reload page after 250ms if product or combination was added (dla trybu add) @@ -649,4 +850,4 @@ if ($productAdded || $combinationAdded) { // echo ""; } -?> +?> \ No newline at end of file