• pooding

    Решил начать небольшую рубрику, где будут простые решения некоторых задач. Сегодня будет вывод рекомендуемых товаров. На этом форуме уже описали решение через collections, но, как мне кажется, оно избыточно тяжёлое (ставить коллекции ради одной задачу - идея не лучшая, да и куда проще заполнять все параметры в одном месте). Поэтому вот вам моё.

    1. Создаём дополнительное поле "recomend", назначаем его шаблону "Товар"
    2. Выбираем тип ввода "список (множественный выбор)"
      В "возможные значения" вставляем код (3 - шаблон "товар")
    @SELECT `pagetitle`, `id` FROM `[[+PREFIX]]site_content` WHERE `template` = 3
    
    1. В "параметры вывода" выбираем "разделитель" и указываем "," без кавычек.
    2. После этого в дополнительных полях товара мы можем выбирать ему рекомендуемые (из множественного списка). Дело за малым - вывести это дело в карточке товара. Делаем это так:
    [[*recomend:isnot=``:then=`<h3>Рекомендуемые товары</h3>
             [[!getProducts?
                    &resources=`[[*recomend]]`
                    &fromParentList=`pagetitle`
                    &processTVs=`1`
                    &processTVList=`params`
                    &includeTVs=`1`
                    &includeTVList=`image,price,oldprice,tags,params`
                    &tpl=`shk_product_recomend`
            ]]
    `]]
    

    т.е. проверяем, не пустое ли это значение, а после - выводим через getProducts, передавая в параметр "resources" список рекомендуемых товаров.

    Тааа-дааа-м! Мы великолепны.

    написал в Недокументированные решения отдельных задач Читать далее
  • pooding

    Добрейшего времени суток. Решил предложить один из самых простых вариантов для печати заказа из под админки. Чуть позже будет "продвинутая" система с плюшками, вроде печати нескольких заказов
    Attention/внимание/увага/piesardzība - решение простое, ничего не сломает. Но предупреждаю - оно колхозное.

    Шаг №1
    Открываем /assets/components/shopkeeper3/mgr/css/shk-style.css и вставляем в конец файла:

    @media print {           
        #modx-header, #modx-leftbar, #x-plain-bwrap, #ext-gen21, .amod-container-b, .modal-footer, .nav-tabs, .modal-header {
        display: none !important;
            
        }
        
        #modx-content {
        width: 100% !important;
        left: 0px !important;
        }
               
        .modal-content {
            border: none !important;
            box-shadow: none !important;
        }
    }
    

    Шаг №2
    Открываем /core/components/shopkeeper3/templates/home.tpl , находим строку 297 (перед </uib-tabset>) и вставляем код:

    <!-- печать заказа -->
                <uib-tab heading="Печать" onclick="window.print();">
                    
                    <div id="print_field">
                         <div style="page-break-after: always;">
                            <h1>Заказ {{data.order.id}}</h1>
                            <table class="table table-bordered">
                               <thead>
                                  <tr>
                                     <td style="width: 50%;">Данные заказчика</td>
                                     <td style="width: 50%;">Информация о заказе</td>
                                  </tr>
                               </thead>
                               <tbody>
                                  <tr>
                                     <td style="width: 50%;">
                                       <span ng-repeat="item in data.order.contacts">
                                            <b>{{item.label}}:</b>
                                            {{item.value}} <br>
                                        </span> 
                                     </td>
                                     <td style="width: 50%;">
                                        <b>Время добавления</b> {{data.order.date}}<br>
                                        <b>№ Заказа</b> {{data.order.id}}<br>
                                        <b>Способ оплаты</b> {{data.order.payment}}<br>
                                        <b>Способ доставки</b> {{data.order.delivery}}<br>
                                     </td>
                                  </tr>
                               </tbody>
                            </table>
            
                            <table class="table table-bordered">
                               <thead>
                                  <tr>
                                     <td><b>#</b></td>
                                     <td><b>ID товара</b></td>
                                     <td><b>Товар</b></td>
                                     <td><b>Параметры</b></td>
                                     <td class="text-right"><b>Количество</b></td>
                                     <td class="text-right"><b>Цена за единицу</b></td>
                                  </tr>
                               </thead>
                               <tbody>
                                   <tr ng-repeat="item in data.order.purchases">
                                            <td>{{$index+1}}</td>
                                            <td>{{item.p_id}}</td>
                                            <td>{{item.name}}</td>
                                            <td>
                                                <div ng-repeat="opt in item.options">{{ opt[0] }}</div>
                                            </td>
                                            <td>{{item.count}}</td>
                                            <td>{{item.price | number: 2}}</td>
                                        </tr>
                                  <tr>
                                     <td class="text-right" colspan="5"><b>{{data.order.delivery}}</b></td>
                                     <td class="text-right">{{data.order.delivery_price}} {{data.order.currency}}</td>
                                  </tr>
                                  <tr>
                                     <td class="text-right" colspan="5"><b>Итого</b></td>
                                     <td class="text-right">{{data.total_price | number: 2}} {{data.order.currency}}</td>
                                  </tr>
                               </tbody>
                            </table>
                         </div>
                      </div>
                    
                </uib-tab>
                <!-- печать заказа -->
    

    Получается вот такой результат:
    0_1488808041431_2.png
    0_1488808023904_1.png

    написал в Недокументированные решения отдельных задач Читать далее
  • pooding

    Всем добрейшего времени суток.
    Пару раз замечал, что люди не знают, как организовать систему брендов/стран-производителей для товара. Сегодня покажу самое простое и весьма полезное решение.

    • Шаг №1
      Создаём ресурс "производители" и для него несколько дочерних ресурсов, которые имеют названия брендов. Назначаем им шаблон "производители" (чуть ниже будет код, который в этот шаблон нужно вставить).

    • Шаг №2
      Создаём TV с именем brand, типом ввода "список ресурсов". В параметр "родители" указываем ID ресурса "производители", а параметр "включать родителей" устанавливаем на "нет". Далее, делаем TV доступным для шаблона "товар".

    • Шаг №3
      В шаблон "производители" вставляем код:

    [[!getProducts?
                    &fromParentList=`pagetitle`
                    &includeTVs=`1`
                    &includeTVList=`image,price`
                    &tvFilters=`{"brand:LIKE":"[[*id]]"}`
                    &tpl=`shk_product`
    ]]
    

    Т.е. на страницу будут выводиться товары, у которых значение TV brand = ID этой самой страницы. &tvFilters={"brand:LIKE":"[[*id]]"}

    • Шаг №4
      В шаблон "товар" выводим название и ссылку на производителя.
    [[*brand:isnot=``:then=`Производитель: <a href="[[~[[*brand]]]]">[[!pdoField?id=`[[*brand]]`&field=`pagetitle`]]</a>`]]
    

    Итог: в карточке товара есть информация о производителе, на странице производителя есть все товары, которые относятся к нему.

    написал в Недокументированные решения отдельных задач Читать далее
  • pooding

    @andchir дад, там вообще мутная тема 😃 Сижу в чатике, Василий иногда новости подтаскивает свежие. Выглядит всё очень странно. С одной стороны, уход от extJS в планах, но не в 3.0, а когда-нибудь. А ведь, объективно, extJS все и хейтят. Вместо этого композер (который и так туда прикручивается за пару минут по гайдам). И редизайн. ВотЪ.
    Получается, 3.0 и правда пустышка. А хороших изменений только к 3.2-3.5 можно ждать. Но, не факт что мы доживём до того момента, зная отношение к срокам в modx. 😃

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

    написал в MODX - Вопросы и обсуждения Читать далее
  • pooding

    @Andchir я им написал, сначала молчали, потом я позвонил уже 😃 Сказали что не больше дня потратят.

    написал в MODX - Вопросы и обсуждения Читать далее
  • pooding

    Решили на JS
    <div id="param">
    [[+tv.params]] или [[*params]]
    </div>
    А ограничит количество вот это:
    $('div#param > input').change(function(){
    if($('div#param > input:checked').length >= 2){
    $('div#param > input[type=checkbox]:not(:checked)').attr('disabled', true);
    } else{
    $('div#param > input[type=checkbox]:disabled').attr('disabled', false);
    }
    });

    Скрипт простой, но вдруг кому нужен будет.

    написал в MODX - Вопросы и обсуждения Читать далее
  • pooding

    Зачем вам эти извращения? Возьмите просто вёрстку, а для оплаты - готовый виджет яндекс.денег с заранее указанной ценой. Всё. Зачем для одной простейшей страницы тянуть modx и к нему ещё и шопкипер?

    написал в MODX - Вопросы и обсуждения Читать далее
  • pooding

    @greenice
    Предлагаю сделать так: создать ТВ, которое будет означать производителя. И далее, в каждом товаре вызывать [[*manufacture:is=Apple:then=[[$apple_param]]]]
    А чанк apple_param, соответственно, будет содержать табличку с определёнными параметрами, которые будут наследоваться. Костыльный вариант, но, вроде как, под ваши пожелания полностью подходит.

    написал в MODX - Вопросы и обсуждения Читать далее
  • pooding

    Опять-таки невероятно бюджетный проект: https://ya-fresh.ru/
    Сначала планировался исключительно как магазин готовых наборов, где заказчик может выбрать только 1 из нескольких блюд из каждой категории. И чем "бохаче" набор, тем вкуснее блюда, в некоторых можно выбирать не по 1, а по 2 блюла (не больше, не меньше). Под конец запросили ещё и обычные товары, т.к. какая-то их служба требует и такого отображения блюд. Теперь "постоянное меню" отличает от других.
    Из необычностей - каждую неделю меняется список блюд (заранее забито на 4 недели).
    Использовал Paykeeper для оплаты через ЯД.

    написал в Галерея сайтов Читать далее
  • pooding

    Однажды делал такое. Категорией было TV с множественным выбором. На странице категории делал вывод через фильтр

     &tvFilters=`{"category:LIKE":"%[[*pagetitle]]%"}`
    

    Где category = tv с множественным выбором и pagetitle = названию категорий. В каталоге можно спокойно фильтровать по этому TV, вместо категории.

    написал в MODX - Вопросы и обсуждения Читать далее
  • pooding

    @slaad в районе 15 проектов. В основном типовые магазины, но было и 5-6 весьма занятных, необычных и сложных.
    Если что - на звание какого-то профессионала не претендую. Но лично мне, человеку, который в WEB-разработке не более полутора лет, связка modx + shopkeeper показалась наиболее удобной для работы. Ну и студия, в которой я работаю, массово пересела на эту связку (долгая история, но в той студии никто ничего не умел толком, кроме WP). Т.е. к моим 15 проектам можно смело добавить ещё штук 30-40 от других разработчиков. И за всё это время мы утыкались только в один единственный баг, мешающий жить (и то не нам, а владельцу. Либо тем, кто наполнял магазин). Нет, может быть, есть и другие, я этого не отрицаю. Но они никак не сказываются на работоспособности.

    написал в Новости Читать далее
  • pooding

    Очередная порция велосипедов подъехала. Сегодня вывод списка заказов пользователя. Работает, сверяя заказы по почте пользователя. Поэтому вообще не важно, Login у вас, Офис или прочие непотребства.

    Есть у Андрея платный плагин, но мне, если честно, его функционал избыточен. Ибо не совсем понимаю, зачем юзверю редактировать свои заказы. Это ведь может путаницу создать, когда заказ принят, а его вдруг поменяли.

    Приступаем.

    1. Создаём страницу "Список заказов" и туда выводим
    [[!user_order_info]]
    
    1. Создаём, соответственно, сниппет user_order_info
    2. Вставляем в сниппет код:
    <?php
    //получаем почту активного юзверя и подставляем её в переменную
    $profile = $modx->user->getOne('Profile');
    $email = $profile ? $profile->get('email') : '';
    
    //просим у БД выдадать нам ID, стоимость заказа и другие данные заказов, относящихся к пользователю с определённой почтой
    $sql   = "SELECT `price`, `id`,`delivery`,`delivery_price`,`payment`,`date`  FROM `modx_shopkeeper3_orders` WHERE `email` = '$email'";
    $query = new xPDOCriteria($modx, $sql, array(
        ':id' => '10'
    ));
    if ($query->prepare() && $query->stmt->execute()) {
        $res = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
     
    //оформляем шапку таблицы    
    echo '
    <table class="table">
       <thead>
          <tr>
             <th>ID</th>
             <th>Цена</th>
             <th>Доставка</th>
             <th>Цена доставки</th>
             <th>Способ оплаты</th>
             <th>Дата</th>
          </tr>
       </thead>
       <tbody>';
    //выводим содержимое - данные о заказе
        foreach ($res as $row) {
            echo "<tr>" 
            . "<td>" . $row['id'] . "</td>" 
            . "<td>" . $row['price'] . "</td>" 
            . "<td>" . $row['delivery'] . "</td>" 
            . "<td>" . $row['delivery_price'] . "</td>" 
            . "<td>" . $row['payment'] . "</td>"
            . "<td>" . $row['date'] . "</td>"
            ."</tr>";
        }
    //закрываем таблицу
        echo '
       </tbody>
    </table>';
    
    }
    
    //если чего-то вдруг не работает
    else
        echo "Запрос не выполнен";
    

    ВАЖНО!!! В этом куске кода

    FROM `modx_shopkeeper3_orders`
    

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

    UPD #1

    Нашёл время - доработал сниппет немного. Теперь научил его выводить дополнительные данные + доработал код, теперь он чище и немного правильнее 😃

    • Появилось содержимое заказа (товары со ссылками) + количество товара в заказе

    • Появились поля: адрес доставки, телефон, комментарий.

    • Поправил код, чтобы вам не приходилось вписывать свой префикс таблиц руками

    Список действий, чтобы получить такую табличку в личном кабинете пользователя:
    alt text

    • Создаём страничку Список заказов и выводим [[!user_order_info]]

    • Создаём сниппет user_order_info

    <?php
    $prefix = $modx->getOption('table_prefix'); // получаем префикс таблицы
    $profile = $modx->user->getOne('Profile'); // получем профиль пользователя
    $email = $profile ? $profile->get('email') : ''; // получем почту пользователя
    $table = $prefix.'shopkeeper3_orders'; // перфикс + название таблицы
    
    
    //просим у БД выдадать нам ID, стоимость заказа и другие данные заказов, относящихся к пользователю
    $sql   = " SELECT `price`, `id`,`delivery`,`delivery_price`,`payment`,`date`,`contacts`  FROM `$table` WHERE `email` = '$email' ";
    $query = new xPDOCriteria($modx, $sql);
    if ($query->prepare() && $query->stmt->execute()) 
    {
        $res = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
     
    //оформляем шапку таблицы    
    echo '
    <table class="table table-bordered table-hover">
       <thead>
          <tr>
             <th>ID</th>
             <th>Цена</th>
             <th>Способ доставки</th>
             <th>Цена доставки</th>
             <th>Способ оплаты</th>
             <th>Дата</th>
             <th>Состав заказа</th>
             <th>Кол-во</th>
             <th>Адрес доставки</th>
             <th>Телефон</th>
             <th>Комментарий к заказу</th>
          </tr>
       </thead>
       <tbody>';
    //выводим содержимое - данные о заказе
        foreach ($res as $row) {
            $json = $row['contacts'];
            $array = json_decode($json);
            
            
            echo 
            '<tr>'
            
            . '<td>' . $row['id'] .             '</td>' // ID заказа (номер)
            . '<td>' . $row['price'] .          '</td>' // Стоимость заказа
            . '<td>' . $row['delivery'] .       '</td>' // Способ доставки
            . '<td>' . $row['delivery_price'] . '</td>' // Цена доставки
            . '<td>' . $row['payment'] .        '</td>' // Способ оплаты
            . '<td>' . $row['date'] .           '</td> '// Дата заказа
            
            . "[[!user_order_list? &order_id = `" . $row['id']  ."`]]" // Сниппет, выводящий одержимое заказа (товары и количество); в параметр order_id  передаёт номер заказа, для которого нужно узнать товары
            
            . '<td>' . $array[1]->value .       '</td>' // Адрес доставки
            . '<td>' . $array[3]->value .       '</td>' // Телефон, на который был оформлен заказ
            . '<td>' . $array[4]->value .       '</td>' //Комментарий к заказу
            
            // Если нужно получить почту, указанную при заказе - удалите //
            // . '<td>' . $array[2]->value . "</td>" 
            
            // Если нужно получить ФИО заказчика - удалите //
            // . '<td>' . $array[0]->value ."</td>"
            
            ."</tr>";
        }
    //закрываем таблицу
        echo '
       </tbody>
    </table>';
    }
    
    //если чего-то вдруг не работает
    else
        echo "Запрос не выполнен";
    
    • Создаём сниппет user_order_list
    <?php
    $prefix = $modx->getOption('table_prefix'); // получаем префикс
    $table = $prefix.'shopkeeper3_purchases'; // перфикс + название таблицы
    
    
    //просим у БД выдадать нам информацию о товарах, находящихся в заказе с ID из user_order_info
    $sql   = "SELECT `name`, `p_id` , `count`  FROM `$table` WHERE `order_id` = '$order_id'";
    $query = new xPDOCriteria($modx, $sql);
    if ($query->prepare() && $query->stmt->execute()) {
        $res = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
        
    //оформляем таблицу  
    echo "<td>";
    
    //выводим содержимое - товары в заказе
    
        foreach ($res as $row) {
            echo  '<a href="[[~' . $row['p_id'] . ']]">' . $row['name'] . '</a> <br>';
        }
    
    //оформляем таблицу       
    echo "</td>";
    
    echo '<td align="center">';
    //выводим содержимое - количество товара в заказе
        foreach ($res as $row) {
            echo  $row['count'] . "<br>";
        }
    
    //оформляем таблицу  
    echo "</td>";
    }
    
    //если чего-то вдруг не работает
    else
        echo "Запрос не выполнен";
    

    Всё. Наслаждаемся табличкой заказов для клиента.

    Единственное гипотетическое "НО", возможно у вас будет другая структура полей в заказе. Тогда нужно просто поменять
    $array[4]->value в user_order_info на, например, $array[3]->value

    написал в Недокументированные решения отдельных задач Читать далее
  • pooding

    @akradeus сделано аккуратно и стильно! Мне нравится.
    Но, это же не каталог. В каталоге нет корзины, только товары с описанием. У вас полноценный ИМ.

    написал в Галерея сайтов Читать далее
  • pooding

    хм, на сложных сайтах действительно прирост почти в 2 раза. Недурно. Но, признаюсь, работал с pdoTppls + Fenom, не понравилось:

    1. Тащить зоопарк, который, если объективно, делает из modx совсем другую систему... Ну такое.
    2. Крайне хреново работает парсер. Тег {ignore} не работает как таковой. Хочешь JS на странице - занимайся любовью с выставлением пробелов перед фигурной скобкой.
    3. Если смешивать феном и стандартный синтаксис, то скорость получается нестабильной. Об этом даже сам Василий писал. А на старых проектах это будет всяко + многие дополнения не перешли на феном. Т.е. эта смесь будет всегда.

    Короче, жутко на любителя тема.

    написал в MODX - Вопросы и обсуждения Читать далее