use yii\web\Response;
use yii_app\helpers\DataHelper;
use yii_app\records\{BouquetComposition,
+ BouquetCompositionPrice,
BouquetCompositionProducts,
BouquetForecast,
CityStore,
+ CityStoreParams,
Files,
MatrixType,
+ PricesDynamic,
Products1cNomenclature,
+ SelfCostProduct,
StoreType,
WriteOffsErp};
use yii_app\services\StorePlanService;
return $data;
}
- public function actionMonthGoal()
+ public function actionMonthGoal($month, $year)
{
- $matrixTypesIds = StorePlanService::getActiveMatrixTypes();
- // var_dump($matrixTypesIds);die();
- $bouquets = [];
- if ($matrixTypesIds) {
- foreach ($matrixTypesIds as $matrixTypeId) {
- $bouquets[$matrixTypeId] = StorePlanService::getBouqetsByDate(5, 2025, $matrixTypeId);
- }
- }
+ $result = StorePlanService::getBouquetSpiecesMonthGoal($month, $year);
+
+ $month = $month ?? 5;
+ $year = $year ?? 2025;
+ $stores = CityStore::find()
+ ->select(['id', 'name'])
+ ->where(['visible' => CityStore::IS_VISIBLE])
+ ->asArray()
+ ->all();
- var_dump($bouquets);die();
+ $storesMap = ArrayHelper::map($stores, 'id', 'name');
+
+ return $this->render('month-goal', [
+ 'result' => $result,
+ 'storesMap' => $storesMap,
+ 'month' => $month,
+ 'year' => $year,
+ ]);
}
}
use yii\helpers\ArrayHelper;
use yii_app\records\BouquetComposition;
use yii_app\records\BouquetCompositionMatrixTypeHistory;
+use yii_app\records\BouquetCompositionPrice;
+use yii_app\records\BouquetCompositionProducts;
+use yii_app\records\BouquetForecast;
use yii_app\records\CityStore;
+use yii_app\records\CityStoreParams;
use yii_app\records\Motivation;
use yii_app\records\PricesDynamic;
use yii_app\records\Products1cAdditionalCharacteristics;
+use yii_app\records\Products1cNomenclature;
use yii_app\records\Sales;
use yii_app\records\SalesProducts;
use yii_app\records\StorePlan;
+use yii_app\records\StoreType;
use yii_app\records\WriteOffsErp;
class StorePlanService
public static function getBouqetsByDate($month, $year, $matrix_type = null) {
$query = BouquetComposition::find()
+ ->select([
+ 'bouquet_composition.*',
+ 'bf.year AS forecast_year',
+ 'bf.month AS forecast_month',
+
+
+ ])
->orderBy(['id' => SORT_DESC])
- ->groupBy('bouquet_composition.id')
+ ->groupBy(['bouquet_composition.id', 'bf.year',
+ 'bf.month'])
->andWhere(['status' => [
WriteOffsErp::STATUS_CREATED_1С,
]])
- ->joinWith('bouquetForecast as bf')
- ->andWhere(['bf.year' => $year])
- ->andWhere(['bf.month' => $month]);
+ ->innerJoinWith(['bouquetForecast bf' => function($query) use ($year, $month) {
+ $query->andWhere(['bf.year' => $year])
+ ->andWhere(['bf.month' => $month])
+ ->andWhere(['not', ['bf.type_sales_value' => null]]);
+ }]);
if ($matrix_type) {
$query->leftJoin(
'mth.is_active' => true
]);
}
+
return $query->asArray()->all();
+
}
+ public static function getBouquetSpiecesMonthGoal($month, $year) {
+ $stores = ArrayHelper::map(CityStore::find()->select(['id'])->where(['visible' => CityStore::IS_VISIBLE])->asArray()->all(), 'id', 'id');
+ $storesParams = ArrayHelper::map(CityStoreParams::find()
+ ->select(['store_id', 'address_region'])
+ ->where(['store_id' => array_keys($stores)])
+ ->andWhere(['not', ['address_region' => '']])
+ ->asArray()
+ ->indexBy('store_id')
+ ->all(), 'store_id', 'address_region');
+
+ $matrixTypesIds = StorePlanService::getActiveMatrixTypes();
+
+ $storesForecasts = [];
+ // получаем букеты из матрицы
+ if ($matrixTypesIds) {
+ foreach ($matrixTypesIds as $matrixTypeId) {
+ $bouquetsArray = StorePlanService::getBouqetsByDate($month, $year, $matrixTypeId);
+ $forecasts = ArrayHelper::getColumn($bouquetsArray , 'bouquetForecast');
+
+ foreach ($forecasts as $forecastArray) {
+ if (is_array($forecastArray)) {
+ foreach ($forecastArray as $fc) {
+ $bouquetPrice = 0;
+ if(isset($storesParams[$fc["type_sales_id"]])){
+ $bouquetPrice = BouquetCompositionPrice::find()
+ ->where(['bouquet_id' => $fc['bouquet_id']])
+ ->andWhere(['region_id' => $storesParams[$fc["type_sales_id"]]])->one()->price;
+ }
+
+ $storesForecasts[] = array_merge($fc, ['matrixTypeId' => $matrixTypeId], ['price' => $bouquetPrice] );
+
+ }
+ }
+ }
+ }
+ }
+ $resultArr = [];
+ foreach ($storesForecasts as $storeForecast) {
+ $products = ArrayHelper::toArray(BouquetCompositionProducts::getCompositionProducts($storeForecast['bouquet_id']));
+ $productGuids = array_filter(array_column($products, 'product_guid'));
+ $pricesData = ArrayHelper::map(PricesDynamic::find()
+ ->where(['product_id' => $productGuids])
+ ->andWhere(['active' => 1])
+ ->andWhere(['region_id' => $storesParams[$fc["type_sales_id"]]])
+ ->select(['price', 'product_id'])->asArray()->all(), 'product_id', 'price') ;
+ // var_dump($products); die();
+ foreach ($products as $product) {
+ $species = Products1cNomenclature::find()->where(['id' => $product['product_guid']])->one()->species;
+ $productCost = round($pricesData[$product['product_guid']] * $product['count'] * 1.15, 2);
+ if (!isset($resultArr[$storeForecast["type_sales_id"]][$species][$storeForecast["type_sales"]])) {
+ $resultArr[$storeForecast["type_sales_id"]][$species][$storeForecast["type_sales"]] = 0;
+ }
+ $resultArr[$storeForecast["type_sales_id"]][$species][$storeForecast["type_sales"]] += $productCost;
+
+ }
+
+ }
+ $finalResult = [];
+ foreach ($resultArr as $typeSalesId => $speciesData) {
+ foreach ($speciesData as $species => $salesDetails) {
+ // Здесь $salesDetails — это массив вида [storeSalesType1 => cost1, storeSalesType2 => cost2, …]
+ $finalResult[$typeSalesId][$species] = round(array_sum($salesDetails), 2);
+ }
+ }
+
+ return ['detail' => $resultArr, 'final' => $finalResult];
+
+
+
+ }
+
+
+ public static function getBouquetGoal($bouquet) {
+ $onlineStores = BouquetForecast::getStoresList(
+ $bouquet['id'],
+ BouquetForecast::ONLINE_STORES,
+ CityStore::class,
+ ['visible' => CityStore::IS_VISIBLE],
+ $bouquet['forecast_month'],
+ $bouquet['forecast_year']
+ );
+ $marketplaceStores = BouquetForecast::getStoresList(
+ $bouquet['id'],
+ BouquetForecast::MARKETPLACE,
+ CityStore::class,
+ ['visible' => CityStore::IS_VISIBLE],
+ $bouquet['forecast_month'],
+ $bouquet['forecast_year']
+ );
+ $offlineStores = BouquetForecast::getStoresList(
+ $bouquet['id'],
+ BouquetForecast::OFFLINE_STORES,
+ StoreType::class,
+ [],
+ $bouquet['forecast_month'],
+ $bouquet['forecast_year']
+ );
+ return [
+ 'onlineStores' => $onlineStores,
+ 'marketplaceStores' => $marketplaceStores,
+ 'offlineStores' => $offlineStores,
+
+ ];
+}
+
}