+++ /dev/null
-<?php
-
-namespace yii_app\jobs;
-
-use DateTime;
-use Throwable;
-use yii\base\BaseObject;
-use yii\helpers\ArrayHelper;
-use yii\queue\JobInterface;
-use yii_app\records\Autoplannogramma;
-use yii_app\records\CityStore;
-use yii_app\services\AutoPlannogrammaService;
-
-class RebuildAutoplannogramJob extends BaseObject implements JobInterface
-{
- public int $year;
- public int $month;
- public int $storeId;
-
- public function execute($queue)
- {
- $service = new AutoPlannogrammaService();
-
- $date = (new DateTime())->setDate($this->year, $this->month, 1);
- $planDate = $date->format('Y-m-01');
-
- /** @var CityStore $store */
- $store = CityStore::findOne($this->storeId);
- if (!$store) {
- throw new \RuntimeException("Store #{$this->storeId} not found");
- }
-
- try {
-
- $forecastParams = [
- 'month' => $this->month,
- 'year' => $this->year,
- 'type' => AutoPlannogrammaService::TYPE_SALES,
- 'store_id' => $this->storeId,
- 'category' => 'Срезка',
- 'subcategory' => null,
- 'species' => null,
- 'plan_date' => $planDate,
- ];
- $forecast = $service->calculateFullForecastForWeek($forecastParams);
- $writeOffsForecast = $service->getWeeklyProductsWriteoffsForecast(
- $this->month, $this->year, $forecast, $this->storeId
- );
- $salesForecast = $service->getWeeklyBouquetProductsSalesForecast(
- $this->month, $this->year, $this->storeId
- );
-
- $existing = Autoplannogramma::find()
- ->where([
- 'store_id' => $this->storeId,
- 'year' => $this->year,
- 'month' => $this->month,
- 'week' => array_unique(ArrayHelper::getColumn($forecast, 'week')),
- ])
- ->indexBy(fn($m) => $m->week . '_' . $m->product_id)
- ->all();
-
- foreach ($forecast as $item) {
- $key = $item['week'] . '_' . $item['product_id'];
- $model = $existing[$key] ?? new Autoplannogramma();
- $quantity = (float)($item['forecast_week_pieces'] ?? 0);
- $details = [];
- $total = $quantity;
-
- if (!empty($writeOffsForecast[$item['product_id']][$item['week']]['writeOffs'])) {
- $w = $writeOffsForecast[$item['product_id']][$item['week']]['writeOffs'];
- $details['writeOffs']['quantity'] = $w;
- $total += is_array($w) ? array_sum($w) : (float)$w;
- }
-
- foreach (['offline','online','marketplace'] as $t) {
- $block = ['share'=>0,'quantity'=>0,'groups'=>[]];
- if (!empty($salesForecast[$this->storeId][$item['product_id']][$t])) {
- $share = $salesForecast[$this->storeId][$t]['share'] ?? 0;
- $block['share'] = $share;
- $block['quantity'] = round($quantity * $share,2);
- $total += $block['quantity'];
-
- foreach ($salesForecast[$this->storeId][$item['product_id']][$t] as $k=>$v) {
- $block['groups'][$k] = (float)$v;
- $total += (float)$v;
- }
- }
- $details[$t] = $block;
- }
-
- $details['forecast'] = ['quantity' => $quantity];
- $total = (float) sprintf('%.2f', $total);
-
- $needsUpdate = $model->isNewRecord
- || $model->calculate != $quantity
- || ceil($model->total) != ceil($total)
- || json_encode($model->details, JSON_UNESCAPED_UNICODE)
- !== json_encode($details, JSON_UNESCAPED_UNICODE);
-
- if ($needsUpdate) {
- $model->setAttributes([
- 'year' => $this->year,
- 'month' => $this->month,
- 'week' => $item['week'],
- 'product_id' => $item['product_id'],
- 'store_id' => $this->storeId,
- 'is_archive' => false,
- 'capacity_type' => 1,
- 'details' => json_encode($details, JSON_UNESCAPED_UNICODE),
- 'calculate' => $quantity,
- 'modify' => ceil($total),
- 'total' => ceil($total),
- ]);
- if (!$model->save()) {
- \Yii::error(
- 'Ошибка сохранения Autoplannogramma: '
- . json_encode($model->getErrors(), JSON_UNESCAPED_UNICODE),
- __METHOD__
- );
- }
- }
- }
- } catch (Throwable $e) {
- \Yii::error("Job failed: " . $e->getMessage(), __METHOD__);
- }
- }
-}
\ No newline at end of file