use yii_app\records\ProductsClass;
use yii_app\records\Sales;
use yii_app\records\SalesProducts;
+ use yii_app\records\TimetableFactModel;
+ use yii_app\records\Timetable;
-
-
-use yii_app\records\EmployeePayment;
-
-
class MotivationService
{
return $totalSalary + $vacationSum;
}
+
+ /**
+ * @param $currentDate
+ * @return array
+ */
+ public static function getEmployeePayments($currentDate): array
+ {
+ // Запрос для получения всех записей, но только с учетом последней даты для каждого admin_id
+ $employeePayments = EmployeePayment::find()
+ ->where(['<=', 'date', $currentDate])
+ ->orderBy(['admin_id' => SORT_ASC, 'date' => SORT_DESC])
+ ->all();
+
+ // Преобразование результатов в массив admin_id => daily_payment
+ $dailyPayments = [];
+ foreach ($employeePayments as $payment) {
+ if (!isset($dailyPayments[$payment->admin_id])) {
+ $dailyPayments[$payment->admin_id] = $payment->daily_payment;
+ }
+ }
+ return $dailyPayments;
+ }
+
+ /**
+ * Возвращает массив, представляющий недели месяца (с указаниме начала и конца недели) для указанного года и месяца.
+ *
+ * @param int|string $year Год в виде числа или строки (например, `2024` или `'2024'`).
+ * @param int|string $month Месяц в виде числа или строки (например, `2` или `'02'`).
+ *
+ * @return array Массив недель месяца, где каждая неделя представлена ассоциативным массивом с ключами 'start' и 'end'.
+ * Пример возвращаемого массива:
+ * [
+ * ['start' => 1, 'end' => 7],
+ * ['start' => 8, 'end' => 14],
+ * ['start' => 15, 'end' => 21],
+ * ['start' => 22, 'end' => 28],
+ * ['start' => 29, 'end' => 30] // если месяц имеет больше 28 дней
+ * ]
+ */
+ public static function getWeeksOfMonthArray($year, $month): array
+ {
+ // Массив недель, изначально включающий первые четыре недели
+ $weeks = [
+ ['start' => 1, 'end' => 7],
+ ['start' => 8, 'end' => 14],
+ ['start' => 15, 'end' => 21],
+ ['start' => 22, 'end' => 28],
+ ];
+
+ // Определяем последний день месяца
+ $lastDayOfMonth = date('t', strtotime("$year-$month-01"));
+
+ // Если в месяце больше 28 дней, добавляем пятую неделю
+ if ($lastDayOfMonth > 28) {
+ $weeks[] = ['start' => 29, 'end' => $lastDayOfMonth];
+ }
+
+ 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,
+ 6, 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,
+ 6, 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);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ 6, 27, "float", $plan);
+ }
+ }
+
+ 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);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ 6, 28, "float", $plan);
+ }
+ }
+
+ 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);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ 6, 29, "float", $tariff * ($timetableFactModels[$motivation->store_id]['cnt'] ?? 0));
+ }
+ }
+
+ 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);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ 6, 31, "float", $plan);
+ }
+ }
+
+ 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);
+ self::saveOrUpdateMotivationValue($motivation->id,
+ 6, 32, "float", $plan);
+ }
+ }
+
+ 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,
+ 6, 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, 6, $index, "float", 0);
+ }
+ }
+ }
}