use Yii;
use yii\base\Exception;
use yii\data\ArrayDataProvider;
+use yii\db\Expression;
+use yii\db\Query;
use yii_app\records\MarketplaceOrders;
use yii_app\records\MarketplaceOrdersSearch;
use yii\web\Controller;
'dataProvider' => $data,
]);
}
+
+ public function actionGetBouquetComposition($order_id, $source)
+ {
+ if ($source == 'amo') {
+ $query = (new \yii\db\Query())
+ ->select([
+ 'guid' => new \yii\db\Expression("item->>'guid'"),
+ 'name' => new \yii\db\Expression("item->>'name'"),
+ 'price' => new \yii\db\Expression("(item->>'price')::NUMERIC"),
+ 'quantity' => new \yii\db\Expression("(item->>'quantity')::NUMERIC")
+ ])
+ ->from(['orders_amo'])
+ ->leftJoin(['bouquet' => new \yii\db\Expression('jsonb_array_elements(products_json::jsonb)')], 'TRUE') // первый JSON-массив
+ ->leftJoin(['item' => new \yii\db\Expression('jsonb_array_elements(bouquet->\'items\')')], 'TRUE') // второй JSON-массив в элементе
+ ->where(['id' => $order_id]) // фильтр по id
+ ->all();
+ } else {
+ $query = (new Query())
+ ->select([
+ new Expression("item->>'guid' AS guid"),
+ new Expression("item->>'name' AS name"),
+ new Expression("(item->>'price')::NUMERIC AS price"),
+ new Expression("(item->>'quantity')::NUMERIC AS quantity")
+ ])
+ ->from(new Expression("
+ marketplace_order_items moi
+ LEFT JOIN products_1c p1c ON moi.offer_id = p1c.articule
+ LEFT JOIN LATERAL jsonb_array_elements(
+ COALESCE(NULLIF(p1c.components, '')::jsonb, '[]'::jsonb)
+ ) AS item ON TRUE
+ "))
+ ->where(['moi.order_id' => $order_id])
+ ->all();
+ }
+
+ return $this->asJson($query);
+ }
}
'price',
'delivery_adress as delivery_address',
new \yii\db\Expression("
- COALESCE((
- SELECT jsonb_agg(jsonb_build_object(
- 'name', bouquet->>'name',
- 'price', bouquet->>'price',
- 'quantity', bouquet->>'count',
- 'items', (
- SELECT jsonb_agg(jsonb_build_object(
- 'guid', item->>'guid',
- 'name', item->>'name',
- 'price', (item->>'price')::NUMERIC,
- 'quantity', (item->>'quantity')::NUMERIC
- ))
- FROM jsonb_array_elements(bouquet->'items') AS item
- )
- ))
- FROM jsonb_array_elements(COALESCE(NULLIF(o.products_json, '')::jsonb, '[]'::jsonb)) AS bouquet
- ), '[]'::jsonb) AS products_json
- ")
+ COALESCE((
+ SELECT jsonb_agg(jsonb_build_object(
+ 'name', bouquet->>'name'
+ ))
+ FROM jsonb_array_elements(COALESCE(NULLIF(o.products_json, '')::jsonb, '[]'::jsonb)) AS bouquet
+ ), '[]'::jsonb) AS products_json
+ ")
])
->from('orders_amo o');
$queryMarketplace = (new Query())
->select([
new \yii\db\Expression("
- CASE
- WHEN ms.warehouse_id = 2 THEN 'yandex'
- WHEN ms.warehouse_id = 1 THEN 'flowwow'
- ELSE 'Marketplace'
- END AS source"),
+ CASE
+ WHEN ms.warehouse_id = 2 THEN 'yandex'
+ WHEN ms.warehouse_id = 1 THEN 'flowwow'
+ ELSE 'Marketplace'
+ END AS source"),
'mo.id',
'mod.delivery_end AS delivery_date',
'mo.status_id',
'mo.total',
new \yii\db\Expression("NULLIF(concat(country, ' ', city, ' ', street, ' ', house, ' ', apartment), '')::TEXT AS delivery_address"),
new \yii\db\Expression("(
- SELECT jsonb_agg(jsonb_build_object(
- 'name', bouquet.name,
- 'price', bouquet.price,
- 'quantity', bouquet.quantity,
- 'items', COALESCE(items_list, '[]'::jsonb)
- ))
- FROM (
- SELECT
- p1c.name,
- pd.price,
- SUM(items.value::INTEGER) AS quantity,
- jsonb_agg(jsonb_build_object(
- 'guid', p2c.id::TEXT,
- 'name', p2c.name,
- 'price', pd.price,
- 'quantity', items.value::INTEGER
- )) FILTER (WHERE p2c.id IS NOT NULL) AS items_list
- FROM erp24.products_1c p1c
- JOIN marketplace_order_items moi ON p1c.articule = moi.offer_id
- LEFT JOIN LATERAL jsonb_each_text(
- COALESCE(NULLIF(p1c.components, '')::jsonb, '{}'::jsonb)
- ) AS items ON true
- LEFT JOIN erp24.products_1c p2c ON p2c.id::TEXT = items.key
- LEFT JOIN prices_dynamic pd ON p2c.id = pd.product_id
- WHERE moi.order_id = mo.id
- GROUP BY p1c.name, pd.price
- ) AS bouquet
- ) AS products_json")
+ SELECT jsonb_agg(jsonb_build_object(
+ 'name', bouquet.name
+ ))
+ FROM (
+ SELECT
+ p1c.name
+ FROM erp24.products_1c p1c
+ JOIN marketplace_order_items moi ON p1c.articule = moi.offer_id
+ WHERE moi.order_id = mo.id
+ GROUP BY p1c.name
+ ) AS bouquet
+ ) AS products_json")
])
->from(['mo' => 'marketplace_orders'])
->leftJoin(['mod' => 'marketplace_order_delivery'], 'mo.id = mod.order_id')
->leftJoin(['ms' => 'marketplace_store'], 'ms.warehouse_guid::TEXT = mo.warehouse_guid::TEXT');
+
$query = (new Query())
->andFilterWhere(['source' => $params['source'] ?? null])
->andFilterWhere(['store_id' => $params['store_id'] ?? null])
use yii_app\records\OrdersAmo;
$this->title = 'Все заказы';
+
+$this->registerJsFile('/js/marketplace-orders/marketplace-orders.js', ['position' => \yii\web\View::POS_END]);
+?>
?>
<div class="all-orders p-5">
<h1><?= Html::encode($this->title) ?></h1>
],
[
'attribute' => 'products_json',
- 'label' => 'СоÑ\81Ñ\82ав',
+ 'label' => 'Ð\91Ñ\83кеÑ\82Ñ\8b',
'format' => 'raw',
'value' => function ($model) {
$products = json_decode($model['products_json'], true);
return '<i>(Нет данных)</i>';
}
- $output = '';
+ $output = '<ul class="bouquet-list">';
foreach ($products as $product) {
- $output .= "<h4>{$product['name']}</h4>";
- $output .= '<table class="table table-bordered"><tr><th>Название</th><th>Кол-во</th><th>Цена</th></tr>';
- foreach ($product['items'] as $item) {
- $output .= "<tr><td>{$item['name']}</td><td>{$item['quantity']}</td><td>{$item['price']} ₽</td></tr>";
- }
- $output .= '</table>';
+ $bouquetName = htmlspecialchars($product['name']);
+ $id = md5($bouquetName . $model['id']); // Уникальный идентификатор для контейнера
+ $dataId = $model['id']; // Допустим, вы хотите использовать 'guid' как data-id
+ $dataSource = $model['source']; // Это пример поля, которое можно использовать для data-source. Убедитесь, что оно существует в модели.
+
+ $output .= "<li>
+ <span>{$bouquetName}</span>
+ <button class='btn btn-link toggle-composition' data-bouquet='{$bouquetName}'
+ data-order='{$model['id']}'
+ data-id='{$dataId}' data-source='{$dataSource}'>
+ ▼
+ </button>
+ <div id='composition-{$id}' class='composition-container' style='display: none;'></div>
+ </li>";
}
+ $output .= '</ul>';
return $output;
}
],
+
],
]); ?>
</div>
--- /dev/null
+$(".toggle-composition").on("click", function () {
+ var button = $(this);
+ var orderId = button.data("id"); // Получаем ID заказа
+ var source = button.data("source"); // Получаем источник данных
+
+ // Если уже открыто — скрываем
+ if (button.next(".composition-content").length) {
+ button.next(".composition-content").slideUp(300, function () {
+ $(this).remove();
+ button.html("▼"); // Стрелка вниз
+ });
+ return;
+ }
+
+ $(".composition-content").remove();
+
+ $.ajax({
+ url: "/marketplace-orders/get-bouquet-composition",
+ type: "GET",
+ data: {
+ order_id: orderId,
+ source: source
+ },
+ beforeSend: function () {
+ button.html("⌛"); // Значок загрузки
+ },
+ success: function (response) {
+ // Проверяем, есть ли данные
+ if (!response || response.length === 0 || response.every(item => !item.guid)) {
+ button.after("<div class='composition-content text-muted' style='display: none;'>Нет данных</div>");
+ button.next(".composition-content").slideDown();
+ button.html("▼"); // Стрелка вниз
+ return;
+ }
+
+ // Создаем HTML-таблицу
+ var tableHtml = `
+ <div class="composition-content" style="display: none; margin-top: 5px;">
+ <table class="table table-bordered mt-2">
+ <thead>
+ <tr>
+ <th>Название</th>
+ <th>Цена</th>
+ <th>Кол-во</th>
+ <th>Сумма</th>
+ </tr>
+ </thead>
+ <tbody>
+ `;
+
+ response.forEach(function (item) {
+ tableHtml += `
+ <tr>
+ <td>${item.name || '-'}</td>
+ <td>${item.price ? parseFloat(item.price).toFixed(2) + ' ₽' : '-'}</td>
+ <td>${item.quantity ? parseFloat(item.quantity) : '-'}</td>
+ <td>${(item.price && item.quantity) ? (parseFloat(item.price) * parseFloat(item.quantity)).toFixed(2) + ' ₽' : '-'}</td>
+ </tr>
+ `;
+ });
+
+ tableHtml += `
+ </tbody>
+ </table>
+ </div>
+ `;
+
+ // Вставляем таблицу после кнопки
+ button.after(tableHtml);
+ button.next(".composition-content").slideDown();
+ button.html("▲"); // Стрелка вверх
+ },
+ error: function () {
+ button.after("<div class='composition-content text-danger' style='display: none;'>Ошибка загрузки данных.</div>");
+ button.next(".composition-content").slideDown();
+ button.html("▼"); // Стрелка вниз
+ }
+ });
+});