Czyli wykonanie po prostu importu. Można oczywiście zrobić plik CSV na podstawie dokumentacji. Jednak może być to karkołomne zadanie, jeśli ktoś widział jak wygląda taki plik (pobierz spakowany plik przykładowy CSV: combinations_import.csv)… Dodatkowo ze świeczką szukać modułu (nawet płatnego) do Presta Shop 1.3-1.4 który automatycznie wygeneruje taki arkusz.
Nasz sposób będzie wykonywany na poziomie bazy danych MySQL. Zupełnie poza zapleczem sklepu (no chyba żeby na końcu sprawdzić czy działa). Więc posiadanie dostępu do narzędzia PhpMyAdmin będzie bardzo wskazane. Dla obu baz – starej i nowej.
Idea jest taka, że tak przebudowujemy zawartość starej bazy z wersji sklepu 1.3-1.4 aby tabele uzyskały wygląd identyczny jak w 1.6.x do której następnie je po prostu zaimportujemy.
Metoda powinna działać także dla przyszłych wersji Presta Shop (na pewno w milestone 1.6) o ile twórcy tego oprogramowania nie zmienią zupełnie idei atrybutów na tej platformie.
Zawartość artykułu
Założenia
- Produkty w nowym (1.6.x) sklepie już zostały zaimportowane ze starego sklepu (1.3-1.4) przy pomocy np. tego darmowego narzędzia: pobierz darmowy moduł csvexport dla Presta Shop 1.4. Nie mają one na razie żadnych atrybutów a obecne w sklepie grupy atrybutów i ich wartości są domyślne i możemy je w całości usunąć. Uwaga! Za pomocą tego modułu nie będziemy importować grup atrybutów (nie ma on po za tym takich możliwości). Importujemy jedynie produkty.
- Produkty podczas importu mają narzucone poprzednie numery ID – poprzez zaznaczenie tych opcji Tego nie przeskoczymy (No chyba, że wykonamy jakieś mapowanie tych numerów ID. Jednak może być to dość trudne w wykonaniu i wymagało by przebudowania naszej metody).
- Ponadto na nowym sklepie wszystkie zastane kombinacje zostaną (tak jak wspomniano wyżej) usunięte. Czyli zaleca się stosować tą metodę dla nowych sklepów gdzie jeszcze nie ma atrybutów lub te które są mogą być w całości usunięte.
- Potrzebujemy 2 osobne bazy danych. „starą” i „nową„. Czyli odpowiednio w wersji 1.3-1.4 i 1.6.x. Będziemy używać tej konwencji w dalszej części artykułu.
- Wszędzie w zapytaniach używamy domyślnego prefixu w nazwach tabel „ps_„. Jeśli Twoje tabele mają inny musisz to uwzględnić inaczej (co logiczne) zapytania SQL nic Ci nie dadzą.
- Jeśli chodzi o Multi Store na sklepie w wersji 1.6.x uwzględniamy tylko 1 sklep i ma on ID = 1. Jeśli import ma być wykonany dla innego sklepu – może wiązać się to z dodatkowymi pracami programistycznymi – prosimy wtedy o kontakt.
- Jeśli chodzi o języki w sklepach:
- Stary sklep ma 6 języków. Gdzie język angielski ma identyfikator o ID=1 a polski ID=6. Inne nas nie interesują i nie będą one brane pod uwagę. Zostaną wręcz usunięte.
- Nowy sklep ma 2 języki: polski ID=1, angielski ID=2
UWAGA! U Ciebie ID języków mogą być inne i należy to uwzględnić.
Tyle założeń, pasuje jeszcze to napisać:
Przed przystąpieniem do prac wykonaj koniecznie kopię bezpieczeństwa obu baz danych. To nic nie kosztuje a prędzej czy później mogą Ci się przydać…
Do dzieła!
Wprowadzenie różnic w strukturze tabel
Nowa wersja Presta Shop posiada w zasadzie te same tabele na których nam zależy, jednak różnią się one ilością kolumn i ich typami. Należy je ujednolicić. Wykonujemy to w starej bazie danych:
Tabela ps_attribute:
ALTER TABLE `ps_attribute` ADD `position` INT( 10 ) NOT NULL ;
Tutaj mały komentarz:
Jak widzimy – doszło tutaj nowe pole „position„. Domyślnie wszystkie wartości w tej tabeli będą ustawione na: 0. Prawdopodobnie Presta Shop odpowiednio je wypełni lub nie będzie to wpływało na pracę systemu. Jednak gdy się tak nie stanie należy w sposób ręczny lub przy pomocy pomocniczego pliku CSV wypełnić te pola aby narastały w porządku wartości kolumny id_attribute_group – zobacz obrazek
Tabela ps_attribute_group:
ALTER TABLE `ps_attribute_group` ADD `group_type` ENUM( 'select', 'radio', 'color', '' ) NOT NULL , ADD `position` INT( 10 ) NOT NULL ;
Z kolei to pole „position” powinno narastać od 0 do wartości takiej jak ilość wierszy w tej tabeli. Należy albo wypełnić tą kolumnę ręcznie albo liczyć na to, że Presta Shop to skoryguje (jest szansa że tak się stanie, niestety tego nie sprawdzaliśmy).
Tabela ps_attribute_impact:
ALTER TABLE `ps_attribute_impact` CHANGE `weight` `weight` DECIMAL( 20, 6 ) NOT NULL ;
Tabela ps_product_attribute:
(radzimy każde zapytanie – są one oddzielone średnikami – realizować osobno)
ALTER TABLE `ps_product_attribute` CHANGE `weight` `weight` DECIMAL( 20, 6 ) NOT NULL DEFAULT '0';
ALTER TABLE `ps_product_attribute` ADD `available_date` DATE NOT NULL ;
ALTER TABLE `ps_product_attribute` CHANGE `unit_price_impact` `unit_price_impact` DECIMAL( 20, 6 ) NOT NULL DEFAULT '0.00', CHANGE `default_on` `default_on` TINYINT( 1 ) UNSIGNED NULL DEFAULT NULL ;
Jeśli powyższe zapytanie zwórci błąd nakleży dodać to pole:
ALTER TABLE `ps_product_attribute` ADD `unit_price_impact` DECIMAL( 20, 6 ) NOT NULL ;
W przypadku nowszych wersji z gałęzi Presta Shop 1.6.x (np. 1.6.1.17) należy dodać jeszcze to pole:
ALTER TABLE `ps_product_attribute` ADD `upc` VARCHAR( 12 ) NOT NULL ;
Bez wykonania tej czynności może występować problem z dodawaniem do koszyka. Karta zamówienia jest wtedy pusta i suma zamówienia to zero.
Dodanie nowych tabel
Wersja 1.3-1.4 nie obsługiwała funkcji Multi Store. W związku z tym pojawiają się nowe tabele, które musimy dodać. Tworzymy je z tej przyczyny, że w dalszych pracach będziemy do nich kopiować wymagane dane. Operujemy w dalszym ciągu na starej bazie danych:
Tabela ps_attribute_group_shop:
CREATE TABLE IF NOT EXISTS `ps_attribute_group_shop` ( `id_attribute_group` int(11) unsigned NOT NULL, `id_shop` int(11) unsigned NOT NULL, PRIMARY KEY (`id_attribute_group`,`id_shop`), KEY `id_shop` (`id_shop`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Tabela ps_attribute_shop:
CREATE TABLE IF NOT EXISTS `ps_attribute_shop` ( `id_attribute` int(11) unsigned NOT NULL, `id_shop` int(11) unsigned NOT NULL, PRIMARY KEY (`id_attribute`,`id_shop`), KEY `id_shop` (`id_shop`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Tabela ps_product_attribute_shop:
CREATE TABLE IF NOT EXISTS `ps_product_attribute_shop` ( `id_product` int(10) unsigned NOT NULL, `id_product_attribute` int(10) unsigned NOT NULL, `id_shop` int(10) unsigned NOT NULL, `wholesale_price` decimal(20,6) NOT NULL DEFAULT '0.000000', `price` decimal(20,6) NOT NULL DEFAULT '0.000000', `ecotax` decimal(17,6) NOT NULL DEFAULT '0.000000', `weight` decimal(20,6) NOT NULL DEFAULT '0.000000', `unit_price_impact` decimal(20,6) NOT NULL DEFAULT '0.000000', `default_on` tinyint(1) unsigned DEFAULT NULL, `minimal_quantity` int(10) unsigned NOT NULL DEFAULT '1', `available_date` date NOT NULL DEFAULT '0000-00-00', PRIMARY KEY (`id_product_attribute`,`id_shop`), UNIQUE KEY `id_product` (`id_product`,`id_shop`,`default_on`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Zapełnie treścią dodatkowych tabel
Nowe tabele w starej bazie danych musimy zapełnić treścią wg. wymagań dokumentacji Presta Shop 1.6. Dla pewności że „autoincremetnowane” pola (których wartości liczbowe są tworzone automatycznie poprzez zwiększanie wartości o +1) będą mieć takie wartości na jakich nam zależy przed wypełnieniem – czyścimy tabele poleceniem truncate:
Wypełnienie tabeli ps_attribute_group_shop:
TRUNCATE ps_attribute_group_shop; INSERT INTO `ps_attribute_group_shop`(`id_attribute_group`) SELECT id_attribute_group FROM ps_attribute_group; UPDATE `ps_attribute_group_shop` SET `id_shop` = 1;
Wypełnienie ps_attribute_shop:
TRUNCATE ps_attribute_shop; INSERT INTO `ps_attribute_shop`(`id_attribute`) SELECT id_attribute FROM ps_attribute; UPDATE `ps_attribute_shop` SET `id_shop` = 1;
Wypełnienie ps_product_attribute_shop:
(radzimy każde zapytanie – są one oddzielone średnikami – realizować osobno)
TRUNCATE ps_product_attribute_shop;
ALTER TABLE ps_product_attribute_shop DROP INDEX id_product;
INSERT INTO `ps_product_attribute_shop`(`id_product`,`id_product_attribute`,`wholesale_price`,`price`,`ecotax`,`weight`,`unit_price_impact`,`default_on`,`minimal_quantity`,`available_date`) SELECT `id_product`,`id_product_attribute`,`wholesale_price`,`price`,`ecotax`,`weight`,`unit_price_impact`,`default_on`,`minimal_quantity`,`available_date` FROM ps_product_attribute;
Jeśli powyższe zapytanie wywoła błąd należy dodać to pole i ponowić w/w zapytanie:
ALTER TABLE `ps_product_attribute` ADD `minimal_quantity` int(10) NOT NULL ;
UPDATE `ps_product_attribute_shop` SET `id_shop` = 1;
UPDATE `ps_product_attribute_shop` SET `default_on` = NULL WHERE `default_on` = 0;
ALTER TABLE `ps_product_attribute_shop` ADD UNIQUE `id_product` (`id_product`, `id_shop`, `default_on`);
Usunięcie niepotrzebnych wpisów językowych
ID języków określiliśmy na początku tego artykułu – Założenia pkt. 7.
Należy teraz tak ustawić wpisy w tabelach odpowiedzialnych za atrybuty (dalej w starej bazie) aby odpowiednio ustawić te indeksy.
Ogólnie usuwamy w starej bazie języki które nie są oznaczone jako polski lub angielski. Czyli w naszym przypadku języki o ID 2,3,4,5 są usuwane, a ID języka polskiego i angielskiego zmienione na takie jak są w nowej bazie.
W Twoim przypadku ID języków w nowej i w starej bazie mogą być inne i musisz to uwzględnić.
Tabela ps_attribute_group_lang:
DELETE FROM `ps_attribute_group_lang` WHERE `id_lang` IN (2,3,4,5); UPDATE `ps_attribute_group_lang` SET `id_lang` = 2 WHERE `id_lang`= 1; UPDATE `ps_attribute_group_lang` SET `id_lang` = 1 WHERE `id_lang`= 6;
Tabela ps_attribute_lang:
DELETE FROM `ps_attribute_lang` WHERE `id_lang` IN (2,3,4,5); UPDATE `ps_attribute_lang` SET `id_lang` = 2 WHERE `id_lang`= 1; UPDATE `ps_attribute_lang` SET `id_lang` = 1 WHERE `id_lang`= 6;
Przykład z innymi ID języków:
Jeśli w starej bazie mamy 3 języki:
- ID = 1 – angielski
- ID = 2 – francuski
- ID = 3 – polski
Natomiast na nowym sklepie 6 języków:
- ID = 1 – angielski
- ID = 2 – niemiecki
- ID = 3 – rosyjski
- ID = 4 – hiszpański
- ID = 5 – francuski
- ID = 6 – polski
W/w zapytania będą miały taką formę:
Usuwanie innych języków niż polski i angielski:
DELETE FROM `ps_attribute_group_lang` WHERE `id_lang` IN (2); DELETE FROM `ps_attribute_lang` WHERE `id_lang` IN (2);
(Jeśli chcemy zachować język francuski nie usuwamy tego języka)
Angielski ma taki sam ID – nie zmieniamy go.
Francuski (jeśli chcemy go zachować):
UPDATE `ps_attribute_group_lang` SET `id_lang` = 5 WHERE `id_lang`= 2; UPDATE `ps_attribute_lang` SET `id_lang` = 5 WHERE `id_lang`= 2;
Polski – analogicznie:
UPDATE `ps_attribute_group_lang` SET `id_lang` = 6 WHERE `id_lang`= 3; UPDATE `ps_attribute_lang` SET `id_lang` = 6 WHERE `id_lang`= 3;
Export i import
Gotowe! Teraz należy wyexportować (w PhpMyAdmin należy kliknąć zakładkę Export i na liście tabel w opcji rozszerzonej zaznaczyć wybrane z wciśniętym klawiszem CTRL) ze starej bazy tabele wraz z zawartością.
Czyli tak naprawdę należy wyeksportować wszystkie tabele z ’attribute’ w nazwie. Następnie taki zrzut tabel musimy zaimportować do nowej bazy danych nadpisując tamte lub uprzednio usuwając:
ps_attribute; ps_attribute_group; ps_attribute_group_lang; ps_attribute_group_shop; ps_attribute_impact; ps_attribute_lang; ps_attribute_shop; ps_product_attribute: ps_product_attribute_combination; ps_product_attribute_image; ps_product_attribute_shop;
UWAGA! Przed wgraniem zrzutu do nowej bazy danych zrób kopię bezpieczeństwa.
W przypadku problemów z wgraniem w/w zrzutu bazy – może być konieczne zmodyfikowanie tabeli ps_product_attribute. W tym celu przed wgraniem zrzutu uruchom kod SQL:
DROP TABLE IF EXISTS `ps_product_attribute`; CREATE TABLE `ps_product_attribute` ( `id_product_attribute` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_product` int(10) unsigned NOT NULL, `reference` varchar(32) DEFAULT NULL, `supplier_reference` varchar(32) DEFAULT NULL, `location` varchar(64) DEFAULT NULL, `ean13` varchar(13) DEFAULT NULL, `upc` varchar(12) DEFAULT NULL, `wholesale_price` decimal(20,6) NOT NULL DEFAULT '0.000000', `price` decimal(20,6) NOT NULL DEFAULT '0.000000', `ecotax` decimal(17,6) NOT NULL DEFAULT '0.000000', `quantity` int(10) NOT NULL DEFAULT '0', `weight` decimal(20,6) NOT NULL DEFAULT '0.000000', `unit_price_impact` decimal(20,6) NOT NULL DEFAULT '0.000000', `default_on` tinyint(1) unsigned DEFAULT NULL, `minimal_quantity` int(10) unsigned NOT NULL DEFAULT '1', `available_date` date NOT NULL, PRIMARY KEY (`id_product_attribute`), KEY `product_attribute_product` (`id_product`), KEY `reference` (`reference`), KEY `supplier_reference` (`supplier_reference`), KEY `product_default` (`id_product`,`default_on`), KEY `id_product_id_product_attribute` (`id_product_attribute`,`id_product`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
Zastąpi on domyślną tabelę, która może okazać się problematyczna.
Aktualizacja ilości
Na nowej bazie danych wywołujemy to zapytanie:
(radzimy każde zapytanie – są one oddzielone średnikami – realizować osobno):
DELETE FROM `ps_stock_available` WHERE `id_product_attribute` != 0;
Spróbuj wywołać poniższe komendy:
INSERT INTO `ps_stock_available`( `id_product`, `id_product_attribute`) SELECT `id_product` , `id_product_attribute` FROM ps_product_attribute;
UPDATE `ps_stock_available` SET `id_shop` = 1, `quantity` = 100 WHERE `id_product_attribute` > 0 ;
W przypadku problemów z wywołaniem zastosuj komendę łączną:
INSERT INTO `ps_stock_available`( `id_product`, `id_product_attribute`,`id_shop`,`id_shop_group`,`quantity`) SELECT `id_product` , `id_product_attribute`,1,0,100 FROM ps_product_attr
Ustawi ono domyślnie 100 sztuk dla każdej z zaimportowanej kombinacji. W innym wypadku na nowym sklepie nie będzie można dodać żadnej kombinacji do koszyka.
Asekuracyjnie na sklepie należy jeszcze wyczyścić cache i przebudować indeks produktów.
I to by było na tyle!
Dzięki za arta, mam sklep 1.4.4.1 i czaję się nad przejściem na 1.6
Może skorzystam..
[…] Sprawa jest dość enigmatyczna i trudno ją naprawić z poziomu zaplecza. Przyczyną jest zapewne błąd podczas importu kombinacji atrybutów (jak importować kombinacje atrybutów z Presta Shop 1.4 do 1.6 opisaliśmy w tym artykule). […]
[…] przeniesienie kombinacji produktów ze sklepu w wersji 1.3-1.4 do 1.6.x [AKTUALIZACJA] […]
[…] Przybliża to artykuł: https://pskrk.com/przeniesienie-kombinacji-produktow-ze-sklepu-w-wersji-1-4-do-najnowszej-1-6-1-2/#P… […]
[…] mowa o specyficznej tabeli ps_stock_available (jest też o niej mowa w tym artykule: https://pskrk.com/przeniesienie-kombinacji-produktow-ze-sklepu-w-wersji-1-4-do-najnowszej-1-6-1-2/). Odpowiada ona za określenie ilości danego produktu. Szczególnie jeśli bazuje on na atrybutach […]