From: Alexander Smirnov Date: Fri, 16 Aug 2024 06:53:16 +0000 (+0300) Subject: Merge branch 'develop' into feature_smirnov_erp-137_motivation_forecast X-Git-Tag: 1.4~36^2 X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=b70d791c019850d12d6f04194a6e3837e61f03b2;p=erp24_rep%2Fyii-erp24%2F.git Merge branch 'develop' into feature_smirnov_erp-137_motivation_forecast # Conflicts: # erp24/actions/motivation/IndexAction.php # erp24/services/MotivationService.php --- b70d791c019850d12d6f04194a6e3837e61f03b2 diff --cc erp24/actions/motivation/IndexAction.php index 09bd0915,dee7445f..65c51637 --- a/erp24/actions/motivation/IndexAction.php +++ b/erp24/actions/motivation/IndexAction.php @@@ -90,9 -90,9 +90,12 @@@ class IndexAction extends Actio // Подсчитываем стоимость услуг по сборке и по доставке. Позже метод будет перенесён в шедулер MotivationService::calculateServiceAssemblyAndDeliveryCost($model->store_id, $model->year, $model->month); + // Сбор данных по продажам + MotivationService::calculateSales($model->store_id, $model->year, $model->month); + + // Подсчитываем прогноз за месяц + MotivationService::calculateMonthForecast($model->store_id, $model->year, $model->month); + $showTable = false; $motivationData = []; $daysInMonth = null; diff --cc erp24/services/MotivationService.php index 67f58551,9344aec8..3d358fc4 --- a/erp24/services/MotivationService.php +++ b/erp24/services/MotivationService.php @@@ -519,57 -520,68 +519,122 @@@ class MotivationServic } } + public static function calculateSales($store_id, $year, $month) { + $monthStart = date("Y-m-d 00:00:00", strtotime($year . '-' . $month . '-1')); + $monthEnd = date("Y-m-t 23:59:59", strtotime($year . '-' . $month . '-1')); + + foreach (range(1, 5) as $ind) { + $weekStart = date("Y-m-d 00:00:00", strtotime("+" . (($ind - 1) * 7) . ' days', strtotime($monthStart))); + $weekEnd = date("Y-m-d 23:59:59", strtotime("+" . ($ind * 7 - 1) . ' days', strtotime($monthStart))); + if ($weekEnd > $monthEnd) { + $weekEnd = $monthEnd; + } + + $sales = Sales::find() + ->where(['between', 'date', $weekStart, $weekEnd]) + ->andWhere(['store_id' => $store_id]) + ->andWhere(['operation' => Sales::OPERATION_SALE]) + ->asArray()->all(); + $salesIds = ArrayHelper::getColumn($sales, 'id'); + + // Ищем чеки-возврат на текущие чеки + $returnSales = Sales::find()->where(['operation' => Sales::OPERATION_RETURN, 'sales_check' => $salesIds])->all(); + $returnSalesIds = ArrayHelper::getColumn($returnSales, 'sales_check'); + + // Offline sales + $salesOffline = Sales::find()->select(['SUM(summ) as total']) + ->where(['between', 'date', $weekStart, $weekEnd]) + ->andWhere(['order_id' => ['', '0']]) + ->andWhere(['store_id' => $store_id]) + ->andWhere(['operation' => Sales::OPERATION_SALE]) + ->andWhere(['NOT IN', 'id', $returnSalesIds]) + ->asArray()->one(); + + // Online sales + $salesOnline = Sales::find()->select(['SUM(summ) as total']) + ->where(['between', 'date', $weekStart, $weekEnd]) + ->andWhere(['NOT IN', 'order_id', ['', '0']]) + ->andWhere(['store_id' => $store_id]) + ->andWhere(['operation' => Sales::OPERATION_SALE]) + ->andWhere(['NOT IN', 'id', $returnSalesIds]) + ->asArray()->one(); + + $motivation = Motivation::find()->where(['store_id' => $store_id, 'year' => $year, 'month' => $month])->one(); + $motivationValueGroup = MotivationValueGroup::find()->where(['alias' => 'week' . $ind])->one(); + foreach (['Оффлайн продажи', 'Онлайн продажи'] as $topicInd => $topic) { + $motivationCostsItem = MotivationCostsItem::find()->where(['name' => $topic])->one(); + /** @var $motivationCostsItem MotivationCostsItem */ + if ($motivation) { + $motivationValue = MotivationValue::find()->where(['motivation_id' => $motivation->id, + 'motivation_group_id' => $motivationValueGroup->id, 'value_id' => $motivationCostsItem->code])->one(); + if (!$motivationValue) { + $motivationValue = new MotivationValue; + $motivationValue->motivation_id = $motivation->id; + $motivationValue->motivation_group_id = $motivationValueGroup->id; + $motivationValue->value_id = $motivationCostsItem->code; + $motivationValue->value_type = $motivationCostsItem->data_type; + } + $motivationValue->value_float = [$salesOffline, $salesOnline][$topicInd]['total']; + $motivationValue->save(); + if ($motivationValue->getErrors()) { + throw new \Exception(Json::encode($motivationValue->getErrors())); + } + } + } + } + } ++ + public static function calculateMonthForecast($store_id, $year, $month) { + $motivationCostsItem = MotivationCostsItem::find()->all(); + $motivationCostsItemCodes = ArrayHelper::getColumn($motivationCostsItem, 'code'); + $additionalItemsKeys = array_keys(self::$additionalItems); + + $items = array_merge($motivationCostsItemCodes, $additionalItemsKeys); + + $motivationValueGroups = []; + foreach (range(1, 5) as $ind) { + $motivationValueGroups []= MotivationValueGroup::find()->where(['alias' => 'week' . $ind])->one(); + } + /** @var $motivationValueGroups MotivationValueGroup[] */ + + $motivationValueGroupForecast = MotivationValueGroup::find()->where(['alias' => 'forecast'])->one(); + /** @var $motivationValueGroupForecast MotivationValueGroup */ + + $motivation = Motivation::find()->where(['store_id' => $store_id, 'year' => $year, 'month' => $month])->one(); + foreach ($items as $code) { + if ($motivation) { + $motivationValue = MotivationValue::find()->where(['motivation_id' => $motivation->id, + 'motivation_group_id' => $motivationValueGroupForecast->id, 'value_id' => $code])->one(); + $sum = 0; + $sum_type = MotivationCostsItem::DATA_TYPE_INT; + foreach (range(1, 5) as $ind) { + $mv = MotivationValue::find()->where(['motivation_id' => $motivation->id, + 'motivation_group_id' => $motivationValueGroups[$ind-1]->id, 'value_id' => $code])->one(); + /** @var $mv MotivationValue */ + if ($mv) { + switch ($mv->value_type) { + case MotivationCostsItem::DATA_TYPE_INT: { $sum += $mv->value_int; break; } + case MotivationCostsItem::DATA_TYPE_FLOAT: { $sum += $mv->value_float; $sum_type = MotivationCostsItem::DATA_TYPE_FLOAT; break; } + case MotivationCostsItem::DATA_TYPE_STRING: { throw new \Exception(Json::encode("Тип string невозможен для вычисления прогноза")); } + }; + } + } + if (!$motivationValue) { + $motivationValue = new MotivationValue; + $motivationValue->motivation_id = $motivation->id; + $motivationValue->motivation_group_id = $motivationValueGroupForecast->id; + $motivationValue->value_id = $code; + } + $motivationValue->value_type = $sum_type; + switch ($sum_type) { + case MotivationCostsItem::DATA_TYPE_INT: { $motivationValue->value_int = $sum; break; } + default: { $motivationValue->value_float = $sum; break; } + } + $motivationValue->save(); + if ($motivationValue->getErrors()) { + throw new \Exception(Json::encode($motivationValue->getErrors())); + } + } + } + } }