's.operation',
'cc.marketplace_order_id',
'cc.is_marketplace',
+ 'COALESCE(cc.marketplace_name, mo.marketplace_name, \'Неизвестный МП\') as marketplace_name',
])
->innerJoin('create_checks cc', 's.id = cc.guid')
+ ->leftJoin('marketplace_orders mo', 'cc.marketplace_order_id = mo.marketplace_order_id')
->andWhere(['cc.is_marketplace' => 1])
->andWhere(['>=', 's.date', DateHelper::getDateTimeStartDay($dateFrom, true)])
->andWhere(['<=', 's.date', DateHelper::getDateTimeEndDay($dateTo, true)])
'operation' => Sales::OPERATION_SALE,
'marketplace_order_id' => $order->marketplace_order_id,
'is_marketplace' => 1,
+ 'marketplace_name' => $order->marketplace_name ?? 'Неизвестный МП',
+ 'marketplace_id' => $order->marketplace_id,
];
}
}
/**
- * Группировка продаж МП по магазинам
+ * Группировка продаж МП по магазинам и маркетплейсам
*
* @param array $sales
* @param string $source
foreach ($sales as $sale) {
$storeId1c = $sale['store_id_1c'];
+ $marketplaceName = $sale['marketplace_name'] ?? 'Неизвестный МП';
+ // Инициализируем структуру для магазина, если её нет
if (!isset($grouped[$storeId1c])) {
$grouped[$storeId1c] = [
'store_id_1c' => $storeId1c,
'total_orders' => 0,
'total_summ' => 0,
'source' => $source,
+ 'marketplaces' => [],
'sales' => [],
];
}
+ // Инициализируем структуру для маркетплейса в этом магазине, если её нет
+ if (!isset($grouped[$storeId1c]['marketplaces'][$marketplaceName])) {
+ $grouped[$storeId1c]['marketplaces'][$marketplaceName] = [
+ 'name' => $marketplaceName,
+ 'orders' => 0,
+ 'summ' => 0,
+ ];
+ }
+
$saleAmount = $sale['summ'] - $sale['skidka'];
// Применяем операцию (продажа или возврат)
if ($sale['operation'] === Sales::OPERATION_SALE) {
$grouped[$storeId1c]['total_summ'] += $saleAmount;
$grouped[$storeId1c]['total_orders']++;
+ $grouped[$storeId1c]['marketplaces'][$marketplaceName]['summ'] += $saleAmount;
+ $grouped[$storeId1c]['marketplaces'][$marketplaceName]['orders']++;
} elseif ($sale['operation'] === Sales::OPERATION_RETURN) {
$grouped[$storeId1c]['total_summ'] -= $saleAmount;
+ $grouped[$storeId1c]['marketplaces'][$marketplaceName]['summ'] -= $saleAmount;
}
$grouped[$storeId1c]['sales'][] = $sale;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
+use yii\helpers\Url;
+
+$this->registerCssFile('/css/dashboard/sales.css');
?>
-<h2>Отчет по заказам маркетплейсов и чекам продаж</h2>
+<div class="d-flex justify-content-between align-items-center mb-3">
+ <h2 class="mb-0">Отчет по заказам маркетплейсов и чекам продаж</h2>
+ <a href="<?= Url::to(['dashboard/sales']) ?>" class="btn btn-secondary">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
+ <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
+ </svg> Назад к продажам
+ </a>
+</div>
<?php $searchForm = ActiveForm::begin([
'id' => 'days-search-form-marketplace',
<?php endif; ?>
</div>
-<?php
-// CSS для оформления
-$this->registerCss('
-.marketplace-report-container {
- padding: 15px;
-}
-
-.accordion-button {
- padding: 12px 15px;
- font-size: 14px;
-}
-
-.accordion-button:not(.collapsed) {
- background-color: #f8f9fa;
- color: #000;
-}
-
-.card {
- box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
-}
-
-.card-header {
- font-weight: 500;
- padding: 10px 15px;
-}
-
-.table-hover tbody tr:hover {
- background-color: #f5f5f5;
-}
-
-.badge {
- margin-left: 5px;
- padding: 5px 8px;
- font-size: 11px;
-}
-
-.text-muted {
- color: #999;
-}
-
-.text-success {
- color: #28a745;
-}
-
-.text-danger {
- color: #dc3545;
-}
-
-.text-warning {
- color: #ffc107;
-}
-
-.text-info {
- color: #17a2b8;
-}
-
-h5 {
- border-bottom: 2px solid #e0e0e0;
- padding-bottom: 10px;
- margin-bottom: 15px;
-}
-
-h6 {
- font-weight: 600;
- color: #333;
-}
-');
-?>
-
use yii\helpers\Html;
use yii\widgets\ActiveForm;
+use yii\helpers\Url;
+
+$this->registerCssFile('/css/dashboard/sales.css');
?>
-<h2>Детальный просмотр продаж</h2>
+<div class="d-flex justify-content-between align-items-center mb-3">
+ <h2 class="mb-0">Детальный просмотр продаж</h2>
+ <a href="<?= Url::to(['dashboard/sales']) ?>" class="btn btn-secondary">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
+ <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
+ </svg> Назад к продажам
+ </a>
+</div>
<?php $searchForm = ActiveForm::begin([
'id' => 'days-search-form-detail',
<?php endif; ?>
</div>
-<?php
-// CSS для оформления
-$this->registerCss('
-.sales-detail-container {
- padding: 15px;
-}
-
-.accordion-button {
- padding: 12px 15px;
- font-size: 14px;
-}
-
-.accordion-button:not(.collapsed) {
- background-color: #f8f9fa;
- color: #000;
-}
-
-.table-hover tbody tr:hover {
- background-color: #f5f5f5;
-}
-
-.badge {
- margin-left: 5px;
- padding: 5px 8px;
-}
-
-.text-muted {
- color: #999;
-}
-
-.text-success {
- color: #28a745;
-}
-
-.text-danger {
- color: #dc3545;
-}
-');
-?>
-
use yii_app\helpers\AppArrayHelper;
+$this->registerCssFile('/css/dashboard/sales.css');
$this->registerCssFile('/azea/assets/plugins/time-picker/jquery.timepicker.css');
$this->registerJsFile('/azea/assets/plugins/time-picker/jquery.timepicker.js', ['position' => \yii\web\View::POS_END]);
$this->registerJsFile('/js/dashboard/index.js', ['position' => \yii\web\View::POS_END]);
-$this->registerCss('
-.ui-timepicker-wrapper {
- z-index: 99999999; /* show timepicker over popup fix */
-}
-
-th, .line>td {
- border-right: 1px solid #e8d5d5;
- padding: 0px 4px 0 4px;
-}
-tr.line.bg-danger>td>a.btn {
- border: 1px solid #e8d5d5;
-}
-');
?>
<div class="d-flex justify-content-between align-items-center mb-3">
<thead>
<tr>
<th>Магазин</th>
+ <th>Маркетплейс</th>
<th>Количество заказов</th>
<th>Сумма продаж</th>
<th>Источник данных</th>
$totalMpOrders = 0;
foreach ($marketplaceSales as $storeId1c => $data):
$storeName = $city_stores[$storeId1c] ?? 'Неизвестный магазин';
- $totalMpSumm += $data['total_summ'];
- $totalMpOrders += $data['total_orders'];
+ $isFirstRow = true;
+ $rowCount = count($data['marketplaces']);
+
+ foreach ($data['marketplaces'] as $marketplaceName => $mpData):
+ $totalMpSumm += $mpData['summ'];
+ $totalMpOrders += $mpData['orders'];
?>
<tr>
- <td><?= $storeName ?></td>
- <td><?= $data['total_orders'] ?></td>
- <td><?= number_format($data['total_summ'], 2, '.', ' ') ?> руб</td>
- <td>
- <span class="badge bg-<?= $data['source'] === 'checks' ? 'success' : 'warning' ?>">
- <?= $data['source'] === 'checks' ? 'Чеки (1С)' : 'Заказы МП' ?>
- </span>
- </td>
+ <?php if ($isFirstRow): ?>
+ <td rowspan="<?= $rowCount ?>"><?= $storeName ?></td>
+ <?php endif; ?>
+ <td><?= htmlspecialchars($marketplaceName) ?></td>
+ <td><?= $mpData['orders'] ?></td>
+ <td><?= number_format($mpData['summ'], 2, '.', ' ') ?> руб</td>
+ <?php if ($isFirstRow): ?>
+ <td rowspan="<?= $rowCount ?>">
+ <span class="badge bg-<?= $data['source'] === 'checks' ? 'success' : 'warning' ?>">
+ <?= $data['source'] === 'checks' ? 'Чеки (1С)' : 'Заказы МП' ?>
+ </span>
+ </td>
+ <?php endif; ?>
</tr>
- <?php endforeach; ?>
+ <?php
+ $isFirstRow = false;
+ endforeach;
+ endforeach;
+ ?>
</tbody>
<tfoot>
<tr class="bg-success">
- <th>Итого</th>
+ <th colspan="2">Итого</th>
<th><?= $totalMpOrders ?></th>
<th><?= number_format($totalMpSumm, 2, '.', ' ') ?> руб</th>
<th></th>
--- /dev/null
+/* Стили для страницы продаж (sales.php) */
+.ui-timepicker-wrapper {
+ z-index: 99999999; /* show timepicker over popup fix */
+}
+
+th, .line>td {
+ border-right: 1px solid #e8d5d5;
+ padding: 0px 4px 0 4px;
+}
+
+tr.line.bg-danger>td>a.btn {
+ border: 1px solid #e8d5d5;
+}
+
+/* Стили для детального просмотра продаж (sales-detail.php) */
+.sales-detail-container {
+ padding: 15px;
+}
+
+.sales-detail-container .accordion-button {
+ padding: 12px 15px;
+ font-size: 14px;
+}
+
+.sales-detail-container .accordion-button:not(.collapsed) {
+ background-color: #f8f9fa;
+ color: #000;
+}
+
+.sales-detail-container .table-hover tbody tr:hover {
+ background-color: #f5f5f5;
+}
+
+.sales-detail-container .badge {
+ margin-left: 5px;
+ padding: 5px 8px;
+}
+
+.sales-detail-container .text-muted {
+ color: #999;
+}
+
+.sales-detail-container .text-success {
+ color: #28a745;
+}
+
+.sales-detail-container .text-danger {
+ color: #dc3545;
+}
+
+/* Стили для отчета по маркетплейсам (marketplace-sales-report.php) */
+.marketplace-report-container {
+ padding: 15px;
+}
+
+.marketplace-report-container .accordion-button {
+ padding: 12px 15px;
+ font-size: 14px;
+}
+
+.marketplace-report-container .accordion-button:not(.collapsed) {
+ background-color: #f8f9fa;
+ color: #000;
+}
+
+.marketplace-report-container .card {
+ box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
+}
+
+.marketplace-report-container .card-header {
+ font-weight: 500;
+ padding: 10px 15px;
+}
+
+.marketplace-report-container .table-hover tbody tr:hover {
+ background-color: #f5f5f5;
+}
+
+.marketplace-report-container .badge {
+ margin-left: 5px;
+ padding: 5px 8px;
+ font-size: 11px;
+}
+
+.marketplace-report-container .text-muted {
+ color: #999;
+}
+
+.marketplace-report-container .text-success {
+ color: #28a745;
+}
+
+.marketplace-report-container .text-danger {
+ color: #dc3545;
+}
+
+.marketplace-report-container .text-warning {
+ color: #ffc107;
+}
+
+.marketplace-report-container .text-info {
+ color: #17a2b8;
+}
+
+.marketplace-report-container h5 {
+ border-bottom: 2px solid #e0e0e0;
+ padding-bottom: 10px;
+ margin-bottom: 15px;
+}
+
+.marketplace-report-container h6 {
+ font-weight: 600;
+ color: #333;
+}
+