From 6dfeeae93adcc6ee3549052b13452bdbb6ad5867 Mon Sep 17 00:00:00 2001 From: Vladimir Fomichev Date: Thu, 29 Aug 2024 17:24:25 +0300 Subject: [PATCH] =?utf8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?utf8?q?=D1=80=D0=B0=D1=81=D1=87=D0=B5=D1=82=20=D1=81=D0=B5=D0=B1=D0=B5?= =?utf8?q?=D1=81=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D0=B8=20=D0=B8?= =?utf8?q?=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=B8=D0=BD=D0=B5?= =?utf8?q?=D0=B8=20=D0=B2=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=83=20M?= =?utf8?q?otivationValues?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- erp24/actions/motivation/IndexAction.php | 3 + erp24/services/MotivationService.php | 226 ++++++++++++++++++++--- 2 files changed, 200 insertions(+), 29 deletions(-) diff --git a/erp24/actions/motivation/IndexAction.php b/erp24/actions/motivation/IndexAction.php index 6cd4abb2..beae4471 100644 --- a/erp24/actions/motivation/IndexAction.php +++ b/erp24/actions/motivation/IndexAction.php @@ -102,6 +102,9 @@ class IndexAction extends Action // Подсчёт количества сотрудников MotivationService::calculatePersonalCount($model->store_id, $model->year, $model->month); + // Подсчёт стоимости товара + MotivationService::saveCostMotivation($model->store_id, $model->year, $model->month); + $showTable = false; $motivationData = []; $daysInMonth = null; diff --git a/erp24/services/MotivationService.php b/erp24/services/MotivationService.php index 89be1bff..e34eb6bb 100644 --- a/erp24/services/MotivationService.php +++ b/erp24/services/MotivationService.php @@ -20,8 +20,7 @@ use yii_app\records\Sales; use yii_app\records\SalesProducts; use yii_app\records\TimetableFactModel; use yii_app\records\Timetable; - - +use yii_app\records\SelfCostProduct; use yii_app\records\EmployeePayment; @@ -29,34 +28,100 @@ use yii_app\records\EmployeePayment; class MotivationService { + const CODE_OFFLINE_SALES = 1; + const CODE_ONLINE_SALES = 2; + const CODE_ASSEMBLY_SERVICES = 3; + const CODE_DELIVERY_SERVICES = 4; + const CODE_DELIVERY_DEFECTS = 6; + const CODE_WRITE_OFF_ILLIQUID_GOODS_SPOOLAGE_EXPIRATION_OF_SHELF_LIFE = 7; + const CODE_EQUIPMENT_FAILURE_DEFECT = 8; + const CODE_REGRADING = 9; + const CODE_CONSUMABLES_SALES_SUPPORT = 10; + const CODE_RENT = 12; + const CODE_PUBLIC_SERVICES = 13; + const CODE_SECURITY = 14; + const CODE_CLEANING_SERVICES_FOR_PREMISES_AND_TERRITORY = 15; + const CODE_DELIVERY_TO_CLIENT_CURRIER = 16; + const CODE_DELIVERY_TO_CLIENT_TAXI = 17; + const CODE_MARKETPLACE_SERVICES = 18; + const CODE_REFRIGERATION_EQUIPMENT_REPAIR_MAINTANANCE = 19; + const CODE_COSTS_FOR_MAINTENANCE_AND_REPAIR_OF_OFFICE_EQUIPMENT_INCLUDING_CONSUMABLES = 20; + const CODE_EXPENSES_FOR_MAINENANCE_AND_REPAIR_OF_OTHER_FIXED_ASSETS = 21; + const CODE_MAINTENANCE_OF_CASH_REGISTERS = 22; + const CODE_INTERNET = 23; + const CODE_HOUSEHOLD_GOODS = 24; + const CODE_STATIONARY = 25; + const CODE_ACCOUNTING_SERVICES_SETTING_UP_AND_MAINTAINING_ACCOUNTING_AND_TAX_RECORDS = 27; + const CODE_LEGAL_SERVICES = 28; + const CODE_PERSONAL_ADMINISTRATION_LABOR_PROTECTION = 29; + const CODE_RECRUITMENT_SERVICES = 30; + const CODE_ADMINISTRATION_OF_IT_INFRASTRUCTURE_CONNECTIONS_TO_DATABASES_SOFTWARE_MAIL_INTERNET = 31; + const CODE_SOFTWARE_LICENSE_ERP_SYSTEM = 32; + const CODE_PROMOTION_AND_SALE_OF_GOODS_THROUGH_THE_WEBSITE = 33; + const CODE_PERSONAL_ADMINISTRATION_LABOR_PROTECTION_TARIFF = 36; + const CODE_BASE_BONUS = 37; + const CODE_BONUS_SIZE = 38; + const CODE_AGENT_SERVICES_TARIFF = 35; + const CODE_NUMBER_OF_EMPLOYEES = 34; + const CODE_PAYROLL_FUND = 11; + const CODE_THRESHOLD_COEFFICIENT = 39; + const CODE_DRINKING_WATER = 26; + const CODE_COSTS_OF_GOODS = 5; + + const CODE_REVENUE_FROM_SALES = 1001; + const CODE_SALE_OF_GOODS = 1002; + const CODE_OTHER_SERVICES = 1003; + const CODE_DIRECT_SELLING_COSTS = 1004; + const CODE_COST_PRICE_OF_GOODS = 1005; + const CODE_AGENT_SERVICES_EXPENSES_FOR_PURCHASING_STORING_DELIVERING_GOODS = 1006; + const CODE_DEFECT_RESORTING = 1007; + const CODE_MARGINAL_INCOME = 1008; + const CODE_OPERATIONAL_EXPANSES_COST = 1009; + const CODE_PAYMENT = 1010; + const CODE_MAINTENANCE_OF_PRIMISES = 1011; + const CODE_DELIVERY_COST = 1012; + const CODE_MAINTENANCE_AND_SERVICE_OF_FIXED_ASSETS_AND_INTANGIBLE_ASSETS = 1013; + const CODE_COMMUNICATION_SERVICES = 1014; + const CODE_OTHER_OPERATING_EXPENSES = 1015; + const CODE_GROSS_PROFIT = 1016; + const CODE_GENERAL_BUSINESS_EXPENSES = 1017; + const CODE_ACCOUNTING_AND_FINANCE = 1018; + const CODE_LEGAL_SUPPORT = 1019; + const CODE_HR_SERVICES = 1020; + const CODE_IT_SERVICES = 1021; + const CODE_NET_PROFIT = 1022; + const CODE_NET_PROFIT_MARGIN_PERCENT = 1023; + const CODE_NET_PROFIT_THRESHOLD_RUB = 1024; + const CODE_CALCULATION_OF_PREMIUM = 1025; // 6. Создание массива дополнительных элементов static $additionalItems = [ - 80 => ['name' => 'Выручка от реализации'], - 90 => ['name' => 'Продажа товара'], - 115 => ['name' => 'Прочие услуги'], - 135 => ['name' => 'Прямые расходы на продажу'], - 143 => ['name' => 'Услуги агентов (Расходы на закупку, хранение, доставку товара)'], - 146 => ['name' => 'Брак, пересорт'], - 192 => ['name' => 'Маржинальный доход'], - 194 => ['name' => 'Операционные расходы (Себестоимость)'], - 196 => ['name' => 'Оплата труда'], - 205 => ['name' => 'Содержание помещения'], - 245 => ['name' => 'Расходы по доставке'], - 275 => ['name' => 'Содержание и обслуживание ОС и НМА'], - 315 => ['name' => 'Услуги связи'], - 325 => ['name' => 'Прочие операционные расходы'], - 353 => ['name' => 'Валовая прибыль'], - 355 => ['name' => 'Общехозяйственные расходы'], - 357 => ['name' => 'Бухгалтерия и финансы'], - 365 => ['name' => 'Юридическое сопровождение'], - 375 => ['name' => 'HR- услуги'], - 395 => ['name' => 'IT услуги'], - 425 => ['name' => 'Чистая прибыль'], - 427 => ['name' => 'Рентабельность по чистой прибыли, %'], - 428 => ['name' => 'Минимальный порог Чистой прибыли, руб.'], - 435 => ['name' => 'Расчет премии'] - ]; + 80 => ['name' => 'Выручка от реализации', 'code' => self::CODE_REVENUE_FROM_SALES], + 90 => ['name' => 'Продажа товара', 'code' => self::CODE_SALE_OF_GOODS], + 115 => ['name' => 'Прочие услуги', 'code' => self::CODE_OTHER_SERVICES], + 135 => ['name' => 'Прямые расходы на продажу', 'code' => self::CODE_DIRECT_SELLING_COSTS], + 139 => ['name' => 'Себестоимость товара', 'code' => self::CODE_COST_PRICE_OF_GOODS], + 143 => ['name' => 'Услуги агентов (Расходы на закупку, хранение, доставку товара)', 'code' => self::CODE_AGENT_SERVICES_EXPENSES_FOR_PURCHASING_STORING_DELIVERING_GOODS], + 146 => ['name' => 'Брак, пересорт', 'code' => self::CODE_DEFECT_RESORTING], + 192 => ['name' => 'Маржинальный доход', 'code' => self::CODE_MARGINAL_INCOME], + 194 => ['name' => 'Операционные расходы (Себестоимость)', 'code' => self::CODE_OPERATIONAL_EXPANSES_COST], + 196 => ['name' => 'Оплата труда', 'code' => self::CODE_PAYMENT], + 205 => ['name' => 'Содержание помещения', 'code' => self::CODE_MAINTENANCE_OF_PRIMISES], + 245 => ['name' => 'Расходы по доставке', 'code' => self::CODE_DELIVERY_COST], + 275 => ['name' => 'Содержание и обслуживание ОС и НМА', 'code' => self::CODE_MAINTENANCE_AND_SERVICE_OF_FIXED_ASSETS_AND_INTANGIBLE_ASSETS], + 315 => ['name' => 'Услуги связи', 'code' => self::CODE_COMMUNICATION_SERVICES], + 325 => ['name' => 'Прочие операционные расходы', 'code' => self::CODE_OTHER_OPERATING_EXPENSES], + 353 => ['name' => 'Валовая прибыль', 'code' => self::CODE_GROSS_PROFIT], + 355 => ['name' => 'Общехозяйственные расходы', 'code' => self::CODE_GENERAL_BUSINESS_EXPENSES], + 357 => ['name' => 'Бухгалтерия и финансы', 'code' => self::CODE_ACCOUNTING_AND_FINANCE], + 365 => ['name' => 'Юридическое сопровождение', 'code' => self::CODE_LEGAL_SUPPORT], + 375 => ['name' => 'HR- услуги', 'code' => self::CODE_HR_SERVICES], + 395 => ['name' => 'IT услуги', 'code' => self::CODE_IT_SERVICES], + 425 => ['name' => 'Чистая прибыль', 'code' => self::CODE_NET_PROFIT], + 427 => ['name' => 'Рентабельность по чистой прибыли, %', 'code' => self::CODE_NET_PROFIT_MARGIN_PERCENT], + 428 => ['name' => 'Минимальный порог Чистой прибыли, руб.', 'code' => self::CODE_NET_PROFIT_THRESHOLD_RUB], + 435 => ['name' => 'Расчет премии', 'code' => self::CODE_CALCULATION_OF_PREMIUM] + ]; // Код из таблицы MotivationCostsItem строки - Фонд оплаты труда персонала const MCI_FOT = 11; @@ -167,10 +232,10 @@ class MotivationService $result[$costsItem->order][$groupAlias] = $actualValue; } - // 5. Сортировка результата по ключу (order) + // Сортировка результата по ключу (order) ksort($result); - // 7. Объединение массивов + // TODO Добавление суперфункции для вычисления значений передавая алиас foreach (self::$additionalItems as $key => $item) { if (!isset($result[$key])) { $result[$key] = array_merge($item, [ @@ -1039,4 +1104,107 @@ class MotivationService return $weeks; } + + /** + * Вычисление суммы себестоимости товара по магазину в определенный промежуток дат. + * + * @param string $startDate Дата начала недели (Y-m-d format). + * @param string $endDate Дата конца недели (Y-m-d format). + * @param int $storeId ID магазина. + * @return float Суммарная себестоимость товаров по магазину в определенный промежуток дат. + */ + public static function getSelfCostSumByStore($startDate, $endDate, $storeId) + { + + $storeId = (int)$storeId; + $startDate = date('Y-m-d', strtotime($startDate)); + $endDate = date('Y-m-d', strtotime($endDate)); + + + $sum = (float)SelfCostProduct::find() + ->where(['store_id' => $storeId]) + ->andWhere(['>=', 'date', $startDate]) + ->andWhere(['<=', 'date', $endDate]) + ->sum('price'); + + return $sum; + } + + /** + * Сохраняет мотивацию по себестоимости товара для указанного магазина и месяца. + * + * @param int $year Год в формате YYYY. + * @param int $month Месяц в формате MM. + * @param int $storeId ID магазина. + * @return bool Возвращает true в случае успешного сохранения данных, иначе false. + */ + public static function saveCostMotivation($storeId, $year, $month ) + { + // Получаем идентификатор мотивации + $motivation = Motivation::find() + ->where([ + 'store_id' => $storeId, + 'year' => $year, + 'month' => $month + ]) + ->one(); + + if (!$motivation) { + Yii::error("Мотивация не найдена для store_id=$storeId, year=$year, month=$month"); + return false; // мотивация не найдена, завершаем выполнение + } + + $motivationId = $motivation->id; + + // Вычисляем начало и конец месяца + $monthStart = date("Y-m-d 00:00:00", strtotime("$year-$month-01")); + $monthEnd = date("Y-m-t 23:59:59", strtotime("$year-$month-01")); + + // Переменная для отслеживания успешности сохранений + $success = true; + + // Проходим по каждой неделе (максимум 5 недель в месяце) + foreach (range(1, 5) as $weekIndex) { + // Вычисляем начало и конец недели + $weekStart = date("Y-m-d 00:00:00", strtotime("+" . (($weekIndex - 1) * 7) . " days", strtotime($monthStart))); + $weekEnd = date("Y-m-d 23:59:59", strtotime("+" . ($weekIndex * 7 - 1) . " days", strtotime($monthStart))); + + // Если конец недели выходит за пределы месяца, ограничиваем его концом месяца + if ($weekEnd > $monthEnd) { + $weekEnd = $monthEnd; + } + + Yii::info("Вычисляем себестоимость для недели $weekIndex: с $weekStart по $weekEnd"); + + // Рассчитываем сумму себестоимости за эту неделю + $costSum = self::getSelfCostSumByStore($weekStart, $weekEnd, $storeId); + + Yii::info("Сумма себестоимости для недели $weekIndex: $costSum"); + + // Определяем alias группы для недели (week1, week2 и т.д.) + $groupAlias = 'week' . $weekIndex; + + // Сохраняем или обновляем значение мотивации + $saveResult = self::saveOrUpdateMotivationValue( + $motivationId, + $groupAlias, + self::CODE_COSTS_OF_GOODS, // константа для себестоимости + 'float', + $costSum + ); + + if ($saveResult === false) { + Yii::error("Ошибка при сохранении значения для недели $weekIndex: $costSum"); + $success = false; + } + + // Прерываем цикл, если достигнут конец месяца + if ($weekEnd == $monthEnd) { + break; + } + } + + return $success; + } + } -- 2.39.5