Редактирование заказа в админке

Доброго времени суток. Кто подскажет готовое решение (компонент) или как реализовать редактирование заказа клиента в админке. Из коробки конечно есть возможность удалить товар из заказа, добавить новый товар из выпадающего списка, но проблема возникла при использовании дополнения msOptionsPrice2, там в товаре, при просмотре заказа, опция прописывается в виде строки, пример:
{"color":"Gold","size":"6 g.","modifications":[26],"modification":26}
И вот тут вопрос, как это дело упростить? Не прописывать же каждый раз такую строку и особенно отсчитывать id модификации (учитывая, что у одного товара их может быть под сотню).
Может кто реализовывал такое, можно платный компонент, главное чтобы работало.
Madao
24 января 2021, 22:19
modx.pro
1
697
0

Комментарии: 5

Артур Шевченко
25 января 2021, 00:13
0
Насколько мне известно, платных компонентов которые решают эту проблему нет. Поэтому вариантов у вас немного
1. Ждать что-то кто-то, напишет решение, а оно будет сложным для неподготовленного человека, т.к. нужно будет кастомизировать админку, а это непросто, как по мне.
2. Написать своё дополнение.
3. Сделать этот функционал как отдельную страницу на фронте доступную только админу.
    Madao
    25 января 2021, 12:02
    0
    3. Сделать этот функционал как отдельную страницу на фронте доступную только админу.
    А разве на фронте можно редактировать уже оформленный заказ? Есть ссылка на документацию по этому направлению?
      Артур Шевченко
      25 января 2021, 12:10
      0
      Вы можете делать что хотите, лишь бы навыков хватило. Вот тут похожей темой интересовался, правда там он спрашивает как вывести заказ. На моём сайте такой функционал реализован, могу скинуть свой код, но позже, пока не у компа. А вот в документации решение этой задачи нет. Вам нужно почитать раздел Разработка компонента minishop2, плюс понимать как с помощью modx api работать с ресурсами, знать какие поля есть у товаров, заказов, как связаны между собой таблицы minishop2. Но это всё не очень сложно, я код скину посмотрите и думаю разберётесь.
        Madao
        28 января 2021, 12:00
        0
        На моём сайте такой функционал реализован, могу скинуть свой код, но позже, пока не у компа.
        Буду очень признателен за пример кода, где реализован такой функционал.
          Артур Шевченко
          28 января 2021, 13:58
          0
          Сразу оговорюсь это говнокод, а то придут старшие товарищи и начнут тапками меня закидывать. Использовать на свой страх и риск, но у меня работает.
          Ссылка имеет вид domain.ru/smeta?order_id=183
          На этой странице вызывается сниппет getOrder
          {set $order = '!getOrder' | snippet:[
              'order_id' => $.get.order_id
          ]}
          Сниппет возвращает массив, посмотреть что внутри можно так
          {$order | print_r}
          Сам сниппет выглядит так
          <?php
          if(!$order_id){return false;}
          $pdoTools = $modx->getService('pdoTools');
          $orderFields = array('id','num', 'createdon', 
                              'updatedon', 'cart_cost', 
                              'delivery_cost', 'comment', 
                              'status', 'cost');
          $orderProductFields = array('id','product_id', 
                                      'name', 'count', 
                                      'price', 'cost', 'options');
                                  
          $addressFields = array('city', 'street',
                                  'receiver', 'phone',
                                  'comment');
          $output = array(
              'meta' => [],
              'address' => [],
              'products' => []
              );
          
          $order = $modx->getObject('msOrder', $order_id);
          if($order){        
              //заполняем массив основных данных заказа
              for($i = 0; $i < count($orderFields); $i++){
                  $output['meta'][$orderFields[$i]] = $order->get($orderFields[$i]); 
              }
              
              //вычисляем срок выполнения заказа
              $output['meta']['duration'] = ceil($output['meta']['cost'] / $modx->getOption('base_cost'));
                      
              //заполняем адрес и дополнительные данные
              $address = $order->getOne('Address');
              $properties = $address->get('properties');
              for($i = 0; $i < count($addressFields); $i++){
                  if($addressFields[$i] != 'properties'){
                      $output['address'][$addressFields[$i]] = $address->get($addressFields[$i]); 
                  }else{
                      foreach($properties as $name => $prop){
                          $output['address'][$name] = $prop; 
                      }
                  }
              }
              //заполняем продукты
              $products = $order->getMany('Products');
              if($products){
                  foreach($products as $key => $product){
                      for($i = 0; $i < count($orderProductFields); $i++){
                          $output['products'][$key][$orderProductFields[$i]] = $product->get($orderProductFields[$i]); 
                      }
                  }  
              }
              
              
              //$modx->log(1, 'OUTPUT getUserOrder ' . print_r($output, 1));
              
              if($tpl){
                  return $pdoTools->getChunk($tpl, $output);
              }
              //$modx->log(1, print_r($output,1));
              return $output;
          }else{
              return false;
          }
          После вызова сниппет идёт такой код
          {if $order}
          <p class="h-6"><span class="text-orange">Номер заказа:</span> {$order['meta']['num']}</p>
          <p class="h-6"><span class="text-orange">Дата заказа:</span> {$order['meta']['createdon'] | date: 'd.m.Y H:i:s'}</p>
          <p class="h-6"><span class="text-orange">Имя заказчика:</span> {$order['address']['receiver']}</p>
          {if $_modx->isAuthenticated('mgr') || $.get.admin}
          <p class="h-6"><span class="text-orange">Телефон заказчика:</span> <a class="service-link" href="tel:{$order['address']['phone'] | replace:'-':'' }">{$order['address']['phone'] | replace:'-':'' }</a></p>
          {/if}
          <p class="h-6"><span class="text-orange">Общая стоимость:</span> <span class="jsTotalOrderCost">{$order['meta']['cost']}</span> руб.</p>
          <p class="h-6"><span class="text-orange">Срок выполнения:</span> <span class="jsOrderDuration">{$order['meta']['duration']}</span> дн.</p>
          <p class="h-6 mb-0"><span class="text-orange">Перечень включенных в состав услуг 
           <small class="small">(в стоимость услуг входит стоимость платных дополнений)</small></span></p>
              {if $_modx->isAuthenticated('mgr') || $.get.admin}
                  <div class="pl-0" id="orderWrap">
                  {if $order['products']}    
                  {set $i = 1}    
                  {foreach $order['products'] as $key => $product}
                      {set $description = $product['product_id'] | resource: 'desc'}
                      {set $introtext = $product['product_id'] | resource: 'introtext'}
                      {set $add_cost = $product['product_id'] | resource: 'add_cost'}
                      {set $weight = $product['product_id'] | resource: 'weight'}
                      {$_modx->parseChunk('@FILE chunks/shop/editOrderProduct.html', [
                          'description' => $product['options']['desc']?:$description,
                          'introtexxt' => $introtext,
                          'index' => $i,
                          'add_cost' => $add_cost,
                          'price' => $product['price'],
                          'weight' => $weight,
                          'count' => $product['count'],
                          'name' => $product['options']['name']?:$product['name'],
                          'cost' => $product['cost'],
                          'id' => $product['id'],
                          'options' => $product['options'],
                          'order_id' => $.get.order_id,
                          'total_cost' => $order['meta']['cost'],
                          'product_id' => $product['product_id']
                      ])}
                      {set $i = $i + 1}
                  {/foreach}
                  {else}
                  <p class="h-6 my-3 text-red">Необходимо добавить услуги!</p>
                  {/if}
                  </div>
                   <p class="h-5 mt-3 mb-3">Найти услугу</p>
                  {'!AjaxForm' | snippet: [
                      'snippet' => 'searchResources',
                      'tpl' => '@FILE chunks/shop/editOrderProductTpl.html',
                      'form' => '@FILE chunks/forms/searchForm.html',
                      'fieldsForSearch' => 'pagetitle,longtitle,menutitle',
                      'validate' => 'query:required:minLength=^3^',
                      'placeholderPrefix' =>'find.'
                  ]}
                  <div id="productList"></div>
                  <p class="h-5 mt-3 mb-0">Добавить услугу</p>
                  <form class="row py-3 jsProductRow border-gray-bottom jsAddForm">
                      <div class="jsCommonFields">
                          <input type="hidden" name="weight" value="1">
                          <input type="hidden" name="order_id" value="{$.get.order_id}">
                          <input type="hidden" name="total_cost" value="{$order['meta']['cost']}">
                          <input type="hidden" name="action" value="editOrder">
                      </div>
                      <input type="hidden" name="product_id" value="130">
                      <div class="col-lg-7 col-md-5 col-6 mb-md-0 mb-3 d-flex flex-column justify-content-center align-items-start">
                          <label class="label-text par mb-0 w-100">
                              <input type="text" class="input pr-1" name="name" placeholder="{130 | resource: 'pagetitle'}" value="" required>
                          </label>
                      </div>
                      <div class="col-lg-1 col-md-2 col-6 mb-md-0 mb-3 d-flex justify-content-center align-items-center">
                          <label class="label-text par mb-0">
                              <input type="number" class="input pr-1" min="1" name="count" value="1">
                          </label>
                      </div>
                      <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                          <label class="label-text par mb-0">
                              <input type="text" class="input pr-1" name="price" placeholder="Цена" value="" required>
                          </label>
                      </div>
                      <div class="col-lg-2 col-md-2 col-6 d-flex justify-content-center align-items-center">
                          <button class="btn btn-orange btn-cart" type="submit">
                              <i class="fa fa-cart-plus"></i>
                          </button>
                      </div>
                      <div class="col-12 order-5 mt-3">
                          <label class="label-text par mb-0">
                              <textarea name="options[desc]" class="textarea w-100" rows="4" placeholder="Описание"></textarea>
                          </label>
                      </div>
                  </form>
              {else}
               <ul class="pl-0">
              {foreach $order['products'] as $key => $product}
                  {set $description = $product['product_id'] | resource: 'description'}
                  {set $introtext = $product['product_id'] | resource: 'introtext'}
                  {set $add_cost = $product['product_id'] | resource: 'add_cost'}
                  <li class="row py-3 jsProductRow border-gray-bottom">
                      <input type="hidden" name="id" value="{$id}">
                      <div class="col-lg-7 col-md-5 col-6 d-flex flex-column justify-content-center align-items-start">
                          <span class="par service-link mb-3">{$product['options']['name']?:$product['name']}</span>
                          <small class="small">{$product['options']['desc']?:$description}</small>
                          {if $add_cost}
                              {if $id == 45}
                              <small class="small text-red">*стоимость шаблона: {$add_cost} руб.</small>
                              {else}
                              <small class="small text-red">*стоимость дополнения: {$add_cost} руб.</small>
                              {/if}
                          {/if}
                      </div>
                      <div class="col-lg-1 col-md-1 col-6 d-flex justify-content-center align-items-center">
                          <span class="price text-orange h-6">{$product['count']} шт.</span>
                      </div>
                      <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                              <span class="text-orange h-6">{$product['price']} руб.</span>
                      </div>
                      <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                          <span class="text-orange h-6">{$product['cost']} руб.</span>
                      </div>
                  </li>
              {/foreach}
              </ul>
              {/if}
          {else}
          <p class="h-4 text-center">Заказ с id = {$.get.order_id} не существует в системе</p>
          {/if}
          <div class="row">
                  <div class="col-lg-3 offset-lg-3 col-sm-6 mt-3">
                  <div class="btn-wrap">
                      <a href="/" class="btn btn-no-bg w-100">На Главную</a>
                  </div>
              </div>
              <div class="col-lg-3 col-sm-6 mt-3">
                  <div class="btn-wrap">
                      <a href="{9 | url}" class="btn btn-no-bg w-100">К Услугам</a>
                  </div>
              </div>
          </div>
          Каждый товар выводится в форму редактирования, а под всеми товарами есть форма добавления нового и форма поиска
          editOrderProduct.htm выглядит так
          <form class="row py-3 jsProductRow border-gray-bottom jsEditForm" name="product-{$id}" id="product-{$id}">
              <input type="hidden" name="id" value="{$id}">
              <input type="hidden" name="weight" value="{$weight}">
              <input type="hidden" name="order_id" value="{$order_id}">
              <input type="hidden" name="total_cost" value="{$total_cost}">
              <input type="hidden" name="action" value="editOrder">
              <input type="hidden" name="price" value="{$price}">
              <input type="hidden" name="options[addcost]" value="{$add_cost | number: '0': '.': ''}">
              <input type="hidden" name="product_id" value="{$product_id}">
              <div class="col-lg-7 col-md-5 col-6 d-flex flex-column justify-content-center align-items-start">
                  <span class="par service-link">{$index}. {$name}</span>
                  {if $introtext}
                  <small class="small">{$introtext}</small>
                  {/if}
                  {if $add_cost}
                  {if $id == 45}
                  <small class="small text-red">*стоимость шаблона: {$add_cost} руб.</small>
                  {else}
                  <small class="small text-red">*стоимость дополнения: {$add_cost} руб.</small>
                  {/if}
                  {/if}
              </div>
              <div class="col-lg-1 col-md-1 col-6 d-flex justify-content-center align-items-center">
                  <label class="label-text par mb-0">
                      <input type="number" class="input pr-1" min="0" name="count" value="{$count}">
                  </label>
              </div>
              <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                  <span class="text-orange h-6">{$price} руб.</span>
              </div>
              <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                  <span class="text-orange h-6">{$cost} руб.</span>
              </div>
              <div class="col-12 order-5 mt-3">
                  <label class="label-text par mb-0">
                      <textarea name="options[desc]" class="textarea w-100" rows="4" placeholder="Описание">{$description}</textarea>
                  </label>
              </div>
          </form>
          Как отправить запрос на сервер думаю разберётесь, в заметке про поиск это есть. Ну и собственно сам сниппет editOrder
          <?php
          if(!isset($_POST['order_id'])){
              $modx->log(1,'EditOrder: Не передан идентификатор заказа');
              return false;
          }
          //$modx->log(1, print_r($_POST,1));
          $res = [];
          $tpl = '@FILE chunks/shop/editOrderProduct.html';
          $order = $modx->getObject('msOrder', $_POST['order_id']);
          if(isset($_POST['id'])){
              $product = $modx->getObject('msOrderProduct', $_POST['id']);
              $productCost = $_POST['price'] * $_POST['count'] + $_POST['options']['addcost'];
              $totalWeight = $_POST['weight'] + $order->get('weight') - $product->get('weight');
              $totalCost = $order->get('cost') + $productCost - $product->get('cost')  - $_POST['options']['addcost'];
              if($_POST['count'] > 0){
                  $product->set('count', $_POST['count']);
          	    $product->set('cost', $_POST['price'] * $_POST['count']);
          	    if($_POST['options']['desc']){
          	        $options = $product->get('options');
          	        $options['desc'] = $_POST['options']['desc'];
          	        $product->set('options', $options);
          	    }
          	    $product->save();
              }else{
                  $totalWeight = $_POST['weight'] - $product->get('weight');
                  $totalCost = $order->get('cost') - $product->get('cost');
                  $product->remove();
                  
              }
          }else{
              $product = $modx->newObject('msOrderProduct');
              $data = $_POST;
              $data['cost'] = $_POST['price'] * $_POST['count'] + $_POST['options']['addcost'];
              $totalWeight = $_POST['weight'] * $_POST['count'] + $order->get('weight');
              $totalCost = $order->get('cost') + $data['cost'];
              $product->fromArray($data);
              $product->save();
          }
          	    
          $order->set('cost', $totalCost);
          $order->set('cart_cost', $totalCost);
          $order->set('weight', $totalWeight);
          $order->set('updatedon', date('Y-m-d H:i:s'));
          $order->save();
          
          if($totalCost){
              $pdoTools = $modx->getService('pdoTools');
              $products = $order->getMany('Products');
              $i = 1;
              foreach($products as $product){
                  $options = $product->get('options');
                  $resource = $modx->getObject('modResource', $product->get('product_id'));
                  $desc = $options['desc']?:$resource->get('description');
                  $name = $options['name']?:$product->get('name');
                    
                  $productData = array(
                          'description' => $desc,
                          'introtexxt' => $resource->get('introtext'),
                          'index' => $i,
                          'add_cost' => $resource->get('add_cost'),
                          'price' => $product->get('price'),
                          'weight' => $product->get('weight'),
                          'count' => $product->get('count'),
                          'name' => $name,
                          'cost' => $product->get('cost') + $resource->get('add_cost'),
                          'id' => $product->get('id'),
                          'options' => $options,
                          'order_id' => $_POST['order_id'],
                          'product_id' => $resource->get('id')
                      );
                  
                  if(isset($tpl)){
                      $res['orderProducts'] .= $pdoTools->getChunk($tpl, $productData);
                  }else{
                      $res['orderProducts'][] = $productData;
                  }
                  $i++;
              }
          }
          else{
              $res['orderProducts'] = '<p class="h-6 my-3 text-red">Необходимо добавить услуги!</p>';
          }       
          $res['total_cost'] = $totalCost;
          $res['duration'] = ceil($totalCost / $modx->getOption('base_cost'));
          
          return json_encode($res);
          Если интересует добавление товаров, то вот сниппет addToOrder
          <?php
          	    $res = [];
          	    $order = $modx->getObject('msOrder', $_POST['order_id']);
          	    
          	    $product = $modx->newObject('msOrderProduct');
          	    $data = $_POST;
          	    //$modx->log(1, print_r($_POST,1));
          	    $data['cost'] = $_POST['price'] * $_POST['count'];
          	    $totalWeight = $_POST['weight'] * $_POST['count'] + $order->get('weight');
          	    $totalCost = $order->get('cost') + $data['cost'] + $data['options']['addcost'];
          	    $product->fromArray($data);
          	    $product->save();
          	    
          	    $order->set('cost', $totalCost);
          	    $order->set('cart_cost', $totalCost);
          	    $order->set('weight', $totalWeight);
          	    $order->set('updatedon', date('Y-m-d H:i:s'));
          	    $order->save();
          	    
          	    $pdoTools = $modx->getService('pdoTools');
          	    $products = $order->getMany('Products');
          	    $i = 1;
                  foreach($products as $product){
                      $options = $product->get('options');
                      $resource = $modx->getObject('modResource', $_POST['product_id']);
                      $res['orderProducts'] .= $pdoTools->getChunk('@FILE chunks/shop/editOrderProduct.html', array(
                              'description' => $options['desc']?:$resource->get('description'),
                              'introtexxt' => $resource->get('introtext'),
                              'index' => $i,
                              'add_cost' => $resource->get('add_cost'),
                              'price' => $product->get('price'),
                              'weight' => $product->get('weight'),
                              'count' => $product->get('count'),
                              'name' => $options['name']?:$product->get('name'),
                              'cost' => $product->get('cost'),
                              'id' => $product->get('id'),
                              'options' => $options,
                              'order_id' => $_POST['order_id'],
                              'total_cost' => $totalCost,
                              'product_id' => $resource->get('id')
                          ));
                          $i++;
                  }
                  $res['total_cost'] = $totalCost;
                  $res['duration'] = ceil($totalCost / $modx->getOption('base_cost'));
                  $res = json_encode($res);
                  return $res;
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    5