From d0d28935beb623f4c593329f75c578343b18efe2 Mon Sep 17 00:00:00 2001 From: Vladimir Fomichev Date: Thu, 6 Nov 2025 14:27:15 +0300 Subject: [PATCH] =?utf8?q?=D0=92=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80?= =?utf8?q?=D0=BE=D0=B4=D0=B0=D0=B6=20=D0=BF=D0=BE=20=D0=9C=D0=9F=20=D0=B2?= =?utf8?q?=20=D0=BE=D1=82=D1=87=D0=B5=D1=82=D0=B5=20/dashboard/sales?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- erp24/actions/dashboard/SalesAction.php | 7 +- erp24/records/CreateChecks.php | 18 +++ erp24/records/Sales.php | 9 ++ .../MarketplaceSalesMatchingService.php | 144 ++++++++++++++++++ erp24/views/dashboard/sales.php | 47 ++++++ 5 files changed, 224 insertions(+), 1 deletion(-) diff --git a/erp24/actions/dashboard/SalesAction.php b/erp24/actions/dashboard/SalesAction.php index 670f9f2f..8f5b5464 100755 --- a/erp24/actions/dashboard/SalesAction.php +++ b/erp24/actions/dashboard/SalesAction.php @@ -207,6 +207,10 @@ class SalesAction extends Action $sales_delivery = $salesService->salesSumCalculate($salesSumDelivery); + // Получение продаж МП + $marketplaceSalesService = new \yii_app\services\MarketplaceSalesMatchingService(); + $marketplaceSales = $marketplaceSalesService->getMarketplaceSalesByStore($date1, $date2); + $salesSumWithCity = $dashboardService->getSalesSumWithCityStoreId($sales_summ, $plan, $city_stores); $sales = ArrayHelper::getValue($salesSumWithCity, 'sales'); @@ -319,7 +323,8 @@ class SalesAction extends Action 'servises' => $servises, 'saleServices' => $saleServices, 'daysSearchForm' => $daysSearchForm, - 'admins' => $admins + 'admins' => $admins, + 'marketplaceSales' => $marketplaceSales, ]; return $this->controller->render('/dashboard/sales.php', $params); diff --git a/erp24/records/CreateChecks.php b/erp24/records/CreateChecks.php index a62ea1eb..edd3ee29 100644 --- a/erp24/records/CreateChecks.php +++ b/erp24/records/CreateChecks.php @@ -90,4 +90,22 @@ class CreateChecks extends \yii\db\ActiveRecord 'marketplace_name' => 'Marketplace Name', ]; } + + /** + * Связь с продажей из 1С + * @return \yii\db\ActiveQueryInterface + */ + public function getSale() + { + return $this->hasOne(Sales::class, ['id' => 'guid']); + } + + /** + * Связь с заказом МП + * @return \yii\db\ActiveQueryInterface + */ + public function getMarketplaceOrder() + { + return $this->hasOne(MarketplaceOrders::class, ['marketplace_order_id' => 'marketplace_order_id']); + } } diff --git a/erp24/records/Sales.php b/erp24/records/Sales.php index 32670e43..f5dfeec1 100755 --- a/erp24/records/Sales.php +++ b/erp24/records/Sales.php @@ -144,4 +144,13 @@ class Sales extends \yii\db\ActiveRecord return $this->hasOne(self::class, ['id' => 'sales_check']) ->from(self::tableName() . ' sc'); } + + /** + * Связь с чеком создания (create_checks) + * @return \yii\db\ActiveQueryInterface + */ + public function getCreateCheck() + { + return $this->hasOne(CreateChecks::class, ['guid' => 'id']); + } } \ No newline at end of file diff --git a/erp24/services/MarketplaceSalesMatchingService.php b/erp24/services/MarketplaceSalesMatchingService.php index 3b3ac07f..8815353b 100644 --- a/erp24/services/MarketplaceSalesMatchingService.php +++ b/erp24/services/MarketplaceSalesMatchingService.php @@ -467,5 +467,149 @@ class MarketplaceSalesMatchingService $productsArr = Products1c::getProductsFromClass(['wrap']); return $productsArr['wrap'] ?? []; } + + /** + * Получить продажи МП из таблицы sales через create_checks + * + * @param string $dateFrom + * @param string $dateTo + * @return array + * @throws \Exception + */ + public function getMarketplaceSalesFromChecks(string $dateFrom, string $dateTo): array + { + $query = Sales::find() + ->alias('s') + ->select([ + 's.id', + 's.date', + 's.summ', + 's.skidka', + 's.store_id_1c', + 's.operation', + 'cc.marketplace_order_id', + 'cc.is_marketplace', + ]) + ->innerJoin('create_checks cc', 's.id = cc.guid') + ->andWhere(['cc.is_marketplace' => 1]) + ->andWhere(['>=', 's.date', DateHelper::getDateTimeStartDay($dateFrom, true)]) + ->andWhere(['<=', 's.date', DateHelper::getDateTimeEndDay($dateTo, true)]) + ->orderBy(['s.date' => SORT_DESC]); + + return $query->asArray()->all(); + } + + /** + * Получить продажи МП из завершенных заказов (fallback) + * + * @param string $dateFrom + * @param string $dateTo + * @return array + * @throws \Exception + */ + public function getMarketplaceSalesFromOrders(string $dateFrom, string $dateTo): array + { + $orders = $this->getMarketplaceOrdersForPeriod($dateFrom, $dateTo); + + $result = []; + foreach ($orders as $order) { + // Получаем store_id_1c через связь + $storeId1c = null; + if ($order->store && $order->store->storeGuid) { + $storeId1c = $order->store->storeGuid->export_val; + } + + if (empty($storeId1c)) { + continue; + } + + $result[] = [ + 'id' => $order->id, + 'date' => $order->updated_at, + 'summ' => $order->total, + 'skidka' => 0, + 'store_id_1c' => $storeId1c, + 'operation' => Sales::OPERATION_SALE, + 'marketplace_order_id' => $order->marketplace_order_id, + 'is_marketplace' => 1, + ]; + } + + return $result; + } + + /** + * Получить продажи МП по магазинам с автоматическим выбором источника + * + * @param string $dateFrom + * @param string $dateTo + * @return array + * @throws \Exception + */ + public function getMarketplaceSalesByStore(string $dateFrom, string $dateTo): array + { + // Сначала пытаемся получить из чеков + $salesFromChecks = $this->getMarketplaceSalesFromChecks($dateFrom, $dateTo); + + $sales = []; + $source = 'orders'; // По умолчанию fallback + + if (!empty($salesFromChecks)) { + // Если есть чеки МП, используем их + $sales = $salesFromChecks; + $source = 'checks'; + } else { + // Fallback: используем заказы МП + $sales = $this->getMarketplaceSalesFromOrders($dateFrom, $dateTo); + } + + // Группируем по магазинам + return $this->groupMarketplaceSalesByStore($sales, $source); + } + + /** + * Группировка продаж МП по магазинам + * + * @param array $sales + * @param string $source + * @return array + */ + private function groupMarketplaceSalesByStore(array $sales, string $source): array + { + $grouped = []; + + foreach ($sales as $sale) { + $storeId1c = $sale['store_id_1c']; + + if (!isset($grouped[$storeId1c])) { + $grouped[$storeId1c] = [ + 'store_id_1c' => $storeId1c, + 'total_orders' => 0, + 'total_summ' => 0, + 'source' => $source, + 'sales' => [], + ]; + } + + $saleAmount = $sale['summ'] - $sale['skidka']; + + // Применяем операцию (продажа или возврат) + if ($sale['operation'] === Sales::OPERATION_SALE) { + $grouped[$storeId1c]['total_summ'] += $saleAmount; + $grouped[$storeId1c]['total_orders']++; + } elseif ($sale['operation'] === Sales::OPERATION_RETURN) { + $grouped[$storeId1c]['total_summ'] -= $saleAmount; + } + + $grouped[$storeId1c]['sales'][] = $sale; + } + + // Сортировка по сумме (убывание) + uasort($grouped, function ($a, $b) { + return $b['total_summ'] <=> $a['total_summ']; + }); + + return $grouped; + } } diff --git a/erp24/views/dashboard/sales.php b/erp24/views/dashboard/sales.php index 7c992bd3..fd680bfb 100755 --- a/erp24/views/dashboard/sales.php +++ b/erp24/views/dashboard/sales.php @@ -316,4 +316,51 @@ foreach($sales_delivery as $storeId => $summ) { } echo" Итого $itog руб по доставке"; +?> + + +
Продажи маркетплейсов
+
+ + + + + + + + + + + $data): + $storeName = $city_stores[$storeId1c] ?? 'Неизвестный магазин'; + $totalMpSumm += $data['total_summ']; + $totalMpOrders += $data['total_orders']; + ?> + + + + + + + + + + + + + + + + +
МагазинКоличество заказовСумма продажИсточник данных
руб + + + +
Итого руб
+
+Итого руб по маркетплейсам + -- 2.39.5