вторник, 1 октября 2013 г.

Миграция сложной схемы товаров из opencart в prestashop.

Попросили перетащить интернет магазин из движка  http://www.opencart.com/ на движок http://www.prestashop.com/

Не знаю что там не так, где там в каком движке лучше, но несколько интересных подзадач встретилось.

Усложняет все то, что на opencart был подключен модуль Option Plus который позволяет для каждого товара добавить любое количество дополнительных характеристик. с любым количеством значений.

Ну например, есть у нас футболки, что бы не вводить миллион разных товаров, мы вводим один "Футболка" и к ней лепим характеристики

Цвет:
Красный, Зеленый, Синий.

Рисунок:
Северный олень, смайл, циферки

Размер:
X,XL

И тому подобное.


В prestashop похожий функционал тоже есть, называется комбинации.
Но помимо характеристик и их значений нужно указать все возможные комбинации.
Определенная логика в этом есть. Что если на складе нет синих футболок с оленями? Сам олень синий, вот и не производят.
Но усложнение сильное.
Представьте например, что у меня были товары у которых 6 характеристик с количеством значений под 20. Число комбинаций удивляет.

Во время ручного ввода, это не очень большая проблема, там есть генератор сочетаний в админке, но мы же не руками будем тащить товары.


Итак, откуда брать данные?
Самое простое из sql dump opencart, он прост, понятен, и в принципе пользуясь одними только "show tables" и "show create table .. ." я за несколько минут приготовил все нужные запросы.

Куда их лить? База prestashop отпала сразу.
Я люблю, и умею делать sql трансформации, но в любых извращениях есть предел.
Структура базы prestashop мне не понравилась. Пусть они сами с ней колупаются.
А я решил воспользоваться и REST API. (Документация)
Т.е. я через http post даю запрос на добавление объекта,а уж по своим таблицам они его распределяют сами.

Следующий этап выбор инструмента. Работаем с http запросами? Парсим dom ответов?
Ну какой тут может быть выбор?
Конечно это Mojolious Mojo/UserAgent и Mojo/DOM.pm


Логика работы скрипта с высоты птичьего полета проста,
1. Получаем объекты из базы opencart
2. Получаем специальным запросом шаблон xml документа
3. Заполняем его нужными значениями
4. Отправляем  http post в prestashop api
5. Проверяем создание и записываем полученный id в специальные хеши, которые связывают id opencart и prestashop

и все это в цикле по нужным типам объектов, не забывая делать нужные трансформации.

В какой то момент, я задумался как же получить все возможные комбинации параметров объектов, но у нас же есть cpan, и решением было
Algorithm::Loops ( NestedLoops )


Ну, что бы разбавить текст: фрагментик кода:

sub manufacturer {
    my $sth =
        $dbh->prepare("select * from manufacturer");
    my $obj = 'manufacturers';
    my $ua  = Mojo::UserAgent->new;
    my $dom = get_proto_dom($obj);

    my $man= $dom->prestashop->manufacturer;
    $man->at('link_rewrite')->remove;
    $sth->execute();
    while ( my $row = $sth->fetchrow_arrayref ) {
        set( $man->name, recode( $row->[1] ) );
        set( $man->active, 1 );
        set( $man->short_description->language, recode( $row->[1] ) );
        my $txn =
            $ua->post( $url . $obj => form => { xml => $dom->content_xml } );
        if ( !$txn->res->dom->find('prestashop>manufacturer') ) {
            print $txn->res->body;
        } else {
            my $id = $txn->res->dom->prestashop->manufacturer->id->text;
            if ( !$id ) {
                print $txn->res->body;
                exit 1;
            } else {
                $man_hash{ $row->[0] } = $id;
            }
        }
    }
}
Попутно перекодируем текстовые поля из win-1251 в utf-8.

В лучших традициях индусокода копипастом этого создаются функции и для других объектов.
Конечно же, благородные доны обязательно выскажутся по поводу копипаста, но я очень очень сомневался что такая задача когда нибудь повторится, и если таки это случится обещаю сделать рефакторинг.
Особенно приятные граждане могут этот рефакторинг сделать сами, ибо код я, как делают это все приличные люди, заливаю на github

Общие впечатления:

1. Mojolicius без всякого сомнения самый настоящий duct tape for web
2. Prestashop постоянно неприятно удивляет, то засунет в schema параметр read-only, который нужно удалять. То молча вернет id объекта , который не был не был создан как положено. Плюс странные проблемы с отображением категорий во frontend. В общем - на любителя.
3. CPAN все еще рулит. Ради шутки, в комментариях дайте мне свое решение создания комбинаций из набора массивов значений на своем любимом питоне или чем там сейчас модно.
4. Я по прежнему не умею оценивать время нужное на задачи. Планировал сделать в 10 раз быстрее, но проплюхался с prestashop фичами.