$grouped = [];
foreach ($weeksProductForecast as $item) {
- $productId = $item['product_guid'];
+ $productId = $item['product_id'];
$week = $item['week'];
$type = 'writeOffs';
$forecastValue = $item['forecast'];
- $grouped[$productId][$week][$type] = $forecastValue;
+ $grouped[$productId][$week][$type] = ceil($forecastValue);
}
}
/**
- * Рассчитывает долю списания (write-offs) каждого товара за заданный месяц
- * на оÑ\81новании иÑ\81Ñ\82оÑ\80иÑ\87еÑ\81киÑ\85 даннÑ\8bÑ\85 за два пÑ\80едÑ\8bдÑ\83Ñ\89иÑ\85 года.
+ * Рассчитывает долю списания товаров за целевой месяц,
+ * иÑ\81полÑ\8cзÑ\83Ñ\8f взвеÑ\88еннÑ\8bе даннÑ\8bе за Ñ\82Ñ\80и пÑ\80едÑ\8bдÑ\83Ñ\89иÑ\85 меÑ\81Ñ\8fÑ\86а.
*
- * @param array $productList Список товаров:
+ * @param array $productList Список товаров с ключами:
+ * ['store_id', 'category', 'subcategory', 'species', 'product_id', …]
+ * @param int $month Целевой месяц (1–12)
+ * @param int $year Целевой год (например, 2025)
+ * @return array [
* [
- * [
- * 'week' => int,
- * 'store_id' => int,
- * 'category' => string,
- * 'subcategory' => string,
- * 'species' => string,
- * 'product_id' => string,
- * 'forecast_month_pieces' => float,
- * 'forecast_week_pieces' => float,
- * ], …
- * ]
- * @param string $monthYear Формат 'YYYY-MM'
- * @return array [
- * [
- * 'store_id' => int,
- * 'month' => int,
- * 'year' => int,
- * 'category' => string,
- * 'subcategory'=> string,
- * 'species' => string,
- * 'product_id' => string,
- * 'writeoff_qty' => float,
- * 'species_qty' => float,
- * 'share' => float, // доля
- * ], …
- * ]
+ * 'store_id', 'month', 'year',
+ * 'category','subcategory','species',
+ * 'product_id','writeoff_qty','species_qty','share'
+ * ],
+ * …
+ * ]
*/
- public function calculateWriteOffShareByMonth(array $productList, int $month, int $year ): array
- {
- $year = $year ?? (int)date("Y");
- $month = $month ?? (int)date("m", strtotime( "+ 2 month" . date('Y-m-01')));
-
- $storeIds = array_unique(array_column($productList, 'store_id'));
+ public function calculateWriteOffShareByMonth(
+ array $productList,
+ int $month,
+ int $year
+ ): array {
+ $targetDate = strtotime(sprintf('%04d-%02d-01', $year, $month));
+ $storeIds = array_unique(array_column($productList, 'store_id'));
if (empty($storeIds)) {
return [];
}
- $productQtyMap = []; // [store][cat][sub][spec][pid] => qty
- $speciesQtyMap = []; // [store][cat][sub][spec] => total qty
+ $periods = StorePlanService::getPeriods($targetDate, 3, false, true);
+
+ $productQtyMap = []; // [store][cat][sub][spec][pid] => weighted qty
+ $speciesQtyMap = []; // [store][cat][sub][spec] => weighted total
+
+ $storeJoin = 'ex.export_val = w.store_id';
- $storeJoinCondition = 'ex.export_val = w.store_id';
- for ($offset = 2; $offset >= 1; $offset--) {
- $histYear = $year - $offset;
- $start = sprintf('%04d-%02d-01 00:00:00', $histYear, $month);
- $end = date('Y-m-d 23:59:59', strtotime("$start +1 month -1 second"));
+ foreach ($periods as $period) {
+ $histYear = (int)$period['year'];
+ $histMonth = (int)$period['month'];
+ $weight = (float)$period['weight'];
+
+
+ $start = sprintf('%04d-%02d-01 00:00:00', $histYear, $histMonth);
+ $end = date(
+ 'Y-m-d 23:59:59',
+ strtotime("$start +1 month -1 second")
+ );
+
- $productsWriteOffs = (new Query())
+ $productsWriteOffs = (new \yii\db\Query())
->select([
'store_id' => 'ex.entity_id',
'category' => 'p1c.category',
'product_id' => 'wp.product_id',
'qty' => new \yii\db\Expression('SUM(wp.quantity)'),
])
- ->from(['w' => 'write_offs'])
- ->innerJoin(['wp' => 'write_offs_products'], 'wp.write_offs_id = w.id')
- ->leftJoin('export_import_table ex', $storeJoinCondition)
- ->leftJoin('products_1c_nomenclature p1c', 'p1c.id = wp.product_id')
- ->leftJoin('products_1c p1', 'p1.id = wp.product_id')
-
+ ->from(['w' => 'write_offs'])
+ ->innerJoin(
+ ['wp' => 'write_offs_products'],
+ 'wp.write_offs_id = w.id'
+ )
+ ->leftJoin(
+ 'export_import_table ex',
+ $storeJoin
+ )
+ ->leftJoin(
+ 'products_1c_nomenclature p1c',
+ 'p1c.id = wp.product_id'
+ )
+ ->leftJoin(
+ 'products_1c p1',
+ 'p1.id = wp.product_id'
+ )
->andWhere(['ex.entity_id' => $storeIds])
->andWhere(['>=', 'w.date', $start])
->andWhere(['<=', 'w.date', $end])
-
->andWhere(['p1.components' => ''])
- ->andWhere(['not in', 'p1c.category', ['', 'букет', 'сборка', 'сервис']])
- ->groupBy(['ex.entity_id','p1c.category','p1c.subcategory','p1c.species','wp.product_id'])
+ ->andWhere([
+ 'not in',
+ 'p1c.category',
+ ['', 'букет', 'сборка', 'сервис']
+ ])
+ ->groupBy([
+ 'ex.entity_id',
+ 'p1c.category',
+ 'p1c.subcategory',
+ 'p1c.species',
+ 'wp.product_id',
+ ])
->all();
+
foreach ($productsWriteOffs as $productsWriteOffsItem) {
$sid = (int)$productsWriteOffsItem['store_id'];
$cat = $productsWriteOffsItem['category'];
$sub = $productsWriteOffsItem['subcategory'];
$spec = $productsWriteOffsItem['species'];
$pid = $productsWriteOffsItem['product_id'];
- $qty = (float)$productsWriteOffsItem['qty'];
-
+ $qty = (float)$productsWriteOffsItem['qty'] * $weight;
$productQtyMap[$sid][$cat][$sub][$spec][$pid] =
- ($productQtyMap[$sid][$cat][$sub][$spec][$pid] ?? 0.0) + $qty;
+ ($productQtyMap[$sid][$cat][$sub][$spec][$pid] ?? 0.0)
+ + $qty;
$speciesQtyMap[$sid][$cat][$sub][$spec] =
- ($speciesQtyMap[$sid][$cat][$sub][$spec] ?? 0.0) + $qty;
+ ($speciesQtyMap[$sid][$cat][$sub][$spec] ?? 0.0)
+ + $qty;
}
}
- $seen = [];
+ $seen = [];
$result = [];
foreach ($productList as $item) {
- $pid = $item['product_id'];
$sid = $item['store_id'];
$cat = $item['category'];
$sub = $item['subcategory'];
$spec = $item['species'];
+ $pid = $item['product_id'];
$key = "{$sid}|{$cat}|{$sub}|{$spec}|{$pid}";
if (isset($seen[$key])) {
$seen[$key] = true;
$productsQty = $productQtyMap[$sid][$cat][$sub][$spec][$pid] ?? 0.0;
- $speciesQty = $speciesQtyMap[$sid][$cat][$sub][$spec] ?? 0.0;
- $share = $speciesQty > 0
+ $speciesQty = $speciesQtyMap[$sid][$cat][$sub][$spec] ?? 0.0;
+ $share = $speciesQty > 0.0
? round($productsQty / $speciesQty, 4)
: 0.0;
$result[] = [
- 'store_id' => $sid,
- 'month' => $month,
- 'year' => $year,
- 'category' => $cat,
- 'subcategory' => $sub,
- 'species' => $spec,
- 'product_id' => $pid,
- 'writeoff_qty' => $productsQty,
- 'species_qty' => $speciesQty,
- 'share' => $share,
+ 'store_id' => $sid,
+ 'month' => $month,
+ 'year' => $year,
+ 'category' => $cat,
+ 'subcategory' => $sub,
+ 'species' => $spec,
+ 'product_id' => $pid,
+ 'writeoff_qty' => round($productsQty, 4),
+ 'species_qty' => round($speciesQty, 4),
+ 'share' => $share,
];
}
return $result;
}
+
}
\ No newline at end of file