use Yii;
use PhpOffice\PhpSpreadsheet\IOFactory;
use yii\helpers\Json;
+use yii_app\records\EmployeePayment;
+ use yii_app\records\AdminGroup;
use yii_app\records\ExportImportTable;
use yii\helpers\ArrayHelper;
use yii_app\records\Motivation;
use yii_app\records\Timetable;
-
-
-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 = [
return $weeks;
}
+ public static function getMotivationValue($motivation_id, $group_id, $value_id) {
+ $value = 0;
+ $motivationValue = MotivationValue::find()->where(['motivation_id' => $motivation_id,
+ 'motivation_group_id' => $group_id, 'value_id' => $value_id])->one();
+ /** @var $motivationValue MotivationValue */
+ if ($motivationValue) {
+ switch ($motivationValue->value_type) {
+ case MotivationCostsItem::DATA_TYPE_INT: { $value = $motivationValue->value_int; break; }
+ default: { $value = $motivationValue->value_float; break;}
+ }
+ }
+ return $value;
+ }
+
+ public static function calculateMonthSales($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'));
+
+ $sales = Sales::find()->where(['between', 'date', $monthStart, $monthEnd])
+ ->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');
+
+ $salesOffline = Sales::find()->select(['SUM(summ) as total', 'store_id'])
+ ->where(['between', 'date', $monthStart, $monthEnd])
+ ->andWhere(['operation' => Sales::OPERATION_SALE])
+ ->andWhere(['order_id' => ['', '0']])
+ ->andWhere(['NOT IN', 'id', $returnSalesIds])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ $salesOnline = Sales::find()->select(['SUM(summ) as total', 'store_id'])
+ ->where(['between', 'date', $monthStart, $monthEnd])
+ ->andWhere(['operation' => Sales::OPERATION_SALE])
+ ->andWhere(['NOT IN', 'order_id', ['', '0']])
+ ->andWhere(['NOT IN', 'id', $returnSalesIds])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ $motivations = Motivation::find()->where(['year' => $year, 'month' => $month])->indexBy('store_id')->all();
+
+ $motivationValueGroupFact = MotivationValueGroup::find()->where(['alias' => 'fact'])->one();
+ $motivationCostsItemOffline = MotivationCostsItem::find()->where(['name' => 'Оффлайн продажи'])->one();
+ $motivationCostsItemOnline = MotivationCostsItem::find()->where(['name' => 'Онлайн продажи'])->one();
+ /** @var $motivationCostsItemOffline MotivationCostsItem */
+ /** @var $motivationCostsItemOnline MotivationCostsItem */
+
+
+ $storeIds = ArrayHelper::getColumn(CityStore::find()->where(['visible' => '1'])->all(), 'id');
+ foreach ($storeIds as $store_id) {
+ if (isset($motivations[$store_id])) {
+ $correction = self::getMotivationValue($motivations[$store_id]->id, 8, $motivationCostsItemOffline->code);
+
+ $motivationValueOffline = MotivationValue::find()->where(['motivation_id' => $motivations[$store_id]->id,
+ 'motivation_group_id' => $motivationValueGroupFact->id, 'value_id' => $motivationCostsItemOffline->code])->one();
+ if (!$motivationValueOffline) {
+ $motivationValueOffline = new MotivationValue;
+ $motivationValueOffline->motivation_id = $motivations[$store_id]->id;
+ $motivationValueOffline->motivation_group_id = $motivationValueGroupFact->id;
+ $motivationValueOffline->value_id = $motivationCostsItemOffline->code;
+ $motivationValueOffline->value_type = $motivationCostsItemOffline->data_type;
+ }
+ $motivationValueOffline->value_float = ($salesOffline[$store_id]['total'] ?? 0) + $correction;
+ $motivationValueOffline->save();
+ if ($motivationValueOffline->getErrors()) {
+ throw new \Exception(Json::encode($motivationValueOffline->getErrors()));
+ }
+
+ $correction = self::getMotivationValue($motivations[$store_id]->id, 8, $motivationCostsItemOnline->code);
+
+ $motivationValueOnline = MotivationValue::find()->where(['motivation_id' => $motivations[$store_id]->id,
+ 'motivation_group_id' => $motivationValueGroupFact->id, 'value_id' => $motivationCostsItemOnline->code])->one();
+ if (!$motivationValueOnline) {
+ $motivationValueOnline = new MotivationValue;
+ $motivationValueOnline->motivation_id = $motivations[$store_id]->id;
+ $motivationValueOnline->motivation_group_id = $motivationValueGroupFact->id;
+ $motivationValueOnline->value_id = $motivationCostsItemOnline->code;
+ $motivationValueOnline->value_type = $motivationCostsItemOnline->data_type;
+ }
+ $motivationValueOnline->value_float = ($salesOnline[$store_id]['total'] ?? 0) + $correction;
+ $motivationValueOnline->save();
+ if ($motivationValueOnline->getErrors()) {
+ throw new \Exception(Json::encode($motivationValueOnline->getErrors()));
+ }
+ }
+ }
+ }
+
+ public static function calculateMonthServices($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'));
+
+ // Ищем каталог-гуиды категории services
+ $productsClass = ProductsClass::find()->select(['category_id', 'tip'])
+ ->where(['tip' => 'services'])
+ ->indexBy('category_id')
+ ->asArray()->all();
+
+ // Ищем продуктовые гуиды по каталог-гуидам категории service
+ $products1c = Products1c::find()->select(['id', 'parent_id', 'name'])
+ ->where(['parent_id' => array_keys($productsClass), 'tip' => 'products'])
+ ->indexBy(['id'])
+ ->asArray()->all();
+
+ // Ищем каталог-гуиды категории services_delivery
+ $productsClassDelivery = ProductsClass::find()->select(['category_id', 'tip'])
+ ->where(['tip' => 'services_delivery'])
+ ->indexBy('category_id')
+ ->asArray()->all();
+
+ // Ищем продуктовые гуиды по каталог-гуидам категории service_delivery
+ $products1cDelivery = Products1c::find()->select(['id', 'parent_id', 'name'])
+ ->where(['parent_id' => array_keys($productsClassDelivery), 'tip' => 'products'])
+ ->indexBy(['id'])
+ ->asArray()->all();
+
+ // Ищем продажи по продуктовым гуидам по каталог-гуидам категории service
+ $sales = Sales::find()->alias('s')
+ ->leftJoin('sales_products p', 'p.check_id = s.id')
+ ->where(['between', 's.date', $monthStart, $monthEnd])
+ ->andWhere(['p.product_id' => array_keys($products1c)])
+ ->andWhere(['s.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');
+
+ // Ищем продукты из категории services
+ $salesProduct = SalesProducts::find()->alias('p')
+ ->select(['SUM(p.summ) as total', 'store_id'])
+ ->leftJoin('sales s', 's.id = p.check_id')
+ ->where(['check_id' => $salesIds])
+ ->andWhere(['NOT IN', 'check_id', $returnSalesIds])
+ ->andWhere(['product_id' => array_keys($products1c)])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ // Ищем продажи по продуктовым гуидам по каталог-гуидам категории services_delivery
+ $salesDelivery = Sales::find()->alias('s')
+ ->leftJoin('sales_products p', 'p.check_id = s.id')
+ ->where(['between', 's.date', $monthStart, $monthEnd])
+ ->andWhere(['p.product_id' => array_keys($products1cDelivery)])
+ ->andWhere(['s.operation' => Sales::OPERATION_SALE])
+ ->asArray()->all();
+ $salesIdsDelivery = ArrayHelper::getColumn($salesDelivery, 'id');
+
+ // Ищем чеки-возврат на текущие чеки
+ $returnSalesDelivery = Sales::find()->where(['operation' => Sales::OPERATION_RETURN, 'sales_check' => $salesIdsDelivery])->all();
+ $returnSalesIdsDelivery = ArrayHelper::getColumn($returnSalesDelivery, 'sales_check');
+
+ // Ищем продукты из категории services_delivery
+ $salesProductDelivery = SalesProducts::find()->alias('p')
+ ->select(['SUM(p.summ) as total', 'store_id'])
+ ->leftJoin('sales s', 's.id = p.check_id')
+ ->where(['check_id' => $salesIdsDelivery])
+ ->andWhere(['NOT IN', 'check_id', $returnSalesIdsDelivery])
+ ->andWhere(['product_id' => array_keys($products1cDelivery)])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ $motivations = Motivation::find()->where(['year' => $year, 'month' => $month])->indexBy('store_id')->all();
+
+ $motivationValueGroupFact = MotivationValueGroup::find()->where(['alias' => 'fact'])->one();
+ $motivationCostsItemServices = MotivationCostsItem::find()->where(['name' => 'Услуги по сборке'])->one();
+ $motivationCostsItemServicesDelivery = MotivationCostsItem::find()->where(['name' => 'Услуги по доставке'])->one();
+ /** @var $motivationCostsItemServices MotivationCostsItem */
+ /** @var $motivationCostsItemServicesDelivery MotivationCostsItem */
+
+ $storeIds = ArrayHelper::getColumn(CityStore::find()->where(['visible' => '1'])->all(), 'id');
+ foreach ($storeIds as $store_id) {
+ if (isset($motivations[$store_id])) {
+ $correction = self::getMotivationValue($motivations[$store_id]->id, 8, $motivationCostsItemServices->code);
+
+ $motivationValueService = MotivationValue::find()->where(['motivation_id' => $motivations[$store_id]->id,
+ 'motivation_group_id' => $motivationValueGroupFact->id, 'value_id' => $motivationCostsItemServices->code])->one();
+ if (!$motivationValueService) {
+ $motivationValueService = new MotivationValue;
+ $motivationValueService->motivation_id = $motivations[$store_id]->id;
+ $motivationValueService->motivation_group_id = $motivationValueGroupFact->id;
+ $motivationValueService->value_id = $motivationCostsItemServices->code;
+ $motivationValueService->value_type = $motivationCostsItemServices->data_type;
+ }
+ $motivationValueService->value_float = ($salesProduct[$store_id]['total'] ?? 0) + $correction;
+ $motivationValueService->save();
+ if ($motivationValueService->getErrors()) {
+ throw new \Exception(Json::encode($motivationValueService->getErrors()));
+ }
+
+ $correction = self::getMotivationValue($motivations[$store_id]->id, 8, $motivationCostsItemServicesDelivery->code);
+
+ $motivationValueServiceDelivery = MotivationValue::find()->where(['motivation_id' => $motivations[$store_id]->id,
+ 'motivation_group_id' => $motivationValueGroupFact->id, 'value_id' => $motivationCostsItemServicesDelivery->code])->one();
+ if (!$motivationValueServiceDelivery) {
+ $motivationValueServiceDelivery = new MotivationValue;
+ $motivationValueServiceDelivery->motivation_id = $motivations[$store_id]->id;
+ $motivationValueServiceDelivery->motivation_group_id = $motivationValueGroupFact->id;
+ $motivationValueServiceDelivery->value_id = $motivationCostsItemServicesDelivery->code;
+ $motivationValueServiceDelivery->value_type = $motivationCostsItemServicesDelivery->data_type;
+ }
+ $motivationValueServiceDelivery->value_float = ($salesProductDelivery[$store_id]['total'] ?? 0) + $correction;
+ $motivationValueServiceDelivery->save();
+ if ($motivationValueServiceDelivery->getErrors()) {
+ throw new \Exception(Json::encode($motivationValueServiceDelivery->getErrors()));
+ }
+ }
+ }
+ }
+
+ public static function calculateMonthDefect($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'));
+
+ $motivations = Motivation::find()->where(['year' => $year, 'month' => $month])->indexBy('store_id')->all();
+ $motivationValueGroup = MotivationValueGroup::find()->where(['alias' => 'fact'])->one();
+ $exportImportTables = ExportImportTable::find()->select(['export_val', 'entity_id'])->where(['entity' => 'city_store',
+ 'entity_id' => array_keys($motivations), 'export_id' => 1])->indexBy('entity_id')->all();
+ /** @var $exportImportTables ExportImportTable[] */
+
+ foreach ($exportImportTables as $store_id => $store_guid) {
+ if (isset($motivations[$store_id])) {
+ $writeOffs = WriteOffs::find()->select(['sum(summ) as total', 'type'])
+ ->where(['between', 'date', $monthStart, $monthEnd])
+ ->andWhere(['store_id' => $store_guid])
+ ->groupBy(['type'])
+ ->indexBy('type')
+ ->asArray()->all();
+ foreach (MotivationCostsItem::writeOffsToMotivationItemArray() as $key => $motivationItemType) {
+ $data = $writeOffs[$key] ?? [];
+ $motivationCostsItem = MotivationCostsItem::find()->where(['name' => $motivationItemType])->one();
+ /** @var $motivationCostsItem MotivationCostsItem */
+
+ $correction = self::getMotivationValue($motivations[$store_id]->id, 8, $motivationCostsItem->code);
+
+ $motivationValue = MotivationValue::find()->where(['motivation_id' => $motivations[$store_id]->id,
+ 'motivation_group_id' => $motivationValueGroup->id, 'value_id' => $motivationCostsItem->code])->one();
+ if (!$motivationValue) {
+ $motivationValue = new MotivationValue;
+ $motivationValue->motivation_id = $motivations[$store_id]->id;
+ $motivationValue->motivation_group_id = $motivationValueGroup->id;
+ $motivationValue->value_id = $motivationCostsItem->code;
+ $motivationValue->value_type = $motivationCostsItem->data_type;
+ }
+ $motivationValue->value_float = ($data['total'] ?? 0) + $correction;
+ $motivationValue->save();
+ if ($motivationValue->getErrors()) {
+ throw new \Exception(Json::encode($motivationValue->getErrors()));
+ }
+ }
+ }
+ }
+ }
+
+ public static function calculateMonthSalary($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'));
+
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $store_id = $motivation->store_id;
+ $monthlyTotalSalary = self::calculateTotalSalary(date("Y-m-d", strtotime($monthStart)), date("Y-m-d", strtotime($monthEnd)), $store_id);
+
+ $correction = self::getMotivationValue($motivation->id, 8, 11);
+
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 11, "float", $monthlyTotalSalary + $correction);
+ }
+ }
+
+ public static function calculateMonthDeliveryCurier($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $correction = self::getMotivationValue($motivation->id, 8, 16);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 16, "float", $correction);
+ }
+ }
+
+ public static function calculateMonthAccauntingAndTax($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $plan = self::getMotivationValue($motivation->id, 7, 27);
+ $adjustment = self::getMotivationValue($motivation->id, 8, 27);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 27, "float", $plan + $adjustment);
+ }
+ }
+
+ public static function calculateMonthLegalServices($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $plan = self::getMotivationValue($motivation->id, 7, 28);
+ $adjustment = self::getMotivationValue($motivation->id, 8, 28);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 28, "float", $plan + $adjustment);
+ }
+ }
+
+ public static function calculateMonthPersonalAdministrationLaborProtection($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'));
+
+ $timetableFactModels = TimetableFactModel::find()->select(['COUNT(DISTINCT(admin_id)) as cnt', 'store_id'])
+ ->where(['!=', 'admin_group_id', '45'])
+ ->andWhere(['between', 'date_shift', $monthStart, $monthEnd])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ /** @var $motivation Motivation */
+ $tariff = self::getMotivationValue($motivation->id, 7, 36);
+ $adjustment = self::getMotivationValue($motivation->id, 8, 36);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 29, "float", $tariff * ($timetableFactModels[$motivation->store_id]['cnt'] ?? 0) + $adjustment);
+ }
+ }
+
+ public static function calculateMonthAdministrationOfItInfrastructureConnectionsToDatabasesSoftwareMailInternet($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $plan = self::getMotivationValue($motivation->id, 7, 31);
+ $adjustment = self::getMotivationValue($motivation->id, 8, 31);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 31, "float", $plan + $adjustment);
+ }
+ }
+
+ public static function calculateMonthSoftwareLicenseErpSystem($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $plan = self::getMotivationValue($motivation->id, 7, 32);
+ $adjustment = self::getMotivationValue($motivation->id, 8, 32);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 32, "float", $plan + $adjustment);
+ }
+ }
+
+ public static function calculateMonthCeoAndSaleOfWebsiteGoods($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ foreach ($motivations as $motivation) {
+ $correction = self::getMotivationValue($motivation->id, 8, 33);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ "fact", 33, "float", $correction);
+ }
+ }
+
+ public static function initMonth1cFields($year, $month) {
+ $motivations = Motivation::find()
+ ->where(['year' => $year, 'month' => $month])
+ ->all();
+
+ $valueIdIndices = [12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 30];
+
+ foreach ($motivations as $motivation) {
+ foreach ($valueIdIndices as $index) {
+ self::saveOrUpdateMotivationValue($motivation->id, "fact", $index, "float", 0);
+ }
+ }
+ }
++
+ public static function calculateFactFormula($motivationDataTableSort, $year, $month) {
+ // Определяем последний день месяца
+ $lastDayOfMonth = date('t', strtotime("$year-$month-01"));
+
+ $indMap = [];
+ foreach ($motivationDataTableSort as $ind => $row) {
+ if (!key_exists('code', $row)) {
+ continue;
+ }
+ $indMap[intval($row['code'])] = $ind;
+ }
+ foreach (range(0,7) as $ind) {
+ switch ($ind) {
+ case 0: { $column = 'plan'; break; }
+ case 6: { $column = 'fact'; break; }
+ case 7: { $column = 'forecast'; break; }
+ default: { $column = 'week' . $ind; break; }
+ }
+
+ $motivationDataTableSort[$indMap[self::CODE_SALE_OF_GOODS]][$column] = // "Продажа товара"
+ $motivationDataTableSort[$indMap[self::CODE_OFFLINE_SALES]][$column] + // "Оффлайн продажи"
+ $motivationDataTableSort[$indMap[self::CODE_ONLINE_SALES]][$column] + 0; // "Онлайн продажи"
+
+ $motivationDataTableSort[$indMap[self::CODE_OTHER_SERVICES]][$column] = // "Прочие услуги"
+ $motivationDataTableSort[$indMap[self::CODE_ASSEMBLY_SERVICES]][$column] + // "Услуги по сборке"
+ $motivationDataTableSort[$indMap[self::CODE_DELIVERY_SERVICES]][$column] + 0; // "Услуги по доставке"
+
+ $motivationDataTableSort[$indMap[self::CODE_REVENUE_FROM_SALES]][$column] = // "Выручка от реализации"
+ $motivationDataTableSort[$indMap[self::CODE_SALE_OF_GOODS]][$column] + // "Продажа товара"
+ $motivationDataTableSort[$indMap[self::CODE_OTHER_SERVICES]][$column] + 0; // "Прочие услуги"
+
+ $motivationDataTableSort[$indMap[self::CODE_COST_PRICE_OF_GOODS]][$column] = // "Себестоимость товара"
+ $motivationDataTableSort[$indMap[self::CODE_COSTS_OF_GOODS]][$column] + 0; // "Стоимость товара"
+
+ $motivationDataTableSort[$indMap[self::CODE_AGENT_SERVICES_EXPENSES_FOR_PURCHASING_STORING_DELIVERING_GOODS]][$column] = // "Услуги агентов (Расходы на закупку, хранение, доставку товара)"
+ (
+ $motivationDataTableSort[$indMap[self::CODE_COST_PRICE_OF_GOODS]][$column] + // "Себестоимость товара"
+ $motivationDataTableSort[$indMap[self::CODE_DEFECT_RESORTING]][$column] // "Брак, пересорт"
+ ) *
+ $motivationDataTableSort[$indMap[self::CODE_AGENT_SERVICES_TARIFF]][$column]; // "Услуги агентов (тариф)"
+
+ $motivationDataTableSort[$indMap[self::CODE_DEFECT_RESORTING]][$column] = // "Брак, пересорт"
+ $motivationDataTableSort[$indMap[self::CODE_DELIVERY_DEFECTS]][$column] + // "Брак с поставки"
+ $motivationDataTableSort[$indMap[self::CODE_WRITE_OFF_ILLIQUID_GOODS_SPOOLAGE_EXPIRATION_OF_SHELF_LIFE]][$column] + // "Списание неликвидного товара: порча, истечение срока годности"
+ $motivationDataTableSort[$indMap[self::CODE_EQUIPMENT_FAILURE_DEFECT]][$column] + // "Брак из-за поломки оборудования"
+ $motivationDataTableSort[$indMap[self::CODE_REGRADING]][$column] + 0; // "Пересорт"
+
+ $motivationDataTableSort[$indMap[self::CODE_DIRECT_SELLING_COSTS]][$column] = // "Прямые расходы на продажу"
+ $motivationDataTableSort[$indMap[self::CODE_COST_PRICE_OF_GOODS]][$column] + // "Себестоимость товара"
+ $motivationDataTableSort[$indMap[self::CODE_AGENT_SERVICES_EXPENSES_FOR_PURCHASING_STORING_DELIVERING_GOODS]][$column] + // "Услуги агентов (Расходы на закупку, хранение, доставку товара)"
+ $motivationDataTableSort[$indMap[self::CODE_DEFECT_RESORTING]][$column] + // "Брак, пересорт"
+ $motivationDataTableSort[$indMap[self::CODE_CONSUMABLES_SALES_SUPPORT]][$column] + 0; // "Расходные материалы (обеспечение продаж)"
+
+ $motivationDataTableSort[$indMap[self::CODE_MARGINAL_INCOME]][$column] = // "Маржинальный доход"
+ $motivationDataTableSort[$indMap[self::CODE_REVENUE_FROM_SALES]][$column] - // "Выручка от реализации"
+ $motivationDataTableSort[$indMap[self::CODE_DIRECT_SELLING_COSTS]][$column] + 0; // "Прямые расходы на продажу"
+
+ $motivationDataTableSort[$indMap[self::CODE_PAYMENT]][$column] = // "Оплата труда"
+ $motivationDataTableSort[$indMap[self::CODE_PAYROLL_FUND]][$column] + 0; // "Фонд оплаты труда персонала"
+
+ $motivationDataTableSort[$indMap[self::CODE_MAINTENANCE_OF_PRIMISES]][$column] = // "Содержание помещения"
+ $motivationDataTableSort[$indMap[self::CODE_RENT]][$column] + // "Аренда"
+ $motivationDataTableSort[$indMap[self::CODE_PUBLIC_SERVICES]][$column] + // "Коммунальные услуги"
+ $motivationDataTableSort[$indMap[self::CODE_SECURITY]][$column] + // "Охрана"
+ $motivationDataTableSort[$indMap[self::CODE_CLEANING_SERVICES_FOR_PREMISES_AND_TERRITORY]][$column] + 0; // "Услуги по уборке помещений и территории"
+
+ $motivationDataTableSort[$indMap[self::CODE_DELIVERY_COST]][$column] = // "Расходы по доставке"
+ $motivationDataTableSort[$indMap[self::CODE_DELIVERY_TO_CLIENT_CURRIER]][$column] + // "Доставка до клиента курьер"
+ $motivationDataTableSort[$indMap[self::CODE_DELIVERY_TO_CLIENT_TAXI]][$column] + 0; // "Доставка до клиента такси"
+
+ $motivationDataTableSort[$indMap[self::CODE_MAINTENANCE_AND_SERVICE_OF_FIXED_ASSETS_AND_INTANGIBLE_ASSETS]][$column] = // "Содержание и обслуживание ОС и НМА"
+ $motivationDataTableSort[$indMap[self::CODE_REFRIGERATION_EQUIPMENT_REPAIR_MAINTANANCE]][$column] + // "Холодильное оборудование (ремонт, содержание, ТО)"
+ $motivationDataTableSort[$indMap[self::CODE_COSTS_FOR_MAINTENANCE_AND_REPAIR_OF_OFFICE_EQUIPMENT_INCLUDING_CONSUMABLES]][$column] + // "Расходы на содержание и ремонт оргтехники, в т.ч. расходные материалы"
+ $motivationDataTableSort[$indMap[self::CODE_EXPENSES_FOR_MAINENANCE_AND_REPAIR_OF_OTHER_FIXED_ASSETS]][$column] + // "Расходы на содержание и ремонт прочих ОС"
+ $motivationDataTableSort[$indMap[self::CODE_MAINTENANCE_OF_CASH_REGISTERS]][$column] + 0; // "Техническое обслуживание кассовых аппаратов"
+
+ $motivationDataTableSort[$indMap[self::CODE_COMMUNICATION_SERVICES]][$column] = // "Услуги связи"
+ $motivationDataTableSort[$indMap[self::CODE_INTERNET]][$column] + 0; // "Интернет"
+
+ $motivationDataTableSort[$indMap[self::CODE_OTHER_OPERATING_EXPENSES]][$column] = // "Прочие операционные расходы"
+ $motivationDataTableSort[$indMap[self::CODE_HOUSEHOLD_GOODS]][$column] + // "Хозяйственные товары"
+ $motivationDataTableSort[$indMap[self::CODE_STATIONARY]][$column] + // "Канцтовары"
+ $motivationDataTableSort[$indMap[self::CODE_DRINKING_WATER]][$column] + 0; // "Вода питьевая"
+
+ $motivationDataTableSort[$indMap[self::CODE_OPERATIONAL_EXPANSES_COST]][$column] = // "Операционные расходы (Себестоимость)"
+ $motivationDataTableSort[$indMap[self::CODE_PAYMENT]][$column] + // "Оплата труда"
+ $motivationDataTableSort[$indMap[self::CODE_MAINTENANCE_OF_PRIMISES]][$column] + // "Содержание помещения"
+ $motivationDataTableSort[$indMap[self::CODE_DELIVERY_COST]][$column] + // "Расходы по доставке"
+ $motivationDataTableSort[$indMap[self::CODE_MARKETPLACE_SERVICES]][$column] + // "Услуги маркетплейсов"
+ $motivationDataTableSort[$indMap[self::CODE_MAINTENANCE_AND_SERVICE_OF_FIXED_ASSETS_AND_INTANGIBLE_ASSETS]][$column] + // "Содержание и обслуживание ОС и НМА"
+ $motivationDataTableSort[$indMap[self::CODE_COMMUNICATION_SERVICES]][$column] + // "Услуги связи"
+ $motivationDataTableSort[$indMap[self::CODE_OTHER_OPERATING_EXPENSES]][$column] + 0; // "Прочие операционные расходы"
+
+ $motivationDataTableSort[$indMap[self::CODE_GROSS_PROFIT]][$column] = // "Валовая прибыль"
+ $motivationDataTableSort[$indMap[self::CODE_MARGINAL_INCOME]][$column] - // "Маржинальный доход"
+ $motivationDataTableSort[$indMap[self::CODE_OPERATIONAL_EXPANSES_COST]][$column] + 0; // "Операционные расходы (Себестоимость)"
+
+ $motivationDataTableSort[$indMap[self::CODE_ACCOUNTING_AND_FINANCE]][$column] = // "Бухгалтерия и финансы"
+ $motivationDataTableSort[$indMap[self::CODE_ACCOUNTING_SERVICES_SETTING_UP_AND_MAINTAINING_ACCOUNTING_AND_TAX_RECORDS]][$column] + 0; // "Бухгалтерские услуги: постановка и ведение БУ и НУ"
+
+ $motivationDataTableSort[$indMap[self::CODE_LEGAL_SUPPORT]][$column] = // "Юридическое сопровождение"
+ $motivationDataTableSort[$indMap[self::CODE_LEGAL_SERVICES]][$column] + 0; // "Юридические услуги"
+
+ $motivationDataTableSort[$indMap[self::CODE_HR_SERVICES]][$column] = // "HR- услуги"
+ $motivationDataTableSort[$indMap[self::CODE_PERSONAL_ADMINISTRATION_LABOR_PROTECTION]][$column] + // "Кадровое администрирование, охрана труда"
+ $motivationDataTableSort[$indMap[self::CODE_RECRUITMENT_SERVICES]][$column] + 0; // "Услуги по подбору персонала"
+
+ $motivationDataTableSort[$indMap[self::CODE_IT_SERVICES]][$column] = // "IT услуги"
+ $motivationDataTableSort[$indMap[self::CODE_ADMINISTRATION_OF_IT_INFRASTRUCTURE_CONNECTIONS_TO_DATABASES_SOFTWARE_MAIL_INTERNET]][$column] + // "Администрирование ИТ инфраструктуры (подключения к базам данных, ПО, почта, интернет)"
+ $motivationDataTableSort[$indMap[self::CODE_SOFTWARE_LICENSE_ERP_SYSTEM]][$column] + 0; // "Лицензия на ПО: ERP система"
+
+ $motivationDataTableSort[$indMap[self::CODE_GENERAL_BUSINESS_EXPENSES]][$column] = // "Общехозяйственные расходы"
+ $motivationDataTableSort[$indMap[self::CODE_ACCOUNTING_AND_FINANCE]][$column] + // "Бухгалтерия и финансы"
+ $motivationDataTableSort[$indMap[self::CODE_LEGAL_SUPPORT]][$column] + // "Юридическое сопровождение"
+ $motivationDataTableSort[$indMap[self::CODE_HR_SERVICES]][$column] + // "HR- услуги"
+ $motivationDataTableSort[$indMap[self::CODE_IT_SERVICES]][$column] + // "IT услуги"
+ $motivationDataTableSort[$indMap[self::CODE_PROMOTION_AND_SALE_OF_GOODS_THROUGH_THE_WEBSITE]][$column] + 0; // "Продвижение и продажа товара через сайт"
+
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT]][$column] = // "Чистая прибыль"
+ $motivationDataTableSort[$indMap[self::CODE_GROSS_PROFIT]][$column] - // "Валовая прибыль"
+ $motivationDataTableSort[$indMap[self::CODE_GENERAL_BUSINESS_EXPENSES]][$column] + 0; // "Общехозяйственные расходы"
+
+ $c5 = $motivationDataTableSort[$indMap[self::CODE_REVENUE_FROM_SALES]][$column]; // "Выручка от реализации"
+ if ($c5 != 0) {
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_MARGIN_PERCENT]][$column] = // "Рентабельность по чистой прибыли, %"
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT]][$column] / $c5; // "Чистая прибыль"
+ }
+
+ if ($ind == 0) {
+ $b62 = $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT]]["plan"]; // "Чистая прибыль"
+ if ($b62 > 0) {
+ $b64 = $b62 * 0.9;
+ } else {
+ $b64 = $b62 * 1.1;
+ }
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]]["plan"] = $b64; // "Минимальный порог Чистой прибыли, руб."
+ }
+ if ($ind >= 1 && $ind <= 4) {
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]][$column] = // "Минимальный порог Чистой прибыли, руб."
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]]["plan"] / $lastDayOfMonth * 7; // "Минимальный порог Чистой прибыли, руб."
+ }
+ if ($ind == 5) {
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]][$column] = // "Минимальный порог Чистой прибыли, руб."
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]]["plan"] / $lastDayOfMonth * ($lastDayOfMonth - 4 * 7); // "Минимальный порог Чистой прибыли, руб."
+ }
+ if ($ind == 7) {
+ $sum = 0;
+ foreach (range(1, 5) as $index) {
+ $sum += $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]]['week' . $index]; // "Минимальный порог Чистой прибыли, руб."
+ }
+ $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]][$column] = $sum; // "Минимальный порог Чистой прибыли, руб."
+ }
+
+ // if ($ind > 0) {
+ // $c62 = $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT]][$column]; // "Чистая прибыль"
+ // $b64 = $motivationDataTableSort[$indMap[self::CODE_NET_PROFIT_THRESHOLD_RUB]][$ind == 6 ? "plan" : $column]; // "Минимальный порог Чистой прибыли, руб."
+ //
+ // $j66 = 0;
+ // if ($c62 >= $b64) {
+ // $formula = $c62 - $c5 * $motivationDataTableSort[$indMap[self::CODE_THRESHOLD_COEFFICIENT]]["plan"]; // "Пороговый коэффициент"
+ // if ($formula > 0) {
+ // $j66 = $formula;
+ // }
+ // }
+ // $motivationDataTableSort[$indMap[self::CODE_CALCULATION_OF_PREMIUM]][$column] = $j66 + 0; // "Расчет премии"
+ // }
+ }
+
+ // Отклонение
+ $deviationFunc = function ($code) use(&$motivationDataTableSort, &$indMap) {
+ if ($motivationDataTableSort[$indMap[$code]]["plan"] != 0) {
+ $motivationDataTableSort[$indMap[$code]]["deviation"] =
+ $motivationDataTableSort[$indMap[$code]]["fact"] /
+ $motivationDataTableSort[$indMap[$code]]["plan"];
+ }
+ };
+ // $names = [
+ // "Выручка от реализации",
+ // "Продажа товара",
+ // "Оффлайн продажи",
+ // "Онлайн продажи",
+ // "Прочие услуги",
+ // "Услуги по сборке",
+ // "Услуги по доставке",
+ // "Прямые расходы на продажу",
+ // "Себестоимость товара",
+ // "Услуги агентов (Расходы на закупку, хранение, доставку товара)",
+ // "Брак, пересорт",
+ // "Брак с поставки",
+ // "Списание неликвидного товара: порча, истечение срока годности",
+ // "Брак из-за поломки оборудования",
+ // "Пересорт",
+ // "Расходные материалы (обеспечение продаж)",
+ // "Маржинальный доход",
+ // "Операционные расходы (Себестоимость)",
+ // "Оплата труда",
+ // "Фонд оплаты труда персонала",
+ // "Содержание помещения",
+ // "Аренда",
+ // "Коммунальные услуги",
+ // "Охрана",
+ // "Услуги по уборке помещений и территории",
+ // "Расходы по доставке",
+ // "Доставка до клиента курьер",
+ // "Доставка до клиента такси",
+ // "Услуги маркетплейсов",
+ // "Содержание и обслуживание ОС и НМА",
+ // "Холодильное оборудование (ремонт, содержание, ТО)",
+ // "Расходы на содержание и ремонт оргтехники, в т.ч. расходные материалы",
+ // "Расходы на содержание и ремонт прочих ОС",
+ // "Техническое обслуживание кассовых аппаратов",
+ // "Услуги связи",
+ // "Интернет",
+ // "Прочие операционные расходы",
+ // "Хозяйственные товары",
+ // "Канцтовары",
+ // "Вода питьевая",
+ // "Валовая прибыль",
+ // "Общехозяйственные расходы",
+ // "Бухгалтерия и финансы",
+ // "Бухгалтерские услуги: постановка и ведение БУ и НУ",
+ // "Юридическое сопровождение",
+ // "Юридические услуги",
+ // "HR- услуги",
+ // "Кадровое администрирование, охрана труда",
+ // "Услуги по подбору персонала",
+ // "IT услуги",
+ // "Администрирование ИТ инфраструктуры (подключения к базам данных, ПО, почта, интернет)",
+ // "Лицензия на ПО: ERP система",
+ // "Продвижение и продажа товара через сайт",
+ // "Чистая прибыль",
+ // "Рентабельность по чистой прибыли, %"
+ // ];
+ foreach (array_keys($indMap) as $code) {
+ $deviationFunc($code);
+ }
+
+ return $motivationDataTableSort;
+ }
}