->indexBy('id');
- if (3 == date("n",strtotime($dateFrom)) || 3 == date("n",strtotime($dateTo))) {
- $queryClusterAdmin->andWhere(['parent_admin_id' => 182]); // для исключения директора по доставке
- }
+// if (3 == date("n",strtotime($dateFrom)) || 3 == date("n",strtotime($dateTo))) {
+// $queryClusterAdmin->andWhere(['parent_admin_id' => 182]); // для исключения директора по доставке
+// }
if (date("Y-m-d",strtotime($dateFrom)) < '2023-04-01' && date("Y-m-d",strtotime($dateTo)) < '2023-04-30') {
$queryClusterAdmin->andWhere(['parent_admin_id' => 182]); // для исключения директора по доставке
$param = array_merge($param, $paramAdditionsValue);
- return $this->controller->render('/cabinet/cluster', $param);
+ $cabinetPrefix = '';
+
+ if ($dateFrom >= '2023-10-01') {
+ $cabinetPrefix = '202310';
+ }
+
+ $view = '/cabinet' . $cabinetPrefix . '/cluster';
+
+ return $this->controller->render($view, $param);
}
}
->indexBy('id');
-
- if (3 == date("n",strtotime($dateFrom)) || 3 == date("n",strtotime($dateTo))) {
- $queryClusterAdmin->andWhere(['parent_admin_id' => 182]); // для исключения директора по доставке
- }
+//
+// if (3 == date("n",strtotime($dateFrom)) || 3 == date("n",strtotime($dateTo))) {
+// $queryClusterAdmin->andWhere(['parent_admin_id' => 182]); // для исключения директора по доставке
+// }
$clusterAdmin = $queryClusterAdmin->asArray()->one();
$date2_smen_time=strtotime($date2)+86400;
$date2_smen=date("Y-m-d",$date2_smen_time);
- $sales_products = [];
- if(!empty($check_id)) {
- $sales_products = $salesService->getSalesProducts($check_id);
- }
-
$equal_days = ($date1==$date2);
$arr_work = [
$saleServices = $salesService->getSalesServices($date1, $date2);
$saleServicesIds = ArrayHelper::getColumn($saleServices, 'id');
- $checkSellerDiscount = SalesProductsService::getCheckSellerDiscount($saleServicesIds);
-
$params = [
'shift' => $shift,
'date1' => $date1,
'number' => $number,
'city_stores' => $city_stores,
'store_traffik' => $store_traffik,
- 'sales_products' => $sales_products,
'equal_days' => $equal_days,
'arr_work' => $arr_work,
'date_timetable' => $date_timetable,
'productsArrayServices' => $productsArrayServices,
'servises' => $servises,
'saleServices' => $saleServices,
- 'checkSellerDiscount' => $checkSellerDiscount,
'daysSearchForm' => $daysSearchForm,
];
if (Yii::$app->user->can("updateAdminSettings", ['id' => $model->id])) {
if (Yii::$app->request->isPost) {
$attributes = Yii::$app->request->post()['Admin'];
- $mobile = $attributes['mobile'];
- if (mb_strlen($mobile) > 2 && $mobile[0] == 8 && $mobile[1] = 9) {
- $mobile[0] = 7;
- $attributes['mobile'] = $mobile;
- }
foreach (['parent_admin_id', 'org_id'] as $fieldName) {
if (empty($attributes[$fieldName])) {
$attributes[$fieldName] = 0;
--- /dev/null
+<?php
+
+namespace yii_app\actions\infoTable;
+
+use yii\base\Action;
+
+class CabinetAction extends Action
+{
+ public function run() {
+ return $this->controller->render('/info_table/cabinet.php', []);
+ }
+
+}
\ No newline at end of file
'allTotalPayroll', // ЗП
'personPrepaidExpense',
'personCounting',
+ 'partTimeWagesSumAdminAllStore',
'personRetention',
'toPayoff',
];
use yii_app\helpers\HtmlHelper;
use yii_app\records\AdminGroup;
use yii_app\records\AdminPayroll;
+use yii_app\records\AdminPayrollHistory;
use yii_app\records\AdminPayrollValues;
use yii_app\records\AdminPayrollValuesDict;
use yii_app\records\CityStore;
$aliasSumFields = [
'oklad', // Оклад
- 'deltaWagesAdmin',
+// 'deltaWagesAdmin',
'worksDayByTableFromSelectDay', // Число смен в графике
'adminSumGameCountShiftTotal', // Число смен геймификации
'personVacationDay',
'bonusMakeMatrix',
'teamBonusValue',
'userQualityPremium',
- 'adminSumGameBonusConversionToMoney',
+// 'adminSumGameBonusConversionToMoney',
'personBonuses', // Персональная Премия
'allTotalPayroll', // ЗП
+ 'adminPayrollCurrentLk', // Значение из личного кабинета
+ 'adminPayrollDelta', // Дельта значения из личного кабинета и текущего в ведомости
'personPrepaidExpense',
'personCounting',
'personRetention',
->asArray()
->all();
+ $lastPacketNum = AdminPayrollHistory::find()
+ ->select(['packet_num'])
+ ->andWhere(['year' => $yearSelect])
+ ->andWhere(['month' => $monthWithZeroSelect])
+ ->orderBy(['packet_num' => SORT_DESC])
+ ->distinct(true)
+ ->scalar();
+
+ $lastPacketDate = date('d.m.Y H:i:s', $lastPacketNum);
+
+ $adminPayrollCurrentLk = AdminPayrollHistory::find()
+ ->select(['admin_id', 'admin_payroll_history.value_number AS value'])
+ ->andWhere(['year' => $yearSelect])
+ ->andWhere(['group_number' => AdminPayrollHistory::GROUP_VALUE_ALL_TOTAL_PAYROLL])
+ ->andWhere(['month' => $monthWithZeroSelect])
+ ->andWhere(['packet_num' => $lastPacketNum])
+ ->indexBy('admin_id')
+ ->asArray()
+ ->all();
+
$sumColumnByAlias = [];
foreach ($adminPayroll as $key => $rowAdmins) {
$payrollIds = $rowAdmins['id'];
+ $adminIdRow = $rowAdmins['admin_id'];
foreach ($aliasSumFields as $keyAlias => $alias) {
if (array_key_exists($alias, $adminPayrollValuesDict)) {
$keyRow = $alias.'.id';
if (!empty($sumRow)) {
$sumColumnByAlias[$keyAlias] += $sumRow;
}
+ } else {
+ if ($dateFrom >= '2023-12-01') {
+ $sumRow = 0;
+ if ('adminPayrollCurrentLk' == $alias) {
+ $payrollStoreColumn[$alias] = 'Значение ЗП в ЛК <br>( на ' . $lastPacketDate . ')';
+
+ if (array_key_exists($adminIdRow, $adminPayrollCurrentLk)) {
+ $keySumRow = $adminIdRow . '.value';
+ $sumRow = (float) ArrayHelper::getValue($adminPayrollCurrentLk, $keySumRow);
+ }
+ $adminPayroll[$key]['column'][$alias] = $sumRow;
+
+ }
+ if ('adminPayrollDelta' == $alias) {
+ $payrollStoreColumn[$alias] = 'Разница ЗП между ведомостью и ЛК';
+
+ $sumHistoryRow = 0;
+ if (!empty($adminPayroll[$key]['column']['adminPayrollCurrentLk'])) {
+ $sumHistoryRow = $adminPayroll[$key]['column']['adminPayrollCurrentLk'];
+ }
+ $sumPayrollRow = 0;
+ $keyAliasNameRow = 'allTotalPayroll.name';
+ $aliasNameRow = ArrayHelper::getValue($adminPayrollValuesDict, $keyAliasNameRow);
+ if (!empty($adminPayroll[$key]['column'][$aliasNameRow])) {
+ $sumPayrollRow = $adminPayroll[$key]['column'][$aliasNameRow];
+ }
+ $sumRow = $sumPayrollRow - $sumHistoryRow;
+ $adminPayroll[$key]['column']['adminPayrollDelta'] = $sumRow;
+ //allTotalPayroll
+ }
+ if (!array_key_exists($keyAlias, $sumColumnByAlias)) {
+ $sumColumnByAlias[$keyAlias] = 0;
+ }
+ if (!empty($sumRow)) {
+ $sumColumnByAlias[$keyAlias] += $sumRow;
+ }
+ }
}
}
}
'yearMonthSearchForm' => $yearMonthSearchForm,
'sumColumnByAlias' => $sumColumnByAlias,
'monthNameSelect' => $monthNameSelect,
+ 'lastPacketDate' => $lastPacketDate,
]);
}
}
\ No newline at end of file
'saveValuesOk' => 'saveValuesOk',
'Командный бонус' => 'teamBonusValue',
'Премия за качество' => 'userQualityPremium',
+ 'Командный бонус детально' => 'teamBonusDetail',
+ 'Оклады за подработку' => 'partTimeWagesSumAdminAllStore',
+ 'Число смен подработок' => 'partTimeWagesCountAdminAllStore',
];
$adminPayrollValuesDict = AdminPayrollValuesDict::find()
]);
}
- $groupIds = [
- 30,
- 35,
- 40,
- 45, // подработчики
- 50, // Администраторы
- 72, //
- -1
- ];
+ $groupIds = Admin::ADMIN_PAYROLL_MAKE_GROUP_IDS;
// пропускать недавно обновлённые, за последние 20 минут
$dateCheckReset = date("Y-m-d H:i:s", time() - (60 * 60));
$aliasSumFields = [
'oklad', // Оклад
'worksDayByTableFromSelectDay', // Число смен в графике
+ 'partTimeWagesCountAdminAllStore',
'personVacationDay',
'personVacationPay',
'userSalaryServicesPremium',
'allTotalPayroll', // ЗП
'personPrepaidExpense',
'personCounting',
+ 'partTimeWagesSumAdminAllStore',
'personRetention',
'toPayoff',
];
namespace yii_app\actions\timetable;
+use Yii;
use yii\base\Action;
use yii\web\Response;
use yii_app\records\Admin;
+use yii_app\records\Timetable;
use yii_app\records\TimetableFact;
use yii_app\records\TimetablePlan;
'store_id' => $this->controller->request->get('storeId'),
];
$slot = TimetablePlan::find()->andWhere($row)->one();
- $fact = TimetableFact::find()->andWhere(['plan_id' => $slot->id])->one();
if (!$slot) {
$slot = new TimetablePlan($row);
/** @var Admin $admin */
$slot->time_start = $slot->shift ? $slot->shift->start_time : null;
$slot->time_end = $slot->shift ? $slot->shift->end_time : null;
}
+ $fact = TimetableFact::find()->andWhere(['plan_id' => $slot->id])->one();
return $this->controller->renderPartial('/timetable/tabel_edit.php', [
'slot' => $slot,
'fact' => $fact,
$slot->admin_group_id = $slot->validate(['admin_id']) ? $slot->admin->group_id : null;
if ($slot->validate(null, false)) {
- $slot->save(false);
+ $session = Yii::$app->session;
+ $groupId = (int) $session->get('group_id');
+
+ $numDay = Timetable::getCountDaysAllowEditShift($groupId);
+
+ if (Timetable::getAllowEditShift($slot->date, $numDay)) {
+ $slot->save(false);
+ }
}
return $this->makeResponse($slot);
}
use yii_app\records\Contest001;
use yii_app\records\ExportImportTable;
use yii_app\records\MessagerUser;
+use yii_app\records\NotifiableUser;
use yii_app\records\Products1c;
use yii_app\records\Sales;
use yii_app\records\Timetable;
private static $SECOND_SALE_PROCENT = 0.15;
private static $MAX_PROCENT = 0.2;
private static $CREDIT_PROCENT = 0.1;
+ private static $CREDIT_HIGH_PROCENT = 0.3;
+ private static $CREDIT_HIGH_PROCENT_PART20 = 0.2;
public function actionGetBonuses()
{
$percent = ($result['phone'] == "79049031399") ? 0.9 : $max_procent;
- $will_be_credited_bonuses = self::$CREDIT_PROCENT * $baza;
- if ($result['phone'] == "79049031399") {
- $will_be_credited_bonuses = $percent * $check_amount;
+ $userFound = Users::find()->where(['phone' => $result['phone']])->one();
+ /** @var $userFound Users */
+ $salesCount = 0;
+ if ($userFound && $userFound->telegram_created_at) {
+ $salesCount = intval(Sales::find()->where(['phone' => $result['phone'], 'operation' => Sales::OPERATION_SALE])
+ ->andWhere(['>=', 'date', $userFound->telegram_created_at])->count());
}
+ $credit_procent = $userFound && $userFound->source > 0 && $salesCount == 0 ? self::$CREDIT_HIGH_PROCENT : self::$CREDIT_PROCENT;
+ $will_be_credited_bonuses = $credit_procent * $baza;
+
$will_be_credited_bonuses = round($will_be_credited_bonuses);
$mess["will_be_credited_bonuses"] = $will_be_credited_bonuses;
// получаем внутренний ID продаца - сотрудника из таблицы admin
$store_id = ClientHelper::getExportId($store_id_1c, "city_store", 1);
- if ($write_off_bonuses) {
+ $writeOffAlready = false;
+ if (!empty($lid_id)) {
+ $writeOffAlready = UsersBonus::find()->where(['lid_id' => $lid_id, 'phone' => $phone, 'tip_sale' => 'sale', 'tip' => 'minus'])->one() != null;
+ }
+
+ $user_balans_new = $user_balans;
+ if ($write_off_bonuses && !$writeOffAlready) {
$user_balans_new = $user_balans - $write_off_bonuses;
$name_b = "Спиcание бонусов по чеку $check_name";
$usersBonus = new UsersBonus;
FILE_APPEND | LOCK_EX);
}
//начисляем кэшбек клиенту 10% от покупки - с базы за вычитом бонусов которые он списывает
- $back = round($baza_back * self::$CREDIT_PROCENT);
- $nm = "Возврат с покупки 10% $check_name сумма чека $check_amount";
+ $userFound = Users::find()->where(['phone' => $result['phone']])->one();
+ /** @var $userFound Users */
+ $salesCount = 0;
+ if ($userFound && $userFound->telegram_created_at) {
+ $salesCount = intval(Sales::find()->where(['phone' => $result['phone'], 'operation' => Sales::OPERATION_SALE])
+ ->andWhere(['>=', 'date', $userFound->telegram_created_at])->count());
+ }
+ $credit_procent_index = $userFound && $userFound->source > 0 && $salesCount == 0 ? 1 : 0;
+
+ $back1 = $back = round($baza_back * self::$CREDIT_PROCENT);
+ $nm = "Возврат с покупки " . (100 * self::$CREDIT_PROCENT) . "% $check_name сумма чека $check_amount";
$userBonus2 = UsersBonus::find()->where(['phone' => $phone])->andWhere(['check_id' => $check_id])->andWhere(['site_id' => $site_id])
->andWhere(['store_id' => $store_id])->andWhere(['tip' => 'plus'])->andWhere(['bonus' => $back])->andWhere(['name' => $nm])->one();
if (!$userBonus2) {
$userBonus2->price = $summa_chek;
$userBonus2->store_id_1c = $store_id_1c;
$userBonus2->seller_id_1c = $seller_id;
- $userBonus2->user_id = $user_id; // Поле не заполнялось в старом апи, но без него бд выдаёт ошибку при сохранении
- $userBonus2->lid_id = $lid_id; // Поле не заполнялось в старом апи, но без него бд выдаёт ошибку при сохранении
- $userBonus2->price_skidka = 0; // Поле не заполнялось в старом апи, но без него бд выдаёт ошибку при сохранении
- $userBonus2->date_dell = $userBonus2->date_end; // Поле не заполнялось в старом апи, но без него бд выдаёт ошибку при сохранении
+ $userBonus2->user_id = $user_id;
+ $userBonus2->lid_id = $lid_id;
+ $userBonus2->price_skidka = 0;
+ $userBonus2->date_dell = $userBonus2->date_end;
$userBonus2->save();
if ($userBonus2->getErrors()) {
file_put_contents(self::$USERS_AUTH_CALL_LOG2,
"" . date("d.m.Y H:i:s", time()) . " PLUS bonus=" . $back . "\n",
FILE_APPEND | LOCK_EX);
+ if ($credit_procent_index) {
+ $back = round($baza_back * self::$CREDIT_HIGH_PROCENT_PART20);
+ $nm = "Возврат с покупки " . (100 * self::$CREDIT_HIGH_PROCENT_PART20) . "% $check_name сумма чека $check_amount";
+
+ $user_balans_new += $back;
+
+ $userBonus2 = new UsersBonus;
+ $userBonus2->tip = 'plus';
+ $userBonus2->tip_sale = 'sale';
+ $userBonus2->date = date('Y-m-d H:i:s');
+ $userBonus2->date_start = date('Y-m-d H:i:s', strtotime('+1 day', time()));
+ $userBonus2->date_end = date('Y-m-d H:i:s', strtotime('+3 month', time()));
+ $userBonus2->phone = $phone;
+ $userBonus2->name = $nm;
+ $userBonus2->check_id = $check_id;
+ $userBonus2->store_id = $store_id;
+ $userBonus2->bonus = $back;
+ $userBonus2->ip = $ip;
+ $userBonus2->site_id = $site_id;
+ $userBonus2->referal_id = 0;
+ $userBonus2->admin_id = $admin_id;
+ $userBonus2->price = $summa_chek;
+ $userBonus2->store_id_1c = $store_id_1c;
+ $userBonus2->seller_id_1c = $seller_id;
+ $userBonus2->user_id = $user_id;
+ $userBonus2->lid_id = $lid_id;
+ $userBonus2->price_skidka = 0;
+ $userBonus2->date_dell = $userBonus2->date_end;
+ $userBonus2->save();
+ if ($userBonus2->getErrors()) {
+
+ LogService::apiErrorLog(json_encode(["error_id" => 5.2, "error" => $userBonus2->getErrors()], JSON_UNESCAPED_UNICODE));
+
+ return $this->asJson(["error_id" => 5.2, "error" => $userBonus2->getErrors()]);
+ }
+ if ($userFound->telegram_created_at == null) {
+ $userFound->telegram_created_at = date("Y-m-d H:i:s");
+ $userFound->save();
+ if ($userFound->getErrors()) {
+
+ LogService::apiErrorLog(json_encode(["error_id" => 5.3, "error" => $userFound->getErrors()], JSON_UNESCAPED_UNICODE));
+
+ return $this->asJson(["error_id" => 5.3, "error" => $userFound->getErrors()]);
+ }
+ }
+
+ $notifiableUser = new NotifiableUser;
+ $notifiableUser->phone = $phone;
+ $notifiableUser->type = "first_given_bonus";
+ $notifiableUser->data = "" . ($back1 + $back);
+ $notifiableUser->save();
+ if ($notifiableUser->getErrors()) {
+ return $this->asJson(["error_id" => 5.4, "error" => $notifiableUser->getErrors()]);
+ }
+ }
}
// /////// Добавляем бонусов рефералу
}
//
- if (!in_array($result['tip_sale'], ['podarok', 'senat', 'nino802'])) {
+ if (!in_array($result['tip_sale'], ['podarok', 'senat', 'nino802', 'sale', '14feb', '23feb', '8mar'])) {
return $this->asJson(["error_id" => 1.1, "error" => "tip_sale не разрешён (podarok, senat, nino802)"]);
}
$yiiApp = dirname(__DIR__, 3);
Yii::setAlias('@yii_app', $yiiApp);
-Yii::setAlias('@upload-checkin', dirname(__DIR__, 3) . "/uploads/checkin");
\ No newline at end of file
+Yii::setAlias('@upload-checkin', dirname(__DIR__, 3) . "/data/admin");
\ No newline at end of file
$error['code'] = $response->data['code'];
}
} elseif($exception instanceof HttpException) {
- $error['type'] = $response->data['name'] ? strtolower(str_replace($response->data['name'], " ", "_")) : "invalid_request";
+ $error['type'] = $response->data['name'] ? strtolower(str_replace($response->data['name'], " ", "_")) : "invalid_request_type_1";
$error['message'] = $exception->getMessage();
} elseif($exception instanceof InvalidArgumentException) {
- $error['type'] = "invalid_request";
+ $error['type'] = "invalid_request_type_2";
$error['message'] = $exception->getMessage();
}
return true;
}
+
+ /**
+ * @throws \yii\base\Exception
+ * @throws Exception
+ */
+ public function bonusWriteOff($data) {
+ $phone = $data->phone;
+ $price = $data->price;
+ $bonus = $data->bonus;
+ $lid_id = $data->lid_id;
+
+ $stop = UsersStopList::find()->select(['phone'])->where(['phone' => $data->phone])->one();
+ if ($stop) {
+ throw new InvalidArgumentException("Номер телефона числится в стоп листе");
+ }
+
+ $found = UsersBonus::find()->where(['phone' => $phone])->andWhere(['>=', 'date_start', date('Y-m-d H:i:s', time() - 14 * 86400)])
+ ->andWhere(['tip_sale' => 'sale'])->andWhere(['tip' => 'minus'])->andWhere(['lid_id' => $lid_id])->andWhere(['bonus' => $bonus])->one();
+
+ if ($found) {
+ throw new InvalidArgumentException("Бонусы уже списаны");
+ }
+
+ $userBonus = new UsersBonus;
+ $userBonus->phone = $phone;
+ $userBonus->name = "Списание $bonus бонусов с заказа номер $lid_id на общую сумму $price";
+ $userBonus->date = date('Y-m-d H:i:s');
+ $userBonus->site_id = 1;
+ $userBonus->setka_id = 1;
+ $userBonus->tip = 'minus';
+ $userBonus->tip_sale = 'sale';
+ $userBonus->bonus = $bonus;
+ $userBonus->price = $price;
+ $userBonus->lid_id = $lid_id;
+ $userBonus->date_start = $data->date_start ?? $userBonus->date;
+ $userBonus->date_end = $data->date_end ?? date("Y-m-d H:i:s", strtotime("+" . self::$YEAR_PERIOD . ' days', strtotime($userBonus->date)));
+ $userBonus->save();
+
+ if ($userBonus->getErrors()) {
+ LogService::apiErrorLog(json_encode(["error_id" => 2, "error" => $userBonus->getErrors()], JSON_UNESCAPED_UNICODE));
+ throw new InvalidArgumentException(array_values($userBonus->firstErrors)[0] ?? "");
+ }
+
+ return true;
+ }
}
\ No newline at end of file
{
public function create(Worker $row)
{
+ $found = Admin::find()->where(['mobile' => $row->phone])->one() != null;
+ if ($found) {
+ throw new InvalidArgumentException("Пользователь с таким номером телефона уже существует, для создания смены перейдите во вкладку «Календарь смен» —> «Создать смену»");
+ }
$model = new EmployeeOnShift($row);
$model->guid = DataHelper::createGuidMy("06");
$model->created_at = date(DATE_ATOM);
$exportImportTable->export_val = $model->guid;
$exportImportTable->save();
- $timeslot = Timetable::TIMESLOT_FREELANCE;
+ $timeslot = Timetable::TIMESLOT_WORK;
} else {
$admin = $oldAdmin;
// Чтобы при создании подработчиков в 1с по guid заявки находился admin,
$timetable->time_end = $model->shift_type == 1 ? '20:00:00' : '08:00:00';
$timetable->work_time = 12;
// $timetable->price_hour = $model->price;
+ $timetable->salary_shift = $model->salary_shift;
$timetable->slot_type_id = $timeslot;
$timetable->date_add = date('Y-m-d H:i:s');
$timetable->status = Timetable::STATUS_PENDING;
$baseIncome = [];
foreach ($plans as $plan) {
/* @var $plan Timetable */
+ if (!isset($workHoursPerPlanId[$plan->id])) {
+ continue;
+ }
// получаем отработку со временем для каждой запланированной смены
$baseIncome [] = [
'date' => $plan->date,
'shift_id' => $plan->shift_id,
+ 'salary_shift' => $plan->salary_shift,
'price' => $plan->shift_id == 1 ? 125 : 145,
'work_hours' => $workHoursPerPlanId[$plan->id] ?? 0, // если план есть, а факта нет, то 0 чаов отработано
'in_shift' => count($plan->checkIns) == 1,
--- /dev/null
+<?php
+
+namespace yii_app\api3\core\services;
+
+use yii\db\Exception;
+use yii\db\Expression;
+use yii\helpers\ArrayHelper;
+use yii_app\records\NotifiableUser;
+use yii_app\records\UsersBonus;
+
+class NotifiableService
+{
+ /**
+ * @throws \yii\base\Exception
+ * @throws Exception
+ */
+ public function getExpiredBonuses() {
+ $buffer = [];
+ foreach (['+1 month', '+1 week'] as $timePeriod) {
+ $userBonus = UsersBonus::find()->where(['between', 'date_end',
+ date("Y-m-d 00:00:00", strtotime($timePeriod, time())),
+ date("Y-m-d 23:59:59", strtotime($timePeriod, time()))])
+ ->andWhere(['tip' => 'plus'])->all();
+ foreach ($userBonus as $bonus) {
+ /** @var $bonus UsersBonus */
+ $percent = $bonus->price > $bonus->bonus ? floor($bonus->bonus / $bonus->price * 100) : 0;
+ $is_cashback = $percent > 19;
+ $buffer[$bonus->phone] =[
+ "date" => date("c", strtotime($bonus->date_end)),
+ "amount" => $bonus->bonus,
+ "is_cashback" => $is_cashback
+ ];
+ }
+ }
+
+ $userBonuses = UsersBonus::find()->select(['phone', 'sum(if(tip=\'plus\', bonus, -bonus)) as sum'])
+ ->where(['in', 'phone', array_keys($buffer)])
+ ->andWhere(['<', 'date_start', new Expression('NOW()')])
+ ->andWhere(['>', 'date_end', new Expression('NOW()')])
+ ->groupBy(['phone'])->all();
+ $buffer2 = ArrayHelper::map($userBonuses, 'phone', 'sum');
+
+ $phones = [];
+ foreach ($buffer as $phone => $data) {
+ $data['amount'] = min($data['amount'], $buffer2[$phone]);
+ if ($data['amount'] < 1) {
+ continue;
+ }
+ $phones [] = ArrayHelper::merge(
+ ["phone" => "" . $phone, "balance" => $buffer2[$phone]],
+ $data
+ );
+ }
+
+ return $phones;
+ }
+
+ /**
+ * @throws \yii\base\Exception
+ * @throws Exception
+ */
+ public function getGetFirstSaleUsers() {
+ // Приготовиться к копированию
+ NotifiableUser::updateAll(['status' => 1], ['status' => 0]);
+ $notifiableUsers = NotifiableUser::find()->where(['status' => 1])->asArray()->all();
+ NotifiableUser::deleteAll(['status' => 1]);
+ return $notifiableUsers;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\api3\core\services;
+
+use yii\db\Exception;
+use yii\db\Expression;
+use yii\helpers\ArrayHelper;
+use yii_app\api3\modules\v1\models\timetable\Timetable;
+use yii_app\records\AdminPayrollDays;
+use yii_app\records\CityStore;
+use yii_app\records\ExportImportTable;
+use yii_app\records\Products1c;
+use yii_app\records\ProductsClass;
+use yii_app\records\Sales;
+use yii_app\records\StoreVisitors;
+use yii_app\records\WriteOffs;
+use yii_app\records\WriteOffsErp;
+
+class ReportService
+{
+ /**
+ * @throws \yii\base\Exception
+ * @throws Exception
+ */
+ public function show($data) {
+ $currentDate = $data->date_start;
+ $reports = [];
+ while ($currentDate <= $data->date_end) {
+ $report = [
+ "date" => $currentDate,
+ "shift_type" => $data->shift_type,
+ ];
+
+ $shift_id = $data->shift_type == 0 ? [1, 2, 5, 8] : ($data->shift_type == 1 ? [1, 5, 8] : [2]);
+
+ $timetablesMonth = Timetable::find()->alias('t')->select(['admin_id', 'a.name as adminName', 't.store_id', 't.shift_id'])
+ ->innerJoin('admin a', 'admin_id = a.id')
+ ->where(['t.store_id' => $data->stores])
+ ->andWhere(['>=', 'date', date("Y-m-01", strtotime($currentDate))])
+ ->andWhere(['<=', 'date', $currentDate])
+ ->andWhere(['shift_id' => $shift_id, 'tabel' => 0, 'slot_type_id' => Timetable::TIMESLOT_WORK])
+ ->asArray()->all();
+
+ $timetables = Timetable::find()->alias('t')->select(['admin_id', 'a.name as adminName', 't.store_id', 't.shift_id'])
+ ->innerJoin('admin a', 'admin_id = a.id')
+ ->where(['t.store_id' => $data->stores])
+ ->andWhere(['date' => $currentDate, 'tabel' => 0])
+ ->andWhere(['shift_id' => $shift_id, 'slot_type_id' => Timetable::TIMESLOT_WORK])
+ ->asArray()->all();
+
+ $adminIdsMonth = ArrayHelper::getColumn($timetablesMonth, 'admin_id');
+ $adminIds = ArrayHelper::getColumn($timetables, 'admin_id');
+
+ $adminPayrollDaysMonth = AdminPayrollDays::find()->select(["FLOOR(SUM(day_payroll)) as total", "store_id"])
+ ->where(['>=', 'date', date("Y-m-01", strtotime($currentDate))])
+ ->andWhere(['<=', 'date', $currentDate])
+ ->andWhere(['admin_id' => $adminIdsMonth])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ $adminPayrollDays = AdminPayrollDays::find()->select(["FLOOR(SUM(day_payroll)) as total", "store_id"])
+ ->where(['date' => $currentDate, 'admin_id' => $adminIds])
+ ->groupBy(['store_id'])
+ ->indexBy('store_id')
+ ->asArray()->all();
+
+ $date_start = $data->shift_type == 2 ?
+ date("Y-m-d 20:00:00", strtotime($currentDate)) :
+ date("Y-m-d 08:00:00", strtotime($currentDate));
+ $date_end = $data->shift_type == 1 ?
+ date("Y-m-d 20:00:00", strtotime($currentDate)) :
+ date("Y-m-d 08:00:00", strtotime("+1 day", strtotime($currentDate)));
+
+ $storeVisitorsQuery = StoreVisitors::find()
+ ->select([
+ 'counter' => new \yii\db\Expression("SUM(counter)"),
+ 'store_id',
+ ]);
+
+ if ($data->shift_type == 1) {
+ $storeVisitorsQuery->andWhere(['>=', 'date_hour', 8])->andWhere(['<=', 'date_hour', 20])
+ ->andWhere(['date' => date("Y-m-d", strtotime($currentDate))]);
+ }
+ if ($data->shift_type == 2) {
+ $storeVisitorsQuery->andWhere([
+ 'or',
+ [
+ 'and',
+ ['>=', 'date_hour', 20],
+ ['<=', 'date_hour', 23],
+ ['date' => date("Y-m-d", strtotime($currentDate))]
+ ],
+ [
+ 'and',
+ ['>=', 'date_hour', 0],
+ ['<=', 'date_hour', 7],
+ ['date' => date("Y-m-d", strtotime("+1 day", strtotime($currentDate)))]
+ ],
+ ]);
+ }
+ if ($data->shift_type == 0) {
+ $storeVisitorsQuery->andWhere([
+ 'or',
+ [
+ 'and',
+ ['>=', 'date_hour', 8],
+ ['<=', 'date_hour', 23],
+ ['date' => date("Y-m-d", strtotime($currentDate))]
+ ],
+ [
+ 'and',
+ ['>=', 'date_hour', 0],
+ ['<=', 'date_hour', 7],
+ ['date' => date("Y-m-d", strtotime("+1 day", strtotime($currentDate)))]
+ ],
+ ]);
+ }
+
+ $storeVisitors = $storeVisitorsQuery->groupBy(['store_id'])->asArray()->all();
+ $storeVisitorsByStore = ArrayHelper::map($storeVisitors, 'store_id', 'counter');
+
+ $salesPhones = Sales::find()->alias('s')->select(["DISTINCT(s.phone)"])
+ ->where(['between', 's.date', $date_start, $date_end])
+ ->andWhere(['IS NOT', 's.phone', new Expression('NULL')])
+ ->andWhere(['s.store_id' => $data->stores])
+ ->asArray()->all();
+
+ $sales = Sales::find()->alias('s')->select(["COUNT(*) as cnt",
+ "sum(IF(operation='Продажа',s.summ,IF(operation='Возврат',-s.summ,0))) as total",
+ "sum(IF(IfNull(s.phone,-1)=-1,0,1)) as bonusUserCount",
+ "sum(IF(IfNull(s.phone,-1)!=-1 AND (IfNull(u.sale_cnt, -1) = -1 OR u.sale_cnt < 2), 1, 0)) as newBonusUserCount",
+ "sum(IF(IfNull(s.phone,-1)!=-1 AND u.sale_cnt > 1, 1, 0)) as repeatBonusUserCount",
+ "s.store_id",
+ "s.admin_id"])
+ ->leftJoin('users u', 'u.phone = s.phone AND u.phone IN (\''
+ . implode('\',\'', ArrayHelper::getColumn($salesPhones, 'phone')) .'\')')
+ ->where(['between', 's.date', $date_start, $date_end])
+ ->andWhere(['s.store_id' => $data->stores])
+ ->groupBy(['s.store_id', 's.admin_id'])->asArray()->all();
+
+ $salesMapArr = [];
+ foreach ($sales as $sale) {
+ $salesMapArr[$sale['store_id']][] = $sale;
+ }
+
+ $writeOffsMonth = WriteOffs::find()->select(['sum(summ) as total', 'store_id'])
+ ->where(['between', 'date', date("Y-m-01", strtotime($currentDate)), $date_end])
+ ->andWhere(['type' => WriteOffsErp::WRITE_OFFS_TYPE_BRAK])
+ ->groupBy(['store_id'])
+ ->indexBy(['store_id'])
+ ->asArray()->all();
+
+ $writeOffs = WriteOffs::find()->select(['sum(summ) as total', 'store_id'])
+ ->where(['between', 'date', $date_start, $date_end])
+ ->andWhere(['type' => WriteOffsErp::WRITE_OFFS_TYPE_BRAK])
+ ->groupBy(['store_id'])
+ ->indexBy(['store_id'])
+ ->asArray()->all();
+
+ $eitMonth = ExportImportTable::find()->where(['export_val' => array_keys($writeOffsMonth)])
+ ->select(['entity_id', 'export_val'])
+ ->where(['export_id' => 1, 'entity' => 'city_store'])
+ ->indexBy(['export_val'])
+ ->asArray()->all();
+
+ $totalWriteOffsByStoreId = [];
+ foreach ($writeOffs as $guid => $value) {
+ $totalWriteOffsByStoreId[$eitMonth[$guid]['entity_id']] = $value['total'];
+ }
+
+ $totalWriteOffsByStoreIdMonth = [];
+ foreach ($writeOffsMonth as $guid => $value) {
+ $totalWriteOffsByStoreIdMonth[$eitMonth[$guid]['entity_id']] = $value['total'];
+ }
+
+ $specificSales = [];
+ foreach (['matrix', 'wrap', 'services', 'potted'] as $productTip) {
+ $productsClass = ProductsClass::find()->select(['category_id', 'tip'])
+ ->where(['tip' => $productTip])
+ ->indexBy('category_id')
+ ->asArray()->all();
+
+ $products1c = Products1c::find()->select(['id', 'parent_id', 'name'])
+ ->where(['parent_id' => array_keys($productsClass), 'tip' => 'products'])
+ ->indexBy(['id'])
+ ->asArray()->all();
+
+ $salesMatrix = Sales::find()->alias('s')->select([
+ "sum(IF(operation='Продажа',p.summ,IF(operation='Возврат',-p.summ,0))) as total",
+ 's.store_id', 's.admin_id'])
+ ->leftJoin('sales_products p', 'p.check_id = s.id')
+ ->where(['between', 's.date', $date_start, $date_end])
+ ->andWhere(['operation' => Sales::OPERATION_SALE])
+ ->andWhere(['p.product_id' => array_keys($products1c)])
+ ->groupBy(['s.store_id', 's.admin_id'])
+ ->asArray()->all();
+
+ $specificSales[$productTip] = $salesMatrix;
+ }
+
+ $adminNames = [];
+ foreach ($timetables as $timetable) {
+ $adminNames[$timetable['store_id']][] = [
+ 'id' => $timetable['admin_id'],
+ 'name' => $timetable['adminName'],
+ 'shift_id' => $timetable['shift_id'],
+ ];
+ }
+
+ $storeVisitorsQuantityTotal = 0;
+ $storeSaleQuantityTotal = 0;
+ $storeSaleTotalTotal = 0;
+ $storeSaleBonusCountTotal = 0;
+ $storeSaleNewBonusCountTotal = 0;
+ $storeSaleRepeatBonusCountTotal = 0;
+ $totalWriteOffsPerDateTotal = 0;
+ $totalWriteOffsPerMonthTotal = 0;
+ $totalPayrollDaysTotal = 0;
+ $totalPayrollMonthTotal = 0;
+ $totalMatrixPerDayTotal = 0;
+ $totalWrapPerDayTotal = 0;
+ $totalServicePerDayTotal = 0;
+ $totalPottedPerDayTotal = 0;
+
+ $stores = CityStore::find()->where(['id' => $data->stores])->all();
+ foreach ($stores as $store) {
+ /** @var CityStore $store */
+ $storeSaleArr = $salesMapArr[$store->id] ?? [];
+ $storeVisitorsQuantity = (int)($storeVisitorsByStore[$store->id] ?? 0);
+ $storeSaleQuantity = 0;
+ $storeSaleTotal = 0;
+ $storeSaleBonusCount = 0;
+ $storeSaleNewBonusCount = 0;
+ $storeSaleRepeatBonusCount = 0;
+ $storeSaleByAdminId = [];
+ foreach ($storeSaleArr as $storeSale) {
+ $storeSaleByAdminId[$storeSale['admin_id']] = $storeSale;
+ $storeSaleQuantity += (int)$storeSale['cnt'];
+ $storeSaleTotal += (int)$storeSale['total'];
+ $storeSaleBonusCount += (int)$storeSale['bonusUserCount'];
+ $storeSaleNewBonusCount += (int)$storeSale['newBonusUserCount'];
+ $storeSaleRepeatBonusCount += (int)$storeSale['repeatBonusUserCount'];
+ }
+
+ $storeVisitorsQuantityTotal += $storeVisitorsQuantity;
+ $storeSaleQuantityTotal += $storeSaleQuantity;
+ $storeSaleTotalTotal += $storeSaleTotal;
+ $storeSaleBonusCountTotal += $storeSaleBonusCount;
+ $storeSaleNewBonusCountTotal += $storeSaleNewBonusCount;
+ $storeSaleRepeatBonusCountTotal += $storeSaleRepeatBonusCount;
+
+ if (isset($adminNames[$store->id])) {
+ foreach ($adminNames[$store->id] as &$adminRecord) {
+ $adminRecord["sale_quantity"] = (int)($storeSaleByAdminId[$adminRecord['id']]['cnt'] ?? 0);
+ $adminRecord["sale_total"] = (int)($storeSaleByAdminId[$adminRecord['id']]['total'] ?? 0);
+ $adminRecord["sale_avg"] = $adminRecord["sale_quantity"] > 0 ? floor($adminRecord["sale_total"] / $adminRecord["sale_quantity"]) : 0;
+ $adminRecord["bonus_user_count"] = (int)($storeSaleByAdminId[$adminRecord['id']]['bonusUserCount'] ?? 0);
+ $adminRecord["bonus_user_per_sale_percent"] = $adminRecord["sale_quantity"] > 0 ? floor($adminRecord["bonus_user_count"] / $adminRecord["sale_quantity"] * 100) : 0;
+ $adminRecord["bonus_new_user_count"] = (int)($storeSaleByAdminId[$adminRecord['id']]['newBonusUserCount'] ?? 0);
+ $adminRecord["bonus_repeat_user_count"] = (int)($storeSaleByAdminId[$adminRecord['id']]['repeatBonusUserCount'] ?? 0);
+ }
+ }
+
+ $totalWriteOffsPerDate = (int)($totalWriteOffsByStoreId[$store->id] ?? 0);
+ $totalWriteOffsPerMonth = (int)($totalWriteOffsByStoreIdMonth[$store->id] ?? 0);
+ $totalWriteOffsPerDateTotal += $totalWriteOffsPerDate;
+ $totalWriteOffsPerMonthTotal += $totalWriteOffsPerMonth;
+
+ $totalPayrollDays = (int)($adminPayrollDays[$store->id]['total'] ?? 0);
+ $totalPayrollMonth = (int)($adminPayrollDaysMonth[$store->id]['total'] ?? 0);
+
+ $totalPayrollDaysTotal += $totalPayrollDays;
+ $totalPayrollMonthTotal += $totalPayrollMonth;
+
+ $totalSpecificPerDay = [];
+ foreach (['matrix', 'wrap', 'services', 'potted'] as $spec) {
+ $totalSpecificPerDay[$spec] = 0;
+ if (isset($adminNames[$store->id])) {
+ foreach ($adminNames[$store->id] as &$adminRecord) {
+ $adminRecord["total_" . $spec . "_per_day"] = 0;
+ }
+ }
+ foreach ($specificSales[$spec] as $specificSale) {
+ if ($specificSale['store_id'] == $store->id) {
+ $totalSpecificPerDay[$spec] += $specificSale['total'];
+ }
+ if (isset($adminNames[$store->id])) {
+ foreach ($adminNames[$store->id] as &$adminRecord) {
+ if ($specificSale['admin_id'] == $adminRecord['id']) {
+ $adminRecord["total_" . $spec . "_per_day"] = (int)$specificSale['total'];
+ }
+ }
+ }
+ }
+ }
+ $totalMatrixPerDay = $totalSpecificPerDay['matrix'];
+ $totalWrapPerDay = $totalSpecificPerDay['wrap'];
+ $totalServicePerDay = $totalSpecificPerDay['services'];
+ $totalPottedPerDay = $totalSpecificPerDay['potted'];
+
+ $totalMatrixPerDayTotal += $totalMatrixPerDay;
+ $totalWrapPerDayTotal += $totalWrapPerDay;
+ $totalServicePerDayTotal += $totalServicePerDay;
+ $totalPottedPerDayTotal += $totalPottedPerDay;
+
+
+ $reportStore = [
+ "name" => $store->name,
+ "id" => $store->id,
+ "admins" => $adminNames[$store->id] ?? [],
+ "visitors_quantity" => $storeVisitorsQuantity,
+ "sale_quantity" => $storeSaleQuantity,
+ "sale_total" => $storeSaleTotal,
+ "sale_avg" => $storeSaleQuantity > 0 ? floor($storeSaleTotal / $storeSaleQuantity) : 0,
+ "bonus_user_count" => $storeSaleBonusCount,
+ "bonus_user_per_sale_percent" => $storeSaleQuantity > 0 ? floor($storeSaleBonusCount / $storeSaleQuantity * 100) : 0,
+ "bonus_new_user_count" => $storeSaleNewBonusCount,
+ "bonus_repeat_user_count" => $storeSaleRepeatBonusCount,
+ "total_write_offs_per_date_percent" => $storeSaleTotal > 0 ? floor($totalWriteOffsPerDate / $storeSaleTotal * 100) : 0,
+ "total_write_offs_per_date" => $totalWriteOffsPerDate,
+ "total_write_offs_per_month" => $totalWriteOffsPerMonth,
+ "total_payroll_days" => $totalPayrollDays,
+ "total_payroll_month" => $totalPayrollMonth,
+ "total_matrix_per_day" => $totalMatrixPerDay,
+ "total_wrap_per_day" => $totalWrapPerDay,
+ "total_services_per_day" => $totalServicePerDay,
+ "total_potted_per_day" => $totalPottedPerDay,
+ ];
+ $report["stores"][] = $reportStore;
+ }
+
+ $report['total'] = [
+ "visitors_quantity" => $storeVisitorsQuantityTotal,
+ "sale_quantity" => $storeSaleQuantityTotal,
+ "sale_total" => $storeSaleTotalTotal,
+ "sale_avg" => $storeSaleQuantityTotal > 0 ? floor($storeSaleTotalTotal / $storeSaleQuantityTotal) : 0,
+ "bonus_user_count" => $storeSaleBonusCountTotal,
+ "bonus_user_per_sale_percent" => $storeSaleQuantityTotal > 0 ? floor($storeSaleBonusCountTotal / $storeSaleQuantityTotal * 100) : 0,
+ "bonus_new_user_count" => $storeSaleNewBonusCountTotal,
+ "bonus_repeat_user_count" => $storeSaleRepeatBonusCountTotal,
+ "total_write_offs_per_date_percent" => $storeSaleTotalTotal > 0 ? floor($totalWriteOffsPerDateTotal / $storeSaleTotalTotal * 100) : 0,
+ "total_write_offs_per_date" => $totalWriteOffsPerDateTotal,
+ "total_write_offs_per_month" => $totalWriteOffsPerMonthTotal,
+ "total_payroll_days" => $totalPayrollDaysTotal,
+ "total_payroll_month" => $totalPayrollMonthTotal,
+ "total_matrix_per_day" => $totalMatrixPerDayTotal,
+ "total_wrap_per_day" => $totalWrapPerDayTotal,
+ "total_services_per_day" => $totalServicePerDayTotal,
+ "total_potted_per_day" => $totalPottedPerDayTotal,
+ ];
+
+ $reports[] = $report;
+ $currentDate = date("Y-m-d", strtotime("+1 day", strtotime($currentDate)));
+ }
+
+ return $reports;
+ }
+}
\ No newline at end of file
use yii_app\records\Products1c;
use yii_app\records\Sales;
use yii_app\records\SalesProducts;
+use yii_app\records\StoreDynamic;
use yii_app\services\LogService;
class StoreService
return ['response' => true];
}
+
+ public function getClusters() {
+ $storeDynamic = StoreDynamic::find()->alias('s')->select(['s.store_id as id', 's.value_int as cluster', 'c.name'])
+ ->innerJoin("city_store c", "c.id = s.store_id")
+ ->asArray()->all();
+
+ $storesPerCluster = [];
+ foreach ($storeDynamic as $data) {
+ $storesPerCluster[$data['cluster']][] = ['id' => $data['id'], 'name' => $data['name']];
+ }
+ $result = [];
+ foreach ($storesPerCluster as $key => $data) {
+ $result[] = ['id' => $key, 'stores' => $data];
+ }
+ return $result;
+ }
}
\ No newline at end of file
use yii_app\api3\modules\v1\requests\timetable\Fact;
use yii_app\records\AdminCheckin;
use yii_app\records\AdminDevice;
+use yii_app\records\AdminGroup;
use yii_app\records\TimetableV3;
use yii_app\records\TimetableWorkbot;
$checkIn->lon = $data->lon;
$checkIn->photo = $imagePath;
$checkIn->device_id = AdminDevice::findOne(['admin_id' => $timetable->admin_id])->id ?? 0;
- $checkIn->type_id = AdminCheckin::TYPE_START;
+ $checkIn->type_id = $checkIn->d_id == AdminGroup::GROUP_ADMINISTRATORS ? AdminCheckin::TYPE_APPEAR : AdminCheckin::TYPE_START;
$checkIn->status = 0;
$checkIn->save();
if ($checkIn->getErrors()) {
$checkIn->photo = $imagePath;
$checkIn->status = 0;
$checkIn->device_id = AdminDevice::findOne(['admin_id' => $timetable->admin_id])->id ?? 0;
- $checkIn->type_id = AdminCheckin::TYPE_END;
+ $checkIn->type_id = $checkIn->d_id == AdminGroup::GROUP_ADMINISTRATORS ? AdminCheckin::TYPE_APPEAR : AdminCheckin::TYPE_END;
$checkIn->save();
if ($checkIn->getErrors()) {
throw new \Exception(Json::encode($checkIn->getErrors()));
return true;
}
+ /**
+ * @throws \yii\base\Exception
+ * @throws Exception
+ */
+ public function appear($data) {
+ /** @var $data Fact */
+ $timetable = Timetable::findOne(['id' => $data->plan_id, 'tabel' => 0]);
+ if(!$timetable) {
+ throw new NotFoundHttpException("План не найден");
+ }
+
+ if ($timetable->date != date("Y-m-d") &&
+ $timetable->date != date("Y-m-d", strtotime("-1 day", time()))) {
+ throw new InvalidArgumentException("План ссылается на другую дату");
+ }
+
+ $currentDate = date('Y-m-d H:i:s'); // вынести в хелпер
+ $transaction = \Yii::$app->db->beginTransaction();
+ try {
+
+ $imagePath = $data->uploadImage($timetable->admin_id);
+ if (!$imagePath) {
+ throw new InvalidArgumentException("Не удалось загрузить картинку");
+ }
+
+ $checkIn = new AdminCheckin();
+ $checkIn->admin_id = $timetable->admin_id;
+ $checkIn->plan_id = $timetable->id;
+ $checkIn->store_id = $timetable->store_id;
+ $checkIn->ball = 5;
+ $checkIn->comment = "";
+ $checkIn->d_id = $timetable->admin->group_id;
+ $checkIn->date = $timetable->date;
+ $checkIn->time = $currentDate;
+ $checkIn->lat = $data->lat;
+ $checkIn->lon = $data->lon;
+ $checkIn->photo = $imagePath;
+ $checkIn->device_id = AdminDevice::findOne(['admin_id' => $timetable->admin_id])->id ?? 0;
+ $checkIn->type_id = AdminCheckin::TYPE_APPEAR;
+ $checkIn->status = 0;
+ $checkIn->save();
+ if ($checkIn->getErrors()) {
+ throw new \Exception(Json::encode($checkIn->getErrors()));
+ }
+
+ $transaction->commit();
+ } catch (Exception $e) {
+ $transaction->rollBack();
+ throw $e;
+ }
+
+ return $timetable;
+ }
+
public function delete($plan_id, $comment, $removed_by) {
$timetable = Timetable::find()->where(['id' => $plan_id])->one();
/* @var $timetable Timetable */
use yii_app\api3\core\services\EmployeeService;
use yii_app\api3\core\services\IncomeService;
use yii_app\api3\core\services\KikService;
+use yii_app\api3\core\services\NotifiableService;
+use yii_app\api3\core\services\ReportService;
use yii_app\api3\core\services\StoreService;
use yii_app\api3\core\services\TimetableService;
public function getKikService() {
return Service::create(KikService::class);
}
+
+ public function getNotifiableService() {
+ return Service::create(NotifiableService::class);
+ }
+
+ public function getReportService() {
+ return Service::create(ReportService::class);
+ }
}
\ No newline at end of file
{
$phone = $phone ?: "";
+ $phone = preg_replace("/\D/", '', $phone);
+
// костыль для русских номеров
- if (str_starts_with($phone, "89") && strlen($phone) == 11)
+ if (str_starts_with($phone, "89"))
$phone = "7" . substr($phone, 1);
- return preg_replace("/\D/", '', $phone);
+ return $phone;
}
}
\ No newline at end of file
namespace yii_app\api3\modules\v1\controllers;
use yii\db\Query;
+use yii\helpers\ArrayHelper;
use yii_app\api3\modules\v1\models\Admin;
+use yii_app\records\AdminGroup;
class AdminController extends \yii_app\api3\controllers\ActiveController
{
'class' => \yii\data\ActiveDataFilter::class,
'searchModel' => $this->modelClass,
];
+ $actions['index']['prepareSearchQuery'] = function ($query, $requestParams) {
+ return $query->andFilterWhere(['not in', 'group_id', [AdminGroup::GROUP_FIRED]]);
+ };
unset($actions['create'], $actions['delete'], $actions['update']);
return $actions;
}
+
+ public function actionEmployees() {
+ $admins = Admin::find()->select(['id', 'name', 'mobile as phone'])
+ ->where(['in', 'group_id', AdminGroup::getGroupsForEmployeeOnCashbox()])->asArray()->all();
+ $results = [];
+ foreach ($admins as $admin) {
+ $results []= [
+ 'id' => (int)$admin['id'],
+ 'name' => $admin['name'],
+ 'phone' => '+7(***)**' . substr($admin['phone'], -4)
+ ];
+ }
+ return $results;
+ }
}
\ No newline at end of file
use yii_app\api3\modules\v1\requests\bonus\ReturnInput;
use yii_app\api3\modules\v1\requests\bonus\SaleInput;
use yii_app\api3\modules\v1\requests\bonus\SaveClientInfoInput;
+use yii_app\api3\modules\v1\requests\bonus\BonusWriteOffInput;
/**
* @property BonusService $bonusService
return $this->bonusService->bonusAdd($data);
}
+
+ public function actionWriteOff() {
+ // localhost:8888/v1/bonus/write-off
+ // {
+ // "phone": "+79200247501",
+ // "lid_id": "12345",
+ // "price": 100,
+ // "bonus": 20,
+ // "date_start": "2023-06-16",
+ // "date_end": "2024-01-01 00:00:00"
+ // }
+ $params = \Yii::$app->request->post();
+
+ $model = new BonusWriteOffInput;
+ $data = $this->validate($model, $params);
+
+ return $this->bonusService->bonusWriteOff($data);
+ }
}
\ No newline at end of file
use yii_app\api3\core\services\EmployeeService;
use yii_app\api3\core\traits\ServiceTrait;
use yii_app\api3\modules\v1\requests\employee\AtStoreInput;
+use yii_app\records\Timetable;
/**
* @property EmployeeService $employeeService
return $this->employeeService->atStore($data);
}
+
+ public function actionSalariesDay() {
+ return Timetable::getSalariesDay();
+ }
}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\api3\modules\v1\controllers;
+
+use yii_app\api3\core\services\NotifiableService;
+use yii_app\api3\core\traits\ServiceTrait;
+
+/**
+ * @property NotifiableService $notifiableService
+ */
+class NotifiableController extends \yii_app\api3\controllers\NoActiveController
+{
+ use ServiceTrait;
+
+ public function actionExpiredBonuses() {
+ // localhost:8888/v1/notifiable/expired-bonuses
+ return $this->notifiableService->getExpiredBonuses();
+ }
+
+ public function actionGetFirstSaleUsers() {
+ // localhost:8888/v1/notifiable/get-first-sale-users
+ return $this->notifiableService->getGetFirstSaleUsers();
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\api3\modules\v1\controllers;
+
+use yii\helpers\Json;
+use yii_app\api3\core\services\ReportService;
+use yii_app\api3\core\traits\ServiceTrait;
+use yii_app\api3\modules\v1\requests\report\ReportInput;
+use yii_app\records\ApiLogs;
+
+/**
+ * @property ReportService $reportService
+ */
+class ReportController extends \yii_app\api3\controllers\NoActiveController
+{
+ use ServiceTrait;
+
+ public function actionShow() {
+ // localhost:8888/v1/report/Show
+ // {
+ // "stores": [1,2,3],
+ // "date_start": "2024-02-15",
+ // "date_end": "2024-02-16"
+ // "shift_type": 1 // 1 - дневная, 2 - ночная, 0 - дневная и ночная смена вместе
+ // }
+ $params = \Yii::$app->request->post();
+
+ $model = new ReportInput;
+ $data = $this->validate($model, $params);
+
+ $result = $this->reportService->show($data);
+
+ $apiLogs = new ApiLogs;
+ $apiLogs->url = \Yii::$app->request->url;
+ $apiLogs->request_id = "";
+ $apiLogs->date = date('Y-m-d H:i:s');
+ $apiLogs->content = Json::encode($data);
+ $apiLogs->hash_content = "";
+ $apiLogs->result = Json::encode($result);
+ $apiLogs->status = 0;
+ $apiLogs->store_id = "report_show";
+ $apiLogs->seller_id = "";
+ $apiLogs->phone = "";
+ $apiLogs->ip = "127.0.0.1";
+ $apiLogs->save();
+
+ return $result;
+ }
+}
\ No newline at end of file
return $this->storeService->assemblies($data);
}
+
+ public function actionGetClusters() {
+ return $this->storeService->getClusters();
+ }
}
\ No newline at end of file
$params = Yii::$app->request->bodyParams;
$data = $this->validate(new Worker(), $params);
- $data->phone = Util::phoneNormalizer($data->phone);
-
$this->claimService->create($data);
return true;
return $this->timetableService->close($data);
}
+
+ public function actionAppear()
+ {
+ $params = \Yii::$app->request->post();
+
+ $model = new Fact();
+ $model->image = UploadedFile::getInstanceByName('image');
+ $data = $this->validate($model, $params);
+
+ return $this->timetableService->appear($data);
+ }
}
\ No newline at end of file
return [
'id',
'name' => fn($m) => mb_substr($m->name, 3),
+ 'city_store_id' => fn($m) => $m->store ? $m->store->id : null,
+ 'tg_chat_id' => fn($m) => $m->store ? (!empty($m->store->tg_chat_id) ? $m->store->tg_chat_id : null) : null,
// 'parent_id' => fn($m) => intval($m->parent_id),
// 'view'
];
return [
'view',
'workAdmins' => fn($m) => array_map(fn($x) => [
+ 'phone' => $x->mobile,
'name' => $x->name,
'id' => $x->id
], $m->workAdmins)
{
public static function getDb()
{
- return Yii::$app->db2;
+ return Yii::$app->db;
}
public function rules(): array
[['tabel'], 'integer', 'skipOnEmpty' => false],
[['id', 'shift_id', 'store_id'], 'integer'],
[['date'], 'date', 'format' => 'yyyy-M-d'],
+ [['salary_shift'], 'in', 'range' => \yii_app\records\Timetable::getSalariesDay(), 'skipOnEmpty' => true],
[['shift_id'], 'in', 'range' => array_keys(Shift::all()), 'skipOnEmpty' => false],
[['store_id'], 'exist', 'targetClass' => CityStore::class, 'targetAttribute' => 'id', 'skipOnEmpty' => false],
[['admin_id', 'admin_id_add'], 'exist', 'targetClass' => Admin::class, 'targetAttribute' => 'id', 'skipOnEmpty' => true],
'admin_id',
'store_id',
'shift_id',
+ 'salary_shift',
// 'price' => fn($x) => $x->shift_id == 2 ? 140 : 125,
'tabel',
'date',
--- /dev/null
+<?php
+
+namespace yii_app\api3\modules\v1\requests\bonus;
+
+use yii\base\Model;
+use yii_app\api3\core\validators\PhoneValidator;
+
+class BonusWriteOffInput extends Model
+{
+ public $phone;
+ public $lid_id;
+ public $price;
+ public $bonus;
+ public $date_start;
+ public $date_end;
+
+ public function rules()
+ {
+ return [
+ [['phone', 'lid_id', 'price', 'bonus'], 'required'],
+ ['phone', PhoneValidator::class],
+ ['lid_id', 'integer'],
+ [['price', 'bonus'], 'number'],
+ [['date_start', 'date_end'], 'datetime', 'format' => "yyyy-MM-dd H:m:s"],
+ ];
+ }
+}
\ No newline at end of file
namespace yii_app\api3\modules\v1\requests\claim;
use yii\base\Model;
+use yii_app\api3\core\validators\PhoneValidator;
use yii_app\records\Admin;
use yii_app\records\EmployeeOnShift;
use yii_app\records\Products1c;
+use yii_app\records\Timetable;
class Worker extends Model
{
public $datetime_start;
public $datetime_end;
public $price;
+ public $salary_shift;
public $shift_type;
public $first_name;
public $last_name;
['shift_date', 'date', 'format' => "yyyy-MM-dd"],
['shift_type', 'in', 'range' => [0, 1, 2]],
[['first_name', 'last_name'], 'string', 'min' => 2, 'max' => 40],
+ [['first_name', 'last_name'], 'filter', 'filter' => 'trim'],
['price', 'number', 'min' => 120, 'max' => 150],
+ [['salary_shift'], 'in', 'range' => Timetable::getSalariesDay(), 'skipOnEmpty' => false],
[['datetime_start', 'datetime_end'], 'datetime', 'format' => "yyyy-MM-dd H:m:s"],
// [['guid'], 'unique'],
['created_by', 'exist', 'targetClass' => Admin::class, 'targetAttribute' => 'id', 'filter' => ['group_id' => [1, 7, 8, 10, 30, 35, 40, 50, 51, 71]]],
['store_id', 'exist', 'targetClass' => Products1c::class, 'targetAttribute' => 'id', 'filter' => ['tip' => 'city_store']],
['phone', 'unique', 'targetClass' => EmployeeOnShift::class, 'targetAttribute' => ['phone', 'store_id'], 'filter' => ['status' => EmployeeOnShift::STATUS_INITIAL]],
+ ['phone', PhoneValidator::class],
['datetime_start', 'checkDateTimeStart']
];
}
--- /dev/null
+<?php
+
+namespace yii_app\api3\modules\v1\requests\report;
+
+use yii\base\Model;
+
+class ReportInput extends Model
+{
+ public $stores;
+ public $date_start;
+ public $date_end;
+ public $shift_type;
+
+ public function rules(): array
+ {
+ return [
+ [['stores', 'date_start', 'date_end', 'shift_type'], 'required'],
+ ['stores', 'each', 'rule' => ['integer']],
+ [['date_start', 'date_end'], 'datetime', 'format' => 'yyyy-M-d'],
+ ['shift_type', 'in', 'range' => [0, 1, 2]]
+ ];
+ }
+}
\ No newline at end of file
{
$uploadDir = \Yii::getAlias("@upload-checkin") . "/";
- // можно сделать проверку на mimetype
- $extension = mb_strtolower(substr($this->image->name, stripos($this->image->name, ".", -5) + 1));
-
- $dir = date("Y") . "/" . date("m") . "/" . substr($adminId, 0, 2) . "/" . $adminId . "/";
-
- $filename = date("d-m-H-i-s") . "." . $extension;
-
- FileHelper::createDirectory($uploadDir . $dir);
-
- $path = $dir . $filename;
+ $Y = date("Y");
+ $m = date("m");
+ if (!is_dir($uploadDir . "$Y/$m")) {
+ mkdir($uploadDir . "$Y/$m", 0777, true);
+ }
+ $fileName = $adminId . '-' . date("YmdHis") . '.jpg';
- if($this->image->saveAs($uploadDir . $path)) {
- return $path;
+ if($this->image->saveAs($uploadDir . "$Y/$m/". $fileName)) {
+ return "data/admin/$Y/$m/" . $fileName;
} else {
return false;
}
--- /dev/null
+<?php
+
+namespace yii_app\controllers;
+
+use Yii;
+use yii\data\ArrayDataProvider;
+use yii\db\Exception;
+use yii\db\Expression;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Json;
+use yii\web\Controller;
+use yii_app\records\Admin;
+use yii_app\records\ChartDataSearch;
+use yii_app\records\WriteOffs;
+
+class ChartForManagementController extends Controller
+{
+ public function actionIndex()
+ {
+ $admin = Admin::findOne(['id' => Yii::$app->user->id]);
+
+ $access_chart = [
+ 'mode_level' => [],
+ 'mode_shift' => [],
+ 'visible' => false,
+ ];
+
+ $access = [
+ 'main' => $access_chart,
+ 'plan_completed_this_day' => $access_chart,
+ 'plan_completed_this_month' => $access_chart,
+ 'sales' => $access_chart,
+ 'matrix_sales_sum' => $access_chart,
+ 'avg_sales_value' => $access_chart,
+ 'fot' => $access_chart,
+ 'sales_sum_on_admin' => $access_chart,
+ 'user_bonus' => $access_chart,
+ 'count_sales_in_hour' => $access_chart,
+ 'write_offs' => $access_chart,
+ ];
+
+ if (in_array($admin->group_id, [1, 81, 71, 51, 10, 9, 74, 14])) {
+ foreach ($access as $key => &$item) {
+ if (in_array($key, ['avg_sales_value', 'sales', 'user_bonus', 'matrix_sales_sum', 'count_sales_in_hour'])) {
+ $item['mode_level'] = [
+ //0 => 'Доставка',
+ 1 => 'Розница',
+ 2 => 'Куст',
+ 3 => 'Магазин'
+ ];
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ 4 => 'Сутки'
+ ];
+ } else {
+ $item['mode_level'] = [
+ 1 => 'Розница',
+ 2 => 'Куст',
+ 3 => 'Магазин'
+ ];
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ //4 => 'Сутки'
+ ];
+ }
+
+ $item['visible'] = true;
+ }
+
+ } else if (in_array($admin->group_id, [Admin::CLUSTER_MANAGER_GROUP_ID])) {
+ foreach ($access as &$item) {
+ $item['mode_level'] = [
+ 2 => 'Куст',
+ 3 => 'Магазин',
+ ];
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+
+ ];
+
+ $item['visible'] = true;
+ }
+
+ } else if (in_array($admin->group_id, [30, 40])) {
+ foreach ($access as $key => &$item) {
+ $item['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $item['mode_shift'] = [
+ 1 => 'День',
+ ];
+
+ if ($key != 'plan_completed_this_day' && $key != 'plan_completed_this_month') {
+ $item['visible'] = true;
+ }
+
+ }
+
+ } else if (in_array($admin->group_id, [35, 72])) {
+ foreach ($access as $key => &$item) {
+ $item['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $item['mode_shift'] = [
+ 2 => 'Ночь',
+ ];
+
+ if ($key != 'plan_completed_this_day' && $key != 'plan_completed_this_month') {
+ $item['visible'] = true;
+ }
+
+ }
+
+ } else if (in_array($admin->group_id, [Admin::ADMINISTRATOR_GROUP_ID])) {
+ foreach ($access as &$item) {
+ $item['mode_level'] = [
+ 3 => 'Магазин'
+ ];
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+
+ ];
+
+ $item['visible'] = true;
+ }
+
+ } else {
+ throw new Exception('Нет доступа');
+ }
+
+ return $this->render('index', [
+ 'access' => $access
+ ]);
+ }
+
+ public function actionWriteOffPosition()
+ {
+ $admin = Admin::findOne(['id' => Yii::$app->user->id]);
+
+ $access = [
+ 'mode_level' => [],
+ 'mode_shift' => [],
+ 'access_plan' => false,
+ ];
+
+ if (in_array($admin->group_id, [1, 81, 71, 51, 10, 9, 74, 14])) {
+
+ $access['mode_level'] = [
+ 1 => 'Розница',
+ 2 => 'Куст',
+ 3 => 'Магазин'
+ ];
+
+ $access['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+
+ ];
+
+ $access['access_plan'] = true;
+
+ } else if (in_array($admin->group_id, [7])) {
+
+ $access['mode_level'] = [
+ 2 => 'Куст',
+ 3 => 'Магазин',
+ ];
+
+ $access['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ ];
+
+ $access['access_plan'] = true;
+
+ } else if (in_array($admin->group_id, [30, 40])) {
+
+ $access['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $access['mode_shift'] = [
+ 1 => 'День',
+ ];
+
+ } else if (in_array($admin->group_id, [35, 72])) {
+
+ $access['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $access['mode_shift'] = [
+ 2 => 'Ночь',
+ ];
+
+ } else if (in_array($admin->group_id, [50])) {
+ $access['mode_level'] = [
+ 3 => 'Магазин'
+ ];
+
+ $access['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ ];
+
+ $access['access_plan'] = true;
+ } else {
+ throw new Exception('Нет доступа');
+ }
+
+ return $this->render('write-offs-position-chart', [
+ 'access' => $access
+ ]);
+ }
+
+ public function actionGetControlDataAjax()
+ {
+ $post_data = Yii::$app->request->post();
+
+ $date_start = date('Y-m-d H:i:s', strtotime($post_data['date_start']));
+ $date_end = date('Y-m-d H:i:s', strtotime($post_data['date_end']));
+
+ $stores = Admin::find()->where(['admin.id' => Yii::$app->user->id])->leftJoin(
+ 'store_dynamic',
+ [
+ 'OR',
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("%," , store_dynamic.store_id, ",%")')],
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("" , store_dynamic.store_id, ",%")')],
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("%," , store_dynamic.store_id, "")')],
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("" , store_dynamic.store_id, "")')],
+ ]
+
+ )
+ ->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1')
+ ->select(
+ [
+ 'cluster_name' => 'CONCAT_WS(\' \', \'Куст\', store_dynamic.value_int)',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_id' => 'store_dynamic.store_id',
+ 'store_name' => 'city_store.name',
+ 'date_from' => 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')',
+ ]
+ )
+ ->andWhere(
+ [
+ 'OR',
+ [
+ 'AND',
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ],
+ [
+ 'AND',
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ['>=', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_end],
+ ],
+ [
+ 'AND',
+ ['<=', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start],
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ],
+ [
+ 'AND',
+ ['<=', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start],
+ ['>=', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start],
+ ],
+ ]
+ )
+ ->orderBy(['store_dynamic.value_int' => SORT_ASC, 'city_store.id' => SORT_ASC])
+ ->asArray()
+ ->all();
+
+ $steps_stores = ArrayHelper::map($stores, 'date_from', 'cluster_name', 'store_name');
+
+ foreach ($steps_stores as $store_name => $step_store) {
+ if (count($step_store) === 1) {
+ unset($steps_stores[$store_name]);
+ }
+ }
+
+ $clusters_unic = [];
+ foreach ($stores as $store) {
+ if (!in_array(['id' => $store['cluster_id'], 'text' => $store['cluster_name']], $clusters_unic)) {
+ $clusters_unic[] = ['id' => $store['cluster_id'], 'text' => $store['cluster_name']];
+ }
+ }
+
+ $store_in_cluster = [];
+ foreach ($stores as $store) {
+ if (!isset($store_in_cluster[$store['cluster_id']])) {
+ $store_in_cluster[$store['cluster_id']]['text'] = $store['cluster_name'];
+ }
+ $store_in_cluster[$store['cluster_id']]['children'][] = ['id' => $store['store_id'], 'text' => $store['store_name']];
+ }
+
+ return Json::encode(['stores_step' => $steps_stores, 'clusters' => $clusters_unic, 'stores_in_cluster' => $store_in_cluster]);
+ }
+
+ public function actionGetDataAjax()
+ {
+ $post_data = Yii::$app->request->post();
+ $chart_data_search = new ChartDataSearch();
+
+ $chart_data_search->mode_level = intval($post_data['mode']);
+ $chart_data_search->attribute_name = $post_data['attribute'];
+ $chart_data_search->date_start = $post_data['date_start'] ?? date('Y-m-d', strtotime('-13 day'));
+ $chart_data_search->date_end = $post_data['date_end'] ?? date('Y-m-d', time());
+ $chart_data_search->cluster_id = $post_data['cluster'];
+ $chart_data_search->store_id = $post_data['store'];
+ $chart_data_search->mode_shift = $post_data['shift'] ?? 3;
+ $chart_data_search->select_cluster = true;
+
+ if ($post_data['attribute'] === 'plan_completed_this_day') {
+ $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month'));
+ $chart_data_search->date_end = date('Y-m-d', time());
+
+ }
+
+ if ($post_data['attribute'] === 'plan_completed_this_month') {
+ $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month'));
+ $chart_data_search->date_end = date('Y-m-d', strtotime('last day of this month'));
+
+ }
+
+ if ($post_data['attribute'] === 'write_offs') {
+ $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month', strtotime($chart_data_search->date_start)));
+ $chart_data_search->mode_shift = 4;
+ }
+
+ $dates = [];
+ $chart_opts = null;
+ $temp_row = ['sales_sum' => 0, 'sum' => 0, 'plan' => 0];
+ $interval_days = (strtotime($chart_data_search->date_end) - strtotime($chart_data_search->date_start)) / (60 * 60 * 24);
+
+ $data_answer = $chart_data_search->attributes_config[$post_data['attribute']];
+
+ if ($post_data['attribute'] === 'write_offs_position') {
+ $answer_query = $chart_data_search->searchWriteOffsItems();
+ }
+
+ if ($post_data['attribute'] === 'write_offs_position') {
+ if (!isset($answer_query[1])) {
+ return -1;
+ }
+
+ $data = $answer_query[1];
+
+ } else {
+ $data = $chart_data_search->search();
+
+ }
+
+ $keys = array_keys($data_answer['attribute']);
+ $step = 0;
+
+ foreach ($data as $index => $datum) {
+ if ($post_data['attribute'] === 'plan_completed_this_day') {
+ $temp_row['sales_sum'] += $datum['value'];
+ $temp_row['plan'] += $datum['plan'];
+
+ } else if ($post_data['attribute'] === 'plan_completed_this_month') {
+ $temp_row['sales_sum'] += $datum['value'];
+ $temp_row['plan'] += $datum['plan'];
+
+ } else if ($post_data['attribute'] === 'sales') {
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'];
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
+
+ } else if ($post_data['attribute'] === 'count_sales_in_hour') {
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'];
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['value'] / ($interval_days > 0 ? $interval_days : 1);
+
+ } else if ($post_data['attribute'] === 'avg_sales_value') {
+ if ($step % 2 != 0) {
+ $step++;
+ continue;
+ }
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / ($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1);
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
+ $step++;
+
+ } else if ($post_data['attribute'] === 'fot') {
+ if ($step % 2 != 0) {
+ $step ++;
+ continue;
+
+ }
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / (($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1) / 100);
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
+ $step++;
+
+ } else if ($post_data['attribute'] === 'sales_sum_on_admin') {
+ if ($step % 2 != 0) {
+ $step ++;
+ continue;
+
+ }
+
+ $step++;
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / ($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1);
+
+ } else if ($post_data['attribute'] === 'write_offs') {
+ if ($step % 2 != 0) {
+ $step++;
+ continue;
+
+ }
+
+ $step++;
+
+ if (date('d', strtotime($datum['date'])) == 1) {
+ $temp_row['sales_sum'] = 0;
+ $temp_row['sum'] = 0;
+ }
+ $temp_row['sales_sum'] += $datum['value'] ?? 0;
+ $temp_row['sum'] += $data[$index + 1]['value'] ?? 0;
+
+ if (strtotime($datum['date']) >= (($post_data['date_start']) ? strtotime($post_data['date_start']) : date('Y-m-d', strtotime('-13 day')))) {
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $data[$index + 1]['value'] ?? 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = ($data[$index + 1]['value'] ?? 0) / (($datum['value'] != 0 ? $datum['value'] : 1) / 100);
+ $data_answer['attribute'][$keys[2]]['data'][] = $temp_row['sum'] / ((($temp_row['sales_sum'] != 0) ? $temp_row['sales_sum'] : 1) / 100);
+ }
+ } else if ($post_data['attribute'] === 'user_bonus') {
+ if ($step % 4 == 0) {
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $data[$index]['value'] ?? 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = 0;
+ $data_answer['attribute'][$keys[3]]['data'][] = 0;
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = $data[$index + 1]['value'] ?? 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = 0;
+ $data_answer['attribute'][$keys[3]]['data'][] = 0;
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = $data[$index + 2]['value'] ?? 0;
+ $data_answer['attribute'][$keys[3]]['data'][] = $data[$index + 3]['value'] ?? 0;
+
+ }
+
+ $step++;
+
+ } else if ($post_data['attribute'] === 'matrix_sales_sum') {
+ if ($step % 3 == 0) {
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $data[$index]['value'] ?? 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = $data[$index + 1]['value'] ?? 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = $data[$index + 2]['value'] ?? 0;
+
+ }
+
+ $step++;
+ }
+ }
+
+ if ($post_data['attribute'] !== 'count_sales_in_hour') {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => $dates,
+ ]
+ ];
+ } else {
+ if ($chart_data_search->mode_shift === 3) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => array_merge(range(8, 23), range(0, 7))
+ ]
+ ];
+ } else if ($chart_data_search->mode_shift === 1) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => range(8, 19)
+ ]
+ ];
+ } else if ($chart_data_search->mode_shift === 2) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => array_merge(range(20, 23), range(0, 7))
+ ]
+ ];
+ } else if ($chart_data_search->mode_shift === 4) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => range(0, 23)
+ ]
+ ];
+ }
+
+ $chart_data_search::sortCountSalesInHour($data_answer, $chart_data_search->mode_shift);
+ }
+
+ if ($chart_data_search->mode_level === 2) {
+ $chart_opts['title'] = ['text' => 'Куст ' . $chart_data_search->cluster_id];
+ } else if ($chart_data_search->mode_level === 3) {
+ if ($chart_data_search->attribute_name === 'write_offs_position') {
+ $chart_opts['title'] = ['text' => 'Магазин: ' . $answer_query[0][0]['store_name']];
+ } else {
+ $chart_opts['title'] = ['text' => 'Магазин: ' . $data[0]['store_name']];
+ }
+
+ } else {
+ $chart_opts['title'] = ['text' => 'Розница'];
+ }
+
+ if ($post_data['attribute'] === 'plan_completed_this_day') {
+ $data_answer = [];
+ $data_answer['attribute']['plan_complete_on_this_day'] = round(
+ $temp_row['sales_sum'] /
+ ($temp_row['plan'] !== 0 ? $temp_row['plan'] : 1) *
+ 100,
+ 2);
+
+ }
+
+ if ($post_data['attribute'] === 'plan_completed_this_month') {
+ $data_answer = [];
+ $data_answer['attribute']['plan_hypothesis_complete_on_this_month'] = round(
+ $temp_row['sales_sum'] /
+ date('d', time()) *
+ date('d', strtotime('last day of this month')) /
+ ($temp_row['plan'] !== 0 ? $temp_row['plan'] : 1) *
+ 100,
+ 2);
+
+ }
+
+ $answer = ['chart_opts' => $chart_opts, 'data_answer' => $data_answer];
+ return Json::encode($answer);
+ }
+
+ public function actionWriteOffsIndex($date, $cluster_id = null, $store_id = null)
+ {
+ $query_write_offs = WriteOffs::find()
+ ->select([
+ 'store_name' => 'city_store.name',
+ 'sum' => 'write_offs.summ',
+ 'date' => 'write_offs.date',
+ 'number' => 'write_offs.number',
+ 'comment' => 'write_offs.comment'
+ ])
+ ->innerJoin('export_import_table', 'export_import_table.export_val = write_offs.store_id')
+ ->innerJoin('city_store', 'city_store.id = export_import_table.entity_id')
+ ->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = city_store.id',
+ [
+ '>=',
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ ],
+ [
+ '<',
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ ]
+ ]
+ )
+ ->andWhere([
+ 'export_import_table.entity' => 'city_store'
+ ])
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $cluster_id,
+ 'city_store.id' => $store_id
+ ])
+ ->andWhere([
+ 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')' => $date
+ ])
+ ->andWhere([
+ 'write_offs.type' => 'Брак'
+ ])
+ ->orderBy([
+ 'store_dynamic.value_int' => SORT_ASC,
+ 'city_store.id' => SORT_ASC,
+ 'write_offs.date' => SORT_ASC,
+ ]);
+
+ $dataProvider = new ArrayDataProvider([
+ 'allModels' => $query_write_offs->asArray()->all()
+ ]);
+
+ return $this->render('write-offs', [
+ 'dataProvider' => $dataProvider,
+ 'date' => $date
+ ]);
+ }
+}
\ No newline at end of file
namespace app\controllers;
+use Yii;
use yii_app\records\CityStore;
use yii_app\records\CityStoreSearch;
use yii\web\Controller;
{
$searchModel = new CityStoreSearch();
$dataProvider = $searchModel->search($this->request->queryParams);
-
+ if (Yii::$app->request->isAjax && Yii::$app->request->post('action') == 'saveTg') {
+ $storeId = Yii::$app->request->post('storeId');
+ $tgInput = Yii::$app->request->post('tgInput');
+ if (empty($tgInput)) {
+ return 'not ok';
+ }
+ $cityStore = CityStore::find()->where(['id' => $storeId])->one();
+ if (!$cityStore) {
+ return 'not ok';
+ }
+ $cityStore->tg_chat_id = $tgInput;
+ $cityStore->save(false);
+ return 'ok';
+ }
return $this->render('/city_store/index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'test' => \yii_app\actions\infoTable\TestAction::class,
'validate' => \yii_app\actions\dashboard\ValidateAction::class,
'charts-fot' => \yii_app\actions\infoTable\ChartsFotAction::class,
+ 'cabinet' => \yii_app\actions\infoTable\CabinetAction::class,
];
}
if ($uploadImage) {
- if (Images::isImageFile(($uploadImage))) {
+ if (Images::isImageFile(($uploadImage), ['png', 'jpg'])) {
$image = new Images();
$imageId = $image->loadImage(($uploadImage));
{
return [
'index' => \yii_app\actions\pages\IndexAction::class,
- 'statistics' => \yii_app\actions\pages\StatisticsAction::class,
];
}
}
\ No newline at end of file
use GuzzleHttp\Client;
use Yii;
use yii\web\Controller;
-use yii\web\Response;
-use yii\filters\VerbFilter;
-use app\models\LoginForm;
-use app\models\ContactForm;
-use yii_app\records\CrmMenu;
-
-class SiteController extends Controller
-{
- /**
- * {@inheritdoc}
- */
- public function behaviors()
- {
- return [
- 'verbs' => [
- 'class' => VerbFilter::class,
- 'actions' => [
- 'logout' => ['get'],
- ],
- ],
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function actions()
- {
- return [
- 'error' => [
- 'class' => 'yii\web\ErrorAction',
- ],
- 'captcha' => [
- 'class' => 'yii\captcha\CaptchaAction',
- 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
- ],
- ];
- }
-
- /**
- * Displays homepage.
- *
- * @return string
- */
- public function actionIndex()
- {
- return $this->render('index');
- }
-
- /**
- * Login action.
- *
- * @return Response|string
- */
- public function actionLogin()
- {
- if (!Yii::$app->user->isGuest) {
- return $this->goHome();
- }
-
- $model = new LoginForm();
- if (Yii::$app->request->isPost) {
- if ($model->load(Yii::$app->request->post()) && $model->login()) {
- return $this->goBack();
- } else {
- return $this->refresh();
- }
- }
-
- $model->password = '';
- return $this->renderPartial('login', [
- 'model' => $model,
- ]);
- }
-
- /**
- * Logout action.
- *
- * @return Response
- */
- public function actionLogout()
- {
- if (!Yii::$app->user->isGuest) {
- Yii::$app->user->logout();
- }
-
- return $this->redirect('/site/login');
- }
-
- /**
- * Displays contact page.
- *
- * @return Response|string
- */
- public function actionContact()
- {
- $model = new ContactForm();
- if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
- Yii::$app->session->setFlash('contactFormSubmitted');
-
- return $this->refresh();
- }
- return $this->render('contact', [
- 'model' => $model,
- ]);
- }
-
- /**
- * Displays about page.
- *
- * @return string
- */
- public function actionAbout()
- {
- return $this->render('about');
- }
+class SiteController extends Controller {
public function actionMenuTree() {
-// $client = new Client(['base_uri' => Yii::$app->params['API2_URL']]);
-// $response = $client->request('GET', '/site/menu-tree?user_id=' . Yii::$app->user->id . '&key=' . Yii::$app->params['API2_TOKEN']);
-// return $this->asJson(json_decode($response->getBody(), true));
- return $this->asJson(CrmMenu::getTreeByUserId(Yii::$app->user->id));
+ $client = new Client(['base_uri' => Yii::$app->params['API2_URL']]);
+ $response = $client->request('GET', '/site/menu-tree?user_id=' . Yii::$app->user->id . '&key=' . Yii::$app->params['API2_TOKEN']);
+// Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
+ return $this->asJson(json_decode($response->getBody(), true));
}
-}
+}
\ No newline at end of file
'group_id' => array_keys(AdminGroup::groupsWithShift())
])
->andFilterWhere(['group_id' => $this->adminGroupId])
- ->orderBy(['group_id' => SORT_ASC, 'name' => SORT_ASC])
+ ->orderBy(['IF(group_id IN ('
+ . AdminGroup::GROUP_WORKERS . ', '
+ . AdminGroup::GROUP_WORKERS_ARCHIVE . ', '
+ . AdminGroup::GROUP_FIRED . '),1,0)' => SORT_ASC, 'group_id' => SORT_ASC, 'name' => SORT_ASC])
->indexBy('id');
if ($this->storeId) {
$adminQuery
$phone = preg_replace("/[^0-9\,]/i", "", $phone);
// $urlstr = preg_replace('/[^A-Za-z0-9_\-]/', '', $urlstr);
$phone_str = strlen($phone);
- if ($phone_str == 10) {
+ if ($phone_str == 10 && $phone[0] != '7') {
$phone = "7$phone";
} elseif ($phone_str == 11) {
$str0 = substr($phone, 0, 1);
{
return json_decode($string,true,512,JSON_UNESCAPED_UNICODE);
}
+
+ public static function arraysAreEqual($array1, $array2): bool
+ {
+ array_multisort($array1);
+ array_multisort($array2);
+
+ return ( serialize($array1) === serialize($array2) );
+ }
+
+ public static function mergeArraysByKey($array1, $array2): array
+ {
+ $mergeArray = [];
+ $array1Keys = array_keys($array1);
+ $array2Keys = array_keys($array2);
+ $keys = array_merge($array1Keys,$array2Keys);
+
+ foreach($keys as $key) {
+ $mergeArray[$key] = array_merge_recursive(isset($array1[$key])?$array1[$key]:[],isset($array2[$key])?$array2[$key]:[]);
+ }
+
+ return $mergeArray;
+
+ }
+
+ public static function ruPlural($number, $titles = array(/*1*/'комментарий', /*2*/'комментария', /*5*/'комментариев')): string
+ {
+ $cases = array (2, 0, 1, 1, 1, 2);
+
+ return $number.' '.$titles[($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)]];
+ }
+
}
\ No newline at end of file
}
self::createDirectory($resizedPath);
- if (!file_exists($resizedFile)) {
+ if (!file_exists($resizedFile) && !empty($imagePath)) {
ImageHelper::resizeImage($imagePath, $resizedFile, $w, $h, $quality);
}
return $resizedUrl;
namespace yii_app\helpers;
+use DateTime;
use yii\helpers\ArrayHelper;
use yii_app\records\Admin;
}
+ public static function getAdministratorWorkDays($month, $year): int
+ {
+ $adminDayCount = 0;
+ $dayMonthDateRow = $year . '-' . $month . '-01';
+ $dayMonthRow = new DateTime($dayMonthDateRow);
+ $days = date('j', strtotime($dayMonthRow->format('Y-m-t')));
+ foreach (range(1, $days) as $day) {
+ $dayRow = $year . '-' . $month . '-' . $day;
+ $time = new DateTime($dayRow);
+ $dayNumRow = $time->format('w');
+ // считаем дни со вторника по субботу
+ if ($dayNumRow >= 2 && $dayNumRow <= 6) {
+ $adminDayCount++;
+ }
+ }
+ return $adminDayCount;
+ }
+
+
}
use yii\helpers\ArrayHelper;
use yii_app\records\Products1c;
use yii_app\records\Sales;
+use yii_app\records\Timetable;
+use yii_app\services\HolidayService;
use yii_app\services\SalesService;
class SalaryHelper
45=>15,
40=>15, //Помощник день
72=>15, //Помощник ночь
+ 90=>15, //Помощник ночь
+ -1=>15, //Помощник ночь
];
public static function getSqlWhereFromArray($array, $pole)
}
- if (count($adminGuidArr)) {
- $i = 0;
- $where_p = " AND (";
- foreach ($adminGuidArr as $adminGuid) {
- if ($i > 0)
- $where_p .= " or ";
- $where_p .= " sales.seller_id='$adminGuid'";
- $i++;
- }
- $where_p .= " )";
+ if (is_array($adminGuidArr) && count($adminGuidArr)) {
+ $adminGuidArrIn = "'" . implode("', '", $adminGuidArr) . "'";
+ $where_p = " AND sales.seller_id IN ($adminGuidArrIn) ";
}
AND
sales.id = p.check_id
+ AND
+ p.type_id = 1
AND
(p.component_parent_id = '' OR p.component_parent_id = 0 OR p.component_parent_id IS NULL)
AND
$allBonus[$row["seller_id"]]["check"][] = $row;
}
- foreach ($allBonus as $sallerId => $bonus) {
- $allBonus2[$sallerId]["bonus"] = round($bonus["bonus"]);
- $allBonus2[$sallerId]["check"] = $bonus["check"];
+ foreach ($allBonus as $sellerId => $bonus) {
+ $allBonus2[$sellerId]["bonus"] = round($bonus["bonus"]);
+ $allBonus2[$sellerId]["check"] = $bonus["check"];
}
$whereProducts = 1;
}
-
- if (count($adminGuidArr)) {
- $i = 0;
- $where_p = " AND (";
- foreach ($adminGuidArr as $adminGuid) {
- if ($i > 0)
- $where_p .= " or ";
- $where_p .= " sales.seller_id='$adminGuid'";
- $i++;
- }
- $where_p .= " )";
+ if (is_array($adminGuidArr) && count($adminGuidArr)) {
+ $adminGuidArrIn = "'" . implode("', '", $adminGuidArr) . "'";
+ $where_p = " AND sales.seller_id IN ($adminGuidArrIn) ";
}
]
);
- $action2 = $command->getRawSql();
$data2 = $command->queryAll();
-
-
}
-
-
-
} else {
-
$command = $connection->createCommand("
SELECT
sales.id,
}
}
-
return $allBonus2;
}
return $command->queryColumn();
}
+
+ public static function getSalariesByFocusGroup(
+ $employeeId,
+ $adminGuid,
+ $arrayProducts,
+ $adminGuidArr,
+ $dateFrom,
+ $dateTo,
+ $exportAdmin,
+ $isAdministrator,
+ $employeeSelectStoreId,
+ $showHolidayVersion = false,
+ $notHolidayCalculate = true
+ ): array {
+ $adminGuidDateArr = [];
+ $adminGuidArrAll = [];
+ if ($showHolidayVersion) {
+ $holidayDatesBetweenPrepared = HolidayService::getHolidayDatesBetween($dateFrom, $dateTo);
+ if ($notHolidayCalculate) {
+ $dataKey = 'notHolidayDatesInterval';
+ } else {
+ $dataKey = 'dayHolidayInArray';
+ $adminGuidDateArr = self::getAdminGuidByStore($dateFrom, $dateTo, $employeeSelectStoreId);
+ $isAdministrator = false;
+ }
+ $dates = ArrayHelper::getValue($holidayDatesBetweenPrepared, $dataKey);
+ } else {
+ $dates = [
+ 0 => [
+ 'dateFrom' => $dateFrom,
+ 'dateTo' => $dateTo,
+ ],
+ ];
+ }
+
+ $arrUsersSalaryServices = [];
+ $arrUsersSalaryRelated = [];
+ $arrUsersSalaryPotted = [];
+ $arrUsersSalaryWrap = [];
+ $arrUsersSalarySalut = [];
+ $arrUsersSalaryOtherItems = [];
+
+ $arrUsersSalary = [
+ "services" => [],
+ "related" => [],
+ "potted" => [],
+ "wrap" => [],
+ "salut" => [],
+ "other_items" => [],
+ ];
+
+ $arrUsersSalaryServicesCheck = [];
+ $arrUsersSalaryRelatedCheck = [];
+ $arrUsersSalaryPottedCheck = [];
+ $arrUsersSalaryWrapCheck = [];
+ $arrUsersSalarySalutCheck = [];
+ $arrUsersSalaryOtherItemsCheck = [];
+
+ foreach ($dates as $key => $datesRow) {
+ $dateFromRow = $datesRow['dateFrom'];
+ $dateToRow = $datesRow['dateTo'];
+ if (
+ false === $notHolidayCalculate
+ &&
+ $dateFromRow == $dateToRow
+ &&
+ !empty($adminGuidDateArr)
+
+ ) {
+ if (array_key_exists($dateFromRow, $adminGuidDateArr)) {
+ $adminGuidArr = $adminGuidDateArr[$dateFromRow];
+ $adminGuidArrAll[$dateFromRow] = $adminGuidArr;
+ } else {
+ continue;
+ }
+ }
+
+ if (!empty($arrayProducts["services"])) {
+ $arrUsersSalaryServicesPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["services"], $adminGuidArr, $dateFromRow, $dateToRow, $exportAdmin, $isAdministrator);
+ $arrUsersSalaryServices[] = array_sum(
+ ArrayHelper::getColumn($arrUsersSalaryServicesPrepared, 'bonus')
+ );
+ $arrUsersSalaryServicesCheck = DataHelper::mergeArraysByKey(
+ $arrUsersSalaryServicesCheck,
+ ArrayHelper::getColumn($arrUsersSalaryServicesPrepared, 'check')
+ );
+ }
+
+ if (!empty($arrayProducts["related"])) {
+ $arrUsersSalaryRelatedPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["related"], $adminGuidArr, $dateFromRow, $dateToRow, $exportAdmin, $isAdministrator);
+ $arrUsersSalaryRelated[] = array_sum(
+ ArrayHelper::getColumn($arrUsersSalaryRelatedPrepared, 'bonus')
+ );
+
+ $arrUsersSalaryRelatedCheck = DataHelper::mergeArraysByKey(
+ $arrUsersSalaryRelatedCheck,
+ ArrayHelper::getColumn($arrUsersSalaryRelatedPrepared, 'check')
+ );
+ }
+
+ if (!empty($arrayProducts["potted"])) {
+ $arrUsersSalaryPottedPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["potted"], $adminGuidArr, $dateFromRow, $dateToRow, $exportAdmin, $isAdministrator);
+ $arrUsersSalaryPotted[] = array_sum(
+ ArrayHelper::getColumn($arrUsersSalaryPottedPrepared, 'bonus')
+ );
+ $arrUsersSalaryPottedCheck = DataHelper::mergeArraysByKey(
+ $arrUsersSalaryPottedCheck,
+ ArrayHelper::getColumn($arrUsersSalaryPottedPrepared, 'check')
+ );
+ }
+
+ if (!empty($arrayProducts["wrap"])) {
+ $arrUsersSalaryWrapPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["wrap"], $adminGuidArr, $dateFromRow, $dateToRow, $exportAdmin, $isAdministrator);
+ $arrUsersSalaryWrap[] = array_sum(
+ ArrayHelper::getColumn($arrUsersSalaryWrapPrepared, 'bonus')
+ );
+ $arrUsersSalaryWrapCheck = DataHelper::mergeArraysByKey(
+ $arrUsersSalaryWrapCheck,
+ ArrayHelper::getColumn($arrUsersSalaryWrapPrepared, 'check')
+ );
+ }
+
+ if (!empty($arrayProducts["other_items"])) {
+ $arrUsersSalaryOtherItemsPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["other_items"], $adminGuidArr, $dateFromRow, $dateToRow, $exportAdmin, $isAdministrator);
+ $arrUsersSalaryOtherItems[] = array_sum(
+ ArrayHelper::getColumn($arrUsersSalaryOtherItemsPrepared, 'bonus')
+ );
+ $arrUsersSalaryOtherItemsCheck = DataHelper::mergeArraysByKey(
+ $arrUsersSalaryOtherItemsCheck,
+ ArrayHelper::getColumn($arrUsersSalaryOtherItemsPrepared, 'check')
+ );
+ }
+
+ if (!empty($arrayProducts["salut"])) {
+ $arrUsersSalarySalutPrepared = SalaryHelper::getSalaryBonusSalut($arrayProducts["salut"], $adminGuidArr, $dateFromRow, $dateToRow, $exportAdmin, $isAdministrator, $employeeSelectStoreId);
+ $arrUsersSalarySalut[] = array_sum(
+ ArrayHelper::getColumn($arrUsersSalarySalutPrepared, 'bonus')
+ );
+ $arrUsersSalarySalutCheck = DataHelper::mergeArraysByKey(
+ $arrUsersSalarySalutCheck,
+ ArrayHelper::getColumn($arrUsersSalarySalutPrepared, 'check')
+ );
+ }
+ }
+
+ $arrUsersSalaryServicesValue = [];
+ if (array_sum($arrUsersSalaryServices) > 0) {
+ $arrUsersSalaryServicesValue = [$adminGuid => array_sum($arrUsersSalaryServices ?? [])];
+ }
+ $arrUsersSalaryRelatedValue = [];
+ if (array_sum($arrUsersSalaryRelated) > 0) {
+ $arrUsersSalaryRelatedValue = [$adminGuid => array_sum($arrUsersSalaryRelated ?? [])];
+ }
+ $arrUsersSalaryPottedValue = [];
+ if (array_sum($arrUsersSalaryPotted) > 0) {
+ $arrUsersSalaryPottedValue = [$adminGuid => array_sum($arrUsersSalaryPotted ?? [])];
+ }
+ $arrUsersSalaryWrapValue = [];
+ if (array_sum($arrUsersSalaryWrap) > 0) {
+ $arrUsersSalaryWrapValue = [$adminGuid => array_sum($arrUsersSalaryWrap ?? [])];
+ }
+ $arrUsersSalarySalutValue = [];
+ if (array_sum($arrUsersSalarySalut) > 0) {
+ $arrUsersSalarySalutValue = [$adminGuid => array_sum($arrUsersSalarySalut ?? [])];
+ }
+ $arrUsersSalaryOtherItemsValue = [];
+ if (array_sum($arrUsersSalaryOtherItems) > 0) {
+ $arrUsersSalaryOtherItemsValue = [$adminGuid => array_sum($arrUsersSalaryOtherItems ?? [])];
+ }
+
+ $arrUsersSalary = [
+ "services" => $arrUsersSalaryServicesValue,
+ "related" => $arrUsersSalaryRelatedValue,
+ "potted" => $arrUsersSalaryPottedValue,
+ "wrap" => $arrUsersSalaryWrapValue,
+ "salut" => $arrUsersSalarySalutValue,
+ "other_items" => $arrUsersSalaryOtherItemsValue,
+ ];
+
+ $arrUsersSalaryCheck = [
+ "services" => self::getSubRows($arrUsersSalaryServicesCheck),
+ "related" => self::getSubRows($arrUsersSalaryRelatedCheck),
+ "potted" => self::getSubRows($arrUsersSalaryPottedCheck),
+ "wrap" => self::getSubRows($arrUsersSalaryWrapCheck),
+ "salut" => self::getSubRows($arrUsersSalarySalutCheck),
+ "other_items" => self::getSubRows($arrUsersSalaryOtherItemsCheck),
+ ];
+
+ return [
+ 'arrUsersSalary' => $arrUsersSalary,
+ 'arrUsersSalaryCheck' => $arrUsersSalaryCheck,
+ 'adminGuidDateArrByFocusGroup' => $adminGuidArrAll,
+ ];
+ }
+
+ public static function getAdminGuidByStore($dateFrom, $dateTo, $employeeSelectStoreId)
+ {
+ $adminsPrepared = Timetable::getAdminsByDates($dateFrom, $dateTo, $employeeSelectStoreId);
+
+ return $adminsPrepared['dateGuids'];
+ }
+
+ public static function getSubRows(array $arrayRows): array
+ {
+ $res = [];
+ if (!empty($arrayRows)) {
+ foreach ($arrayRows as $rows) {
+ if (!empty($rows) && is_array($rows)) {
+ foreach ($rows as $item) {
+ $res[] = $item;
+ }
+ }
+ }
+ }
+
+ return $res;
+ }
}
\ No newline at end of file
public static function tableName()
{
- return '{{%admin_checkin}}';
+ return 'admin_checkin';
}
public function isStart()
public static function tableName()
{
- return '{{%admin_desktop}}';
+ return 'admin_desktop';
}
/**
{
public static function tableName()
{
- return '{{%admin_device}}';
+ return 'admin_device';
}
}
\ No newline at end of file
*/
class AdminGroup extends ActiveRecord
{
+ const GROUP_FIRED = -1;
const NOT_INITIALIZED_GROUP = 1000;
const GROUP_HR = 20;
const GROUP_FLORIST_NIGHT = 35;
const GROUP_FLORIST_SUPPORT_DAY = 40;
const GROUP_WORKERS = 45;
+ const GROUP_WORKERS_ARCHIVE = 90;
const GROUP_ADMINISTRATORS = 50;
const GROUP_FLORIST_SUPPORT_NIGHT = 72;
const GROUP_OPERATIONAL_DIRECTOR = 51;
public static function tableName()
{
- return '{{%admin_group}}';
+ return 'admin_group';
}
public function rules()
--- /dev/null
+<?php
+
+namespace yii_app\records;
+
+use Yii;
+use yii\helpers\ArrayHelper;
+
+/**
+ * This is the model class for table "admin_payroll_history".
+ *
+ * @property int $id
+ * @property int $admin_id
+ * @property int $store_id
+ * @property int $year
+ * @property int $month
+ * @property int $type_value
+ * @property float $value
+ * @property string $created_at
+ */
+class AdminPayrollHistory extends \yii\db\ActiveRecord
+{
+ const GROUP_VALUE_ALL_TOTAL_PAYROLL = 1;
+ const GROUP_VALUE_TEAM_BONUS_VALUE = 2;
+ const GROUP_VALUE_TEAM_BONUS_DETAIL = 3;
+ const TYPE_VALUE_NUMBER = 'number';
+ const TYPE_VALUE_STRING = 'string';
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return 'admin_payroll_history';
+ }
+
+ public static function setValues(
+ ?array $payrollValues,
+ $employeeId,
+ $storeId,
+ $yearSelect,
+ $monthSelect,
+ $packetNum
+ )
+ {
+ $arrayList = [
+ 'allTotalPayroll' => [
+ 'value_type' => AdminPayrollHistory::TYPE_VALUE_NUMBER,
+ 'group_number' => AdminPayrollHistory::GROUP_VALUE_ALL_TOTAL_PAYROLL,
+ ],
+ 'teamBonusValue' => [
+ 'value_type' => AdminPayrollHistory::TYPE_VALUE_NUMBER,
+ 'group_number' => AdminPayrollHistory::GROUP_VALUE_TEAM_BONUS_VALUE,
+ ],
+ 'teamBonusDetail' => [
+ 'value_type' => AdminPayrollHistory::TYPE_VALUE_STRING,
+ 'group_number' => AdminPayrollHistory::GROUP_VALUE_TEAM_BONUS_DETAIL,
+ ],
+ ];
+
+ foreach ($arrayList as $key => $row) {
+ $groupNumber = ArrayHelper::getValue($row, 'group_number');
+ $typeValue = ArrayHelper::getValue($row, 'value_type');
+ $fieldName = 'value_' . $typeValue;
+ $adminPayrollHistory = new AdminPayrollHistory();
+ $adminPayrollHistory->admin_id = $employeeId;
+ $adminPayrollHistory->store_id = $storeId;
+ $adminPayrollHistory->year = $yearSelect;
+ $adminPayrollHistory->month = $monthSelect;
+ $adminPayrollHistory->$fieldName = $payrollValues[$key];
+ $adminPayrollHistory->group_number = $groupNumber;
+ $adminPayrollHistory->value_type = $typeValue;
+ $adminPayrollHistory->created_at = date('Y-m-d H:i:s');
+ $adminPayrollHistory->created_date = date('Y-m-d');
+ $adminPayrollHistory->packet_num = $packetNum;
+ if ($adminPayrollHistory->validate()) {
+ $adminPayrollHistory->save();
+ } else {
+ if (!empty($adminPayrollHistory->getErrors())) {
+ $errorString = json_encode($adminPayrollHistory->getErrors(), JSON_UNESCAPED_UNICODE);
+ $error = 'Error: ' . $errorString . ' >>> ' . __FILE__. ' >>> ' . __LINE__;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [
+ [['admin_id', 'store_id', 'year', 'month','packet_num', 'value_type', 'created_at'], 'required'],
+ [['admin_id', 'store_id', 'year', 'month','packet_num', 'group_number'], 'integer'],
+ [['created_at', 'created_date'], 'safe'],
+ [['value_number'], 'number'],
+ [['value_string'], 'safe'],
+ [['value_type'], 'safe'],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'ID',
+ 'admin_id' => 'Admin ID',
+ 'store_id' => 'Store ID',
+ 'year' => 'Year',
+ 'month' => 'Month',
+ 'group_number' => 'Group Value',
+ 'value_number' => 'Value Number',
+ 'value_string' => 'Value String',
+ 'value_type' => 'Value Type',
+ 'created_at' => 'Created At',
+ 'created_date' => 'Created Date',
+ 'packet_num' => 'packet num',
+ ];
+ }
+}
* @property int|null $shift_correction
* @property int|null $vacation_day
* @property string $date_time
+ * @property int|null $part_time_job_hours
+ * @property string $retention_comment
*/
class AdminPersonBonuses extends \yii\db\ActiveRecord
{
'prepaid_expense',
'counting',
'shift_correction',
- 'vacation_day'
+ 'vacation_day',
+ 'part_time_job_hours'
],
'integer'
],
- [['date_time'], 'safe'],
+ [['date_time', 'retention_comment'], 'safe'],
[['date'], 'string', 'max' => 100],
];
}
'bonuses' => 'Премия',
'color_ruble_bonuses' => 'Премия в цвето-рублях',
'retention' => 'Вычет',
+ 'retention_comment' => 'Коментарий к вычету',
'shift_correction' => 'Коррекция смены',
+ 'part_time_job_hours' => 'Подработка в часах',
'vacation_day' => 'Отпуск, число оплаченных дней',
'prepaid_expense' => 'Аванс',
'counting' => 'Подсчёт',
$plan_query->andWhere([
'plan_store.shift_type' => [1, 2]
]);
+ } else if ($this->mode_shift === 4) {
+ $rnp_query->andWhere([
+ 'rnp_index.shift_type' => 4
+ ]);
}
if ($this->mode_level === 2) {
}
- static function CalculationCompanyDataForCharts($date_start, $date_end)
+ static function CalculationCompanyDataForChartsShifts($date_start, $date_end)
{
$query = StoreDynamic::find();
//region Проверка на возвраты
/* Проверка продажи */
- $invalid_sales = Sales::find()->alias('invalid_sales')->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])->select(['check_id' => 'invalid_sales.sales_check']);
+ $invalid_sales = Sales::find()->alias('invalid_sales');
+
+ $invalid_sales->innerJoin(
+ 'city_store',
+ 'city_store.id = invalid_sales.store_id'
+ );
+
+ $invalid_sales->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = invalid_sales.store_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))')
+ ],
+ ]
+ );
+
+ $invalid_sales->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])
+ ->select([
+ 'date' => 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ 'shift_type' => 'if(HOUR(invalid_sales.date) >= 8 && HOUR(invalid_sales.date) < 20, 1, 2)',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id'
+ ]);
+
$invalid_sales->andWhere([
'>=',
'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
]);
$invalid_sales->andWhere([
- '<=',
+ '<',
'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
- date('Y-m-d', strtotime('+1 week', strtotime($date_start)))
+ date('Y-m-d', strtotime($date_end))
]);
- $sales_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
- $sales_query->andWhere(['NOT IN', 'sales.id', $invalid_sales]);
+ $invalid_sales->groupBy([
+ 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ 'if(HOUR(invalid_sales.date) >= 8 && HOUR(invalid_sales.date) < 20, 1, 2)',
+ 'store_dynamic.value_int',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+
+ $invalid_sales->andWhere('invalid_sales.order_id = \'\'');
+
/* Конец проверки продажи */
//endregion
+ $sales_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
+
//Исключение доставки
$sales_query->andWhere('sales.order_id = \'\'');
'city_store.id'
]);
/* Конец продажи */
-
- /*
- SELECT SUM(summ)
- FROM `sales`
- INNER JOIN city_store ON sales.store_id = city_store.id
- WHERE (date BETWEEN "2023-08-01 8:00:00" AND "2023-08-02 7:59:59") AND
- (sales.order_id = "") AND
- (sales.operation = "Продажа") AND
- (sales.id NOT IN (
- SELECT sales.sales_check FROM sales WHERE sales.sales_check != ""
- ));
- */
//endregion
// region ФОТ
*/
// endregion
- //region Списания
- $write_offs_query = WriteOffs::find();
-
- $write_offs_query->addSelect([
- 'date' => 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
- 'shift_type' => 'if(HOUR(write_offs.date) >= 8 && HOUR(write_offs.date) < 20, 1, 2)',
- 'cluster_id' => 'store_dynamic.value_int',
- 'store_dynamic_id' => 'store_dynamic.id',
- 'store_id' => 'city_store.id'
- ]);
-
- $write_offs_query->innerJoin(
- 'export_import_table',
- 'write_offs.store_id = export_import_table.export_val'
- );
-
- $write_offs_query->innerJoin(
- 'city_store',
- 'export_import_table.entity_id = city_store.id'
- );
-
- $write_offs_query->innerJoin(
- 'store_dynamic',
- [
- 'AND',
- 'store_dynamic.store_id = export_import_table.entity_id',
- [
- '<=',
- new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
- new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')')
- ],
- [
- '>',
- new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
- new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')')
- ],
- ]
- );
-
- $write_offs_query->andWhere([
- 'write_offs.type' => 'Брак'
- ]);
-
- $write_offs_query->addGroupBy([
- 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
- 'if(HOUR(write_offs.date) >= 8 && HOUR(write_offs.date) < 20, 1, 2)',
- 'store_dynamic.value_int',
- 'store_dynamic.id',
- 'city_store.id'
- ]);
- //endregion
-
//region Ограничения
//region Даты
date('Y-m-d', strtotime($date_end))
]);
- //Списания
- $write_offs_query->andWhere([
- 'BETWEEN',
- 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
- date('Y-m-d', strtotime($date_start)),
- date('Y-m-d', strtotime($date_end))
- ]);
-
//Основной запрос
$query->andWhere([
'BETWEEN',
'admin_payroll_days.smena_type' => [1, 2]
]);
- //Списания
- $write_offs_query->andWhere([
- 'if(HOUR(write_offs.date) >= 8 && HOUR(write_offs.date) < 20, 1, 2)' => [1, 2]
- ]);
-
//Основной запрос
$query->andWhere([
'shift_types.shift_type' => [1, 2]
]
);
+ $query->leftJoin(['invalid_sub_sales' => $invalid_sales],
+ [
+ 'AND',
+ 'city_store.id = invalid_sub_sales.store_id',
+ 'store_dynamic.id = invalid_sub_sales.store_dynamic_id',
+ 'dates_column.date = invalid_sub_sales.date',
+ 'shift_types.shift_type = invalid_sub_sales.shift_type'
+ ]
+ );
+
$sales_query->addSelect([
'sales_sum' => 'SUM(sales.summ)',
'count' => 'COUNT(sales.id)',
]);
+ $invalid_sales->addSelect([
+ 'invalid_sales' => 'SUM(invalid_sales.summ)',
+ 'invalid_count' => 'COUNT(invalid_sales.id)',
+ ]);
+
$query->addSelect([
- 'sales_sum' => 'SUM(sub_sales.sales_sum)',
- 'count_sales' => 'SUM(sub_sales.count)',
+ 'sales_sum' => 'SUM(sub_sales.sales_sum) - SUM(if (invalid_sub_sales.invalid_sales IS NOT NULL, invalid_sub_sales.invalid_sales, 0))',
+ 'count_sales' => 'SUM(sub_sales.count) - SUM(if (invalid_sub_sales.invalid_count IS NOT NULL, invalid_sub_sales.invalid_count, 0))',
]);
$select_array_sales_query = [];
]);
//endregion
- //region Списания
- $query->leftJoin(
- ['sub_write_offs' => $write_offs_query],
- [
- 'AND',
- 'city_store.id = sub_write_offs.store_id',
- 'store_dynamic.id = sub_write_offs.store_dynamic_id',
- 'dates_column.date = sub_write_offs.date',
- 'shift_types.shift_type = sub_write_offs.shift_type'
- ]
- );
-
-
- $write_offs_query->addSelect([
- 'write_offs' => 'SUM(write_offs.summ)',
- ]);
-
- $query->addSelect([
- 'write_offs' => 'SUM(sub_write_offs.write_offs)',
- ]);
-
-
- //endregion
//endregion
$query->orderBy([
]);
//var_dump($plan_store_query->asArray()->all()); exit();
- //var_dump($write_offs_query->asArray()->all()); exit();
//var_dump($sales_query->asArray()->all()); exit();
//var_dump($admin_payroll_days_query->asArray()->all()); exit();
+ //var_dump($invalid_sales->asArray()->all()); exit();
//var_dump($query->asArray()->all()); exit();
//var_dump($query->createCommand()->getRawSql()); exit();
$sales_data_batch = $query->asArray()->batch(200);
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+
foreach ($sales_data_batch as $sales_data) {
foreach ($sales_data as $datum) {
}
if ($id != -1) {
- $rows = [];
foreach ($datum as $key => $item) {
if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type'])) {
- $rows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
}
}
+ }
+ }
+ }
- try {
- $transaction = \Yii::$app->db->beginTransaction();
- RnpData::deleteAll(['AND', ['index_id' => $id], ['NOT IN', 'alias_id', [RnpAlias::USERS_COUNT_ID, RnpAlias::FIRST_MINUS_USER_BONUS_ID, RnpAlias::SECOND_MINUS_USER_BONUS_ID]]]);
- Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rows)->execute();
- $transaction->commit();
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(['AND', ['index_id' => $rnpIndexId], ['NOT IN', 'alias_id', [RnpAlias::USERS_COUNT_ID, RnpAlias::FIRST_MINUS_USER_BONUS_ID, RnpAlias::SECOND_MINUS_USER_BONUS_ID]]]);
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+ $message .= "COUNT(RnpRows) = " . count($rnpDataRows);
- } catch (\Exception $exception) {
- $transaction->rollBack();
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
- $message .= "ЗАПИСЬ store_id = " . $datum['store_id'] . " ОТ: " . $datum['date'] . " АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
- $message .= $exception->getMessage() . "\n";
- }
- }
- }
+ $message .= "АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
}
return $message;
}
- static function CalculationCompanyDataUsersBonusForCharts($date_start, $date_end)
+ static function CalculationCompanyDataForChartsDay($date_start, $date_end)
{
$query = StoreDynamic::find();
//Генерирует столбец типов смен для каждой даты
//region Смены
- $shift_query = (new Query())->from('(SELECT 1 AS shift_type UNION ALL SELECT 2) shift_types')
+ $shift_query = (new Query())->from('(SELECT 4 AS shift_type) shift_types')
->select(['shift_type' => 'shift_types.shift_type']);
$query->leftJoin(
$sales_query = Sales::find();
$sales_query->addSelect([
- 'date' => 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
- 'shift_type' => 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'date' => 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
'cluster_id' => 'store_dynamic.value_int',
'store_dynamic_id' => 'store_dynamic.id',
'store_id' => 'city_store.id'
[
'<=',
new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
- new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
],
[
'>',
new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
- new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
],
]
);
//region Проверка на возвраты
/* Проверка продажи */
- $invalid_sales = Sales::find()->alias('invalid_sales')->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])->select(['check_id' => 'invalid_sales.sales_check']);
+ $invalid_sales = Sales::find()->alias('invalid_sales');
+
+ $invalid_sales->innerJoin(
+ 'city_store',
+ 'city_store.id = invalid_sales.store_id'
+ );
+
+ $invalid_sales->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = invalid_sales.store_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')')
+ ],
+ ]
+ );
+
+ $invalid_sales->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])
+ ->select([
+ 'date' => 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id'
+ ]);
+
$invalid_sales->andWhere([
'>=',
- 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
date('Y-m-d', strtotime($date_start))
]);
$invalid_sales->andWhere([
- '<=',
- 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
- date('Y-m-d', strtotime('+1 week', strtotime($date_start)))
+ '<',
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
+ date('Y-m-d', strtotime($date_end))
]);
- $sales_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
- $sales_query->andWhere(['NOT IN', 'sales.id', $invalid_sales]);
+ $invalid_sales->groupBy([
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
+ 'store_dynamic.value_int',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+
+ $invalid_sales->andWhere('invalid_sales.order_id = \'\'');
+
/* Конец проверки продажи */
//endregion
+ $sales_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
+
//Исключение доставки
$sales_query->andWhere('sales.order_id = \'\'');
$sales_query->addGroupBy([
- 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
- 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
'store_dynamic.value_int',
'store_dynamic.id',
'city_store.id'
/* Конец продажи */
//endregion
+
+ //region Списания
+ $write_offs_query = WriteOffs::find();
+
+ $write_offs_query->addSelect([
+ 'date' => 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id'
+ ]);
+
+ $write_offs_query->innerJoin(
+ 'export_import_table',
+ 'write_offs.store_id = export_import_table.export_val'
+ );
+
+ $write_offs_query->innerJoin(
+ 'city_store',
+ 'export_import_table.entity_id = city_store.id'
+ );
+
+ $write_offs_query->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = export_import_table.entity_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')')
+ ],
+ ]
+ );
+
+ $write_offs_query->andWhere([
+ 'write_offs.type' => 'Брак'
+ ]);
+
+ $write_offs_query->addGroupBy([
+ 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
+ 'store_dynamic.value_int',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+
+ //endregion
+
//region Ограничения
//region Даты
//Продажи
$sales_query->andWhere([
'BETWEEN',
- 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ date('Y-m-d', strtotime($date_start)),
+ date('Y-m-d', strtotime($date_end))
+ ]);
+
+ //Списания
+ $write_offs_query->andWhere([
+ 'BETWEEN',
+ 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
date('Y-m-d', strtotime($date_start)),
date('Y-m-d', strtotime($date_end))
]);
$query->addGroupBy(['dates_column.date']);
//endregion
- //region Тип смены
+ $query->addSelect([
+ 'shift_type' => 'shift_types.shift_type'
+ ]);
- //Продажи
- $sales_query->andWhere([
- 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)' => [1, 2]
+ $query->addGroupBy([
+ 'shift_types.shift_type'
+ ]);
+
+
+ //region Уровень данных
+
+ $query->addSelect([
+ 'cluster_id' => 'store_dynamic.value_int'
+ ]);
+
+ $query->addGroupBy([
+ 'store_dynamic.value_int'
+ ]);
+
+ $query->addSelect([
+ 'store_id' => 'city_store.id',
+ ]);
+
+ $query->addGroupBy([
+ 'city_store.id',
+ ]);
+
+ //endregion
+ //endregion
+
+ //region Атрибут
+
+ //region Продажи
+ $query->leftJoin(
+ ['sub_sales' => $sales_query],
+ [
+ 'AND',
+ 'city_store.id = sub_sales.store_id',
+ 'store_dynamic.id = sub_sales.store_dynamic_id',
+ 'dates_column.date = sub_sales.date',
+ ]
+ );
+
+ $query->leftJoin(['invalid_sub_sales' => $invalid_sales],
+ [
+ 'AND',
+ 'city_store.id = invalid_sub_sales.store_id',
+ 'store_dynamic.id = invalid_sub_sales.store_dynamic_id',
+ 'dates_column.date = invalid_sub_sales.date',
+ ]
+ );
+
+
+ $sales_query->addSelect([
+ 'sales_sum' => 'SUM(sales.summ)',
+ 'count' => 'COUNT(sales.id)',
+ ]);
+
+ $invalid_sales->addSelect([
+ 'invalid_sales' => 'SUM(invalid_sales.summ)',
+ 'invalid_count' => 'COUNT(invalid_sales.id)',
+ ]);
+
+ $query->addSelect([
+ 'sales_sum' => 'SUM(sub_sales.sales_sum) - SUM(if (invalid_sub_sales.invalid_sales IS NOT NULL, invalid_sub_sales.invalid_sales, 0))',
+ 'count_sales' => 'SUM(sub_sales.count) - SUM(if (invalid_sub_sales.invalid_count IS NOT NULL, invalid_sub_sales.invalid_count, 0))',
+ ]);
+
+ $select_array_sales_query = [];
+ $select_array_query = [];
+ $range = array_merge(range(8, 23), range(0, 7));
+
+ foreach ($range as $item) {
+ $select_array_sales_query['count_sales_in_' . $item . '_hour'] = 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', ' . $item . ', 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', ' . $item . ', 59, 59), \'%H:%i:%s\'), 1, 0))';
+ $select_array_query['count_sales_in_' . $item . '_hour'] = 'SUM(sub_sales.count_sales_in_' . $item . '_hour)';
+ }
+
+ $sales_query->addSelect($select_array_sales_query);
+ $query->addSelect($select_array_query);
+
+ //region Списания
+ $query->leftJoin(
+ ['sub_write_offs' => $write_offs_query],
+ [
+ 'AND',
+ 'city_store.id = sub_write_offs.store_id',
+ 'store_dynamic.id = sub_write_offs.store_dynamic_id',
+ 'dates_column.date = sub_write_offs.date',
+ ]
+ );
+
+
+ $write_offs_query->addSelect([
+ 'write_offs' => 'SUM(write_offs.summ)',
+ ]);
+
+ $query->addSelect([
+ 'write_offs' => 'SUM(sub_write_offs.write_offs)',
+ ]);
+
+
+ //endregion
+ //endregion
+
+ $query->orderBy([
+ 'dates_column.date' => SORT_ASC,
+ 'store_dynamic.value_int' => SORT_ASC,
+ 'city_store.id' => SORT_ASC,
+ 'shift_types.shift_type' => SORT_ASC
+ ]);
+
+ //var_dump($plan_store_query->asArray()->all()); exit();
+ //var_dump($write_offs_query->asArray()->all()); exit();
+ //var_dump($sales_query->asArray()->all()); exit();
+ //var_dump($admin_payroll_days_query->asArray()->all()); exit();
+ //var_dump($invalid_sales->asArray()->all()); exit();
+ //var_dump($query->asArray()->all()); exit();
+ //var_dump($query->createCommand()->getRawSql()); exit();
+
+ $message = "";
+
+ $aliases = RnpAlias::find()->select(['id', 'alias'])->asArray()->all();
+
+ $aliases = ArrayHelper::map($aliases, 'alias', 'id');
+
+ $rnp_old_index = RnpIndex::find()->where(['BETWEEN', 'date', $date_start, $date_end])->select([
+ 'id',
+ 'cluster_id',
+ 'store_id',
+ 'shift_type',
+ 'date',
+ ])->asArray()->all();
+
+ $ids = [];
+ foreach ($rnp_old_index as $index) {
+ $ids[$index['cluster_id'] . $index['store_id'] . $index['shift_type'] . $index['date']] = $index['id'];
+ }
+
+ $sales_data_batch = $query->asArray()->batch(200);
+
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+
+ foreach ($sales_data_batch as $sales_data) {
+ foreach ($sales_data as $datum) {
+
+ $id = -1;
+
+ if (array_key_exists($datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date'], $ids)) {
+ $id = $ids[$datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date']];
+ } else {
+ $rnp_index = new RnpIndex(['cluster_id' => $datum['cluster_id'], 'store_id' => $datum['store_id'], 'shift_type' => $datum['shift_type'], 'date' => $datum['date']]);
+
+ if ($rnp_index->save()) {
+ $id = $rnp_index->id;
+ } else {
+ $message .= "ЗАПИСЬ store_id = " . $datum['store_id'] . " ОТ: " . $datum['date'] . " НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= "Ошибки валидации модели:\n";
+ foreach ($rnp_index->getErrors() as $error) {
+ $message .= $error[0] . "\n";
+ }
+
+ }
+ }
+
+ if ($id != -1) {
+
+ foreach ($datum as $key => $item) {
+ if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type'])) {
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(['AND', ['index_id' => $rnpIndexId], ['NOT IN', 'alias_id', [RnpAlias::USERS_COUNT_ID, RnpAlias::FIRST_MINUS_USER_BONUS_ID, RnpAlias::SECOND_MINUS_USER_BONUS_ID]]]);
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+ $message .= "COUNT(RnpRows) = " . count($rnpDataRows);
+
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
+
+ $message .= "АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
+ }
+
+ return $message;
+ }
+
+ static function CalculationCompanyDataUsersBonusForChartsShifts($date_start, $date_end)
+ {
+
+ $query = StoreDynamic::find();
+
+ $query->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1');
+
+ // Генерирует столбец дат для каждого магазина в соответствии с кустом
+ //region Даты
+ // Нужно для соединения составляющих запроса (left join)
+ $dates_query = (new Query())->from('(
+ SELECT :date_end - INTERVAL (units.mul + (10 * tens.mul) + (100 * hundreds.mul) + (1000 * thousands.mul)) DAY AS date
+ FROM (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS units
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS tens
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS hundreds
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS thousands
+ ) a'
+ )->params([':date_end' => date('Y-m-d', strtotime($date_end))])
+ ->andWhere([
+ 'BETWEEN', 'a.date', date('Y-m-d', strtotime($date_start)), date('Y-m-d', strtotime($date_end))
+ ]);
+
+ $dates_query->orderBy(['date' => SORT_ASC]);
+
+ $query->leftJoin(
+ ['dates_column' => $dates_query],
+ [
+ 'BETWEEN',
+ 'dates_column.date',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ ]
+ );
+ //endregion
+
+ //Генерирует столбец типов смен для каждой даты
+ //region Смены
+ $shift_query = (new Query())->from('(SELECT 1 AS shift_type UNION ALL SELECT 2) shift_types')
+ ->select(['shift_type' => 'shift_types.shift_type']);
+
+ $query->leftJoin(
+ ['shift_types' => $shift_query],
+ [
+ '=',
+ 1,
+ 1
+ ]
+ );
+ //endregion
+
+ //region Продажи
+ /* Продажи */
+
+ $sales_query = Sales::find();
+
+ $sales_query->addSelect([
+ 'date' => 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'shift_type' => 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id'
+ ]);
+
+ $sales_query->innerJoin(
+ 'city_store',
+ 'city_store.id = sales.store_id'
+ );
+
+ $sales_query->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = sales.store_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ ],
+ ]
+ );
+
+ //region Проверка на возвраты
+ /* Проверка продажи */
+ $invalid_sales = Sales::find()->alias('invalid_sales')->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])->select(['check_id' => 'invalid_sales.sales_check']);
+ $invalid_sales->andWhere([
+ '>=',
+ 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime($date_start))
+ ]);
+
+ $invalid_sales->andWhere([
+ '<=',
+ 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime('+1 week', strtotime($date_start)))
+ ]);
+
+ $sales_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
+ $sales_query->andWhere(['NOT IN', 'sales.id', $invalid_sales]);
+ /* Конец проверки продажи */
+ //endregion
+
+ //Исключение доставки
+ $sales_query->andWhere('sales.order_id = \'\'');
+
+ $sales_query->addGroupBy([
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'store_dynamic.value_int',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+ /* Конец продажи */
+ //endregion
+
+ //region Ограничения
+ //region Даты
+
+ //Продажи
+ $sales_query->andWhere([
+ 'BETWEEN',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime($date_start)),
+ date('Y-m-d', strtotime($date_end))
+ ]);
+
+ //Основной запрос
+ $query->andWhere([
+ 'BETWEEN',
+ 'dates_column.date',
+ date('Y-m-d', strtotime($date_start)),
+ date('Y-m-d', strtotime($date_end))
+ ]);
+ $query->addSelect(['date' => 'dates_column.date']);
+ $query->addGroupBy(['dates_column.date']);
+ //endregion
+
+ //region Тип смены
+
+ //Продажи
+ $sales_query->andWhere([
+ 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)' => [1, 2]
+ ]);
+
+ //Основной запрос
+ $query->andWhere([
+ 'shift_types.shift_type' => [1, 2]
+ ]);
+
+ $query->addSelect([
+ 'shift_type' => 'shift_types.shift_type'
+ ]);
+
+ $query->addGroupBy([
+ 'shift_types.shift_type'
+ ]);
+ //endregion
+
+ //region Уровень данных
+
+ $query->addSelect([
+ 'cluster_id' => 'store_dynamic.value_int'
+ ]);
+
+ $query->addGroupBy([
+ 'store_dynamic.value_int'
+ ]);
+
+ $query->addSelect([
+ 'store_id' => 'city_store.id',
+ ]);
+
+ $query->addGroupBy([
+ 'city_store.id',
+ ]);
+
+ //endregion
+ //endregion
+
+ //region Атрибут
+
+ //region Продажи
+ $query->leftJoin(
+ ['sub_sales' => $sales_query],
+ [
+ 'AND',
+ 'city_store.id = sub_sales.store_id',
+ 'store_dynamic.id = sub_sales.store_dynamic_id',
+ 'dates_column.date = sub_sales.date',
+ 'shift_types.shift_type = sub_sales.shift_type'
+ ]
+ );
+
+ ////region Бонусная
+ $sales_query->leftJoin('users', 'sales.phone = users.phone')
+ ->leftJoin('users_bonus', 'users.id = users_bonus.user_id AND sales.id = users_bonus.check_id AND users_bonus.check_id != \'\'');
+
+ ////endregion
+
+ $sales_query->addSelect([
+ 'count_users' => 'SUM( IF (sales.phone IS NOT NULL AND sales.phone != \'\', 1, 0))',
+ 'first_minus_user_bonus' => 'SUM( IF (users.first_minus_balance = users_bonus.date, 1, 0))',
+ 'second_minus_user_bonus' => 'SUM( IF (users.first_minus_balance < users_bonus.date, 1, 0))'
+ ]);
+
+ $query->addSelect([
+ 'count_users' => 'SUM(sub_sales.count_users)',
+ 'first_minus_user_bonus' => 'SUM(sub_sales.first_minus_user_bonus)',
+ 'second_minus_user_bonus' => 'SUM(sub_sales.second_minus_user_bonus)'
+ ]);
+
+ $query->orderBy([
+ 'dates_column.date' => SORT_ASC,
+ 'store_dynamic.value_int' => SORT_ASC,
+ 'city_store.id' => SORT_ASC,
+ 'shift_types.shift_type' => SORT_ASC
+ ]);
+
+ $message = "";
+
+ $aliases = RnpAlias::find()->select(['id', 'alias'])->asArray()->all();
+
+ $aliases = ArrayHelper::map($aliases, 'alias', 'id');
+
+ $rnp_old_index = RnpIndex::find()->where(['BETWEEN', 'date', $date_start, $date_end])->select([
+ 'id',
+ 'cluster_id',
+ 'store_id',
+ 'shift_type',
+ 'date',
+ ])->asArray()->all();
+
+ $ids = [];
+ foreach ($rnp_old_index as $index) {
+ $ids[$index['cluster_id'] . $index['store_id'] . $index['shift_type'] . $index['date']] = $index['id'];
+ }
+
+ //var_dump($date_start); exit();
+ $sales_data_batch = $query->asArray()->batch(200);
+
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+
+ foreach ($sales_data_batch as $sales_data) {
+ foreach ($sales_data as $datum) {
+
+ $id = -1;
+
+ if (array_key_exists($datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date'], $ids)) {
+ $id = $ids[$datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date']];
+ } else {
+ $rnp_index = new RnpIndex(['cluster_id' => $datum['cluster_id'], 'store_id' => $datum['store_id'], 'shift_type' => $datum['shift_type'], 'date' => $datum['date']]);
+
+ if ($rnp_index->save()) {
+ $id = $rnp_index->id;
+ } else {
+ $message .= "ЗАПИСЬ store_id = " . $datum['store_id'] . " ОТ: " . $datum['date'] . " НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= "Ошибки валидации модели:\n";
+ foreach ($rnp_index->getErrors() as $error) {
+ $message .= $error[0] . "\n";
+ }
+
+ }
+ }
+
+ if ($id != -1) {
+
+ foreach ($datum as $key => $item) {
+ if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type'])) {
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(['AND', ['index_id' => $rnpIndexId], ['alias_id' => [RnpAlias::USERS_COUNT_ID, RnpAlias::FIRST_MINUS_USER_BONUS_ID, RnpAlias::SECOND_MINUS_USER_BONUS_ID]]]);
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+ $message .= "COUNT(RnpRows) = " . count($rnpDataRows);
+
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
+
+ $message .= "АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
+ }
+
+ return $message;
+ }
+
+ static function CalculationCompanyDataUsersBonusForChartsDay($date_start, $date_end)
+ {
+
+ $query = StoreDynamic::find();
+
+ $query->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1');
+
+ // Генерирует столбец дат для каждого магазина в соответствии с кустом
+ //region Даты
+ // Нужно для соединения составляющих запроса (left join)
+ $dates_query = (new Query())->from('(
+ SELECT :date_end - INTERVAL (units.mul + (10 * tens.mul) + (100 * hundreds.mul) + (1000 * thousands.mul)) DAY AS date
+ FROM (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS units
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS tens
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS hundreds
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS thousands
+ ) a'
+ )->params([':date_end' => date('Y-m-d', strtotime($date_end))])
+ ->andWhere([
+ 'BETWEEN', 'a.date', date('Y-m-d', strtotime($date_start)), date('Y-m-d', strtotime($date_end))
+ ]);
+
+ $dates_query->orderBy(['date' => SORT_ASC]);
+
+ $query->leftJoin(
+ ['dates_column' => $dates_query],
+ [
+ 'BETWEEN',
+ 'dates_column.date',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ ]
+ );
+ //endregion
+
+ //Генерирует столбец типов смен для каждой даты
+ //region Смены
+ $shift_query = (new Query())->from('(SELECT 4 AS shift_type) shift_types')
+ ->select(['shift_type' => 'shift_types.shift_type']);
+
+ $query->leftJoin(
+ ['shift_types' => $shift_query],
+ [
+ '=',
+ 1,
+ 1
+ ]
+ );
+ //endregion
+
+ //region Продажи
+ /* Продажи */
+
+ $sales_query = Sales::find();
+
+ $sales_query->addSelect([
+ 'date' => 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id'
+ ]);
+
+ $sales_query->innerJoin(
+ 'city_store',
+ 'city_store.id = sales.store_id'
+ );
+
+ $sales_query->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = sales.store_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
+ ],
+ ]
+ );
+
+ //region Проверка на возвраты
+ /* Проверка продажи */
+ $invalid_sales = Sales::find()->alias('invalid_sales')->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])->select(['check_id' => 'invalid_sales.sales_check']);
+ $invalid_sales->andWhere([
+ '>=',
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
+ date('Y-m-d', strtotime($date_start))
+ ]);
+
+ $invalid_sales->andWhere([
+ '<=',
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
+ date('Y-m-d', strtotime('+1 week', strtotime($date_start)))
+ ]);
+
+ $sales_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
+ $sales_query->andWhere(['NOT IN', 'sales.id', $invalid_sales]);
+ /* Конец проверки продажи */
+ //endregion
+
+ //Исключение доставки
+ $sales_query->andWhere('sales.order_id = \'\'');
+
+ $sales_query->addGroupBy([
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ 'store_dynamic.value_int',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+ /* Конец продажи */
+ //endregion
+
+ //region Ограничения
+ //region Даты
+
+ //Продажи
+ $sales_query->andWhere([
+ 'BETWEEN',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ date('Y-m-d', strtotime($date_start)),
+ date('Y-m-d', strtotime($date_end))
+ ]);
+
+ //Основной запрос
+ $query->andWhere([
+ 'BETWEEN',
+ 'dates_column.date',
+ date('Y-m-d', strtotime($date_start)),
+ date('Y-m-d', strtotime($date_end))
+ ]);
+ $query->addSelect(['date' => 'dates_column.date']);
+ $query->addGroupBy(['dates_column.date']);
+ //endregion
+
+ //Основной запрос
+ $query->addSelect([
+ 'shift_type' => 'shift_types.shift_type'
+ ]);
+
+ $query->addGroupBy([
+ 'shift_types.shift_type'
+ ]);
+ //endregion
+
+ //region Уровень данных
+
+ $query->addSelect([
+ 'cluster_id' => 'store_dynamic.value_int'
+ ]);
+
+ $query->addGroupBy([
+ 'store_dynamic.value_int'
+ ]);
+
+ $query->addSelect([
+ 'store_id' => 'city_store.id',
+ ]);
+
+ $query->addGroupBy([
+ 'city_store.id',
+ ]);
+
+ //endregion
+ //endregion
+
+ //region Атрибут
+
+ //region Продажи
+ $query->leftJoin(
+ ['sub_sales' => $sales_query],
+ [
+ 'AND',
+ 'city_store.id = sub_sales.store_id',
+ 'store_dynamic.id = sub_sales.store_dynamic_id',
+ 'dates_column.date = sub_sales.date',
+ ]
+ );
+
+ ////region Бонусная
+ $sales_query->leftJoin('users', 'sales.phone = users.phone')
+ ->leftJoin('users_bonus', 'users.id = users_bonus.user_id AND sales.id = users_bonus.check_id AND users_bonus.check_id != \'\'');
+
+ ////endregion
+
+ $sales_query->addSelect([
+ 'count_users' => 'SUM( IF (sales.phone IS NOT NULL AND sales.phone != \'\', 1, 0))',
+ 'first_minus_user_bonus' => 'SUM( IF (users.first_minus_balance = users_bonus.date, 1, 0))',
+ 'second_minus_user_bonus' => 'SUM( IF (users.first_minus_balance < users_bonus.date, 1, 0))'
+ ]);
+
+ $query->addSelect([
+ 'count_users' => 'SUM(sub_sales.count_users)',
+ 'first_minus_user_bonus' => 'SUM(sub_sales.first_minus_user_bonus)',
+ 'second_minus_user_bonus' => 'SUM(sub_sales.second_minus_user_bonus)'
+ ]);
+
+ $query->orderBy([
+ 'dates_column.date' => SORT_ASC,
+ 'store_dynamic.value_int' => SORT_ASC,
+ 'city_store.id' => SORT_ASC,
+ 'shift_types.shift_type' => SORT_ASC
+ ]);
+
+ $message = "";
+
+ $aliases = RnpAlias::find()->select(['id', 'alias'])->asArray()->all();
+
+ $aliases = ArrayHelper::map($aliases, 'alias', 'id');
+
+ $rnp_old_index = RnpIndex::find()->where(['BETWEEN', 'date', $date_start, $date_end])->select([
+ 'id',
+ 'cluster_id',
+ 'store_id',
+ 'shift_type',
+ 'date',
+ ])->asArray()->all();
+
+ $ids = [];
+ foreach ($rnp_old_index as $index) {
+ $ids[$index['cluster_id'] . $index['store_id'] . $index['shift_type'] . $index['date']] = $index['id'];
+ }
+
+ $sales_data_batch = $query->asArray()->batch(200);
+
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+
+ foreach ($sales_data_batch as $sales_data) {
+ foreach ($sales_data as $datum) {
+
+ $id = -1;
+
+ if (array_key_exists($datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date'], $ids)) {
+ $id = $ids[$datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date']];
+ } else {
+ $rnp_index = new RnpIndex(['cluster_id' => $datum['cluster_id'], 'store_id' => $datum['store_id'], 'shift_type' => $datum['shift_type'], 'date' => $datum['date']]);
+
+ if ($rnp_index->save()) {
+ $id = $rnp_index->id;
+ } else {
+ $message .= "ЗАПИСЬ store_id = " . $datum['store_id'] . " ОТ: " . $datum['date'] . " НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= "Ошибки валидации модели:\n";
+ foreach ($rnp_index->getErrors() as $error) {
+ $message .= $error[0] . "\n";
+ }
+
+ }
+ }
+
+ if ($id != -1) {
+
+ foreach ($datum as $key => $item) {
+ if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type'])) {
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(['AND', ['index_id' => $rnpIndexId], ['alias_id' => [RnpAlias::USERS_COUNT_ID, RnpAlias::FIRST_MINUS_USER_BONUS_ID, RnpAlias::SECOND_MINUS_USER_BONUS_ID]]]);
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+ $message .= "COUNT(RnpRows) = " . count($rnpDataRows);
+
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
+
+ $message .= "АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
+ }
+
+ return $message;
+ }
+
+ static function CalculationCompanyDataMatrixSalesForChartsShifts($date_start, $date_end)
+ {
+
+ $query = StoreDynamic::find();
+
+ $query->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1');
+
+ // Генерирует столбец дат для каждого магазина в соответствии с кустом
+ //region Даты
+ // Нужно для соединения составляющих запроса (left join)
+ $dates_query = (new Query())->from('(
+ SELECT :date_end - INTERVAL (units.mul + (10 * tens.mul) + (100 * hundreds.mul) + (1000 * thousands.mul)) DAY AS date
+ FROM (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS units
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS tens
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS hundreds
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS thousands
+ ) a'
+ )->params([':date_end' => date('Y-m-d', strtotime($date_end))])
+ ->andWhere([
+ 'BETWEEN', 'a.date', date('Y-m-d', strtotime($date_start)), date('Y-m-d', strtotime($date_end))
+ ]);
+
+ $dates_query->orderBy(['date' => SORT_ASC]);
+
+ $query->leftJoin(
+ ['dates_column' => $dates_query],
+ [
+ 'BETWEEN',
+ 'dates_column.date',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ ]
+ );
+ //endregion
+
+ //Генерирует столбец типов смен для каждой даты
+ //region Смены
+ $shift_query = (new Query())->from('(SELECT 1 AS shift_type UNION ALL SELECT 2) shift_types')
+ ->select(['shift_type' => 'shift_types.shift_type']);
+
+ $query->leftJoin(
+ ['shift_types' => $shift_query],
+ [
+ '=',
+ 1,
+ 1
+ ]
+ );
+ //endregion
+
+ //region Матрица
+ $matrix_query = Sales::find();
+
+ $matrix_query->addSelect([
+ 'date' => 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'shift_type' => 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id'
+ ]);
+
+ $matrix_query->innerJoin(
+ 'city_store',
+ 'city_store.id = sales.store_id'
+ );
+
+ $matrix_query->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = sales.store_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ ],
+ ]
+ );
+
+ //region Проверка на возвраты
+ /* Проверка продажи */
+ $invalid_sales = Sales::find()->alias('invalid_sales')->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])->select(['check_id' => 'invalid_sales.sales_check']);
+ $invalid_sales->andWhere([
+ '>=',
+ 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime($date_start))
+ ]);
+
+ $invalid_sales->andWhere([
+ '<=',
+ 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime('+1 week', strtotime($date_start)))
+ ]);
+ /* Конец проверки продажи */
+ //endregion
+
+ //Исключение доставки
+ $matrix_query->andWhere('sales.order_id = \'\'');
+ /* Конец продажи */
+
+ $matrix_query->andWhere(['sales.operation' => Sales::OPERATION_SALE]);
+ $matrix_query->andWhere(['NOT IN', 'sales.id', $invalid_sales]);
+
+ $matrix_query->addGroupBy([
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'store_dynamic.value_int',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+
+ $matrix_query->andWhere([
+ 'AND',
+ [
+ '>=',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime($date_start))
+ ],
+ [
+ '<=',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime($date_end))
+ ]
+ ]);
+
+ $matrix_query->innerJoin('sales_products', 'sales.id = sales_products.check_id')
+ ->innerJoin('products_1c', 'sales_products.product_id = products_1c.id')
+ ->innerJoin('products_class', 'products_1c.parent_id = products_class.category_id AND products_class.tip = \'matrix\'');
+
+ $matrix_season_guid = Products1c::find()->where(['LIKE', 'name', 'Сезонная матрица'])->select(['id'])->column()[0] ?? '';
+ $matrix_base_guid = Products1c::find()->where(['LIKE', 'name', 'Матрица базовая'])->select(['id'])->column()[0] ?? '';
+ $matrix_new_guid = Products1c::find()->where(['LIKE', 'name', 'Новая матрица'])->select(['id'])->column()[0] ?? '';
+
+ $matrix_group = Products1c::find()
+ ->andWhere(
+ ['IN',
+ 'products_1c.parent_id',
+ [
+ $matrix_season_guid, // Сезонная
+ $matrix_base_guid, // Базовая
+ $matrix_new_guid, // Новая
+ ],
+ ]
+ )
+ ->select([
+ 'id' => 'products_1c.id',
+ 'parent_id' => 'products_1c.parent_id'
+ ]);
+
+ $matrix_query->leftJoin(['matrix_group' => $matrix_group], '(products_1c.id = matrix_group.id OR products_1c.parent_id = matrix_group.id)')
+ ->addSelect([
+ 'matrix_base_summ' => 'SUM(if (matrix_group.parent_id = \'' . $matrix_base_guid . '\' OR matrix_group.id = \'' . $matrix_base_guid . '\', sales_products.summ, 0))', // Базовая
+ 'matrix_season_summ' => 'SUM(if (matrix_group.parent_id = \'' . $matrix_season_guid . '\' OR matrix_group.id = \'' . $matrix_season_guid . '\', sales_products.summ, 0))', // Сезонная
+ 'matrix_new_summ' => 'SUM(if (matrix_group.parent_id = \'' . $matrix_new_guid . '\' OR matrix_group.id = \'' . $matrix_new_guid . '\', sales_products.summ, 0))' // Новая
+ ]);
+
+ $query->leftJoin(
+ ['matrix' => $matrix_query],
+ [
+ 'AND',
+ 'city_store.id = matrix.store_id',
+ 'store_dynamic.id = matrix.store_dynamic_id',
+ 'dates_column.date = matrix.date',
+ 'shift_types.shift_type = matrix.shift_type'
+ ]
+ );
+ // endregion
+
+ //region Ограничения
+ //region Даты
+
+ //Основной запрос
+ $query->andWhere([
+ 'BETWEEN',
+ 'dates_column.date',
+ date('Y-m-d', strtotime($date_start)),
+ date('Y-m-d', strtotime($date_end))
+ ]);
+
+ $query->addSelect(['date' => 'dates_column.date']);
+ $query->addGroupBy(['dates_column.date']);
+ //endregion
+
+ //region Тип смены
+
+ //Продажи
+ $matrix_query->andWhere([
+ 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)' => [1, 2]
]);
//Основной запрос
//endregion
//endregion
- //region Атрибут
-
- //region Продажи
- $query->leftJoin(
- ['sub_sales' => $sales_query],
- [
- 'AND',
- 'city_store.id = sub_sales.store_id',
- 'store_dynamic.id = sub_sales.store_dynamic_id',
- 'dates_column.date = sub_sales.date',
- 'shift_types.shift_type = sub_sales.shift_type'
- ]
- );
-
- ////region Бонусная
- $sales_query->leftJoin('users', 'sales.phone = users.phone')
- ->leftJoin('users_bonus', 'users.id = users_bonus.user_id AND sales.id = users_bonus.check_id AND users_bonus.check_id != \'\'');
-
- ////endregion
-
- $sales_query->addSelect([
- 'count_users' => 'SUM( IF (sales.phone IS NOT NULL AND sales.phone != \'\', 1, 0))',
- 'first_minus_user_bonus' => 'SUM( IF (users.first_minus_balance = users_bonus.date, 1, 0))',
- 'second_minus_user_bonus' => 'SUM( IF (users.first_minus_balance < users_bonus.date, 1, 0))'
- ]);
-
$query->addSelect([
- 'count_users' => 'SUM(sub_sales.count_users)',
- 'first_minus_user_bonus' => 'SUM(sub_sales.first_minus_user_bonus)',
- 'second_minus_user_bonus' => 'SUM(sub_sales.second_minus_user_bonus)'
+ 'matrix_base_summ' => 'SUM(matrix.matrix_base_summ)',
+ 'matrix_season_summ' => 'SUM(matrix.matrix_season_summ)',
+ 'matrix_new_summ' => 'SUM(matrix.matrix_new_summ)',
]);
+
+ //endregion
+
$query->orderBy([
'dates_column.date' => SORT_ASC,
'store_dynamic.value_int' => SORT_ASC,
$sales_data_batch = $query->asArray()->batch(200);
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+
foreach ($sales_data_batch as $sales_data) {
foreach ($sales_data as $datum) {
}
if ($id != -1) {
- $rows = [];
foreach ($datum as $key => $item) {
if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type'])) {
- $rows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
}
}
+ }
+ }
+ }
- try {
- $transaction = \Yii::$app->db->beginTransaction();
- RnpData::deleteAll(['AND', ['index_id' => $id], ['alias_id' => [RnpAlias::USERS_COUNT_ID, RnpAlias::FIRST_MINUS_USER_BONUS_ID, RnpAlias::SECOND_MINUS_USER_BONUS_ID]]]);
- Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rows)->execute();
- $transaction->commit();
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(['AND', ['index_id' => $rnpIndexId], ['alias_id' => [RnpAlias::MATRIX_NEW_SUMM_ID, RnpAlias::MATRIX_SEASON_SUMM_ID, RnpAlias::MATRIX_BASE_SUMM_ID]]]);
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+ $message .= "COUNT(RnpRows) = " . count($rnpDataRows);
- } catch (\Exception $exception) {
- $transaction->rollBack();
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
- $message .= "ЗАПИСЬ store_id = " . $datum['store_id'] . " ОТ: " . $datum['date'] . " АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
- $message .= $exception->getMessage() . "\n";
- }
- }
- }
+ $message .= "АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
}
return $message;
}
- static function CalculationCompanyDataMatrixSalesForCharts($date_start, $date_end)
+ static function CalculationCompanyDataMatrixSalesForChartsDay($date_start, $date_end)
{
$query = StoreDynamic::find();
//Генерирует столбец типов смен для каждой даты
//region Смены
- $shift_query = (new Query())->from('(SELECT 1 AS shift_type UNION ALL SELECT 2) shift_types')
+ $shift_query = (new Query())->from('(SELECT 4 AS shift_type) shift_types')
->select(['shift_type' => 'shift_types.shift_type']);
$query->leftJoin(
$matrix_query = Sales::find();
$matrix_query->addSelect([
- 'date' => 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
- 'shift_type' => 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'date' => 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
'cluster_id' => 'store_dynamic.value_int',
'store_dynamic_id' => 'store_dynamic.id',
'store_id' => 'city_store.id'
[
'<=',
new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
- new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
],
[
'>',
new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
- new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
],
]
);
$invalid_sales = Sales::find()->alias('invalid_sales')->andWhere(['invalid_sales.operation' => Sales::OPERATION_RETURN])->select(['check_id' => 'invalid_sales.sales_check']);
$invalid_sales->andWhere([
'>=',
- 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
date('Y-m-d', strtotime($date_start))
]);
$invalid_sales->andWhere([
'<=',
- 'if (HOUR(invalid_sales.date) < 8, DATE_FORMAT(DATE_SUB(invalid_sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\'))',
+ 'DATE_FORMAT(invalid_sales.date, \'%Y-%m-%d\')',
date('Y-m-d', strtotime('+1 week', strtotime($date_start)))
]);
/* Конец проверки продажи */
$matrix_query->andWhere(['NOT IN', 'sales.id', $invalid_sales]);
$matrix_query->addGroupBy([
- 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
- 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
'store_dynamic.value_int',
'store_dynamic.id',
'city_store.id'
'AND',
[
'>=',
- 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
date('Y-m-d', strtotime($date_start))
],
[
'<=',
- 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
date('Y-m-d', strtotime($date_end))
]
]);
'city_store.id = matrix.store_id',
'store_dynamic.id = matrix.store_dynamic_id',
'dates_column.date = matrix.date',
- 'shift_types.shift_type = matrix.shift_type'
]
);
// endregion
//region Тип смены
- //Продажи
- $matrix_query->andWhere([
- 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)' => [1, 2]
- ]);
-
//Основной запрос
- $query->andWhere([
- 'shift_types.shift_type' => [1, 2]
- ]);
-
$query->addSelect([
'shift_type' => 'shift_types.shift_type'
]);
$sales_data_batch = $query->asArray()->batch(200);
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+
foreach ($sales_data_batch as $sales_data) {
foreach ($sales_data as $datum) {
}
if ($id != -1) {
- $rows = [];
foreach ($datum as $key => $item) {
if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type'])) {
- $rows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
}
}
+ }
+ }
+ }
- try {
- $transaction = \Yii::$app->db->beginTransaction();
- RnpData::deleteAll(['AND', ['index_id' => $id], ['IN', 'alias_id', [RnpAlias::MATRIX_NEW_SUMM_ID, RnpAlias::MATRIX_SEASON_SUMM_ID, RnpAlias::MATRIX_BASE_SUMM_ID]]]);
- Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rows)->execute();
- $transaction->commit();
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(['AND', ['index_id' => $rnpIndexId], ['alias_id' => [RnpAlias::MATRIX_NEW_SUMM_ID, RnpAlias::MATRIX_SEASON_SUMM_ID, RnpAlias::MATRIX_BASE_SUMM_ID]]]);
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+ $message .= "COUNT(RnpRows) = " . count($rnpDataRows);
- } catch (\Exception $exception) {
- $transaction->rollBack();
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
- $message .= "ЗАПИСЬ store_id = " . $datum['store_id'] . " ОТ: " . $datum['date'] . " АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
- $message .= $exception->getMessage() . "\n";
- }
- }
- }
+ $message .= "АТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
}
return $message;
$data['attribute']['count_sales_in_hour']['data'] = array_merge(array_slice($data['attribute']['count_sales_in_hour']['data'], 20, 4), array_slice($data['attribute']['count_sales_in_hour']['data'], 0, 8));
$data['attribute']['avg_count_sales_in_hour']['data'] = array_merge(array_slice($data['attribute']['avg_count_sales_in_hour']['data'], 20, 4), array_slice($data['attribute']['avg_count_sales_in_hour']['data'], 0, 8));
- } else {
+ } else if ($shift_type === 3) {
$data['attribute']['count_sales_in_hour']['data'] = array_merge(array_slice($data['attribute']['count_sales_in_hour']['data'], 8, 12), array_slice($data['attribute']['count_sales_in_hour']['data'], 20, 4), array_slice($data['attribute']['count_sales_in_hour']['data'], 0, 8));
$data['attribute']['avg_count_sales_in_hour']['data'] = array_merge(array_slice($data['attribute']['avg_count_sales_in_hour']['data'], 8, 12), array_slice($data['attribute']['avg_count_sales_in_hour']['data'], 20, 4), array_slice($data['attribute']['avg_count_sales_in_hour']['data'], 0, 8));
}
+
}
}
\ No newline at end of file
{
public static function tableName()
{
- return '{{%crm_menu}}';
+ return 'crm_menu';
}
/** Свёрнуто ли меню для данной страницы */
* @property int $created_by Кто создал, ID из Admin
* @property string $store_id GUID магазина
* @property int $price Ставка в рублях за час
+ * @property int $salary_shift Ставка в рублях за смену
* @property int $status 0 - в ожидании, 1 - подтверждено, 2 - отказано
* @property int $status_source -1 - получена ошибка в системе, 0 - не создано, 1 - создано в 1С
*/
[['guid', 'phone', 'created_at', 'shift_date', 'shift_type', 'datetime_start', 'datetime_end', 'created_by', 'store_id', 'price'], 'required'],
[['created_at', 'shift_date', 'datetime_start', 'datetime_end'], 'safe'],
[['shift_type', 'created_by', 'price', 'status', 'status_source'], 'integer'],
+ [['salary_shift'], 'in', 'range' => Timetable::getSalariesDay(), 'skipOnEmpty' => false],
[['guid', 'store_id'], 'string', 'max' => 36],
[['phone'], 'string', 'max' => 16],
[['first_name', 'last_name'], 'string', 'max' => 40],
'created_by' => 'Created By',
'store_id' => 'Store ID',
'price' => 'Price',
+ 'salary_shift' => 'Salary Shift',
'status' => 'Status',
'status_source' => 'status_source',
];
public static function tableName()
{
- return '{{%error_log}}';
+ return 'error_log';
}
}
\ No newline at end of file
public static function tableName()
{
- return '{{%holiday}}';
+ return 'holiday';
}
public function attributeLabels()
return false;
}
- public static function isImageFile($file)
+ public static function isImageFile($file, $extension = null)
{
$result = false;
if(!empty($file)) {
$ar_file_name = explode('/', $file->type);
- $type = ($ar_file_name[array_key_first($ar_file_name)]);
+ $type = array_shift($ar_file_name);
+
if ($type === 'image') {
- $result = true;
+ if (!empty($extension) && is_array($extension)) {
+ $extensionFile = array_shift($ar_file_name);
+ if (in_array($extensionFile, $extension)) {
+ $result = true;
+ }
+ } else {
+ $result = true;
+ }
}
}
[['description'], 'string'],
[['id'], 'integer'],
[['image_id', 'created_admin_id', 'updated_admin_id'], 'integer'],
- [['imageFile'], 'file', 'extensions' => 'png, jpg',],
+ [
+ [
+ 'imageFile'
+ ],
+ 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg', 'checkExtensionByMimeType' => false
+ ],
[['mediaFile'], 'safe'],
[['guid', 'date', 'created_at', 'updated_at'], 'string', 'max' => 100],
[['url_link_video'], 'string', 'max' => 255],
--- /dev/null
+<?php
+
+namespace yii_app\records;
+
+use Yii;
+
+/**
+ * This is the model class for table "notifiable_user".
+ *
+ * @property int $id
+ * @property string $phone Номер телефона
+ * @property string $type Тип сообщения
+ * @property string $data Дополнительная информация, например, в виде json-объекта
+ * @property int $status Вспомогательная переменная для маркировки записей перед удалением во время копирования
+ */
+class NotifiableUser extends \yii\db\ActiveRecord
+{
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return 'notifiable_user';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [
+ [['phone', 'type', 'data'], 'required'],
+ [['data'], 'string'],
+ [['status'], 'integer'],
+ [['phone'], 'string', 'max' => 16],
+ [['type'], 'string', 'max' => 255],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'ID',
+ 'phone' => 'Phone',
+ 'type' => 'Type',
+ 'data' => 'Data',
+ 'status' => 'Status',
+ ];
+ }
+}
* @property int $1c_send Отправлено в 1c
* @property string $check_id_arr
* @property string $data_md5
- *
- * @property Sales $sales
- * @property CityStore $storeObj
- * @property Admin $courierObj
- * @property Admin $floristObj
- * @property OrdersStatus $status
*/
class OrdersAmo extends \yii\db\ActiveRecord
{
'data_md5' => 'Data Md5',
];
}
-
- public function getSales()
- {
- return $this->hasMany(Sales::class, ['order_id' => 'id'])
- ->orderBy([
- 'date' => SORT_ASC
- ]);
- }
-
- public function getStoreObj()
- {
- return $this->hasOne(CityStore::class, ['id' => 'store_id']);
- }
-
- public function getFloristObj()
- {
- return $this->hasOne(Admin::class, ['id' => 'florist_id']);
- }
-
- public function getCourierObj()
- {
- return $this->hasOne(Admin::class, ['id' => 'courier_id']);
- }
-
- public function getStatus()
- {
- return $this->hasOne(OrdersStatus::class, ['status_id' => 'status_id']);
- }
}
*/
class SchedulerTaskLogSearch extends SchedulerTaskLog
{
+
+ public $status;
+
+ public $statusArray = [
+ -1 => 'Пропущено',
+ 0 => 'Все',
+ 1 => 'Выполнено'
+ ];
+
/**
* {@inheritdoc}
*/
public function rules()
{
return [
- [['id', 'task_num'], 'integer'],
+ [['id', 'task_num', 'status'], 'integer'],
[['date_start', 'date_stop', 'name', 'alias', 'description', 'result', 'error', 'log', 'date'], 'safe'],
+ ['status', 'default', 'value' => 0]
];
}
->andFilterWhere(['like', 'log', $this->log])
->andFilterWhere(['like', 'date', $this->date]);
+ if ($this->status == -1) {
+ $query->andWhere([
+ 'AND',
+ 'date_start IS NULL',
+ 'date_stop IS NULL',
+ ]);
+
+ } else if ($this->status == 1) {
+ $query->andWhere([
+ 'AND',
+ 'date_start IS NOT NULL',
+ 'date_stop IS NOT NULL'
+ ]);
+
+ }
+
return $dataProvider;
}
}
public static function tableName()
{
- return '{{%timetable_shift}}';
+ return 'timetable_shift';
}
public function rules()
* @property string $division_date дата деления
* @property int $division_hours
* @property string $delivery_date_fact Дата прихода товара на склад
- * @ property int $price_logistic
+ * @property int $price_logistic
* @property string $comments
* @property int $admin_id
* @property string $date_add
* @property string $status_logi
* @property string $date_update Дата и врепмя обновления информации в таблице храннеия data
* @property string $update_html HTML блок расчета по формулам
- * @property int city_id
*/
class StoreOrders extends \yii\db\ActiveRecord
{
- public $providers;
-
/**
* {@inheritdoc}
*/
public function rules()
{
return [
- [['name', 'parent_id', 'date_start', 'date_end', 'delivery_date', 'division_date', 'division_hours', 'delivery_date_fact', /*'price_logistic',*/ 'comments', 'admin_id', 'date_add', 'providers_arr', 'status_logi', 'date_update', 'update_html'], 'required'],
- [['parent_id', 'division_hours', /*'price_logistic',*/ 'admin_id', 'status'], 'integer'],
- [['date_start', 'date_end', 'delivery_date', 'division_date', 'delivery_date_fact', 'date_add', 'date_update', 'city_id', 'providers'], 'safe'],
+ [['name', 'parent_id', 'date_start', 'date_end', 'delivery_date', 'division_date', 'division_hours', 'delivery_date_fact', 'price_logistic', 'comments', 'admin_id', 'date_add', 'providers_arr', 'status_logi', 'date_update', 'update_html'], 'required'],
+ [['parent_id', 'division_hours', 'price_logistic', 'admin_id', 'status'], 'integer'],
+ [['date_start', 'date_end', 'delivery_date', 'division_date', 'delivery_date_fact', 'date_add', 'date_update'], 'safe'],
[['comments', 'status_logi', 'update_html'], 'string'],
[['name', 'providers_arr'], 'string', 'max' => 255],
];
'update_html' => 'Update Html',
];
}
-
- public function getCity() {
- return $this->hasOne(CityStore::class, ['id' => 'city_id']);
- }
-
- public function getProviders() {
- return explode(',', $this->providers_arr);
- }
-
- public function setProviders() {
- $this->providers_arr = implode(',', $this->providers);
- }
}
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
+use yii\helpers\ArrayHelper;
/**
* Табель сотрудников
* @property string $time_end
* @property float $work_time
* @ property float $price_hour
+ * @property int $salary_shift
* @property int $slot_type_id
* @property string $comment
* @property int $date_add
public static function tableName()
{
- return '{{%timetable}}';
+ return 'timetable';
+ }
+
+ public static function getSalariesDay() {
+ return [900, 1200, 1500, 1700, 1800, 2000, 2500, 3500, 5000];
+ }
+
+ public function getSalaryShift($timetableId) : array
+ {
+
+ $salesByAdminPrepared = $this->salesService->getSalesByAdmin($adminGuid, $dateFrom, $dateTo, $isAdministrator);
+
+ $timeTable = [];
+ if (in_array($adminGuid, $this->adminAdministratorGuids)) {
+ if (!empty($this->timeTable)) {
+ $timeTable = $this->timeTable;
+ }
+ }
+
+ $result = $this->salesService->getSaleSumByDateArray($salesByAdminPrepared, $timeTable);
+
+ return $result;
+
+ }
+
+ public static function getAllowEditShift($slotDate, $days = 5) : bool
+ {
+ return (
+ date('Y-m-d',strtotime($slotDate)) >= date('Y-m-d')
+ ||
+ date('n',strtotime($slotDate)) == date('n')
+ ||
+ (
+ date('n',strtotime($slotDate)) == date('n', strtotime("-1 month"))
+ &&
+ date('j') <= $days
+ )
+ );
+ }
+
+ public static function getCountDaysAllowEditShift($groupId) : int
+ {
+ $numDay = 5;
+
+ $accessArray = [
+ 1, // Директор
+ 7, // Кустовые директора
+ 8, // Руководитель HR
+ 9, // Главный бухгалтер
+ 20, // Администратор платформы (HR)
+ 51, // Операционный директор
+ ];
+
+ if (in_array($groupId, $accessArray)) {
+ $numDay = 13;
+ }
+
+ return $numDay;
}
public function getDateTimeStart(): \DateTime
'comment' => 'Комментарий',
'date_add' => 'Дата добавления',
'status' => 'Статус',
+ 'salary_shift' => 'Оклад в смену',
'datetime_start' => 'Дата и время начала смены',
'datetime_end' => 'Дата и время окончания смены',
];
[['tabel'], 'integer', 'skipOnEmpty' => false],
[['id', 'shift_id', 'store_id'], 'integer'],
// [['price_hour'], 'number', 'safe'],
+ [['salary_shift'], 'in', 'range' => self::getSalariesDay(), 'skipOnEmpty' => true],
[['date'], 'date', 'format' => 'php:Y-m-d'],
[['shift_id'], 'in', 'range' => array_keys(Shift::all()), 'skipOnEmpty' => false],
[['store_id'], 'exist', 'targetClass' => CityStore::class, 'targetAttribute' => 'id', 'skipOnEmpty' => false],
{
return $this->hasOne(Shift::class, ['id' => 'shift_id']);
}
+
+ public static function getAdminsByDates($dateFrom, $dateTo, $employeeSelectStoreId)
+ {
+ $slotTypeId = [
+ Timetable::TIMESLOT_WORK, // "работа"
+ ];
+
+ $timeTableDateList = Timetable::find()
+ ->with('admin')
+ ->with('shift')
+ ->andWhere(['>=', 'date', $dateFrom])
+ ->andWhere(['<=', 'date', $dateTo])
+ ->andWhere(['d_id' => Admin::ADMIN_WORK_GROUP_IDS])
+ ->andWhere(['slot_type_id' => $slotTypeId])
+ ->andWhere(['store_id' => $employeeSelectStoreId])
+ ->andWhere(['tabel' => 0])
+ ->asArray()
+ ->all();
+
+
+ $dateStores = [];
+
+ foreach ($timeTableDateList as $item) {
+ $dateStores[] = [
+ 'date' => $item['date'],
+ 'store_id' => $item['store_id'],
+ ];
+ }
+
+ foreach ($timeTableDateList as $item) {
+ $keyRow = $item['date'] . '_' . $item['store_id'];
+ $timeTableDateAdminList[$keyRow] = Timetable::find()
+ ->with('admin')
+ ->with('shift')
+ ->andWhere(['date' => $item['date']])
+ ->andWhere(['store_id' => $item['store_id']])
+ ->andWhere(['d_id' => Admin::ADMIN_WORK_GROUP_IDS])
+ ->andWhere(['slot_type_id' => $slotTypeId])
+ ->andWhere(['tabel' => 0])
+ ->asArray()
+ ->all();
+ }
+
+ $adminsPrepared = [];
+ $adminsByDateGuids = [];
+ $adminsByDate = [];
+ if (!empty($timeTableDateAdminList)) {
+ foreach ($timeTableDateAdminList as $keyRow => $itemRows) {
+ $dateKeyPreparedRow = explode('_', $keyRow);
+ $dateKeyRow = ArrayHelper::getValue($dateKeyPreparedRow, array_key_first($dateKeyPreparedRow));
+ foreach ($itemRows as $itemRow) {
+ $arrayRow = [
+ 'admin_id' => $itemRow['admin']['id'],
+ 'admin_guid' => $itemRow['admin']['guid'],
+ 'admin_name' => $itemRow['admin']['name'],
+ ];
+ $adminsPrepared[$keyRow][] = $arrayRow;
+ $adminsByDate[$dateKeyRow][] = $arrayRow;
+ $adminsByDateGuids[$dateKeyRow][] = $itemRow['admin']['guid'];
+ }
+ }
+ }
+
+ return [
+ 'dateGuids' => $adminsByDateGuids,
+ 'dateAdmins' => $adminsByDate,
+ ];
+ }
}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\records\metrics;
+
+use yii\db\Expression;
+use yii_app\records\AdminPayrollDays;
+use yii_app\records\metrics\Metrics;
+
+class FotMetrics extends Metrics
+{
+
+ protected bool $calculateDay = false;
+
+ protected array $alias = [
+ 'sales_sum_admin',
+ 'day_payroll',
+ 'admin_count'
+ ];
+
+ protected function getQueryDataDay(): bool
+ {
+ return false;
+ }
+
+ protected function getQueryDataShifts(): \yii\db\ActiveQuery
+ {
+ return AdminPayrollDays::find()
+ ->select([
+ 'date' => 'admin_payroll_days.date',
+ 'shift_type' => 'admin_payroll_days.smena_type',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id',
+ 'day_payroll' => 'SUM(admin_payroll_days.day_payroll)',
+ 'sales_sum_admin' => 'SUM(admin_payroll_days.sales_sum)',
+ 'admin_count' => 'COUNT(admin_payroll_days.admin_id)',
+ ])
+ ->innerJoin('city_store', 'admin_payroll_days.store_id = city_store.id')
+ ->innerJoin('store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = city_store.id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(admin_payroll_days.date, \'%Y-%m-%d\')')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(admin_payroll_days.date, \'%Y-%m-%d\')')
+ ],
+ ])
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $this->cluster,
+ 'city_store.id' => $this->store,
+ ])
+ ->andWhere([
+ 'AND',
+ ['admin_payroll_days.smena_type' => [1, 2]],
+ [
+ '>=',
+ 'DATE_FORMAT(admin_payroll_days.date, \'%Y-%m-%d\')',
+ $this->dateStart
+ ],
+ [
+ '<=',
+ 'DATE_FORMAT(admin_payroll_days.date, \'%Y-%m-%d\')',
+ $this->dateEnd
+ ],
+ ])
+ ->addGroupBy([
+ 'admin_payroll_days.date',
+ 'admin_payroll_days.smena_type',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\records\metrics;
+
+use yii\helpers\ArrayHelper;
+use yii_app\records\metrics\Metrics;
+use yii_app\records\Products1c;
+
+class MatrixMetrics extends SalesMetrics
+{
+
+ private array $matrixGroupSearchGuidDictionary;
+ private array $matrixGroupSearchGuid;
+
+ private array $guids;
+
+ protected array $alias = [
+ 'matrix_base_summ',
+ 'matrix_season_summ',
+ 'matrix_new_summ'
+ ];
+
+ protected array $listSelectedQuery = [
+ 'matrix_base_summ' => 'SUM(IF (:baseGuids LIKE CONCAT("%", products_1c.id, "%"), sales_products.summ, 0))', // Базовая
+ 'matrix_season_summ' => 'SUM(IF (:seasonGuids LIKE CONCAT("%", products_1c.id, "%"), sales_products.summ, 0))', // Сезонная
+ 'matrix_new_summ' => 'SUM(IF (:newGuids LIKE CONCAT("%", products_1c.id, "%"), sales_products.summ, 0))' // Новая
+ ];
+
+ protected function loadDefaultValues()
+ {
+ $this->getMatrixSearchGroupId();
+ $this->guids = $this->getGuidsArray();
+ }
+
+ protected function getQueryDataDay(): \yii\db\ActiveQuery
+ {
+ return parent::getQueryDataDay()
+ ->innerJoin('sales_products', 'sales.id = sales_products.check_id')
+ ->innerJoin('products_1c', 'sales_products.product_id = products_1c.id')
+ ->params([
+ ':baseGuids' => isset($this->guids[$this->matrixGroupSearchGuidDictionary['Сезонная матрица']]) ? implode("/", $this->guids[$this->matrixGroupSearchGuidDictionary['Сезонная матрица']]) : '',
+ ':seasonGuids' => isset($this->guids[$this->matrixGroupSearchGuidDictionary['Матрица базовая']]) ? implode("/", $this->guids[$this->matrixGroupSearchGuidDictionary['Матрица базовая']]) : '',
+ ':newGuids' => isset($this->guids[$this->matrixGroupSearchGuidDictionary['Новая матрица']]) ? implode("/", $this->guids[$this->matrixGroupSearchGuidDictionary['Новая матрица']]) : '',
+ ]);
+
+ }
+
+ protected function getQueryDataShifts(): \yii\db\ActiveQuery
+ {
+ return parent::getQueryDataShifts()
+ ->innerJoin('sales_products', 'sales.id = sales_products.check_id')
+ ->innerJoin('products_1c', 'sales_products.product_id = products_1c.id')
+ ->params([
+ ':baseGuids' => isset($this->guids[$this->matrixGroupSearchGuidDictionary['Сезонная матрица']]) ? implode("/", $this->guids[$this->matrixGroupSearchGuidDictionary['Сезонная матрица']]) : '',
+ ':seasonGuids' => isset($this->guids[$this->matrixGroupSearchGuidDictionary['Матрица базовая']]) ? implode("/", $this->guids[$this->matrixGroupSearchGuidDictionary['Матрица базовая']]) : '',
+ ':newGuids' => isset($this->guids[$this->matrixGroupSearchGuidDictionary['Новая матрица']]) ? implode("/", $this->guids[$this->matrixGroupSearchGuidDictionary['Новая матрица']]) : '',
+ ]);
+ }
+
+ private function getArrayIndexParentId($array): array
+ {
+ $answer = [];
+
+ foreach ($array as $item) {
+ $answer[$item['parent_id']][] = $item;
+ }
+
+ return $answer;
+ }
+
+ private function getTreeMatrixGroup($array, $parent_id = null, $treeGuid = null): array
+ {
+ $tree = [];
+
+ if ($parent_id === null) {
+ foreach ($array[""] as $item) {
+ if ($item['name'] === 'МАТРИЦА') {
+ $tree[$item['id']]['name'] = $item['name'];
+ $tree[$item['id']]['treeGuid'] = '/' . $item['id'] . '/';
+ $tree[$item['id']]['group'] = $this->getTreeMatrixGroup($array, $item['id'], $tree[$item['id']]['treeGuid']);
+ $tree[$item['id']]['items'] = [];
+ }
+ }
+ } else {
+ if (isset($array[$parent_id])) {
+ foreach ($array[$parent_id] as $item) {
+ if ($item['tip'] === 'products_group') {
+ $tree[$item['id']]['name'] = $item['name'];
+ $tree[$item['id']]['id'] = $item['id'];
+ $tree[$item['id']]['treeGuid'] = $treeGuid . $item['id'] . '/';
+ $tree[$item['id']]['group'] = $this->getTreeMatrixGroup($array, $item['id'], $tree[$item['id']]['treeGuid']);
+
+ if (isset($array[$item['id']])) {
+ foreach ($array[$item['id']] as $product) {
+ if ($product['tip'] === 'products') {
+ $tree[$item['id']]['items'][$product['id']]['name'] = $product['name'];
+ $tree[$item['id']]['items'][$product['id']]['id'] = $product['id'];
+ $tree[$item['id']]['items'][$product['id']]['treeGuid'] = $treeGuid . $item['id'] . '/' . $product['id'] . '/';
+ }
+ }
+
+ } else {
+ $tree[$item['id']]['items'] = [];
+
+ }
+ }
+ }
+ }
+ }
+
+ return $tree;
+ }
+
+ private function getTreeMatrix(): array
+ {
+ $products = Products1c::find()
+ ->select([
+ 'id',
+ 'parent_id',
+ 'name',
+ 'tip'
+ ])
+ ->asArray()
+ ->all();
+
+ $productsTree = $this->getArrayIndexParentId($products);
+
+ return $this->getTreeMatrixGroup($productsTree);
+ }
+
+
+ private function getGuidProductsInGroup($tree, &$array, $guids, $guid = null): void
+ {
+ foreach ($tree['group'] as $item) {
+ if (in_array($item['id'], $guids)) {
+ $this->getGuidProductsInGroup($tree['group'][$item['id']], $array, $guids, $item['id']);
+ } else if (!in_array($item['id'], $guids) && $guid != null) {
+ $this->getGuidProductsInGroup($tree['group'][$item['id']], $array, $guids, $guid);
+ }
+ }
+
+ if ($guid != null) {
+ foreach ($tree['items'] as $item) {
+ $array[$guid][] = $item['id'];
+ }
+ }
+
+
+ }
+
+ private function getGuidsArray()
+ {
+ $tree = $this->getTreeMatrix();
+
+ $parentId = array_key_first($tree);
+ $array = [];
+
+ $this->getGuidProductsInGroup($tree[$parentId], $array, $this->matrixGroupSearchGuid);
+
+ return $array;
+ }
+
+ private function getMatrixSearchGroupId()
+ {
+ $matrix_season_guid = Products1c::find()->where(['LIKE', 'name', 'Сезонная матрица'])->select(['id'])->column()[0] ?? '';
+ $matrix_base_guid = Products1c::find()->where(['LIKE', 'name', 'Матрица базовая'])->select(['id'])->column()[0] ?? '';
+ $matrix_new_guid = Products1c::find()->where(['LIKE', 'name', 'Новая матрица'])->select(['id'])->column()[0] ?? '';
+
+ $this->matrixGroupSearchGuid = [
+ $matrix_season_guid,
+ $matrix_base_guid,
+ $matrix_new_guid
+ ];
+
+ $this->matrixGroupSearchGuidDictionary = [
+ 'Сезонная матрица' => $matrix_season_guid,
+ 'Матрица базовая' => $matrix_base_guid,
+ 'Новая матрица' => $matrix_new_guid
+ ];
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\records\metrics;
+
+use Yii;
+use yii\base\Model;
+use yii\db\Exception;
+use yii\db\Expression;
+use yii\db\Query;
+use yii\helpers\ArrayHelper;
+use yii_app\records\RnpAlias;
+use yii_app\records\RnpData;
+use yii_app\records\RnpIndex;
+use yii_app\records\StoreDynamic;
+
+abstract class Metrics extends Model
+{
+ public function rules()
+ {
+ return [
+ [['cluster', 'store'], 'safe'],
+ [['dateStart', 'dateEnd'], 'date', 'format' => 'php:Y-m-d'],
+ ['dateStart', 'compare', 'compareAttribute' => 'dateEnd', 'operator' => '<='],
+ ];
+ }
+
+ public $dateStart;
+
+ public $dateEnd;
+
+ public $cluster;
+
+ public $store;
+
+ protected array $alias = [];
+
+ protected array $selectQuery = [];
+
+ protected array $listOfExceptionsByShiftType = [
+ 1 => [
+
+ ],
+ 2 => [
+
+ ],
+ 4 => [
+
+ ],
+ ];
+
+ protected bool $calculateShifts = true;
+
+ protected bool $calculateDay = true;
+
+ private bool $calculateIndex = false;
+
+ protected function loadDefaultValues()
+ {
+
+ }
+
+ protected function loadSelectQuery()
+ {
+ $temp = [];
+
+ foreach ($this->alias as $alias) {
+ if ($this->calculateShifts && $this->calculateDay) {
+ $temp[$alias] = "IF (shift_types.shift_type != 4, data_shifts.$alias, data_day.$alias)";
+ } else if ($this->calculateShifts) {
+ $temp[$alias] = "data_shifts.$alias";
+ } else if ($this->calculateDay) {
+ $temp[$alias] = "data_day.$alias";
+ }
+ }
+
+ $this->selectQuery = $temp;
+ }
+
+ protected abstract function getQueryDataDay();
+
+ protected abstract function getQueryDataShifts();
+
+ final public function insertData(): string
+ {
+ if (!$this->validate()) {
+ return 'Неккоректные свойства объекта';
+ }
+
+ $message = "";
+
+ $start = microtime(true);
+
+ $query = $this->getQueryDataCollection();
+ $dataBatch = $query->asArray()->batch(1000);
+
+ $this->calculateShifts = false;
+ $this->calculateDay = false;
+ $this->calculateIndex = true;
+
+ $indexQuery = $this->getQueryDataCollection();
+
+ $rnpOldIndex = RnpIndex::find()
+ ->where(['BETWEEN', 'date', $this->dateStart, $this->dateEnd])
+ ->select([
+ 'index' => 'CONCAT(rnp_index.cluster_id, rnp_index.store_id, rnp_index.date, rnp_index.shift_type)'
+ ])
+ ->indexBy('index')
+ ->asArray()
+ ->all();
+
+ $rnpNewIndex = $indexQuery
+ ->addSelect([
+ 'index' => 'CONCAT(store_dynamic.value_int, city_store.id, dates_column.date, shift_types.shift_type)',
+ ])
+ ->indexBy('index')
+ ->asArray()
+ ->all();
+
+
+ $rnpIndexData = array_diff_key($rnpNewIndex, $rnpOldIndex);
+
+ $timeSearch = sprintf('%.6f sec.', microtime(true) - $start);
+
+ $start = microtime(true);
+
+ if (count($rnpIndexData) > 0) {
+ $rnpIndexRows = [];
+ foreach ($rnpIndexData as $index) {
+ $rnpIndexRows[] = [$index['cluster_id'], $index['store_id'], $index['shift_type'], $index['date']];
+ }
+
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ Yii::$app->db->createCommand()->batchInsert('rnp_index', ['cluster_id', 'store_id', 'shift_type', 'date'], $rnpIndexRows)->execute();
+ $transaction->commit();
+
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
+
+ $message .= "\nИНДЕКСЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
+ }
+ }
+
+
+ $timeInsertIndex = sprintf('%.6f sec.', microtime(true) - $start);
+
+ $aliases = RnpAlias::find()->select(['id', 'alias'])->asArray()->all();
+
+ $aliases = ArrayHelper::map($aliases, 'alias', 'id');
+
+ $rnp_old_index = RnpIndex::find()->where(['BETWEEN', 'date', $this->dateStart, $this->dateEnd])->select([
+ 'id',
+ 'cluster_id',
+ 'store_id',
+ 'shift_type',
+ 'date',
+ ])->asArray()->all();
+
+ $ids = [];
+ foreach ($rnp_old_index as $index) {
+ $ids[$index['cluster_id'] . $index['store_id'] . $index['shift_type'] . $index['date']] = $index['id'];
+ }
+
+ $start = microtime(true);
+
+ $rnpDataRows = [];
+ $rnpIndexId = [];
+ foreach ($dataBatch as $data) {
+ foreach ($data as $datum) {
+ $id = -1;
+
+ if (array_key_exists($datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date'], $ids)) {
+ $id = $ids[$datum['cluster_id'] . $datum['store_id'] . $datum['shift_type'] . $datum['date']];
+ }
+
+ if ($id != -1) {
+ foreach ($datum as $key => $item) {
+ if (!in_array($key, ['cluster_id', 'store_id', 'date', 'shift_type', 'store_name']) && !in_array($key, $this->listOfExceptionsByShiftType[$datum['shift_type']])) {
+ $rnpDataRows[] = [$id, $aliases[$key], $item ? round($item, 2) : 0];
+ $rnpIndexId[] = $id;
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ $transaction = \Yii::$app->db->beginTransaction();
+ RnpData::deleteAll(
+ [
+ 'AND',
+ ['index_id' => $rnpIndexId],
+ [
+ 'IN',
+ 'alias_id',
+ RnpAlias::find()
+ ->select('id')
+ ->where(['alias' => $this->alias])
+ ]
+ ]
+ );
+ Yii::$app->db->createCommand()->batchInsert('rnp_data', ['index_id', 'alias_id', 'value'], $rnpDataRows)->execute();
+ $transaction->commit();
+
+ } catch (\Exception $exception) {
+ $transaction->rollBack();
+
+ $message .= "\nАТРИБУТЫ НЕ УДАЛОСЬ СОХРАНИТЬ -\n";
+ $message .= $exception->getMessage() . "\n";
+ }
+
+ $timeInsertData = sprintf('%.6f sec.', microtime(true) - $start);
+
+ $message .= "\n|Время поиска: $timeSearch|Время записи индексов: $timeInsertIndex|Время записи данных: $timeInsertData|\n";
+
+ return $message;
+ }
+
+ final public function getQueryDataCollection(): \yii\db\ActiveQuery
+ {
+ $this->loadDefaultValues();
+
+ $this->loadSelectQuery();
+
+ $datesQuery = (new Query())->from('(
+ SELECT :date_end - INTERVAL (units.mul + (10 * tens.mul) + (100 * hundreds.mul) + (1000 * thousands.mul)) DAY AS date
+ FROM (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS units
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS tens
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS hundreds
+ CROSS JOIN (SELECT 0 AS mul UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS thousands
+ ) a'
+ )
+ ->params([':date_end' => $this->dateEnd])
+ ->andWhere([
+ 'BETWEEN', 'a.date', $this->dateStart, $this->dateEnd
+ ])
+ ->orderBy(['date' => SORT_ASC]);
+
+ $shiftsQuerySelect = '';
+
+ if ($this->calculateShifts && $this->calculateDay || $this->calculateIndex) {
+ $shiftsQuerySelect = '(
+ SELECT 1 AS shift_type UNION ALL SELECT 2 UNION ALL SELECT 4
+ ) shift_types';
+
+ } else if ($this->calculateShifts) {
+ $shiftsQuerySelect = '(
+ SELECT 1 AS shift_type UNION ALL SELECT 2
+ ) shift_types';
+
+ } else if ($this->calculateDay) {
+ $shiftsQuerySelect = '(
+ SELECT 4 AS shift_type
+ ) shift_types';
+
+ }
+
+ $shiftQuery = (new Query())->from(
+ $shiftsQuerySelect
+ )
+ ->select(['shift_type' => 'shift_types.shift_type']);
+
+ $query = StoreDynamic::find()
+ ->select(array_merge(
+ [
+ 'date' => 'dates_column.date',
+ 'shift_type' => 'shift_types.shift_type',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_id' => 'city_store.id',
+ ],
+ $this->calculateIndex ? [] : $this->selectQuery
+ ))
+ ->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1')
+ ->leftJoin(
+ ['dates_column' => $datesQuery],
+ [
+ 'BETWEEN',
+ 'dates_column.date',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ ]
+ )
+ ->leftJoin(['shift_types' => $shiftQuery], '1=1');
+
+
+ if ($this->calculateShifts) {
+ $query->leftJoin(
+ ['data_shifts' => $this->getQueryDataShifts()],
+ [
+ 'AND',
+ 'city_store.id = data_shifts.store_id',
+ 'store_dynamic.id = data_shifts.store_dynamic_id',
+ 'dates_column.date = data_shifts.date',
+ 'shift_types.shift_type = data_shifts.shift_type'
+ ]
+ );
+ }
+
+ if ($this->calculateDay) {
+ $query->leftJoin(
+ ['data_day' => $this->getQueryDataDay()],
+ [
+ 'AND',
+ 'city_store.id = data_day.store_id',
+ 'store_dynamic.id = data_day.store_dynamic_id',
+ 'dates_column.date = data_day.date',
+ 'shift_types.shift_type = data_day.shift_type'
+ ]
+ );
+ }
+
+ $query->andWhere([
+ 'AND',
+ ['>=', 'dates_column.date', $this->dateStart],
+ ['<=', 'dates_column.date', $this->dateEnd]
+ ])
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $this->cluster,
+ 'city_store.id' => $this->store,
+ ]);
+
+ return $query;
+ }
+
+ final protected function getDataArray($clusterId, $storeId, $shift): array
+ {
+ return RnpData::find()
+ ->select([
+ 'date' => 'rnp_index.date',
+ 'shift' => 'rnp_index.shift_type',
+ 'alias' => 'rnp_alias.alias',
+ 'value' => 'rnp_data.value'
+ ])
+ ->innerJoin('rnp_alias', 'rnp_data.alias_id = rnp_alias.id')
+ ->innerJoin('rnp_index', 'rnp_data.index_id = rnp_index.id')
+ ->andWhere([
+ 'AND',
+ [
+ 'rnp_alias.alias' => $this->alias
+ ],
+ [
+ '>=',
+ 'rnp_index.date',
+ $this->dateStart
+ ],
+ [
+ '<=',
+ 'rnp_index.date',
+ $this->dateEnd
+ ]
+ ])
+ ->andFilterWhere([
+ 'rnp_index.cluster_id' => $clusterId,
+ 'rnp_index.store_id' => $storeId,
+ 'rnp_index.shift_type' => $shift
+ ])
+ ->orderBy([
+ 'rnp_index.date' => SORT_ASC,
+ 'rnp_index.shift_type' => SORT_ASC,
+ 'rnp_alias.id' => SORT_ASC
+ ])
+ ->asArray()
+ ->all();
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\records\metrics;
+
+use Exception;
+use yii\db\Expression;
+use yii_app\records\RnpData;
+use yii_app\records\Sales;
+
+class SalesMetrics extends Metrics
+{
+ protected array $alias = [
+ 'sales_sum',
+ 'count_sales',
+ 'count_sales_in_0_hour',
+ 'count_sales_in_1_hour',
+ 'count_sales_in_2_hour',
+ 'count_sales_in_3_hour',
+ 'count_sales_in_4_hour',
+ 'count_sales_in_5_hour',
+ 'count_sales_in_6_hour',
+ 'count_sales_in_7_hour',
+ 'count_sales_in_8_hour',
+ 'count_sales_in_9_hour',
+ 'count_sales_in_10_hour',
+ 'count_sales_in_11_hour',
+ 'count_sales_in_12_hour',
+ 'count_sales_in_13_hour',
+ 'count_sales_in_14_hour',
+ 'count_sales_in_15_hour',
+ 'count_sales_in_16_hour',
+ 'count_sales_in_17_hour',
+ 'count_sales_in_18_hour',
+ 'count_sales_in_19_hour',
+ 'count_sales_in_20_hour',
+ 'count_sales_in_21_hour',
+ 'count_sales_in_22_hour',
+ 'count_sales_in_23_hour',
+ ];
+
+ protected array $listOfExceptionsByShiftType = [
+ 1 => [
+ 'count_sales_in_0_hour',
+ 'count_sales_in_1_hour',
+ 'count_sales_in_2_hour',
+ 'count_sales_in_3_hour',
+ 'count_sales_in_4_hour',
+ 'count_sales_in_5_hour',
+ 'count_sales_in_6_hour',
+ 'count_sales_in_7_hour',
+ 'count_sales_in_20_hour',
+ 'count_sales_in_21_hour',
+ 'count_sales_in_22_hour',
+ 'count_sales_in_23_hour',
+ ],
+ 2 => [
+ 'count_sales_in_8_hour',
+ 'count_sales_in_9_hour',
+ 'count_sales_in_10_hour',
+ 'count_sales_in_11_hour',
+ 'count_sales_in_12_hour',
+ 'count_sales_in_13_hour',
+ 'count_sales_in_14_hour',
+ 'count_sales_in_15_hour',
+ 'count_sales_in_16_hour',
+ 'count_sales_in_17_hour',
+ 'count_sales_in_18_hour',
+ 'count_sales_in_19_hour',
+ ],
+ 4 => [
+
+ ],
+ ];
+
+ protected array $listSelectedQuery = [
+ 'sales_sum' => 'SUM(IF(sales.sales_check = \'\', sales.summ, 0)) - SUM(IF(sales.sales_check != \'\', sales.summ, 0))',
+ //'sales_sum' => 'SUM(sales.summ)',
+ 'count_sales' => 'COUNT(sales.id)',
+ 'count_sales_in_0_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 0, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 0, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_1_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 1, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 1, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_2_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 2, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 2, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_3_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 3, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 3, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_4_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 4, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 4, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_5_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 5, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 5, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_6_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 6, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 6, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_7_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 7, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 7, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_8_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 8, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 8, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_9_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 9, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 9, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_10_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 10, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 10, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_11_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 11, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 11, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_12_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 12, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 12, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_13_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 13, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 13, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_14_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 14, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 14, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_15_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 15, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 15, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_16_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 16, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 16, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_17_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 17, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 17, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_18_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 18, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 18, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_19_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 19, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 19, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_20_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 20, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 20, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_21_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 21, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 21, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_22_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 22, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 22, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ 'count_sales_in_23_hour' => 'SUM(if (TIME_FORMAT(sales.date, \'%H:%i:%s\') >= TIME_FORMAT(CONCAT_WS(\':\', 23, 0, 0), \'%H:%i:%s\') AND TIME_FORMAT(sales.date, \'%H:%i:%s\') <= TIME_FORMAT(CONCAT_WS(\':\', 23, 59, 59), \'%H:%i:%s\'), 1, 0))',
+ ];
+
+ protected function getQueryDataDay(): \yii\db\ActiveQuery
+ {
+ return Sales::find()
+ ->select(array_merge(
+ [
+ 'date' => 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ 'store_id' => 'city_store.id',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'shift_type' => '(SELECT 4 AS shift_type)',
+ ],
+ $this->listSelectedQuery
+ ))
+ ->innerJoin('city_store', 'sales.store_id = city_store.id')
+ ->innerJoin('store_dynamic',
+ [
+ 'AND',
+ [
+ '=',
+ new Expression('store_dynamic.store_id'),
+ new Expression('city_store.id')
+ ],
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(sales.date, \'%Y-%m-%d\')')
+ ]
+ ]
+ )
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $this->cluster,
+ 'city_store.id' => $this->store,
+ ])
+ ->andWhere([
+ 'AND',
+ [
+ '>=',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ $this->dateStart
+ ],
+ [
+ '<=',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ $this->dateEnd
+ ],
+ /*[
+ 'NOT IN',
+ 'sales.id',
+ Sales::find()
+ ->select([
+ 'id' => 'sales.sales_check'
+ ])
+ ->andWhere([
+ 'AND',
+ [
+ '>=',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ $this->dateStart
+ ],
+ [
+ '<',
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ date('Y-m-d', strtotime('+1 week', strtotime($this->dateEnd)))
+ ],
+ ])
+ ],*/
+ ['sales.operation' => 'Продажа'],
+ ['sales.order_id' => '']
+ ])
+ ->groupBy([
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')',
+ 'city_store.id',
+ 'store_dynamic.id'
+ ])
+ ->orderBy([
+ 'DATE_FORMAT(sales.date, \'%Y-%m-%d\')' => SORT_ASC,
+ 'city_store.id' => SORT_ASC
+ ]);
+ }
+
+ protected function getQueryDataShifts(): \yii\db\ActiveQuery
+ {
+ return Sales::find()
+ ->select(array_merge(
+ [
+ 'date' => 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'store_id' => 'city_store.id',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'shift_type' => 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ ],
+ $this->listSelectedQuery
+ ))
+ ->innerJoin('city_store', 'sales.store_id = city_store.id')
+ ->innerJoin('store_dynamic',
+ [
+ 'AND',
+ [
+ '=',
+ new Expression('store_dynamic.store_id'),
+ new Expression('city_store.id')
+ ],
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))')
+ ]
+ ]
+ )
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $this->cluster,
+ 'city_store.id' => $this->store,
+ ])
+ ->andWhere([
+ 'AND',
+ [
+ '>=',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ $this->dateStart
+ ],
+ [
+ '<=',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ $this->dateEnd
+ ],
+ /*[
+ 'NOT IN',
+ 'sales.id',
+ Sales::find()
+ ->select([
+ 'id' => 'sales.sales_check'
+ ])
+ ->andWhere([
+ 'AND',
+ [
+ '>=',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ $this->dateStart
+ ],
+ [
+ '<',
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ date('Y-m-d', strtotime('+1 week', strtotime($this->dateEnd)))
+ ],
+ ])
+ ],*/
+ ['sales.operation' => 'Продажа'],
+ ['sales.order_id' => '']
+ ])
+ ->groupBy([
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))',
+ 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)',
+ 'city_store.id',
+ 'store_dynamic.id'
+ ])
+ ->orderBy([
+ 'if (HOUR(sales.date) < 8, DATE_FORMAT(DATE_SUB(sales.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(sales.date, \'%Y-%m-%d\'))' => SORT_ASC,
+ 'if(HOUR(sales.date) >= 8 && HOUR(sales.date) < 20, 1, 2)' => SORT_ASC,
+ 'city_store.id' => SORT_ASC
+ ]);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\records\metrics;
+
+use yii\db\Expression;
+use yii_app\records\metrics\Metrics;
+use yii_app\records\Sales;
+use yii_app\records\UsersBonus;
+
+class UserBonusMetrics extends SalesMetrics
+{
+ protected array $alias = [
+ 'count_users',
+ 'first_minus_user_bonus',
+ 'second_minus_user_bonus'
+ ];
+
+ protected array $listSelectedQuery = [
+ 'count_users' => 'SUM( IF (sales.phone IS NOT NULL AND sales.phone != \'\', 1, 0))',
+ 'first_minus_user_bonus' => 'SUM( IF (users.first_minus_balance = sub_users_bonus.date, 1, 0))',
+ 'second_minus_user_bonus' => 'SUM( IF (users.first_minus_balance < sub_users_bonus.date, 1, 0))',
+ ];
+
+ protected function getQueryDataDay(): \yii\db\ActiveQuery
+ {
+ $subUsersBonusQuery = UsersBonus::find()
+ ->select([
+ 'users_bonus.user_id',
+ 'users_bonus.check_id',
+ 'users_bonus.date'
+ ])
+ ->andWhere([
+ 'AND',
+ ['>=', 'DATE_FORMAT(users_bonus.date, \'%Y-%m-%d\')', $this->dateStart],
+ ['<=', 'DATE_FORMAT(users_bonus.date, \'%Y-%m-%d\')', $this->dateStart],
+ ['!=', 'users_bonus.check_id', ''],
+ ['users_bonus.tip' => 'minus'],
+ ]);
+
+ return parent::getQueryDataDay()
+ ->leftJoin('users', 'sales.phone = users.phone')
+ ->leftJoin(['sub_users_bonus' => $subUsersBonusQuery],
+ [
+ 'AND',
+ [
+ '=',
+ new Expression('users.id'),
+ new Expression('sub_users_bonus.user_id')
+ ],
+ [
+ '=',
+ new Expression('sales.id'),
+ new Expression('sub_users_bonus.check_id')
+ ],
+ ]
+ );
+ }
+
+ protected function getQueryDataShifts(): \yii\db\ActiveQuery
+ {
+
+ $subUsersBonusQuery = UsersBonus::find()
+ ->select([
+ 'users_bonus.user_id',
+ 'users_bonus.check_id',
+ 'users_bonus.date'
+ ])
+ ->andWhere([
+ 'AND',
+ ['>=', 'if (HOUR(users_bonus.date) < 8, DATE_FORMAT(DATE_SUB(users_bonus.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(users_bonus.date, \'%Y-%m-%d\'))', $this->dateStart],
+ ['<=', 'if (HOUR(users_bonus.date) < 8, DATE_FORMAT(DATE_SUB(users_bonus.date, INTERVAL 1 DAY), \'%Y-%m-%d\'), DATE_FORMAT(users_bonus.date, \'%Y-%m-%d\'))', $this->dateStart],
+ ['!=', 'users_bonus.check_id', ''],
+ ['users_bonus.tip' => 'minus'],
+ ]);
+
+ return parent::getQueryDataShifts()
+ ->leftJoin('users', 'sales.phone = users.phone')
+ ->leftJoin(['sub_users_bonus' => $subUsersBonusQuery],
+ [
+ 'AND',
+ [
+ '=',
+ new Expression('users.id'),
+ new Expression('sub_users_bonus.user_id')
+ ],
+ [
+ '=',
+ new Expression('sales.id'),
+ new Expression('sub_users_bonus.check_id')
+ ],
+ ]
+ );
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace yii_app\records\metrics;
+
+use yii\db\Expression;
+use yii_app\records\metrics\Metrics;
+use yii_app\records\WriteOffs;
+
+class WriteOffsMetrics extends Metrics
+{
+ protected array $alias = [
+ 'write_offs'
+ ];
+
+ protected bool $calculateShifts = false;
+
+ protected function getQueryDataDay()
+ {
+ return WriteOffs::find()
+ ->select([
+ 'date' => 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
+ 'shift_type' => '(SELECT 4)',
+ 'store_dynamic_id' => 'store_dynamic.id',
+ 'store_id' => 'city_store.id',
+ 'write_offs' => 'SUM(write_offs.summ)',
+ ])
+ ->innerJoin('export_import_table', 'write_offs.store_id = export_import_table.export_val')
+ ->innerJoin('city_store', 'export_import_table.entity_id = city_store.id')
+ ->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = export_import_table.entity_id',
+ [
+ '<=',
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')')
+ ],
+ [
+ '>',
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')')
+ ],
+ ]
+ )
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $this->cluster,
+ 'city_store.id' => $this->store,
+ ])
+ ->andWhere([
+ 'AND',
+ ['write_offs.type' => 'Брак'],
+ ['>=', 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')', $this->dateStart],
+ ['<=', 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')', $this->dateEnd]
+ ])
+ ->addGroupBy([
+ 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')',
+ 'store_dynamic.id',
+ 'city_store.id'
+ ]);
+ }
+
+ protected function getQueryDataShifts(): bool
+ {
+ return false;
+ }
+}
\ No newline at end of file
$paramMinusDays = null;
$dayMonthNum = date("j", time());
-// if ('22' . $dateTimeMinuet == $timeGi) {
-// $paramDateFrom = date("Y-m-01", time());
-// }
+ if ('22' . $dateTimeMinuet == $timeGi) {
+ $paramDateFrom = date("Y-m-01", time());
+ }
-// if ('07' . $dateTimeMinuet == $timeGi && $dayMonthNum > 7) {
-// $paramMinusDays = 7;
-// }
+ if ('07' . $dateTimeMinuet == $timeGi && $dayMonthNum > 7) {
+ $paramMinusDays = 7;
+ }
if ('09' . $dateTimeMinuet == $timeGi && $dayMonthNum > 3) {
$paramMinusDays = 3;
$minuetTimeInTask = date('i', $time);
$fullTimeInTask = date('Y-m-d H:i:s', $time);
-$condition2 = (date('Gi', $time) == '1030' && date("d") < $nmDayStopCalculateLastMonth);
+$condition2 = (date('Gi', $time) == '0830' && date("d") < $nmDayStopCalculateLastMonth);
$info = ' ================ test Task 0' . $taskNum . ' stop ================';
echo $info;
$log .= $info;
+ $log .= ' ' . $dateFrom;
+ $log .= ' ' . $dateTo;
$dateTaskStop = date('Y-m-d H:i:s');
} else {
$info = ' Task 0' . $taskNum . ' skip ';
$infoText .= ' test ';
//////////////////////////////////////////////
- $sales = Sales::find()->where(['>', 'date', '2023-10-23 00:00:00'])->andWhere(['<=', 'date', '2024-01-07 23:59:59'])
+ $sales = Sales::find()->where(['>', 'date', '2024-01-15 00:00:00'])->andWhere(['<=', 'date', '2024-03-30 23:59:59'])
->andWhere(['operation' => 'Продажа'])->andWhere(['>=', 'summ', '2500'])->orderBy(['date' => SORT_ASC])->all();
- $returns = Sales::find()->where(['>', 'date', '2023-10-23 00:00:00'])->andWhere(['<=', 'date', '2024-01-07 23:59:59'])
+ $returns = Sales::find()->where(['>', 'date', '2024-01-15 00:00:00'])->andWhere(['<=', 'date', '2024-03-30 23:59:59'])
->andWhere(['operation' => 'Возврат'])->all();
$returnCheckIds = [];
$info = ' ================ test Task ' . $taskNum . ' stop ================';
echo $info;
$log .= $info;
+ $log .= ' ' . $dateFrom;
+ $log .= ' ' . $dateTo;
$dateTaskStop = date('Y-m-d H:i:s');
} else {
$info = ' Task ' . $taskNum . ' skip ';
$info = ' ================ test Task ' . $taskNum . ' stop ================';
echo $info;
$log .= $info;
+ $log .= ' ' . $date_start;
+ $log .= ' ' . $date_end;
$dateTaskStop = date('Y-m-d H:i:s');
} else {
$info = ' Task ' . $taskNum . ' skip ';
--- /dev/null
+<?php
+
+/**
+ * @var $time integer
+ */
+
+use yii_app\records\ChartDataSearch;
+use yii_app\records\metrics\SalesMetrics;
+use yii_app\records\SchedulerTask;
+use yii_app\records\SchedulerTaskLog;
+
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time2_" . $time . "_time2 ";
+$taskNum = 21;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = true;
+$start = false;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+$time_start = '0300';
+try {
+ if (
+ (
+ date('Gi', $time) == $time_start
+ || $force
+ )
+ && $enable
+ ) {
+
+
+
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ if (date('Y-m-02') == date('Y-m-d', strtotime('today'))) {
+ $dateStart = date('Y-m-d', strtotime('first day of previous month'));
+ $dateEnd = date('Y-m-01');
+ } else {
+ $dateStart = date('Y-m-d', strtotime('yesterday -1 day'));
+ $dateEnd = date('Y-m-d', strtotime('yesterday'));
+ }
+
+ $salesMetrics = new SalesMetrics();
+ $salesMetrics->dateStart = $dateStart;
+ $salesMetrics->dateEnd = $dateEnd;
+
+
+ $startExecution = microtime( true );
+ $log .= $salesMetrics->insertData();
+ $timeExecution = sprintf( '%.6f sec.', microtime( true ) - $startExecution );
+
+ $log.= "\nВремя выполнения: $timeExecution\n";
+
+ $errorsCount = null;
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+// $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+// $error .= $valueErrors;
+ }
+
+
+
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $log .= ' ' . $dateStart;
+ $log .= ' ' . $dateEnd;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ';
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage();
+}
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
\ No newline at end of file
* @var $time integer
*/
+use yii\helpers\ArrayHelper;
use yii_app\helpers\DataHelper;
use yii_app\records\Admin;
use yii_app\records\AdminGroup;
use yii_app\records\EmployeeOnShift;
use yii_app\records\ExportImportTable;
use yii_app\records\SchedulerTaskLog;
+use yii_app\services\ExportImportService;
ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
//////////////////////////////////////////////
+ $compareDate = date('Y-m-d H:i:s', strtotime("-1 month", time()));
+
+ $entityCityStore = ExportImportService::getEntityByType();
+ $exportCityStore = ArrayHelper::map($entityCityStore, 'entity_id', 'export_val');
+
$admins = Admin::find()
- ->select(['id', 'guid', 'name', 'mobile as phone'])
+ ->select(['id', 'guid', 'name', 'store_id', 'mobile as phone'])
->where(['and', ['guid' => ''], ['!=', 'mobile', '']])
->andWhere(['in', 'group_id', AdminGroup::getGroupsForEmployeeOnCashbox()])
- ->andWhere(['>=', 'date_add', date('Y-m-d H:i:s', strtotime("-2 hour", time()))])
+ ->andWhere(['>=', 'date_add', $compareDate])
->all();
+ $adminsIds = implode(',',ArrayHelper::getColumn($admins, 'id'));
+
+ $phones = ArrayHelper::getColumn(EmployeeOnShift::find()->all(), 'phone');
foreach ($admins as $admin) {
+ /** @var Admin $admin */
+ if (in_array($admin->phone, $phones)) {
+ continue;
+ }
+
+ $storeGuid = '--';
+
+ if (!empty($admin->store_id)) {
+ if (array_key_exists($admin->store_id, $exportCityStore)) {
+ $storeGuid = $exportCityStore[$admin->store_id];
+ }
+ }
+
$model = new EmployeeOnShift([
'first_name' => $admin->name, 'last_name' => '', 'phone' => $admin->phone,
'shift_date' => date('Y-m-d H:i:s'), 'shift_type' => 1,
'datetime_start' => date('Y-m-d H:i:s'),
'datetime_end' => date('Y-m-d H:i:s'),
'created_by' => 1,
- 'store_id' => '-',
+ 'store_id' => $storeGuid,
'price' => 0,
+ 'salary_shift' => 1500,
]);
$model->guid = DataHelper::createGuidMy("06");
$model->created_at = date("Y-m-d H:i:s");
$model->status = EmployeeOnShift::STATUS_ACCEPT;
$model->status_source = EmployeeOnShift::STATUS_SOURCE_NOT_CREATED_IN_1C;
$model->save();
+ if ($model->getErrors()) {
+ $error .= json_encode($model->getErrors(), JSON_UNESCAPED_UNICODE);
+ }
$admin->guid = $model->guid;
$admin->save(false);
$info = ' ================ test Task ' . $taskNum . ' stop ================';
echo $info;
$log .= $info;
+ $log .= ' count($admins) = '. count($admins);
+ $log .= ' $adminsIds = '. $adminsIds;
+ $log .= ' date_add >='. $compareDate;
+
$dateTaskStop = date('Y-m-d H:i:s');
} else {
$info = ' Task ' . $taskNum . ' skip ';
--- /dev/null
+<?php
+
+/**
+ * @var $time integer
+ */
+
+use yii_app\records\ChartDataSearch;
+use yii_app\records\metrics\UserBonusMetrics;
+use yii_app\records\SchedulerTask;
+use yii_app\records\SchedulerTaskLog;
+
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time2_" . $time . "_time2 ";
+$taskNum = 23;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = true;
+$start = false;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+$time_start = '0400';
+try {
+ if (
+ (
+ date('Gi', $time) == $time_start
+ || $force
+
+ )
+ && $enable
+ ) {
+
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ if (date('Y-m-02') == date('Y-m-d', strtotime('today'))) {
+ $dateStart = date('Y-m-d', strtotime('first day of previous month'));
+ $dateEnd = date('Y-m-01');
+ } else {
+ $dateStart = date('Y-m-d', strtotime('yesterday -1 day'));
+ $dateEnd = date('Y-m-d', strtotime('yesterday'));
+ }
+
+ $userBonusMetrics = new UserBonusMetrics();
+ $userBonusMetrics->dateStart = $dateStart;
+ $userBonusMetrics->dateEnd = $dateEnd;
+
+ $startExecution = microtime( true );
+ $log .= $userBonusMetrics->insertData();
+ $timeExecution = sprintf( '%.6f sec.', microtime( true ) - $startExecution );
+
+ $log.= "\nВремя выполнения: $timeExecution\n";
+
+ $errorsCount = null;
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+// $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+// $error .= $valueErrors;
+ }
+
+
+
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $log .= ' ' . $dateStart;
+ $log .= ' ' . $dateEnd;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ';
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage();
+}
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * @var $time integer
+ */
+
+use yii_app\records\ChartDataSearch;
+use yii_app\records\metrics\MatrixMetrics;
+use yii_app\records\SchedulerTask;
+use yii_app\records\SchedulerTaskLog;
+
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time2_" . $time . "_time2 ";
+$taskNum = 24;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = true;
+$start = false;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+$time_start = '0330';
+try {
+ if (
+ (
+ date('Gi', $time) == $time_start
+ || $force
+ )
+ && $enable
+ ) {
+
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ if (date('Y-m-02') == date('Y-m-d', strtotime('today'))) {
+ $dateStart = date('Y-m-d', strtotime('first day of previous month'));
+ $dateEnd = date('Y-m-01');
+ } else {
+ $dateStart = date('Y-m-d', strtotime('yesterday -1 day'));
+ $dateEnd = date('Y-m-d', strtotime('yesterday'));
+ }
+
+ $matrixMetrics = new MatrixMetrics();
+ $matrixMetrics->dateStart = $dateStart;
+ $matrixMetrics->dateEnd = $dateEnd;
+
+ $startExecution = microtime( true );
+ $log .= $matrixMetrics->insertData();
+ $timeExecution = sprintf( '%.6f sec.', microtime( true ) - $startExecution );
+
+ $log.= "\nВремя выполнения: $timeExecution\n";
+
+ $errorsCount = null;
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+// $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+// $error .= $valueErrors;
+ }
+
+
+
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $log .= ' ' . $dateStart;
+ $log .= ' ' . $dateEnd;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ';
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage() . ' ' . $e->getFile() . ' >>> ' . $e->getLine();
+}
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
\ No newline at end of file
use yii\helpers\ArrayHelper;
+use yii_app\records\NotifiableUser;
use yii_app\records\Users;
use yii_app\records\UsersBonus;
use yii_app\api3\modules\v1\models\orders\OrdersAmo;
$userFound = Users::find()->where(['phone' => $phone])->one();
/** @var $userFound Users */
- $credit_procent = $cnt == 0
- && $userFound && $userFound->source > 0
- && in_array($sale->store_id_1c, [
- '0a575763-8871-11ee-84e2-ac1f6b1b7573', // 31 Энтузиастов 22/18 (Москва)
- 'e7fc2ba3-8870-11ee-84e2-ac1f6b1b7573' // 30 Леонова 18 (Москва)
- ])
- && date('Y-m-d H:i:s') <= '2023-12-25 23:59:59' ? 0.3 : 0.1;
- $back = round($sale->summ * $credit_procent);
- $nm = "Возврат с покупки " . (100 * $credit_procent) . "% " . $sale->number . " сумма чека " . $sale->summ;
+ $salesCount = 0;
+ if ($userFound && $userFound->telegram_created_at) {
+ $salesCount = intval(Sales::find()->where(['phone' => $phone, 'operation' => Sales::OPERATION_SALE])
+ ->andWhere(['>=', 'date', $userFound->telegram_created_at])->count());
+ }
+ $credit_procent_index = $userFound && $userFound->source > 0 && $salesCount == 0 ? 1 : 0;
+
+ $back1 = $back = round($sale->summ * 0.1);
+ $nm = "Возврат с покупки " . (100 * 0.1) . "% " . $sale->number . " сумма чека " . $sale->summ;
$userBonus = new UsersBonus;
$userBonus->tip = 'plus';
if ($userBonus->getErrors()) {
$log .= json_encode($userBonus->getErrors(), JSON_UNESCAPED_UNICODE);
}
+ if ($credit_procent_index) {
+ $back = round($sale->summ * 0.2);
+ $nm = "Возврат с покупки " . (100 * 0.2) . "% " . $sale->number . " сумма чека " . $sale->summ;
+
+ $userBonus = new UsersBonus;
+ $userBonus->tip = 'plus';
+ $userBonus->tip_sale = 'sale';
+ $userBonus->date = $sale->date;
+ $userBonus->date_start = date('Y-m-d H:i:s', strtotime('+1 day', strtotime($userBonus->date)));
+ $userBonus->date_end = date('Y-m-d H:i:s', strtotime('+3 month', strtotime($userBonus->date)));
+ $userBonus->phone = $phone;
+ $userBonus->name = $nm;
+ $userBonus->check_id = $sale->id;
+ $userBonus->store_id =
+ $userBonus->bonus = $back;
+ $userBonus->site_id = 0;
+ $userBonus->referal_id = 0;
+ $userBonus->admin_id = $sale->admin_id;
+ $userBonus->price = $sale->summ;
+ $userBonus->store_id_1c = $sale->store_id_1c;
+ $userBonus->seller_id_1c = $sale->seller_id;
+ $userBonus->lid_id = $sale->order_id;
+ $userBonus->save();
+ if ($userBonus->getErrors()) {
+ $log .= json_encode($userBonus->getErrors(), JSON_UNESCAPED_UNICODE);
+ }
+ if ($userFound->telegram_created_at == null) {
+ $userFound->telegram_created_at = date("Y-m-d H:i:s");
+ $userFound->save();
+ if ($userFound->getErrors()) {
+ $log .= json_encode(["error_id" => 5.3, "error" => $userFound->getErrors()]);
+ }
+ }
+
+ $notifiableUser = new NotifiableUser;
+ $notifiableUser->phone = $phone;
+ $notifiableUser->type = "first_given_bonus";
+ $notifiableUser->data = "" . ($back1 + $back);
+ $notifiableUser->save();
+ }
}
}
use yii_app\api3\modules\v1\models\orders\OrdersAmo;
use yii_app\records\Sales;
use yii_app\records\SchedulerTaskLog;
-
+use yii_app\records\NotifiableUser;
ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
ini_set('display_errors', 'on');
$userFound = Users::find()->where(['phone' => $phone])->one();
/** @var $userFound Users */
- $credit_procent = $cnt == 0
- && $userFound && $userFound->source > 0
- && in_array($sale->store_id_1c, [
- '0a575763-8871-11ee-84e2-ac1f6b1b7573', // 31 Энтузиастов 22/18 (Москва)
- 'e7fc2ba3-8870-11ee-84e2-ac1f6b1b7573' // 30 Леонова 18 (Москва)
- ])
- && date('Y-m-d H:i:s') <= '2023-12-25 23:59:59' ? 0.3 : 0.1;
- $back = round($sale->summ * $credit_procent);
- $nm = "Возврат с покупки " . (100 * $credit_procent) . "% " . $sale->number . " сумма чека " . $sale->summ;
+ $salesCount = 0;
+ if ($userFound && $userFound->telegram_created_at) {
+ $salesCount = intval(Sales::find()->where(['phone' => $phone, 'operation' => Sales::OPERATION_SALE])
+ ->andWhere(['>=', 'date', $userFound->telegram_created_at])->count());
+ }
+ $credit_procent_index = $userFound && $userFound->source > 0 && $salesCount == 0 ? 1 : 0;
+
+ $back1 = $back = round($sale->summ * 0.1);
+ $nm = "Возврат с покупки " . (100 * 0.1) . "% " . $sale->number . " сумма чека " . $sale->summ;
$userBonus = new UsersBonus;
$userBonus->tip = 'plus';
if ($userBonus->getErrors()) {
$log .= json_encode($userBonus->getErrors(), JSON_UNESCAPED_UNICODE);
}
+ if ($credit_procent_index) {
+ $back = round($sale->summ * 0.2);
+ $nm = "Возврат с покупки " . (100 * 0.2) . "% " . $sale->number . " сумма чека " . $sale->summ;
+
+ $userBonus = new UsersBonus;
+ $userBonus->tip = 'plus';
+ $userBonus->tip_sale = 'sale';
+ $userBonus->date = $sale->date;
+ $userBonus->date_start = date('Y-m-d H:i:s', strtotime('+1 day', strtotime($userBonus->date)));
+ $userBonus->date_end = date('Y-m-d H:i:s', strtotime('+3 month', strtotime($userBonus->date)));
+ $userBonus->phone = $phone;
+ $userBonus->name = $nm;
+ $userBonus->check_id = $sale->id;
+ $userBonus->store_id =
+ $userBonus->bonus = $back;
+ $userBonus->site_id = 0;
+ $userBonus->referal_id = 0;
+ $userBonus->admin_id = $sale->admin_id;
+ $userBonus->price = $sale->summ;
+ $userBonus->store_id_1c = $sale->store_id_1c;
+ $userBonus->seller_id_1c = $sale->seller_id;
+ $userBonus->lid_id = $sale->order_id;
+ $userBonus->save();
+ if ($userBonus->getErrors()) {
+ $log .= json_encode($userBonus->getErrors(), JSON_UNESCAPED_UNICODE);
+ }
+ if ($userFound->telegram_created_at == null) {
+ $userFound->telegram_created_at = date("Y-m-d H:i:s");
+ $userFound->save();
+ if ($userFound->getErrors()) {
+ $log .= json_encode(["error_id" => 5.3, "error" => $userFound->getErrors()]);
+ }
+ }
+
+ $notifiableUser = new NotifiableUser;
+ $notifiableUser->phone = $phone;
+ $notifiableUser->type = "first_given_bonus";
+ $notifiableUser->data = "" . ($back1 + $back);
+ $notifiableUser->save();
+ }
}
}
$info = ' ================ test Task ' . $taskNum . ' stop ================';
echo $info;
$log .= $info;
+ $log .= ' date >= ' . strtotime("-1 week", time());
$dateTaskStop = date('Y-m-d H:i:s');
} else {
$info = ' Task ' . $taskNum . ' skip ';
--- /dev/null
+<?php
+
+/* @var $time integer */
+
+use yii_app\records\SchedulerTaskLog;
+use yii_app\services\AdminPayrollMonthInfoService;
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time_" . $time . "_time ";
+$taskNum = 27;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = true;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+
+try {
+ if (
+ (
+ (date('Gi', $time) == '0850'
+ &&
+ in_array(date('j', $time), range(6,11))
+ )
+ || $force
+ )
+ && $enable
+ ) {
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $dateFrom = date("Y-m-01", strtotime('-1 month'));
+ $dateTo = date("Y-m-t", strtotime('-1 month'));
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ $result = (new AdminPayrollMonthInfoService($dateFrom))->setAdminPayrollHistory();
+
+ $errorsCount = $result['errorsCount'];
+ $errors = $result['errors'];
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+ $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+ $error .= $valueErrors;
+ }
+
+ $infoText .= ' dateFrom = ' . $dateFrom . ' dateTo ' . $dateTo . 'errors count ' . $errorsCount;
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ' . $time . ' ' . date('Y-m-d H:i:s', $time). ' ' . date('Gi', $time);
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage() . ' >>> ' . $e->getLine();
+}
+
+
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
--- /dev/null
+<?php
+
+/**
+ * @var $time integer
+ */
+
+use yii_app\records\ChartDataSearch;
+use yii_app\records\metrics\FotMetrics;
+use yii_app\records\SchedulerTask;
+use yii_app\records\SchedulerTaskLog;
+
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time2_" . $time . "_time2 ";
+$taskNum = 28;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = true;
+$start = false;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+$time_start = '0315';
+try {
+ if (
+ (
+ date('Gi', $time) == $time_start
+ || $force
+ )
+ && $enable
+ ) {
+
+
+
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ if (date('Y-m-02') == date('Y-m-d', strtotime('today'))) {
+ $dateStart = date('Y-m-d', strtotime('first day of previous month'));
+ $dateEnd = date('Y-m-01');
+ } else {
+ $dateStart = date('Y-m-d', strtotime('yesterday -1 day'));
+ $dateEnd = date('Y-m-d', strtotime('yesterday'));
+ }
+
+ $fotMetrics = new FotMetrics();
+ $fotMetrics->dateStart = $dateStart;
+ $fotMetrics->dateEnd = $dateEnd;
+
+ $startExecution = microtime( true );
+ $log .= $fotMetrics->insertData();
+ $timeExecution = sprintf( '%.6f sec.', microtime( true ) - $startExecution );
+
+ $log.= "\nВремя выполнения: $timeExecution\n";
+
+ $errorsCount = null;
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+// $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+// $error .= $valueErrors;
+ }
+
+
+
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $log .= ' ' . $dateStart;
+ $log .= ' ' . $dateEnd;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ';
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage();
+}
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * @var $time integer
+ */
+
+use yii_app\records\ChartDataSearch;
+use yii_app\records\metrics\WriteOffsMetrics;
+use yii_app\records\SchedulerTask;
+use yii_app\records\SchedulerTaskLog;
+
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time2_" . $time . "_time2 ";
+$taskNum = 29;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = true;
+$start = false;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+$time_start = '0415';
+try {
+ if (
+ (
+ date('Gi', $time) == $time_start
+ || $force
+
+ )
+ && $enable
+ ) {
+
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ if (date('Y-m-02') == date('Y-m-d', strtotime('today'))) {
+ $dateStart = date('Y-m-d', strtotime('first day of previous month'));
+ $dateEnd = date('Y-m-01');
+ } else {
+ $dateStart = date('Y-m-d', strtotime('yesterday -1 day'));
+ $dateEnd = date('Y-m-d', strtotime('yesterday'));
+ }
+
+ $writeOffsMetrics = new WriteOffsMetrics();
+ $writeOffsMetrics->dateStart = $dateStart;
+ $writeOffsMetrics->dateEnd = $dateEnd;
+
+ $startExecution = microtime( true );
+ $log .= $writeOffsMetrics->insertData();
+ $timeExecution = sprintf( '%.6f sec.', microtime( true ) - $startExecution );
+
+ $log.= "\nВремя выполнения: $timeExecution\n";
+
+ $errorsCount = null;
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+// $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+// $error .= $valueErrors;
+ }
+
+
+
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $log .= ' ' . $dateStart;
+ $log .= ' ' . $dateEnd;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ';
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage();
+}
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * @var $time integer
+ */
+
+use yii_app\records\ChartDataSearch;
+use yii_app\records\SchedulerTask;
+use yii_app\records\SchedulerTaskLog;
+
+
+ini_set('max_execution_time', (string)(60 * 60 * 1)); // 1 час
+ini_set('display_errors', 'on');
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
+echo "time2_" . $time . "_time2 ";
+$taskNum = 30;
+$dateTask = date('Y-m-d H:i:s');
+$dateTaskStart = null;
+$dateTaskStop = null;
+$log = '';
+$error = '';
+$infoError = '';
+$infoText = '';
+$description = '';
+$result = 0;
+
+$enable = false;
+$start = false;
+$force = false;
+
+$minuetTimeInTask = date('i', $time);
+$fullTimeInTask = date('Y-m-d H:i:s', $time);
+$time_start = '0345';
+try {
+ if (
+ (
+ date('Gi', $time) == $time_start
+ || $force
+ )
+ && $enable
+ ) {
+
+ $dateTaskStart = date('Y-m-d H:i:s');
+ $info = ' ================ test Task ' . $taskNum . ' start ================';
+ echo $info;
+ $log .= $info;
+ $log .= $time;
+
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ;
+ $validate = $schedulerTaskLog->validate();
+ if ($validate) {
+ $schedulerTaskLog->save();
+ }
+
+ if (date('Y-m-02') == date('Y-m-d', strtotime('today'))) {
+ $dateStart = date('Y-m-d', strtotime('first day of previous month'));
+ $dateEnd = date('Y-m-01');
+ } else {
+ $dateStart = date('Y-m-d', strtotime('yesterday -1 day'));
+ $dateEnd = date('Y-m-d', strtotime('yesterday'));
+ }
+
+ $log .= ChartDataSearch::CalculationCompanyDataMatrixSalesForChartsDay($dateStart, $dateEnd);
+
+ $errorsCount = null;
+
+ if (!empty($errorsCount)) {
+ $infoError .= 'errors count ' . $errorsCount;
+ $error .= $infoError;
+// $valueErrors = json_encode($errors,JSON_UNESCAPED_UNICODE);
+// $error .= $valueErrors;
+ }
+
+
+
+
+ $info = ' ================ test Task ' . $taskNum . ' stop ================';
+ echo $info;
+ $log .= $info;
+ $log .= ' ' . $dateStart;
+ $log .= ' ' . $dateEnd;
+ $dateTaskStop = date('Y-m-d H:i:s');
+ } else {
+ $info = ' Task ' . $taskNum . ' skip ';
+ echo $info;
+ $log .= $info;
+ }
+} catch (Exception $e) {
+ $error = 'Exception: ' . $e->getMessage() . ' ' . $e->getFile() . ' >>> ' . $e->getLine();
+}
+
+if (empty($schedulerTaskLog)) {
+ $schedulerTaskLog = new SchedulerTaskLog();
+ $schedulerTaskLog->setTaskNum($taskNum)
+ ->setName('Task ' . $taskNum)
+ ->setDate($dateTask)
+ ->setDateStart($dateTaskStart)
+ ->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+} else {
+ $schedulerTaskLog->setDateStop($dateTaskStop)
+ ->setDescription($description)
+ ->setError($error)
+ ->setInfo($infoText)
+ ->setLog($log)
+ ;
+}
+$validate = $schedulerTaskLog->validate();
+if ($validate) {
+ $schedulerTaskLog->save();
+}
\ No newline at end of file
namespace yii_app\services;
use yii\helpers\ArrayHelper;
-use yii_app\helpers\DateHelper;
use yii_app\helpers\HtmlHelper;
use yii_app\records\Admin;
use yii_app\records\AdminGroup;
-use yii_app\records\AdminPayrollDays;
+use yii_app\records\AdminPayroll;
+use yii_app\records\AdminPayrollHistory;
use yii_app\records\AdminPayrollMonthInfo;
use yii_app\records\CityStore;
use yii_app\records\EmployeePosition;
class AdminPayrollMonthInfoService
{
+ private $notInStoreIds;
+ private $yearSelect;
+ private $monthSelect;
+ private $monthWithZeroSelect;
+ private $dateFromBeginMonth;
+ private $dateToEndMonth;
+ private $dateTo;
+ private $dateFrom;
+ private $groupIds;
+ private $entityCityStore;
+ private $exportCityStore;
+ private $entityAdmin;
+ private $exportAdmin;
+ private $employeePosition;
+ private $employeeAdminGroup;
+ private $cityStoreNames;
+ private $monthNameSelect;
+ private $cabinetService;
+
+ public function __construct($dateFrom)
+ {
+ $this->cabinetService = new CabinetService();
+
+ $this->dateFrom = $dateFrom;
+ $this->notInStoreIds = Admin::NOT_IN_STORE_IDS;
+ $this->yearSelect = date("Y", strtotime($this->dateFrom));
+ $this->monthSelect = date("n", strtotime($this->dateFrom));
+ $this->monthWithZeroSelect = date("m", strtotime($this->dateFrom));
+ $this->dateFromBeginMonth = date("Y-m-01", strtotime($this->dateFrom));
+ $this->dateToEndMonth = date("Y-m-t", strtotime($this->dateFrom));
+ $this->dateTo = $this->dateToEndMonth;
+ if ($this->monthSelect == date("n")) {
+ $this->dateTo = date('Y-m-d', strtotime("-1 day"));
+ }
+ $this->groupIds = Admin::ADMIN_PAYROLL_MAKE_GROUP_IDS;
+ $this->employeePosition = EmployeePosition::getAllIdName();
+
+
+ $this->entityCityStore = ExportImportService::getEntityByType('city_store');
+ $this->exportCityStore = ArrayHelper::map($this->entityCityStore, 'entity_id', 'export_val');
+ $this->entityAdmin = ExportImportService::getEntityByType('admin');
+ $this->exportAdmin = ArrayHelper::map($this->entityAdmin, 'entity_id', 'export_val');
+ $this->employeePosition = EmployeePosition::getAllIdName();
+ $this->employeeAdminGroup = AdminGroup::getNames();
+ $this->cityStoreNames = CityStore::getNames();
+ $this->monthNameSelect = HtmlHelper::getMonthName($this->monthWithZeroSelect);
+ }
+
+ public function setAdminPayrollHistory()
+ {
+ AdminPayroll::clearPayrollFiredAdmin($this->yearSelect, $this->monthSelect);
+ AdminPayroll::clearPayrollWithoutShiftAdmin($this->yearSelect, $this->monthSelect);
+
+ $idsTimeTableArray = $this->cabinetService->getTimetableDataList($this->dateFrom, $this->dateTo);
+ $idsAdminTimeTable = ArrayHelper::getColumn($idsTimeTableArray, 'admin_id');
+
+ $admins = Admin::getAdmins(
+ $idsAdminTimeTable,
+ $this->groupIds,
+ 'ASC',
+ null,
+ null,
+ $this->notInStoreIds,
+ true
+ );
+
+ $errors = [];
+ $adminInfo = [];
+
+ if (empty($admins)) {
+ $errors[] = 'admins is empty';
+ } else {
+ $packetNum = time();
+ $winStoreIdDayChallenge = [];
+
+ foreach ($admins as $employeeSelect) {
+ $employeeId = $employeeSelect['id'];
+ $controller = null;
+ $employeeGroupId = $employeeSelect['group_id'];
+
+ $isAdministrator = Admin::isAdministrator($employeeGroupId);
+ $ratingId = RatingService::getRatingId($employeeGroupId);
+
+ $payrollValues = $this->cabinetService->getDataDynamic202310(
+ $employeeId,
+ $employeeSelect,
+ $employeeGroupId,
+ $isAdministrator,
+ $ratingId,
+ $this->dateFrom,
+ $this->dateTo,
+ $controller,
+ $winStoreIdDayChallenge,
+ $this->exportCityStore,
+ $this->exportAdmin,
+ $this->yearSelect,
+ $this->monthSelect,
+ $this->monthWithZeroSelect,
+ $this->monthNameSelect,
+ $this->dateFromBeginMonth,
+ $this->dateToEndMonth,
+ $this->employeePosition,
+ $this->employeeAdminGroup,
+ $this->cityStoreNames
+ );
+
+ if (array_key_exists('errorText', $payrollValues)) {
+ $errors[] = $errorRow = $payrollValues['errorText'];
+ InfoLogService::setInfoLog(__FILE__, __LINE__, $error ?? [] , 'error payrollHistoryValues');
+ } else {
+ AdminPayrollHistory::setValues($payrollValues,
+ $employeeId,
+ $employeeSelect['store_id'],
+ $this->yearSelect,
+ $this->monthSelect,
+ $packetNum
+ );
+ }
+
+ $adminInfo[$employeeId] = $payrollValues;
+ }
+ }
+ return [
+ 'errors' => $errors,
+ 'errorsCount' => count($errors),
+ 'adminInfo' => $adminInfo,
+ ];
+ }
public static function setAdminPayrollMonth($dateFrom, $dateTo)
{
use yii\helpers\ArrayHelper;
use yii_app\helpers\DateHelper;
+use yii_app\records\Admin;
use yii_app\records\AdminBonusConversion;
use yii_app\records\AdminPayrollDays;
use yii_app\records\CityStore;
return $rateId;
}
+
+ public function getAdminTeamPayrollTable($teamBonus) : array
+ {
+ $adminTeamPayroll = [];
+
+ // $teamBonusAdminPayDayAll
+ // key 893_2023-12-01
+ // value = sum;
+ $teamBonusAdminPayDayAll = ArrayHelper::getValue($teamBonus, 'adminPayDayAll');
+
+ // $teamBonusPayrollVariableDaysAll
+ // key 297_2023-12-07
+ // value = sum;
+ $teamBonusPayrollVariableDaysAll = ArrayHelper::getValue($teamBonus, 'payrollVariableDaysAll');
+
+ if (!empty($teamBonusAdminPayDayAll) && is_array($teamBonusAdminPayDayAll)) {
+ $arrayKeysAdminIdDate = array_unique(array_merge(array_keys($teamBonusAdminPayDayAll), array_keys($teamBonusPayrollVariableDaysAll)));
+ }
+ $adminIds = [];
+ $days = [];
+ if (!empty($arrayKeysAdminIdDate)) {
+ foreach ($arrayKeysAdminIdDate as $key => $row) {
+ $arrayRow = explode('_',$row);
+ $adminIdRow = $arrayRow[0];
+ $dateRow = $arrayRow[1];
+ $adminIds[] = $adminIdRow;
+ $days[] = $dateRow;
+ }
+ }
+
+ $adminIds = array_unique($adminIds);
+
+ $admins = Admin::getAdmins($adminIds, null, 'ASC');
+
+ $days = array_unique($days);
+
+ $result = [];
+ foreach ($admins as $admin) {
+ $result[$admin['id']]['admin_id'] = $admin['id'];
+ $result[$admin['id']]['admin_name'] = $admin['name'];
+ $result[$admin['id']]['group_name'] = $admin['group_name'];
+ $daysRow = [];
+
+ foreach ($days as $day) {
+ $keyAdminIdDateRow = $admin['id'] . '_' . $day;
+ $payConstantRow = 0;
+ if (array_key_exists($keyAdminIdDateRow, $teamBonusAdminPayDayAll)) {
+ $payConstantRow = ArrayHelper::getValue($teamBonusAdminPayDayAll, $keyAdminIdDateRow);
+ }
+ $payVariableRow = 0;
+
+ if (array_key_exists($keyAdminIdDateRow, $teamBonusPayrollVariableDaysAll)) {
+ $payVariableRow = ArrayHelper::getValue($teamBonusPayrollVariableDaysAll, $keyAdminIdDateRow);
+ }
+ $daysRow[$day] = [
+ 'pay_constant' => $payConstantRow,
+ 'pay_variable' => $payVariableRow,
+ ];
+ }
+ ksort($daysRow);
+
+ $result[$admin['id']]['days'] = $daysRow;
+ }
+
+ return $result;
+ }
/**
* @param array $normaSmena
* @param $summ
*/
public function getTeamBonus($adminId, $storeId, $storeGuid, $dateFrom, $dateTo): array
{
- $result = [];
+ $percentTeamBonusInMonth = self::getPercentTeamBonusInMonth($storeId, $dateFrom);
+
+ $result = [
+ 'adminStoreFotStableSum' => 0,
+ 'adminStoreFotVariableSum' => 0,
+ 'adminStoreFotSum' => 0,
+ 'writeOffsSum' => 0,
+ 'fotStoreAndWriteOff' => 0,
+ 'salesByStore' => 0,
+ 'salesByStorePart' => 0,
+ 'primeFondStore' => 0,
+ 'shiftCountAll' => 0,
+ 'primeFondStoreOneShift' => 0,
+ 'personShiftCount' => 0,
+ 'personPrimeFondStore' => 0,
+ 'adminStoreFotSumPercent' => 0,
+ 'writeOffsSumPercent' => 0,
+ 'adminStoreFotAndWriteOffsSumPercent' => 0,
+ 'percentTeamBonusInMonth' => $percentTeamBonusInMonth,
+ ];
$slotTypeId = [
Timetable::TIMESLOT_WORK, // "работа"
->all();
$adminTimetable = [];
+ $adminTimetableSalaryShift = [];
if (!empty($timeTable)){
foreach ($timeTable as $row) {
$adminTimetable[$row['admin_id']][] = $row['date'];
+ if (!empty($row['salary_shift'])) {
+ $adminTimetableSalaryShift[$row['admin_id']][$row['date']] = $row['salary_shift'];
+ }
}
$adminTimetableRow = $adminTimetable[$adminId];
foreach ($dates as $date) {
if (in_array($date, $adminTimetableRow)) {
- $adminPayDayRow = EmployeePayment::getSalary($adminId, $date, $adminPayDayDict);
+ if (
+ array_key_exists($adminId, $adminTimetableSalaryShift)
+ &&
+ array_key_exists($date, $adminTimetableSalaryShift[$adminId])
+ ) {
+ $adminPayDayRow = $adminTimetableSalaryShift[$adminId][$date];
+ } else {
+ $adminPayDayRow = EmployeePayment::getSalary($adminId, $date, $adminPayDayDict);
+ }
+
$keyAdminPayDayDictAllRow = $adminId . '_' . $date;
$adminPayDayAll[$keyAdminPayDayDictAllRow] = $adminPayDayRow;
$adminPayDay[$adminId][$date] = $adminPayDayRow;
// echo '<br>';
$salesByStore = (new CabinetService())->getSalesSaleSum($dateFrom, $dateTo, $storeGuid);
- $percentTeamBonusInMonth = self::getPercentTeamBonusInMonth($storeId, $dateFrom);
+
$percentCoefficient = $percentTeamBonusInMonth / 100;
$salesByStorePart = $salesByStore * $percentCoefficient;
'writeOffsSumPercent' => $writeOffsSumPercent,
'adminStoreFotAndWriteOffsSumPercent' => $adminStoreFotAndWriteOffsSumPercent,
'percentTeamBonusInMonth' => $percentTeamBonusInMonth,
+ 'days' => $dates,
+ 'adminPayDayAll' => $adminPayDayAll,
+ 'payrollVariableDaysAll' => $payrollVariableDaysAll,
];
}
}
}
- public static function getPercentTeamBonusInMonth($storeId, $dateFrom)
+ public static function getPercentTeamBonusInMonth($storeId, $dateFrom) : int
{
- $percentDefault = 20;
- $year = date("Y" , strtotime($dateFrom));
- $month = date("m" , strtotime($dateFrom));
+ $percentDefault = 0;
+ $year = (int) date("Y" , strtotime($dateFrom));
+ $month = (int) date("n" , strtotime($dateFrom));
$percentPrepared = TeambonusSettings::find()
->select(['procent'])
->andWhere(['store_id' => $storeId])
->andWhere(['year' => $year])
->andWhere(['month' => $month])
+ ->orderBy(['created_at' => SORT_DESC])
->scalar();
- $percent = (!empty($percentPrepared)) ? $percentPrepared : $percentDefault;
+ $percent = (isset($percentPrepared)) ? $percentPrepared : $percentDefault;
return $percent;
}
33, // Должанская 33/11
29, // ул. Страж Революции, 1А
],
+ '2023-11' => [
+ 37, // Тимирязева 9к2
+ ],
+ '2023-12' => [
+ 37, // Тимирязева 9к2
+ ],
];
/**
* Расчет демотивации Год к Году заблокирован на указанный месяц
$cityStoreNames,
bool $calculatePersonalRating = true
)
- {
+ { //getDataDynamic
if (!empty($employeeSelect['store_id'])) {
$employeeSelectStoreId = $employeeSelect['store_id'];
$cityStoreNames,
bool $calculatePersonalRating = true
)
- {
+ { // getDataDynamic202310
if (!empty($employeeSelect['store_id'])) {
$employeeSelectStoreId = $employeeSelect['store_id'];
$normalCountShiftArray = SalaryHelper::$normalCountShift;
if (!empty($employeeSelect["group_id"])) {
if (Admin::ADMINISTRATOR_GROUP_ID == $employeeSelect["group_id"]){
- // у Администратора число смен равно количеству рабочих дней в месяце
- $normalCountShift = HtmlHelper::getWorkDays($monthSelect, $yearSelect);
-
+ if ($dateFrom >= '2023-12-01') {
+ $dayMonthDateRow = $yearSelect . '-' . $monthSelect . '-01';
+ $timeRow = strtotime($dayMonthDateRow);
+ $monthSelectRow = date('n', $timeRow);
+ $yearSelectRow = date('Y', $timeRow);
+ if ($yearSelectRow == '2024' && $monthSelectRow == 1) {
+ $normalCountShift = 20;
+ } else {
+ // у Администратора число смен равно количеству дней со вторника по субботу в месяце
+ $normalCountShift = HtmlHelper::getAdministratorWorkDays($monthSelect, $yearSelect);
+ }
+ } else {
+ // у Администратора число смен равно количеству рабочих дней в месяце
+ $normalCountShift = HtmlHelper::getWorkDays($monthSelect, $yearSelect);
+ }
} else {
$employeeSelectGroupId = $this->getGroupId($employeeId, $employeeSelect['group_id'], $dateFrom, $dateTo);
- $normalCountShift = $normalCountShiftArray[$employeeSelectGroupId];
+ if (array_key_exists($employeeSelectGroupId, $normalCountShiftArray)) {
+ $normalCountShift = $normalCountShiftArray[$employeeSelectGroupId];
+ } else {
+ $normalCountShift = 15;
+ }
}
}
$planMonthCalculate = round($salaryAdministratorByDay * $normalCountShiftValue, 1);
$planMonthCalculatePercent = round(100 * $planMonthCalculate /$planMonthAdministrator,1);
- $administratorOklad = $this->bonusService->getAdministratorOklad($planMonthCalculate);
+ $administratorOklad = $this->getAdministratorSalaryShift($employeeId, $dateFrom, $planMonthCalculate);
}
$saleByMonthCalculate = 0;
}
if ($isAdministrator) {
- $administratorOklad = $this->bonusService->getAdministratorOklad($saleByMonthCalculate);
+ $administratorOklad = $this->getAdministratorSalaryShift($employeeId, $dateFrom, $saleByMonthCalculate);
}
} elseif ($isAdministrator && !empty($salesByStore)) {
- $administratorOklad = $this->bonusService->getAdministratorOklad($salesByStore);
+ $administratorOklad = $this->getAdministratorSalaryShift($employeeId, $dateFrom, $salesByStore);
$showBlockForecast = true;
}
+ $hourPayment = 10; //default value
+
if (!empty($normalCountShift)) {
if ($isAdministrator) {
$normalCostShift = round($administratorOklad / $normalCountShift, 1);
$dailyPayment = $normalCostShift;
+ $hourPayment = $dailyPayment / Admin::SHIFT_HOUR_COUNT_ADMINISTRATOR;
+
} else {
$normalCostShift = round($monthlySalary['monthly_salary'] / $normalCountShift, 1);
$dailyPayment = $monthlySalary['daily_payment'];
+
+ $hourPayment = $dailyPayment / Admin::SHIFT_HOUR_COUNT_FLORIST;
}
}
$bonusByConvertionPercent = $this->bonusService->getBonusByConvertionPercent($conversionPercent, $employeeSelectStoreId, $dateFrom, $dateTo);
$timetableAdmin = [];
+ $partTimeWagesSumAdminStore = 0;
+ $partTimeWagesCountAdminStore = 0;
if (!empty($timetable)) {
if (!empty($storeAdminsGuids)) {
- $timetableAdmin = $this->getTimetableDate($timetable, $employeeId, $adminGuid, $storeAdminsGuids, $dateFrom, $dateTo, $normalCostShift, $isAdministrator, $entityCityStoreEmployeeSelect);
+ $timetableAdminValues = $this->getTimetableDate($timetable, $employeeId, $adminGuid, $storeAdminsGuids, $dateFrom, $dateTo, $normalCostShift, $isAdministrator, $entityCityStoreEmployeeSelect);
+ $timetableAdmin = ArrayHelper::getValue($timetableAdminValues, 'timetable');
+ $partTimeWagesSumAdminStore = ArrayHelper::getValue($timetableAdminValues, 'partTimeWagesSum');
+ $partTimeWagesCountAdminStore = ArrayHelper::getValue($timetableAdminValues, 'partTimeWagesCount');
} else {
$errorText = 'У сотрудника "' . $employeeSelect['name_full'] . '" <br>';
$errorText .= 'за выбранный интервал с ' . $dateFrom . ' по ' . $dateTo . ' <br>';
$timetableAdminTypeFirstShift = $timetableAdmin[array_key_first($timetableAdmin)]['typeSmenaInt'];
}
- if (!empty($timetableAnotherStore)) {
- $timetableAdminAnotherStore = $this->getTimetableDate($timetableAnotherStore, $employeeId, $adminGuid, $anotherStoreAdminsGuids, $dateFrom, $dateTo, $normalCostShift, $isAdministrator);
+ $partTimeWagesSumAdminAnotherStore = 0;
+ $partTimeWagesCountAdminAnotherStore = 0;
+ if (!empty($timetableAnotherStore)) {
+ $timetableAdminAnotherStoreValues = $this->getTimetableDate($timetableAnotherStore, $employeeId, $adminGuid, $anotherStoreAdminsGuids, $dateFrom, $dateTo, $normalCostShift, $isAdministrator);
+ $timetableAdminAnotherStore = ArrayHelper::getValue($timetableAdminAnotherStoreValues, 'timetable');
+ $partTimeWagesSumAdminAnotherStore = ArrayHelper::getValue($timetableAdminAnotherStoreValues, 'partTimeWagesSum');
+ $partTimeWagesCountAdminAnotherStore = ArrayHelper::getValue($timetableAdminAnotherStoreValues, 'partTimeWagesCount');
}
+ $partTimeWagesSumAdminAllStore = $partTimeWagesSumAdminStore + $partTimeWagesSumAdminAnotherStore;
+ $partTimeWagesCountAdminAllStore = $partTimeWagesCountAdminStore + $partTimeWagesCountAdminAnotherStore;
+
if ($allowedConversionCalculate) {
$conversionDayAdministrator = $this->getSumListConversion($employeeSelectStoreId, $dateFromConversion, $dateTo);
$conversionShift = $this->getConversionShift($dateFromConversion, $dateTo, $employeeSelectStoreId);
$personBonuses = ArrayHelper::getValue($personBonusesArray, 'bonuses'); // Персональная премия
$personColorRubleBonuses = ArrayHelper::getValue($personBonusesArray, 'color_ruble_bonuses'); // Персональная премия
$personRetention = ArrayHelper::getValue($personBonusesArray, 'retention'); // Персональный вычет
+ $personRetentionСomment = 'Персональный вычет';
+ $personRetentionСommentText = ArrayHelper::getValue($personBonusesArray, 'retention_comment'); // Комментарий персонального вычета
+ if (!empty($personRetentionСommentText)) {
+ $personRetentionСomment = $personRetentionСommentText;
+ }
$personPrepaidExpense = ArrayHelper::getValue($personBonusesArray, 'prepaid_expense'); // Аванс
$personCounting = ArrayHelper::getValue($personBonusesArray, 'counting'); // Подсчёт
$personVacationDay = ArrayHelper::getValue($personBonusesArray, 'vacation_day'); // Оплаченный отпуск
$personVacationPay = $personVacationDay * $normalCostShift;//Стоимость одной смены
+ $personPartTimeJobHours = ArrayHelper::getValue($personBonusesArray, 'part_time_job_hours'); // Подработки в часах
+ $personPartTimeJobHoursPay = $personPartTimeJobHours * $hourPayment; // Стоимость подработки по часам в рублях
$possibleSumGameBonusValuesFlorist = [];
$allSumGameBonusValues = $allPossibleSumGameBonusValuesFlorist + $personSumColorRubleBonusesValues;
+ // Командный бонус
+ $teamBonus = $this->bonusService->getTeamBonus( $employeeId, $employeeSelectStoreId, $entityCityStoreEmployeeSelect, $dateFrom, $dateToEndMonth);
+ $teamBonusDetail = json_encode($teamBonus,JSON_UNESCAPED_UNICODE);
+ $teamBonusValuePrepared = ArrayHelper::getValue($teamBonus, 'personPrimeFondStore');
+ $teamBonusValue = ($teamBonusValuePrepared > 0) ? $teamBonusValuePrepared : 0;
+
+ $adminTeamPayrollTable = [];
+ if (!empty($teamBonus) && $isAdministrator) {
+ $adminTeamPayrollTable = $this->bonusService->getAdminTeamPayrollTable($teamBonus);
+ }
+
+ // Премия за процент качества
+ $userQualityPercent = 0; // % качества
+
+ $userQualityPercentPrepared = QualityRating::getQualityRating($employeeId, $dateTo);
+ if (!empty($userQualityPercentPrepared)) {
+ $userQualityPercent = $userQualityPercentPrepared;
+ }
+ $userQualityPremium = $this->bonusService->getBonusForQuality($userQualityPercent);
$arrayTypes = ["wrap", "potted", "related","services","salut","other_items"];
$this->arr = [$adminGuid];
$adminGuidArr = $this->arr;
- if (!empty($arrayProducts["services"])) {
- $arrUsersSalaryServicesPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["services"], $adminGuidArr, $dateFrom, $dateTo, $exportAdmin, $isAdministrator);
- $arrUsersSalaryServices = ArrayHelper::getColumn($arrUsersSalaryServicesPrepared, 'bonus');
- $arrUsersSalaryServicesCheck = ArrayHelper::getColumn($arrUsersSalaryServicesPrepared, 'check');
- }
- if (!empty($arrayProducts["related"])) {
- $arrUsersSalaryRelatedPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["related"], $adminGuidArr, $dateFrom, $dateTo, $exportAdmin, $isAdministrator);
- $arrUsersSalaryRelated = ArrayHelper::getColumn($arrUsersSalaryRelatedPrepared, 'bonus');
- $arrUsersSalaryRelatedCheck = ArrayHelper::getColumn($arrUsersSalaryRelatedPrepared, 'check');
- }
- if (!empty($arrayProducts["potted"])) {
- $arrUsersSalaryPottedPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["potted"], $adminGuidArr, $dateFrom, $dateTo, $exportAdmin, $isAdministrator);
- $arrUsersSalaryPotted = ArrayHelper::getColumn($arrUsersSalaryPottedPrepared, 'bonus');
- $arrUsersSalaryPottedCheck = ArrayHelper::getColumn($arrUsersSalaryPottedPrepared, 'check');
- }
- if (!empty($arrayProducts["wrap"])) {
- $arrUsersSalaryWrapPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["wrap"], $adminGuidArr, $dateFrom, $dateTo, $exportAdmin, $isAdministrator);
- $arrUsersSalaryWrap = ArrayHelper::getColumn($arrUsersSalaryWrapPrepared, 'bonus');
- $arrUsersSalaryWrapCheck = ArrayHelper::getColumn($arrUsersSalaryWrapPrepared, 'check');
- }
- if (!empty($arrayProducts["other_items"])) {
- $arrUsersSalaryOtherItemsPrepared = SalaryHelper::getSalaryBonusMulty($arrayProducts["other_items"], $adminGuidArr, $dateFrom, $dateTo, $exportAdmin, $isAdministrator);
- $arrUsersSalaryOtherItems = ArrayHelper::getColumn($arrUsersSalaryOtherItemsPrepared, 'bonus');
- $arrUsersSalaryOtherItemsCheck = ArrayHelper::getColumn($arrUsersSalaryOtherItemsPrepared, 'check');
- }
- if (!empty($arrayProducts["salut"])) {
-// $dateFromToSalutArray = $this->salesService->getAllowedStart($dateFrom, $dateTo, SalesService::$allowedCalculateBonusForSalut);
+ /**/
+ $showHolidayVersion = HolidayService::getHolidayVersionShow($dateFrom, $dateTo);
+// $showHolidayVersion = false;
+ /**/
- $arrUsersSalarySalutPrepared = SalaryHelper::getSalaryBonusSalut($arrayProducts["salut"], $adminGuidArr, $dateFrom, $dateTo, $exportAdmin, $isAdministrator, $employeeSelectStoreId);
- $arrUsersSalarySalut = ArrayHelper::getColumn($arrUsersSalarySalutPrepared, 'bonus');
- $arrUsersSalarySalutCheck = ArrayHelper::getColumn($arrUsersSalarySalutPrepared, 'check');
+ $arrResSalariesByFocusGroup = SalaryHelper::getSalariesByFocusGroup(
+ $employeeId,
+ $adminGuid,
+ $arrayProducts,
+ $adminGuidArr,
+ $dateFrom,
+ $dateTo,
+ $exportAdmin,
+ $isAdministrator,
+ $employeeSelectStoreId,
+ $showHolidayVersion
+ );
- }
+ $arrUsersSalary = ArrayHelper::getValue($arrResSalariesByFocusGroup, 'arrUsersSalary');
+ $arrUsersSalaryCheck = ArrayHelper::getValue($arrResSalariesByFocusGroup, 'arrUsersSalaryCheck');
- $arrUsersSalary = [
- "services" => $arrUsersSalaryServices ?? [],
- "related" => $arrUsersSalaryRelated ?? [],
- "potted" => $arrUsersSalaryPotted ?? [],
- "wrap" => $arrUsersSalaryWrap ?? [],
- "salut" => $arrUsersSalarySalut ?? [],
- "other_items" => $arrUsersSalaryOtherItems ?? [],
- ];
+ $premiumByFocusGroups = $this->getPremiumByFocusGroups($adminGuid, $arrUsersSalary, $dateFrom, $dateTo, $isAdministrator);
- $arrUsersSalaryCheck = [
- "services" => $arrUsersSalaryServicesCheck[$adminGuid] ?? [],
- "related" => $arrUsersSalaryRelatedCheck[$adminGuid] ?? [],
- "potted" => $arrUsersSalaryPottedCheck[$adminGuid] ?? [],
- "wrap" => $arrUsersSalaryWrapCheck[$adminGuid] ?? [],
- "salut" => $arrUsersSalarySalutCheck[$adminGuid] ?? [],
- "other_items" => $arrUsersSalaryOtherItemsCheck[$adminGuid] ?? [],
- ];
+ $userSalaryServices = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryServices');
+ $userSalaryServicesPremium = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryServicesPremium');
- $userSalaryServices = 0;
- if (array_key_exists($adminGuid, $arrUsersSalary["services"])) {
- $userSalaryServices = ($arrUsersSalary["services"][$adminGuid] > 0) ? $arrUsersSalary["services"][$adminGuid] : 0;
- }// услуги
+ $userSalaryRelated = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryRelated');
+ $userSalaryRelatedPremium = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryRelatedPremium');
- $userSalaryRelated = 0;
- if (array_key_exists($adminGuid, $arrUsersSalary["related"])) {
- $userSalaryRelated = ($arrUsersSalary["related"][$adminGuid] > 0) ? $arrUsersSalary["related"][$adminGuid] : 0; // сопутка
- }
+ $userSalaryPotted = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryPotted');
+ $userSalaryPottedPremium = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryPottedPremium');
- $userSalaryPotted = 0;
- if (array_key_exists($adminGuid, $arrUsersSalary["potted"])) {
- $userSalaryPotted = ($arrUsersSalary["potted"][$adminGuid] > 0) ? $arrUsersSalary["potted"][$adminGuid] : 0; // горшечка
- }
+ $userSalaryWrap = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryWrap');
+ $userSalaryWrapPremium = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryWrapPremium');
- $userSalaryWrap = 0;
- if (array_key_exists($adminGuid, $arrUsersSalary["wrap"])) {
- $userSalaryWrap = ($arrUsersSalary["wrap"][$adminGuid] > 0) ? $arrUsersSalary["wrap"][$adminGuid] : 0; // упаковка
- }
+ $userSalarySalut = ArrayHelper::getValue($premiumByFocusGroups, 'userSalarySalut');
+ $userSalarySalutPremium = ArrayHelper::getValue($premiumByFocusGroups, 'userSalarySalutPremium');
- $userSalarySalut = 0;
- if (array_key_exists($adminGuid, $arrUsersSalary["salut"])) {
- $userSalarySalut = ($arrUsersSalary["salut"][$adminGuid] > 0) ? $arrUsersSalary["salut"][$adminGuid] : 0; // пиротехника
- }
+ $userSalaryOtherItems = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryOtherItems');
+ $userSalaryOtherItemsPremium = ArrayHelper::getValue($premiumByFocusGroups, 'userSalaryOtherItemsPremium');
- $userSalaryOtherItems = 0;
- if (array_key_exists($adminGuid, $arrUsersSalary["other_items"])) {
- $userSalaryOtherItems = ($arrUsersSalary["other_items"][$adminGuid] > 0) ? $arrUsersSalary["other_items"][$adminGuid] : 0; // Другие товары
- }
+ $premiumByMatrix = $this->getPremiumByMatrix(
+ $employeeSelectStoreId,
+ $adminGuid,
+ $dateFrom,
+ $dateTo,
+ $isAdministrator,
+ $showHolidayVersion
+ );
- $userQualityPercent = 0; // % качества
+ $salesMatrix = ArrayHelper::getValue($premiumByMatrix, 'salesMatrix');
+ $salaryMatrix = ArrayHelper::getValue($premiumByMatrix, 'salaryMatrix');
+ $salaryMakeMatrix = ArrayHelper::getValue($premiumByMatrix, 'salaryMakeMatrix');
+ $bonusSalaryMatrix = ArrayHelper::getValue($premiumByMatrix, 'bonusSalaryMatrix');
+ $makeMatrix = ArrayHelper::getValue($premiumByMatrix, 'makeMatrix');
+ $bonusMakeMatrix = ArrayHelper::getValue($premiumByMatrix, 'bonusMakeMatrix');
+ $matrixPrime = ArrayHelper::getValue($premiumByMatrix, 'matrixPrime');
- $userQualityPercentPrepared = QualityRating::getQualityRating($employeeId, $dateTo);
- if (!empty($userQualityPercentPrepared)) {
- $userQualityPercent = $userQualityPercentPrepared;
- }
- $userQualityPremium = $this->bonusService->getBonusForQuality($userQualityPercent);
+ $consolidatedPremiumByStore = 0;
+ $onePartHolidayPremium = 0;
+ $adminsHolidayShiftCount = 0;
+ $personPremiumByStore = 0;
- $teamBonus = $this->bonusService->getTeamBonus( $employeeId, $employeeSelectStoreId, $entityCityStoreEmployeeSelect, $dateFrom, $dateToEndMonth);
- $teamBonusValuePrepared = ArrayHelper::getValue($teamBonus, 'personPrimeFondStore');
- $teamBonusValue = ($teamBonusValuePrepared > 0) ? $teamBonusValuePrepared : 0;
+ $onePartHolidayPremium = 0;
+ $personHolidayShiftCount = 0;
- $userSalaryServicesPremium = round($userSalaryServices * 0.1); // 10% за продажу услуг
- $userSalaryRelatedPremium = round($userSalaryRelated * 0.05); // 5% за личные продажи сопутки
- $userSalaryPottedPremium = round($userSalaryPotted * 0.05);
- $userSalaryWrapPremium = round($userSalaryWrap * 0.05); // 5% за личные продажи упаковки
+ if ($showHolidayVersion) {
+ // Премирование на праздники
+ $consolidatedArrResSalariesByFocusGroup = SalaryHelper::getSalariesByFocusGroup(
+ $employeeId,
+ $adminGuid,
+ $arrayProducts,
+ $adminGuidArr,
+ $dateFrom,
+ $dateTo,
+ $exportAdmin,
+ $isAdministrator,
+ $employeeSelectStoreId,
+ $showHolidayVersion,
+false
+ );
- $userSalarySalutPremium = round($userSalarySalut * 0.05); // 5% за личные продажи пиротехники
+ $consolidatedArrUsersSalary = ArrayHelper::getValue($consolidatedArrResSalariesByFocusGroup, 'arrUsersSalary');
+ $consolidatedArrUsersSalaryCheck = ArrayHelper::getValue($consolidatedArrResSalariesByFocusGroup, 'arrUsersSalaryCheck');
+ $consolidatedAdminGuidDateArrByFocusGroup = ArrayHelper::getValue($consolidatedArrResSalariesByFocusGroup, 'adminGuidDateArrByFocusGroup');
- $userSalaryOtherItemsPremium = round($userSalaryOtherItems * 0.01); // 1% за личные продажи не фокусной продукции (Другме товары)
- //Букеты по матрице
+ $consolidatedPremiumByFocusGroups = $this->getPremiumByFocusGroups($adminGuid, $consolidatedArrUsersSalary, $dateFrom, $dateTo, $isAdministrator);
- $salesMatrix = $this->salesService->getMatrixSalesProducts($adminGuid, $dateFrom, $dateTo, $isAdministrator);
+ $consolidatedUserSalaryServices = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryServices');
+ $consolidatedUserSalaryServicesPremium = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryServicesPremium');
- $salesMatrixProductGuids = ArrayHelper::getColumn($salesMatrix, 'product_guid');
- $salesMatrixProducts = Products1c::getProducts1cByType('products', $salesMatrixProductGuids);
- $salesMatrixProductNames = ArrayHelper::map($salesMatrixProducts, 'id','name');
+ $consolidatedUserSalaryRelated = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryRelated');
+ $consolidatedUserSalaryRelatedPremium = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryRelatedPremium');
- $salaryMatrix = 0;
- $bonusSalaryMatrix = 0;
- $salesMatrixTemp = $salesMatrix;
- foreach ($salesMatrixTemp as $keySalesMatrix => $row) {
- $matrixBonusCoefficientRow = $this->bonusService->getMatrixBonusCoefficient($row['date']);
- $rowBonus = $row["summ"] * $matrixBonusCoefficientRow;
- $salesMatrix[$keySalesMatrix]["bonus"] = $rowBonus;
- if($row["operation"] == Sales::OPERATION_SALE) {
- $salaryMatrix += $row["summ"];
- $bonusSalaryMatrix += $rowBonus;
- } elseif($row["operation"] == Sales::OPERATION_RETURN) {
- $salaryMatrix -= $row["summ"];
- $bonusSalaryMatrix -= $rowBonus;
- }
- $productNameRow = '';
- if (array_key_exists($row["product_guid"], $salesMatrixProductNames)) {
- $productNameRow = ArrayHelper::getValue($salesMatrixProductNames, $row["product_guid"]);
- }
- $salesMatrix[$keySalesMatrix]["product_name"] = $productNameRow;
- }
+ $consolidatedUserSalaryPotted = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryPotted');
+ $consolidatedUserSalaryPottedPremium = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryPottedPremium');
- $bonusSalaryMatrix = round($bonusSalaryMatrix);
+ $consolidatedUserSalaryWrap = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryWrap');
+ $consolidatedUserSalaryWrapPremium = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryWrapPremium');
- $makeMatrix = $this->salesService->getMatrixMakeProducts($adminGuid, $dateFrom, $dateTo, $isAdministrator);
+ $consolidatedUserSalarySalut = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalarySalut');
+ $consolidatedUserSalarySalutPremium = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalarySalutPremium');
- $makeMatrixProductGuids = ArrayHelper::getColumn($makeMatrix, 'product_guid');
- $makeMatrixProducts = Products1c::getProducts1cByType('products', $makeMatrixProductGuids);
- $makeMatrixProductNames = ArrayHelper::map($makeMatrixProducts, 'id','name');
+ $consolidatedUserSalaryOtherItems = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryOtherItems');
+ $consolidatedUserSalaryOtherItemsPremium = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryOtherItemsPremium');
- $salaryMakeMatrix = 0;
- $bonusMakeMatrix = 0;
- $makeMatrixTemp = $makeMatrix;
- foreach ($makeMatrixTemp as $kayMakeMatrix => $row) {
- $matrixBonusCoefficientRow = $this->bonusService->getMatrixBonusCoefficient($row['date']);
- $rowBonus = $row["summ"] * $matrixBonusCoefficientRow;
- $makeMatrix[$kayMakeMatrix]["bonus"] = $rowBonus;
- if($row["operation"] == Sales::OPERATION_SALE) {
- $salaryMakeMatrix += $row["summ"];
- $bonusMakeMatrix += $rowBonus;
- } elseif($row["operation"] == Sales::OPERATION_RETURN) {
- $salaryMakeMatrix -= $row["summ"];
- $bonusMakeMatrix -= $rowBonus;
+ $consolidatedUserSalaryPremiumSum = ArrayHelper::getValue($consolidatedPremiumByFocusGroups, 'userSalaryPremiumSum');
+
+
+
+ $adminGuidNames = Admin::getAdminGuidNames();
+
+ $consolidatedArrUsersSalaryCheckTmp = $consolidatedArrUsersSalaryCheck;
+ foreach ($consolidatedArrUsersSalaryCheckTmp as $key => $rows) {
+ foreach ($rows as $keyInner => $item) {
+ $consolidatedArrUsersSalaryCheck[$key][$keyInner]['name'] = $adminGuidNames[$item['seller_id']] ?? $item['seller_id'];
+ }
}
- $productNameRow = '';
- if (array_key_exists($row["product_guid"], $makeMatrixProductNames)) {
- $productNameRow = ArrayHelper::getValue($makeMatrixProductNames, $row["product_guid"]);
+ // Премия за матрицу в праздники
+
+ $consolidatedPremiumByMatrix = $this->getPremiumByMatrix(
+ $employeeSelectStoreId,
+ $adminGuid,
+ $dateFrom,
+ $dateTo,
+ $isAdministrator,
+ $showHolidayVersion,
+ false
+ );
+
+ $consolidatedSalesMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'salesMatrix');
+ $consolidatedSalaryMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'salaryMatrix');
+ $consolidatedSalaryMakeMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'salaryMakeMatrix');
+ $consolidatedBonusSalaryMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'bonusSalaryMatrix');
+ $consolidatedMakeMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'makeMatrix');
+ $consolidatedBonusMakeMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'bonusMakeMatrix');
+ $consolidatedMatrixPrime = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'matrixPrime');
+ $consolidatedAdminGuidDateArrByMatrix = ArrayHelper::getValue($consolidatedPremiumByMatrix, 'adminGuidDateArrByMatrix');
+
+ $consolidatedPremiumByStore = $consolidatedMatrixPrime + $consolidatedUserSalaryPremiumSum;
+
+ $shiftCount = [];
+ $countByUser = [];
+
+ foreach ($consolidatedAdminGuidDateArrByFocusGroup as $subKey => $users) {
+ $shiftCount[] = count($users);
+ foreach ($users as $user) {
+ if (array_key_exists($user, $countByUser)){
+ ++$countByUser[$user];
+ } else {
+ $countByUser[$user] = 1;
+ }
+ }
}
- $makeMatrix[$kayMakeMatrix]["product_name"] = $productNameRow;
- }
- $bonusMakeMatrix = round($bonusMakeMatrix);
+ $adminsHolidayShiftCount = array_sum($shiftCount) ;
+ $personHolidayShiftCount = $countByUser[$adminGuid] ?? 0;
+ if (!empty($adminsHolidayShiftCount)) {
+ $onePartHolidayPremium = $consolidatedPremiumByStore / $adminsHolidayShiftCount;
+ }
+ $personPremiumByStore = $onePartHolidayPremium * $personHolidayShiftCount;
- // итого: премия с матрицы
- $matrixPrime = $bonusSalaryMatrix + $bonusMakeMatrix;
+ }
$wagesBonusNormaSmenaAnotherStore = [];
if (!empty($timetableAdminAnotherStoreById)) {
$arrayColumnWages = array_merge($arrayColumnWages, $personBonusesArrayInfo);
}
+ if (!empty($personPartTimeJobHoursPay)) {
+ $personBonusesArrayInfo = [
+ 'Оплата подработок по часам' . ' ('. $personPartTimeJobHours . '*' . $hourPayment . ' руб/час из оклада)' => (int) $personPartTimeJobHoursPay,
+ ];
+ $arrayColumnWages = array_merge($arrayColumnWages, $personBonusesArrayInfo);
+ }
+
if (!empty($personVacationPay)) {
$personBonusesArrayInfo = [
'Оплата за отпуск ' . $personVacationDay. ' дня' => $personVacationPay,
'Командный бонус' => $teamBonusValue,
);
+ if (!empty($personPremiumByStore)) {
+ $personBonusesArrayInfo = [
+ 'Премия за продажу фокусных позиции в праздники' => $personPremiumByStore,
+ ];
+ $variableSumValuesAdministrator = array_merge($personBonusesArrayInfo, $variableSumValuesAdministrator);
+ }
+
+
$allVariableSumValuesAdministrator = array_sum($variableSumValuesAdministrator);
'Премия за сборку матрицы' => $bonusMakeMatrix, //
'Премия за продажи не фокусной продукции (Другме товары)' => $userSalaryOtherItemsPremium,
];
+
+ if (!empty($personPremiumByStore)) {
+ $personBonusesArrayInfo = [
+ 'Премия за продажу фокусных позиции в праздники' => $personPremiumByStore,
+ ];
+ $bonusVariable = array_merge($personBonusesArrayInfo, $bonusVariable);
+ }
+
$bonusVariableByMonth = [
'Премия за качество' => $userQualityPremium,
];
$bonusVariableByMonth = array_merge($personBonusesArrayInfo, $bonusVariableByMonth);
}
+
+ if (!empty($personPartTimeJobHoursPay)) {
+ $personBonusesArrayInfo = [
+ 'Оплата подработок по часам' . ' ('. $personPartTimeJobHours . '*' . $hourPayment . ' руб/час из оклада)'=> $personPartTimeJobHoursPay,
+ ];
+ $bonusVariableByMonth = array_merge($personBonusesArrayInfo, $bonusVariableByMonth);
+ }
+
$bonusConstant = [
];
$sumValuesFlorist = array_merge($personBonusesArrayInfo, $sumValuesFlorist);
}
+ if (!empty($personPremiumByStore)) {
+ $personBonusesArrayInfo = [
+ 'Премия за продажу фокусных позиции в праздники' => $personPremiumByStore,
+ ];
+ $sumValuesFlorist = array_merge($personBonusesArrayInfo, $sumValuesFlorist);
+ }
+
+ if (!empty($personPartTimeJobHoursPay)) {
+ $personBonusesArrayInfo = [
+ 'Оплата подработок по часам' . ' ('. $personPartTimeJobHours . '*' . $hourPayment . ' руб/час из оклада)' => (int) $personPartTimeJobHoursPay,
+ ];
+ $arrayColumnWages = array_merge($arrayColumnWages, $personBonusesArrayInfo);
+ }
+
if (!empty($personVacationPay)) {
$personBonusesArrayInfo = [
'Оплата за отпуск ' . $personVacationDay. ' дня' => $personVacationPay,
'Премия за продажи не фокусной продукции (Другме товары)' => $userSalaryOtherItemsPremium,
];
+ if (!empty($personPremiumByStore)) {
+ $personBonusesArrayInfo = [
+ 'Премия за продажу фокусных позиции в праздники' => $personPremiumByStore,
+ ];
+ $bonusVariable = array_merge($personBonusesArrayInfo, $bonusVariable);
+ }
+
+
$bonusVariableByMonth = [
'Премия за качество' => $userQualityPremium,
];
];
$bonusVariableByMonth = array_merge($personBonusesArrayInfo, $bonusVariableByMonth);
}
+
+
+ if (!empty($personPartTimeJobHoursPay)) {
+ $personBonusesArrayInfo = [
+ 'Оплата подработок по часам' . ' ('. $personPartTimeJobHours . '*' . $hourPayment . ' руб/час из оклада)' => $personPartTimeJobHoursPay,
+ ];
+ $bonusVariableByMonth = array_merge($personBonusesArrayInfo, $bonusVariableByMonth);
+ }
+
if (!empty($sumValuesFloristAnotherStore)) {
$bonusConstant = array_merge($bonusConstant, $sumValuesFloristAnotherStore);
}
$alreadyPay = [
'Аванс' => $personPrepaidExpense,
- 'Подсчет' => $personCounting,
];
+ if (!empty($personCounting)) {
+ $alreadyPay = array_merge($alreadyPay, [
+ 'Подсчет' => $personCounting,
+ ]);
+ }
+
+ if (!empty($partTimeWagesSumAdminAllStore)) {
+ $alreadyPay = array_merge($alreadyPay, [
+ 'Оплата подработок (количество смен ' . $partTimeWagesCountAdminAllStore . ')' => $partTimeWagesSumAdminAllStore,
+ ]);
+ }
+
$personRetentionValue = 0;
if (!empty($personRetention)) {
}
$personRetentionArray = [
- 'Персональный вычет' => $personRetentionValue,
+ $personRetentionСomment => $personRetentionValue,
];
+ $sumPersonRetention = array_sum($personRetentionArray);
+
+ $alreadyPaySum = array_sum($alreadyPay);
+
$minusSum = array_merge($alreadyPay, $personRetentionArray);
$minusSumValue = array_sum($minusSum);
$toPayoff = $allTotalPayroll - $minusSumValue;
+
+ $allowShowPersonRetention = date('Y-m-d',time()) >= date('Y-m-t',strtotime($dateFrom));
+
return [
+ 'allowShowPersonRetention' => $allowShowPersonRetention,
'dateFrom' => $dateFrom,
'employeeId' => $employeeId,
'userQualityPremium' => $userQualityPremium ?? 0,
'teamBonus' => $teamBonus ?? [], // 'Командный бонус'
+ 'teamBonusDetail' => $teamBonusDetail ?? '', // 'Командный бонус детально'
+ 'adminTeamPayrollTable' => $adminTeamPayrollTable ?? [], // 'Командный бонус детально'
'teamBonusValue' => $teamBonusValue ?? 0, // 'Командный бонус'
'userSalaryServicesPremium' => $userSalaryServicesPremium ?? [],
'arrUsersSalaryCheck' => $arrUsersSalaryCheck ?? [],
+ 'showHolidayVersion' => $showHolidayVersion,
+
'daysInSelectMonth' => $daysInSelectMonth,
'daysRemainsInSelectMonth' => $daysRemainsInSelectMonth,
'personBonuses' => $personBonuses, // Персональная премия
'personRetention' => $personRetention, // Персональный вычет
+ 'personRetentionArray' => $personRetentionArray, // Персональный вычет массив
+ 'sumPersonRetention' => $sumPersonRetention, // Персональный вычет сумма
+
'personPrepaidExpense' => $personPrepaidExpense, // Аванс
'personCounting' => $personCounting, // Подсчёт
+ 'alreadyPay' => $alreadyPay, // Выплат за выбранный месяц
+ 'alreadyPaySum' => $alreadyPaySum, // Сумма выплат за выбранный месяц
+ 'partTimeWagesSumAdminAllStore' => $partTimeWagesSumAdminAllStore, // Оклады за подработку
+ 'partTimeWagesCountAdminAllStore' => $partTimeWagesCountAdminAllStore, // Число смен подработок
+
'toPayoff' => $toPayoff, // К выплате
'oklad' => $oklad, // Оклад штатный
'sumChecksStore' => $sumChecksStore ?? 0,
'sumIncomingTrafficStore' => $sumIncomingTrafficStore ?? 0,
'conversionPercent' => $conversionPercent ?? 0,
+
+ 'consolidatedArrUsersSalaryCheck' => $consolidatedArrUsersSalaryCheck ?? [],
+ 'consolidatedPremiumByFocusGroups' => $consolidatedPremiumByFocusGroups ?? [],
+
+ 'consolidatedPremiumByMatrix' => $consolidatedPremiumByMatrix ?? [],
+ 'consolidatedPremiumByStore' => $consolidatedPremiumByStore ?? 0,
+
+ 'onePartHolidayPremium' => $onePartHolidayPremium,
+ 'adminsHolidayShiftCount' => $adminsHolidayShiftCount,
+ 'personPremiumByStore' => $personPremiumByStore,
+ 'personHolidayShiftCount' => $personHolidayShiftCount,
+
'saveValuesOk' => 'ok',
];
}
*/
public function getTimetableDate($timetable ,$employeeId , $adminGuid, array $storeAdminsGuids, $dateFrom, $dateTo, $normalCostShift, bool $isAdministrator, $entityCityStoreEmployeeSelect = null): array
{
-
-
-
-
$salesForAdmin = $this->getSalurySum($adminGuid, $dateFrom, $dateTo, $isAdministrator);
$salesForStore = [];
-
-
$salesAdmins[$adminId] = [
'id' => $adminId,
'group_id' => $adminGroupIdRow,
$adminGroupId = AdminGroupDynamic::getGroupByDate($employeeId, $dateFrom, $dateTo);
$timetableTemp = $timetable;
-
+ $partTimeWagesSum = 0;
+ $partTimeWagesCount = 0;
+ $parTimeWagesAdminIds = [];
foreach ($timetableTemp as $keyTimetable => $row) {
$daySale = 0;
+ $timetable[$keyTimetable]['wagesInfo'] = '';
+ $wagesInfo = '';
$timetable[$keyTimetable]['daySale'] = 0;
if ($isAdministrator && $timetable[$keyTimetable]['admin_id'] != $employeeId) {
$timetable[$keyTimetable]['wages'] = 0;
} else {
- $timetable[$keyTimetable]['wages'] = $normalCostShift;
+ $normalCostShiftRow = $normalCostShift;
+ if (!empty($row['salary_shift'])) {
+ $normalCostShiftRow = ($row['salary_shift']);
+ }
+ $timetable[$keyTimetable]['wages'] = $normalCostShiftRow;
+ if ($row['d_id'] == Admin::PART_TIME_WORKER_GROUP_ID) {
+ $timetable[$keyTimetable]['wagesInfo'] = 'подработка';
+ $wagesInfo = ' (подработка)';
+ $timetable[$keyTimetable]['partTimeWorkWages'] = $normalCostShiftRow;
+ $partTimeWagesSum = $partTimeWagesSum + $normalCostShiftRow;
+ $parTimeWagesAdminIds[] = $row['admin_id'];
+ ++$partTimeWagesCount;
+ }
}
-
-
$timetableAdminsIds = ArrayHelper::getValue($row, 'timetable_admins_ids');
$rateTimetableAdminsNames = [];
];
$adminsSales[$timetableAdminsId] = $sumRow;
-
-
}
$adminsSalesSum = 0;
}
}
-
-
$adminNameColumn = ArrayHelper::getColumn($rateTimetableAdminsNames, 'name');
$adminNameList = implode(',<br>' , $adminNameColumn);
- $timetable[$keyTimetable]['typeSmena'] = $typeSmena;
+ $timetable[$keyTimetable]['typeSmena'] = $typeSmena . $wagesInfo;
$timetable[$keyTimetable]['adminNameList'] = $adminNameList;
$timetable[$keyTimetable]['typeSmenaInt'] = $typeSmenaInt;
$timetable[$keyTimetable]['adminsSalesSum'] = $adminsSalesSum;
}
- return $timetable;
+ return [
+ 'timetable' => $timetable,
+ 'partTimeWagesSum' => $partTimeWagesSum,
+ 'partTimeWagesCount' => $partTimeWagesCount,
+ ];
}
$storeIdsString = ArrayHelper::getValue($clusterAdmin, 'store_arr');
$clusterAdminId = ArrayHelper::getValue($clusterAdmin, 'id');
- $storeIds = explode(',', $storeIdsString);
+ $storeIds = array_unique(explode(',', $storeIdsString));
$groupIds = [
Admin::ADMINISTRATOR_GROUP_ID // Администраторы
return $result;
}
+ /**
+ * @return int
+ */
+ public function getAdministratorSalaryShift($employeeId, $dateFrom, $salesByStore = null) : int
+ {
+ $administratorOklad = 0;
+
+ if ($dateFrom >= '2023-12-01') {
+ $monthlySalary = EmployeePayment::getMonthlySalary($employeeId, $dateFrom);
+ $administratorOklad = ArrayHelper::getValue($monthlySalary, 'monthly_salary');
+
+ } else {
+ $administratorOklad = $this->bonusService->getAdministratorOklad($salesByStore);
+ }
+
+ return (int) $administratorOklad;
+ }
+
+ public function getPremiumByFocusGroups($adminGuid, $arrUsersSalary, $dateFrom, $dateTo, $isAdministrator): array
+ {
+ $userSalaryServices = 0;
+ if (array_key_exists($adminGuid, $arrUsersSalary["services"])) {
+ $userSalaryServices = ($arrUsersSalary["services"][$adminGuid] > 0) ? $arrUsersSalary["services"][$adminGuid] : 0;
+ }// услуги
+
+ $userSalaryRelated = 0;
+ if (array_key_exists($adminGuid, $arrUsersSalary["related"])) {
+ $userSalaryRelated = ($arrUsersSalary["related"][$adminGuid] > 0) ? $arrUsersSalary["related"][$adminGuid] : 0; // сопутка
+ }
+
+ $userSalaryPotted = 0;
+ if (array_key_exists($adminGuid, $arrUsersSalary["potted"])) {
+ $userSalaryPotted = ($arrUsersSalary["potted"][$adminGuid] > 0) ? $arrUsersSalary["potted"][$adminGuid] : 0; // горшечка
+ }
+
+ $userSalaryWrap = 0;
+ if (array_key_exists($adminGuid, $arrUsersSalary["wrap"])) {
+ $userSalaryWrap = ($arrUsersSalary["wrap"][$adminGuid] > 0) ? $arrUsersSalary["wrap"][$adminGuid] : 0; // упаковка
+ }
+
+ $userSalarySalut = 0;
+ if (array_key_exists($adminGuid, $arrUsersSalary["salut"])) {
+ $userSalarySalut = ($arrUsersSalary["salut"][$adminGuid] > 0) ? $arrUsersSalary["salut"][$adminGuid] : 0; // пиротехника
+ }
+
+ $userSalaryOtherItems = 0;
+ if (array_key_exists($adminGuid, $arrUsersSalary["other_items"])) {
+ $userSalaryOtherItems = ($arrUsersSalary["other_items"][$adminGuid] > 0) ? $arrUsersSalary["other_items"][$adminGuid] : 0; // Другие товары
+ }
+
+ $userSalaryServicesPremium = round($userSalaryServices * 0.1); // 10% за продажу услуг
+ $userSalaryRelatedPremium = round($userSalaryRelated * 0.05); // 5% за личные продажи сопутки
+ $userSalaryPottedPremium = round($userSalaryPotted * 0.05);
+ $userSalaryWrapPremium = round($userSalaryWrap * 0.05); // 5% за личные продажи упаковки
+
+ $userSalarySalutPremium = round($userSalarySalut * 0.05); // 5% за личные продажи пиротехники
+
+ $userSalaryOtherItemsPremium = round($userSalaryOtherItems * 0.01); // 1% за личные продажи не фокусной продукции (Другме товары)
+
+ $userSalaryPremium = [
+ 'userSalaryServicesPremium' => $userSalaryServicesPremium,
+ 'userSalaryRelatedPremium' => $userSalaryRelatedPremium,
+ 'userSalaryPottedPremium' => $userSalaryPottedPremium,
+ 'userSalaryWrapPremium' => $userSalaryWrapPremium,
+ 'userSalarySalutPremium' => $userSalarySalutPremium,
+ 'userSalaryOtherItemsPremium' => $userSalaryOtherItemsPremium,
+ ];
+
+ $userSalaryPremiumSum = array_sum($userSalaryPremium);
+
+ return [
+ 'userSalaryServices' => $userSalaryServices,
+ 'userSalaryServicesPremium' => $userSalaryServicesPremium,
+ 'userSalaryRelated' => $userSalaryRelated,
+ 'userSalaryRelatedPremium' => $userSalaryRelatedPremium,
+ 'userSalaryPotted' => $userSalaryPotted,
+ 'userSalaryPottedPremium' => $userSalaryPottedPremium,
+ 'userSalaryWrap' => $userSalaryWrap,
+ 'userSalaryWrapPremium' => $userSalaryWrapPremium,
+ 'userSalarySalut' => $userSalarySalut,
+ 'userSalarySalutPremium' => $userSalarySalutPremium,
+ 'userSalaryOtherItems' => $userSalaryOtherItems,
+ 'userSalaryOtherItemsPremium' => $userSalaryOtherItemsPremium,
+ 'userSalaryPremiumSum' => $userSalaryPremiumSum,
+ ];
+ }
+
+ public function getPremiumByMatrix(
+ $employeeSelectStoreId,
+ $adminGuid,
+ $dateFrom,
+ $dateTo,
+ $isAdministrator,
+ $showHolidayVersion = false,
+ $notHolidayCalculate = true
+ ): array {
+ $adminGuidDateArr = [];
+ $adminGuidArrAll = [];
+ if ($showHolidayVersion) {
+ $holidayDatesBetweenPrepared = HolidayService::getHolidayDatesBetween($dateFrom, $dateTo);
+ if ($notHolidayCalculate) {
+ $dataKey = 'notHolidayDatesInterval';
+ } else {
+ $dataKey = 'dayHolidayInArray';
+ $adminGuidDateArr = SalaryHelper::getAdminGuidByStore($dateFrom, $dateTo, $employeeSelectStoreId);
+ $isAdministrator = false;
+ }
+ $dates = ArrayHelper::getValue($holidayDatesBetweenPrepared, $dataKey);
+ } else {
+ $dates = [
+ 0 => [
+ 'dateFrom' => $dateFrom,
+ 'dateTo' => $dateTo,
+ ],
+ ];
+ }
+
+ $salesMatrixTemp = [];
+ $makeMatrixTemp = [];
+
+ foreach ($dates as $key => $datesRow) {
+ $dateFromRow = $datesRow['dateFrom'];
+ $dateToRow = $datesRow['dateTo'];
+ $adminGuids = [];
+ if (
+ true === $showHolidayVersion
+ &&
+ $dateFromRow == $dateToRow
+ &&
+ !empty($adminGuidDateArr)
+
+ ) {
+ if (array_key_exists($dateFromRow, $adminGuidDateArr)) {
+ $adminGuids = $adminGuidDateArr[$dateFromRow];
+ $adminGuidArrAll[] = $adminGuids;
+ } else {
+ $testtt = 0;
+ continue;
+ }
+ }
+
+ //Букеты по матрице
+
+ $salesMatrixRow = $this->salesService->getMatrixSalesProducts($adminGuid, $dateFromRow, $dateToRow, $isAdministrator, $adminGuids);
+ $salesMatrixTemp = array_merge($salesMatrixTemp, $salesMatrixRow);
+
+
+ $makeMatrixRow = $this->salesService->getMatrixMakeProducts($adminGuid, $dateFromRow, $dateToRow, $isAdministrator, $adminGuids);
+ $makeMatrixTemp = array_merge($makeMatrixTemp, $makeMatrixRow);
+ }
+
+ $productMatrixTemp = array_merge($salesMatrixTemp, $makeMatrixTemp);
+
+ $adminGuidNames = Admin::getAdminGuidNames();
+
+ $matrixProductGuids = ArrayHelper::getColumn($productMatrixTemp, 'product_guid');
+ $matrixProducts = Products1c::getProducts1cByType('products', $matrixProductGuids);
+ $matrixProductNames = ArrayHelper::map($matrixProducts, 'id', 'name');
+
+ $salaryMatrix = 0;
+ $bonusSalaryMatrix = 0;
+ $salesMatrix = $salesMatrixTemp;
+ foreach ($salesMatrixTemp as $keySalesMatrix => $row) {
+ $matrixBonusCoefficientRow = $this->bonusService->getMatrixBonusCoefficient($row['date']);
+ $rowBonus = $row["summ"] * $matrixBonusCoefficientRow;
+ $salesMatrix[$keySalesMatrix]["bonus"] = $rowBonus;
+ if ($row["operation"] == Sales::OPERATION_SALE) {
+ $salaryMatrix += $row["summ"];
+ $bonusSalaryMatrix += $rowBonus;
+ } elseif ($row["operation"] == Sales::OPERATION_RETURN) {
+ $salaryMatrix -= $row["summ"];
+ $bonusSalaryMatrix -= $rowBonus;
+ }
+ $productNameRow = '';
+ if (array_key_exists($row["product_guid"], $matrixProductNames)) {
+ $productNameRow = ArrayHelper::getValue($matrixProductNames, $row["product_guid"]);
+ }
+ $salesMatrix[$keySalesMatrix]["product_name"] = $productNameRow;
+
+ if (!$notHolidayCalculate) {
+ $adminNameRow = '';
+ if (array_key_exists($row["seller_id"], $adminGuidNames)) {
+ $adminNameRow = ArrayHelper::getValue($adminGuidNames, $row["seller_id"]);
+ }
+ $salesMatrix[$keySalesMatrix]["admin_name"] = $adminNameRow;
+ }
+ }
+
+ $bonusSalaryMatrix = round($bonusSalaryMatrix);
+
+
+ $salaryMakeMatrix = 0;
+ $bonusMakeMatrix = 0;
+ $makeMatrix = $makeMatrixTemp;
+ foreach ($makeMatrixTemp as $kayMakeMatrix => $row) {
+ $matrixBonusCoefficientRow = $this->bonusService->getMatrixBonusCoefficient($row['date']);
+ $rowBonus = $row["summ"] * $matrixBonusCoefficientRow;
+ $makeMatrix[$kayMakeMatrix]["bonus"] = $rowBonus;
+ if ($row["operation"] == Sales::OPERATION_SALE) {
+ $salaryMakeMatrix += $row["summ"];
+ $bonusMakeMatrix += $rowBonus;
+ } elseif ($row["operation"] == Sales::OPERATION_RETURN) {
+ $salaryMakeMatrix -= $row["summ"];
+ $bonusMakeMatrix -= $rowBonus;
+ }
+
+ $productNameRow = '';
+ if (array_key_exists($row["product_guid"], $matrixProductNames)) {
+ $productNameRow = ArrayHelper::getValue($matrixProductNames, $row["product_guid"]);
+ }
+ $makeMatrix[$kayMakeMatrix]["product_name"] = $productNameRow;
+
+ if (!$notHolidayCalculate) {
+ $adminNameRow = '';
+ if (array_key_exists($row["seller_id"], $adminGuidNames)) {
+ $adminNameRow = ArrayHelper::getValue($adminGuidNames, $row["seller_id"]);
+ }
+ $makeMatrix[$kayMakeMatrix]["admin_name"] = $adminNameRow;
+ }
+ }
+
+ $bonusMakeMatrix = round($bonusMakeMatrix);
+
+ // итого: премия с матрицы
+ $matrixPrime = $bonusSalaryMatrix + $bonusMakeMatrix;
+
+ return [
+ 'salesMatrix' => $salesMatrix,
+ 'bonusSalaryMatrix' => $bonusSalaryMatrix,
+ 'makeMatrix' => $makeMatrix,
+ 'salaryMatrix' => $salaryMatrix,
+ 'salaryMakeMatrix' => $salaryMakeMatrix,
+ 'bonusMakeMatrix' => $bonusMakeMatrix,
+ 'matrixPrime' => $matrixPrime,
+ 'adminGuidDateArrByMatrix' => $adminGuidArrAll,
+ ];
+ }
}
$data = $command->queryAll();
$dataArraySalesAll = [];
+ $dataSaleCumulative = [];
$SalesMStores = [];
$SalesM = [];
} else {
continue;
}
- $sale = $dataSaleCumulative[$row["date_p"]][$storeId];
+ $sale = 0;
+
+ if (
+ array_key_exists($row["date_p"], $dataSaleCumulative)
+ &&
+ array_key_exists($storeId, $dataSaleCumulative[$row["date_p"]])
+ &&
+ !empty($dataSaleCumulative[$row["date_p"]][$storeId])
+ ) {
+ $sale = $dataSaleCumulative[$row["date_p"]][$storeId];
+ }
if (!array_key_exists($row["date_m"], $write_offs)) {
--- /dev/null
+<?php
+
+
+namespace yii_app\services;
+
+
+use yii_app\helpers\DateHelper;
+
+class HolidayService
+{
+ private static array $holiday = [
+ '2024-03-05',
+ '2024-03-06',
+ '2024-03-07',
+ '2024-03-08',
+ ];
+
+ public static function getHoliday(): array
+ {
+ return self::$holiday;
+ }
+
+
+ public static function getHolidayVersionShow($dateFrom, $dateTo): bool
+ {
+ $datesBetween = DateHelper::getDatesBetween($dateFrom, $dateTo);
+
+ $holidays = self::getHoliday();
+
+ $dayHolidayIn = (array_uintersect($holidays, $datesBetween, "strcasecmp"));
+
+ $dayHolidayVersion = false;
+
+ if (!empty($dayHolidayIn)) {
+ $dayHolidayVersion = true;
+ }
+
+ return $dayHolidayVersion;
+ }
+
+
+ public static function getHolidayDatesBetween($dateFrom, $dateTo): array
+ {
+ $datesBetween = DateHelper::getDatesBetween($dateFrom, $dateTo);
+
+ $holidays = self::getHoliday();
+
+ $dayHolidayIn = (array_uintersect($holidays, $datesBetween, "strcasecmp"));
+
+ $keyInterval = 1;
+ $datesIntervals = [];
+ foreach ($datesBetween as $item) {
+ if (!in_array($item, $holidays)) {
+ $datesIntervals[$keyInterval][] = $item;
+ } else {
+ ++$keyInterval;
+ }
+ }
+
+ $notHolidayDatesInterval = [];
+ if (!empty($datesIntervals)) {
+ foreach ($datesIntervals as $row) {
+ $notHolidayDatesInterval[] = [
+ 'dateFrom' => $row[array_key_first($row)],
+ 'dateTo' => $row[array_key_last($row)],
+ ];
+ }
+ }
+ $holidaysDatesInterval = [];
+
+ if (!empty($dayHolidayIn)) {
+ foreach ($dayHolidayIn as $row) {
+ $holidaysDatesInterval[] = [
+ 'dateFrom' => $row,
+ 'dateTo' => $row,
+ ];
+ }
+ }
+
+ return [
+ 'dayHolidayInArray' => $holidaysDatesInterval,
+ 'notHolidayDatesInterval' => $notHolidayDatesInterval,
+ ];
+ }
+}
\ No newline at end of file
}
-
/**
* "СТАРУЮ МАТРИЦУ" пробитую до 16.11 в зп начисляем как 2,5 %,
* с 16.11 по 7.12 за "СТАРУЮ МАТРИЦУ" НАЧИСЛЯЕМ 2%, после 7.12 ее не считаем в ЗП совсем.
* @param string $adminGuid
* @param string $dateFrom
* @param string $dateTo
+ * @param $isAdministrator
+ * @param null $adminGuids
* @return array
* @throws \yii\db\Exception
*/
- public function getMatrixSalesProducts(string $adminGuid, string $dateFrom, string $dateTo, $isAdministrator) : array
+ public function getMatrixSalesProducts(string $adminGuid, string $dateFrom, string $dateTo, $isAdministrator, $adminGuids = null) : array
{
$adminsGuids = $this->adminsGuids;
$adminId = null;
- if (array_key_exists($adminGuid, $adminsGuids)) {
+ if (array_key_exists($adminGuid, $adminsGuids) && empty($adminGuids)) {
$adminId = ArrayHelper::getValue($adminsGuids, $adminGuid);
}
+ if (!empty($adminGuids) && is_array($adminGuids)) {
+ $adminGuid = implode("','", $adminGuids);
+ }
+
$dateTimeStartDay = false;
$dateTimeEndDay = false;
sales_products as p,
sales
WHERE
- sales.seller_id = :admin_guid
+ sales.seller_id IN ('$adminGuid')
AND
sales.id = p.check_id
AND (
sales.date ASC
",
- [ ':admin_guid' => $adminGuid,
+ [
':date_from' => DateHelper::getDateTimeStartDay($dateFrom, $dateTimeStartDay, $adminId),
':date_to' => DateHelper::getDateTimeEndDay($dateTo, $dateTimeEndDay, $adminId),
]
);
}
+ $action = $command->getRawSql();
+
return $command->queryAll();
}
* @param string $adminGuid
* @param string $dateFrom
* @param string $dateTo
+ * @param bool $isAdministrator
+ * @param null|array $adminGuids
* @return array
* @throws \yii\db\Exception
*/
- public function getMatrixMakeProducts(string $adminGuid, string $dateFrom, string $dateTo, $isAdministrator) : array
+ public function getMatrixMakeProducts(string $adminGuid, string $dateFrom, string $dateTo,bool $isAdministrator, $adminGuids = null) : array
{
$adminsGuids = $this->adminsGuids;
$adminId = null;
- if (array_key_exists($adminGuid, $adminsGuids)) {
+ if (array_key_exists($adminGuid, $adminsGuids) && empty($adminGuids)) {
$adminId = ArrayHelper::getValue($adminsGuids, $adminGuid);
}
+ if (!empty($adminGuids) && is_array($adminGuids)) {
+ $adminGuid = implode("','", $adminGuids);
+ }
+
$dateTimeStartDay = false;
$dateTimeEndDay = false;
$command = $connection->createCommand("
SELECT
DISTINCT (sales.id),
- sales.seller_id,
+ p.seller_id,
sales.date,
sales.number,
(p.summ) AS summ,
sales_products as p,
sales
WHERE
- p.seller_id = :admin_guid
+ p.seller_id IN ('$adminGuid')
AND
sales.id = p.check_id
AND (
sales.date ASC
",
- [':admin_guid' => $adminGuid,
+ [
':date_from' => DateHelper::getDateTimeStartDay($dateFrom, $dateTimeStartDay, $adminId),
':date_to' => DateHelper::getDateTimeEndDay($dateTo, $dateTimeEndDay, $adminId),
]
sales_products as p,
sales
WHERE
- p.seller_id = :admin_guid
+ p.seller_id IN ('$adminGuid')
AND
sales.id = p.check_id
AND (
sales_products as p,
sales
WHERE
- p.seller_id = :admin_guid
+ p.seller_id IN ('$adminGuid')
AND
sales.id = p.check_id
AND (
sales.date <= :date_to
",
- [':admin_guid' => $adminGuid,
+ [
':date_from' => DateHelper::getDateTimeStartDay($dateFrom, $dateTimeStartDay, $adminId),
':date_to' => DateHelper::getDateTimeEndDay($dateTo, $dateTimeEndDay, $adminId),
]
);
}
+
+ $action = $command->getRawSql();
+
+
return $command->queryAll();
}
--- /dev/null
+<?php
+
+return [
+ [
+ 'name' => 'Город тест',
+ 'code' => 'city-test',
+ 'social' => 'socialsocial',
+ 'phone' => '+7 (232) 4-335-647',
+ 'email' => 'nicole.paucek@schultz.info',
+ 'phone_support' => '8 800 770 70 22',
+ 'active' => '1',
+ 'created_at' => '1402312317',
+ 'updated_at' => '1402312317',
+ ],
+];
*
-!.gitignore
\ No newline at end of file
+!.gitignore
--- /dev/null
+_generated
<?php
+namespace backend\tests;
+use Codeception\Actor;
+use Codeception\Lib\Friend;
/**
* Inherited Methods
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
- * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
+ * @method Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
-*/
-class FunctionalTester extends \Codeception\Actor
+ */
+class FunctionalTester extends Actor
{
use _generated\FunctionalTesterActions;
-
+ /**
+ * Define custom actions here
+ */
}
<?php
+namespace backend\tests;
+use Codeception\Actor;
+use Codeception\Lib\Friend;
/**
* Inherited Methods
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
- * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
+ * @method Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
-*/
-class UnitTester extends \Codeception\Actor
+ */
+class UnitTester extends Actor
{
use _generated\UnitTesterActions;
-
/**
* Define custom actions here
*/
--- /dev/null
+<?php
+namespace backend\tests\fixtures;
+
+use yii\test\ActiveFixture;
+
+class CityFixture extends ActiveFixture
+{
+ public $modelClass = 'backend\models\City';
+}
\ No newline at end of file
--- /dev/null
+<?php namespace backend\tests\functional;
+use backend\models\City;
+use backend\tests\fixtures\CityFixture;
+use backend\tests\FunctionalTester;
+use Codeception\Example;
+use common\fixtures\UserFixture;
+
+class CityCest
+{
+ public function _before(FunctionalTester $I)
+ {
+ }
+
+ /**
+ * Load fixtures before db transaction begin
+ * Called in _before()
+ * @see \Codeception\Module\Yii2::_before()
+ * @see \Codeception\Module\Yii2::loadFixtures()
+ * @return array
+ */
+ public function _fixtures()
+ {
+ return [
+ 'user' => [
+ 'class' => UserFixture::className(),
+ 'dataFile' => codecept_data_dir() . 'login_data.php'
+ ],
+ 'city' => [
+ 'class' => CityFixture::className(),
+ 'dataFile' => codecept_data_dir() . 'city.php'
+ ]
+
+ ];
+ }
+
+ /**
+ * @param FunctionalTester $I
+ * @dataProvider pageProvider
+ */
+ public function testSortLinkClick(FunctionalTester $I, Example $data)
+ {
+ $pageH1 = 'Города';
+ $I->amLoggedInAs(1);
+
+ $I->amOnPage('/city/');
+ $I->see($pageH1, 'h1');
+ $I->click(['link' => $data['link']]);
+ $I->see($pageH1, 'h1');
+ $I->seeInTitle($pageH1);
+ $I->click(['link' => $data['link']]);
+ $I->see($pageH1, 'h1');
+ $I->seeInTitle($pageH1);
+
+ }
+
+ /**
+ * @return array
+ */
+ protected function pageProvider()
+ {
+ return [
+ ['link'=>"Название"],
+ ['link'=>"Символьный код"],
+ ['link'=>"Телефон"],
+ ['link'=>"Активность"],
+ ];
+ }
+
+
+
+ /**
+ * @param FunctionalTester $I
+ */
+ public function createCity(FunctionalTester $I)
+ {
+
+ $I->amLoggedInAs(1);
+
+ $I->amOnPage('/city/create/');
+ $I->fillField('City[name]', 'Город Город');
+ $I->fillField('City[code]', 'codecity');
+ $I->fillField('City[phone]', '+7 (132) 4-542-132');
+ $I->click('Сохранить');
+
+ $I->see('Город Город');
+
+ }
+
+ /**
+ * @param FunctionalTester $I
+ */
+ public function viewCity(FunctionalTester $I)
+ {
+ $I->amLoggedInAs(1);
+
+ $model = City::find()->one();
+
+ $urlView = '/city/view/'.$model->id.'/';
+ $name = $model->name;
+ $I->amOnPage($urlView);
+ $I->click(['link' => 'Изменить']);
+
+ $I->see($name);
+
+ }
+
+ /**
+ * @param FunctionalTester $I
+ */
+ public function updateCity(FunctionalTester $I)
+ {
+ $I->amLoggedInAs(1);
+
+ $model = City::find()->one();
+
+ $urlView = '/city/update/'.$model->id.'/';
+ $name = $model->name;
+ $I->amOnPage($urlView);
+ $I->click('Сохранить');
+
+ $I->see($name);
+
+ }
+}
<?php
+/**
+ * Here you can initialize variables via \Codeception\Util\Fixtures class
+ * to store data in global array and use it in Cests.
+ *
+ * ```php
+ * // Here _bootstrap.php
+ * \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
+ * ```
+ *
+ * In Cests
+ *
+ * ```php
+ * \Codeception\Util\Fixtures::get('user1');
+ * ```
+ */
\ No newline at end of file
-# Codeception Test Suite Configuration
-
-# suite for unit (internal) tests.
-# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
-
+suite_namespace: tests\unit
actor: UnitTester
+bootstrap: false
modules:
- enabled:
- - Asserts
- - Yii2:
- part: [orm, email, fixtures]
+ enabled:
+ - Yii2:
+ part: [orm, email, fixtures]
+ - Asserts
+coverage:
+ enabled: true
+ whitelist:
+ include:
+ - models/*
<?php
-
-// add unit testing specific bootstrap code here
+/**
+ * Here you can initialize variables via \Codeception\Util\Fixtures class
+ * to store data in global array and use it in Tests.
+ *
+ * ```php
+ * // Here _bootstrap.php
+ * \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
+ * ```
+ *
+ * In Tests
+ *
+ * ```php
+ * \Codeception\Util\Fixtures::get('user1');
+ * ```
+ */
--- /dev/null
+<?php
+
+namespace backend\tests\unit\models;
+
+use Codeception\Test\Unit;
+use common\tests\UnitTester;
+use Yii;
+use backend\models\City;
+use backend\tests\fixtures\CityFixture;
+
+/**
+ * Login form test
+ */
+class CityTest extends Unit
+{
+ /**
+ * @var UnitTester
+ */
+ protected $tester;
+ protected $className;
+
+ protected function _before()
+ {
+
+ $this->className = City::className();
+
+ }
+
+
+ /**
+ * @return array
+ */
+ public function _fixtures()
+ {
+ return [
+ 'city' => [
+ 'class' => CityFixture::className(),
+ 'dataFile' => codecept_data_dir() . 'city.php'
+ ]
+ ];
+ }
+
+ public function testEmptyValues()
+ {
+ $model = new $this->className;
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ }
+
+ public function testNameOnly()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'name' => 'Город'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+
+ }
+ public function testWrongName()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'name' => 'one title'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key name must have in array errors', $model->errors)->hasKey('name');
+
+ }
+
+ public function testShortName()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'name' => 'H'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key name must have in array errors', $model->errors)->hasKey('name');
+
+ }
+
+ public function testFieldActiveNotInteger()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'active' => 'string'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key active must have in array errors', $model->errors)->hasKey('active');
+
+ }
+
+ public function testLongPhoneSupport()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'phone_support' => '123456789012345678901'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key phone_support must have in array errors', $model->errors)->hasKey('phone_support');
+
+ }
+
+ /**
+ * @dataProvider providerIntegerFields
+ */
+ public function testIntegerFieldsWrongSetRussianText($a)
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ $a => 'Название'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key '.$a.' must have in array errors', $model->errors)->hasKey($a);
+
+ }
+
+ /**
+ * @return array
+ */
+ public function providerIntegerFields()
+ {
+ $obj = new City();
+ return $obj->getAllFieldsGroupByType()->getFieldsByType('integer');
+ }
+
+
+ public function testLongPhone()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'phone' => '123456789012345678901'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key phone must have in array errors', $model->errors)->hasKey('phone');
+
+ }
+
+ public function testLongName()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'name' => 'цщукзшгецзщушкгезщцушкгезщцшугкещзшугкцезщшгцзукешгцушгкеншщцугкенщшгншщгцункещшцгукеншщгцкежрлордорфжваопрфваопрылжвоапрыдлвоапрывалопрылдвоапрылваопрлыдпаловаарыплдоршдкгеншгукрпвшгкеершупоыаршгнкешыгарлыовврппршгыукрлпоыршгыукршшывгралопршыгкршорпчлоавр'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key name must have in array errors', $model->errors)->hasKey('name');
+
+ }
+
+ public function testLongCode()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'code' => 'qwertwpieurtypiweurtyiweurtyioweurytioweurytioweurtyioaslkjdfhklajfhlkjahfklgjahdkfjghkadjfgkajdfgkajddfhgkajddfhkgkjaddhfkgkjadhfkgkjahdkfjghklazcvbvbzkcvjhblzkcvjhblkzjcvhblkzuvycoiuzyoiuyzouvybozhvblzvzuvbhoizuvcybiozucvhbzjcvhobzciuvhkjewrhtklwjehrtklj'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key code must have in array errors', $model->errors)->hasKey('code');
+
+ }
+
+//[['name', 'code', 'phone', 'email'], 'string', 'min' => 2, 'max' => 255],
+ public function testShortPhoneSupport()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'phone_support' => '1'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key phone_support must have in array errors', $model->errors)->hasKey('phone_support');
+
+ }
+
+ public function testShortPhone()
+ {
+ $model = new $this->className;
+
+ $model->attributes = [
+ 'phone' => '1'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key phone must have in array errors', $model->errors)->hasKey('phone');
+
+ }
+
+ public function testNotUniqueName()
+ {
+ $model = new $this->className;
+
+ $nameCityTest = 'Город тест';
+
+ $model->attributes = [
+ 'name' => $nameCityTest,
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect($model->getFirstError('name'));
+ expect('key name must have in array errors', $model->errors)->hasKey('name');
+
+ }
+
+ public function testNotUniqueCode()
+ {
+ $model = new $this->className;
+
+ $codeTest = 'city-test';
+
+// $message = 'Значение «'.$codeTest.'» для «Символьный код» уже занято.';
+
+ $model->attributes = [
+ 'code' => $codeTest,
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+ expect('key code must have in array errors', $model->errors)->hasKey('code');
+ }
+
+ public function testWrongCode()
+ {
+ $model = new $this->className;
+
+ $codeTest = 'фываы';
+
+// $message = 'Значение «'.$codeTest.'» для «Символьный код» уже занято.';
+
+ $model->attributes = [
+ 'code' => $codeTest,
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+// $test = $model->getFirstError('code');
+// expect($model->getFirstError('code'))->equals($message);
+ expect('key code must have in array errors', $model->errors)->hasKey('code');
+
+ }
+
+ public function testCityWrongMail()
+ {
+ $model = new $this->className;
+ $model->attributes = [
+ 'email' => 'WrongMail'
+ ];
+
+ $validate = $model->validate();
+
+ expect('Validation should be failed', $validate)->false();
+ expect($model->hasErrors())->true();
+// expect($model->getFirstError('email'))->equals('Значение «E-mail» не является правильным email адресом.');
+ expect('key email must have in array errors', $model->errors)->hasKey('email');
+ }
+
+ public function testTrueCity()
+ {
+ $model = new $this->className;
+ $expectedAttrs = [
+ 'name' => 'Город Тест Тест',
+ 'code' => 'testcode',
+ 'phone' => '+7 (332) 4-375-847',
+ 'email' => 'nicuole.pacek@schultz.info',
+ 'phone_support' => '8 800 770 70 22',
+ 'active' => '1',
+ 'created_at' => '1402312317',
+ 'updated_at' => '1402312317',
+ ];
+
+ $model->attributes = $expectedAttrs;
+
+ expect('Validation should be success', $model->validate())->true();
+ expect($model->hasErrors())->false();
+
+ $this->assertTrue($model->save());
+
+ $expectedAttrs['id'] = $model->id;
+
+ $city = City::find()->where(['id' =>$expectedAttrs['id']])->one();
+ $this->assertNotNull($city);
+
+ $this->assertEquals($expectedAttrs['name'], $city->name);
+ $this->tester->assertEquals($expectedAttrs['name'], $city->name);
+
+ $this->assertEquals($expectedAttrs['email'], $city->email);
+ $this->assertEquals($expectedAttrs['code'], $city->code);
+
+ }
+
+ public function testDeleteCity()
+ {
+ // delete
+ $record = new $this->className;
+ $record->name = 'Город Тест Тест Первый Тест';
+ $record->code = 'testcode';
+ $record->phone = '+7 (332) 4-375-847';
+ $record->email = 'nicuole.pacek@schultz.info';
+ $record->phone_support = '8 800 770 70 22';
+ $record->active = 1;
+ $record->created_at = 1402312317;
+ $record->updated_at = 1402312317;
+
+ $record->save();
+
+ $recordId = $record->id;
+
+ $record = City::findOne($recordId);
+ $record->delete();
+ $record = City::findOne($recordId);
+ $this->assertNull($record);
+
+ // deleteAll
+ $record = new $this->className;
+ $record->name = 'Город Тест Тест Второй Тест';
+ $record->code = 'testcode';
+ $record->phone = '+7 (332) 4-375-847';
+ $record->email = 'nicuole.pacek@schultz.info';
+ $record->phone_support = '8 800 770 70 22';
+ $record->active = 1;
+ $record->created_at = 1402312317;
+ $record->updated_at = 1402312317;
+ $record->save();
+
+ $ret = City::deleteAll(['name' => 'Город Тест Тест Второй Тест']);
+ $this->assertEquals(1, $ret);
+ $records = City::find()->where(['name' => 'Город Тест Тест Второй Тест'])->all();
+ $this->assertEquals(0, count($records));
+ }
+}
]); ?>
<?= $form->field($model, 'year')->dropDownList(
- array_combine(range(2022,2026),range(2022,2026))
+ array_combine(range(2022,2028),range(2022,2028))
) ?>
<?= $form->field($model, 'month')->dropDownList(
<?= $form->field($model, 'retention')->textInput() ?>
+ <?= $form->field($model, 'retention_comment')->textarea() ?>
+
+ <?= $form->field($model, 'part_time_job_hours')->textInput() ?>
+
<?= $form->field($model, 'shift_correction')->textInput() ?>
<?= $form->field($model, 'prepaid_expense')->textInput() ?>
<?= $form->field($model, 'vacation_day')->textInput() ?>
<?= $form->field($model, 'retention')->textInput() ?>
+ <?= $form->field($model, 'retention_comment')->textarea() ?>
+ <?= $form->field($model, 'part_time_job_hours')->textInput() ?>
<?= $form->field($model, 'shift_correction')->textInput() ?>
$this->params['breadcrumbs'][] = ['label' => 'Персональные премии, авансы и подсчёт ', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
-<div class="admin-person-bonuses-create">
+<div class="admin-person-bonuses-create m-5">
<h1><?= Html::encode($this->title) ?></h1>
$this->title = 'Персональные премии, авансы и подсчёт';
$this->params['breadcrumbs'][] = $this->title;
?>
-<div class="admin-person-bonuses-index">
+<div class="admin-person-bonuses-index m-5">
<h1><?= Html::encode($this->title) ?></h1>
$this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Изменмть';
?>
-<div class="admin-person-bonuses-update">
+<div class="admin-person-bonuses-update m-5">
<h1><?= Html::encode($this->title) ?></h1>
$this->params['breadcrumbs'][] = $this->title;
\yii\web\YiiAsset::register($this);
?>
-<div class="admin-person-bonuses-view">
+<div class="admin-person-bonuses-view m-5">
<h1><?= Html::encode($this->title) ?></h1>
'color_ruble_bonuses',
'vacation_day',
'retention',
+ 'retention_comment',
+ 'part_time_job_hours',
'shift_correction',
'prepaid_expense',
'counting',
<th>Магазин</th>
<th>Число сотрудников в смене</th>
<th>Сотрудники смены</th>
- <th>Нормы смены магазина</th>
<th>Продажи магазина (00:00 - 23:59)</th>
- <th>Норма смена сотрудника</th>
<th>Сумма продаж сотрудника</th>
<th>Число чеков сотрудника</th>
<th>Сумма оклада за смену</th>
<th>Средний чек магазина</th>
- <th>Баллы геймификации</th>
</thead>
<?php
<td><?php echo $item['typeSmena'] ?></td>
<td><?php echo $storeName ?></td>
<td><?php echo $item['count_admin_store'] ?></td>
- <td><?php echo $item['adminNameWithRateList'] ?></td>
- <td><?php echo $item['normaSmenaAdminsSumByLevelList'] ?></td>
+ <td><?php echo $item['adminNameList'] ?></td>
<td><?php echo HtmlHelper::getNumberFormat($item['adminsSalesSum']) ?></td>
- <td><?php echo HtmlHelper::getNumberFormat($item['normaSmena']['rate_1_condition']) ?></td>
<td><?php echo HtmlHelper::getNumberFormat($item['daySale']) ?></td>
<td><?php echo $item['countCheckByDay'] ?></td>
<td><?php echo HtmlHelper::getNumberFormat($item['wages']) ?></td>
<td><?php echo HtmlHelper::getNumberFormat($avgCheckValue) ?></td>
- <td><?php echo $item['game']['values_sum'] ?></td>
</tr>
<?php
$key++;
<td></td>
<td></td>
<td></td>
- <td></td>
- <td></td>
<td><?php echo HtmlHelper::getNumberFormat($wagesAdminAnotherStore[$storeKey]) ?></td>
<td></td>
- <td></td>
</tr>
</table>
</div>
<?php
}?>
- <h4>Сумма баллов геймификации <?php echo $context ?> : <?php echo $adminSumGameBonus?></h4>
<?php
}
--- /dev/null
+<?php
+
+/* @var $toPayoff float */
+/* @var $alreadyPay float */
+/* @var $alreadyPaySum float */
+
+use yii_app\helpers\HtmlHelper;
+
+if (!empty($alreadyPay) && !empty($alreadyPaySum)) {
+ ?>
+ <br>
+
+ <b>Таблица выплат за выбранный месяц:</b>
+ <table class=" table table-border">
+ <thead>
+ <th>Название</th>
+ <th>Сумма, руб</th>
+ </thead>
+ <?php
+ foreach ($alreadyPay as $keyName => $value) {
+ ?>
+ <tr>
+ <td><?php echo $keyName ?></td>
+ <td><?php echo HtmlHelper::getNumberFormat($value) ?> </td>
+ </tr><?php
+ }
+ ?>
+ <tfoot>
+ <th></th>
+ <th><?php echo HtmlHelper::getNumberFormat($alreadyPaySum) ?></th>
+ </tfoot>
+
+ </table>
+ <?php
+}
+?>
+
+<?php
+
+if (!empty($toPayoff)) {
+ ?>
+ <br>
+ <b>К выплате</b> за выбранный месяц <b><?php echo HtmlHelper::getNumberFormat($toPayoff) ?> руб</b>
+ <br>
+ <?php
+}
+?>
$endKey = 1;
echo '<br><h4>Персональные показатели</h4>';
-echo '<br> Сумма баллов геймификации : ' . $clusterAdminSumGameBonus;
echo '<br> Число магазинов : ' . $administratorCountInRating;
-echo '<br> Среднее значение баллов геймификации : ' . $clusterAdminAvgSumGameBonus;
-if (!empty($ratingPerson)) {
- echo '<br> Ваш рейтинг по ' . $ratingBy . ' : ' . $ratingPerson . ' из ' . $countRatingList;
-}
$tbl = '';
-if (!empty($ratingList)){
- $tbl = '';
-
- $arrayReverseKeys = array_reverse(array_keys($ratingList));
-
- foreach ($ratingList as $key => $row) {
- $firstKeys = range(0,$endKey);
-
- $cssCurrentUser = '';
- $cssCurrentUserCell = '';
- if ($clusterAdminId == $row['admin_id']) {
- $cssCurrentUser = 'table-info';
- $cssCurrentUserCell = 'bg-orange-lighter';
- }
-
- $sortArray = [];
- foreach ( $firstKeys as $item) {
- if (array_key_exists($item, $arrayReverseKeys)) {
- $sortArray[] = $arrayReverseKeys[$item];
- }
- }
-
-
- if ($clusterAdminId == $row['admin_id']) {
- $cssCurrentUser .= ' border-info';
- }
-
- $addText = '';
- $addText = ' (' . $row['value'] . ' балов/' . $row['administrators_count'] . ' администраторов)';
-
- $tbl .= "<tr class='" . $cssCurrentUser . "'>
- <td>" . $row['rating'] . " </td>
- <td>" . $row[$valueKey] . $addText . "</td>
- <td class='" . $cssCurrentUserCell . "'>" . $row['admin']['name_full'] . " </td>
- </tr>";
-
- }
-
-
- $sumRow = '
- <tr>
- <td></td>
- <td>Сумма баллов ' . $ratingListSum . '</td>
- <td></td>
- </tr>
- ';
-
-
-echo'
- <div class="block_info">
- <span class="btn_toggle_block" >показать рейтинг<i class="arrow down"></i></span>
- <div class="block_body block_body_hide">
- <table class="salary table table-border">
- <thead>
- <th>Рейтинг</th>
- <th>' . $valueName . '</th>
- <th>Имя</th>
- </thead>
-
- <tbody>
- ' . $tbl . '
- ' . $sumRow . '
- </tbody>
- </table>
- </div>
- </div>
-
- <br>';
-} else {
- echo '<br> рейтинга нет';
-}
+
--- /dev/null
+<?php
+
+use yii_app\helpers\DataHelper;
+use yii_app\helpers\HtmlHelper;
+
+
+/* @var $consolidatedPremiumByFocusGroups array */
+/* @var $consolidatedArrUsersSalaryCheck array */
+/* @var $consolidatedPremiumByStore float */
+/* @var $onePartHolidayPremium float */
+/* @var $adminsHolidayShiftCount float */
+/* @var $personPremiumByStore float */
+/* @var $personHolidayShiftCount float */
+
+
+$this->registerCssFile('/yii_app/css/common/block-info.css');
+$this->registerJsFile('/yii_app/js/common/block-info.js', ['position' => \yii\web\View::POS_END]);
+
+
+echo '<h4>Блок премирования магазина <br>за продажу фокусных позиций в мартовские праздники</h4>';
+
+
+if (!empty($consolidatedPremiumByFocusGroups)) {
+
+ $fields = [
+ 0 => [
+ 'name' => ' услуг ',
+ 'percentText' => ' 10% ',
+ 'keySum' => 'userSalaryServices',
+ 'keyPremium' => 'userSalaryServicesPremium',
+ 'alias' => 'services',
+ 'tableName' => 'продажи услуг',
+ ],
+ 1 => [
+ 'name' => ' сопутки ',
+ 'percentText' => ' 5% ',
+ 'keySum' => 'userSalaryRelated',
+ 'keyPremium' => 'userSalaryRelatedPremium',
+ 'alias' => 'related',
+ 'tableName' => 'продажи сопутки',
+ ],
+ 2 => [
+ 'name' => ' горшечки ',
+ 'percentText' => ' 5% ',
+ 'keySum' => 'userSalaryPotted',
+ 'keyPremium' => 'userSalaryPottedPremium',
+ 'alias' => 'potted',
+ 'tableName' => 'продажи горшечки',
+ ],
+ 3 => [
+ 'name' => ' упаковки ',
+ 'percentText' => ' 5% ',
+ 'keySum' => 'userSalaryWrap',
+ 'keyPremium' => 'userSalaryWrapPremium',
+ 'alias' => 'wrap',
+ 'tableName' => 'продажи упаковки',
+ ],
+ 4 => [
+ 'name' => ' пиротехники ',
+ 'percentText' => ' 5% ',
+ 'keySum' => 'userSalarySalut',
+ 'keyPremium' => 'userSalarySalutPremium',
+ 'alias' => 'salut',
+ 'tableName' => 'продажи пиротехники',
+ ],
+ 5 => [
+ 'name' => ' не фокусных товаров ',
+ 'percentText' => ' 1% ',
+ 'keySum' => 'userSalaryOtherItems',
+ 'keyPremium' => 'userSalaryOtherItemsPremium',
+ 'alias' => 'other_items',
+ 'tableName' => 'продажи не фокусных товаров',
+ ],
+ ];
+
+ foreach ($fields as $field) {
+ if (!empty($consolidatedPremiumByFocusGroups[$field['keySum']])) {
+ echo '<br> Факт продаж ' . $field['name'] . ' : ' . HtmlHelper::getNumberFormat($consolidatedPremiumByFocusGroups[$field['keySum']]) . ' руб';
+ echo '<br> Премия за продажу ' . $field['name'] . ' ' . $field['percentText'] . ' : ' . HtmlHelper::getNumberFormat($consolidatedPremiumByFocusGroups[$field['keyPremium']]) . ' руб';
+
+ echo $this->render('_table_salary_checks', [
+ 'arrUsersSalary' => $consolidatedArrUsersSalaryCheck[$field['alias']],
+ 'tableName' => $field['tableName'],
+ 'userSalarySum' => $consolidatedPremiumByFocusGroups[$field['keySum']],
+ 'sellerShow' => true,
+ ]);
+
+ } else {
+ echo '<br> Факта продажи ' . $field['name'] . ' нет<br>';
+ }
+ }
+
+ if (!empty($consolidatedPremiumByFocusGroups['userSalaryPremiumSum'])) {
+ echo '<br><h5>Сумма премии магазина за продажу фокусных позиций <b>' . HtmlHelper::getNumberFormat($consolidatedPremiumByFocusGroups['userSalaryPremiumSum']) . ' руб </b></h5>';
+ }
+
+}
+
+/**/
+
+$textInfoMatrix = ' 2% ';
+
+if (!empty($consolidatedPremiumByMatrix) && !empty($consolidatedPremiumByMatrix['salesMatrix'])) {
+
+ echo"<br>";
+ echo"<h4>Продажи букетов по матрице за праздники по магазину</h4>";
+ echo"<h5>Проданные букеты по матрице за праздники</h5>";
+
+ $tbl = '';
+
+ foreach ($consolidatedPremiumByMatrix['salesMatrix'] as $row) {
+ $tbl .= "<tr><td>" . $row["date"] . " </td><td>" . $row["admin_name"] . " </td><td>" . $row["operation"] . " </td><td> " . $row["number"] . " </td><td> " . $row["product_name"] . " </td><td> " . HtmlHelper::getNumberFormat($row["summ"]) . " </td><td>" . HtmlHelper::getNumberFormat($row["bonus"]) . " </td></tr>";
+ }
+
+ echo'
+ <div class="block_info">
+ <span class="btn_toggle_block" >показать список<i class="arrow down"></i></span>
+ <div class="block_body block_body_hide">
+ <table class="salary table table-border">
+ <thead>
+ <th>Дата</th>
+ <th>Сотрудник</th>
+ <th>Операция</th>
+ <th>Название чека</th>
+ <th>Букет</th>
+ <th>Сумма</th>
+ <th>Бонус</th>
+ </thead>
+ <tbody>' . $tbl . '</tbody>
+ </table>
+ <p class="p-3">
+ <span>Число чеков ' . count($consolidatedPremiumByMatrix['salesMatrix']) . '</span>
+ </p>
+ </div>
+ <br>
+ <div>
+ Сумма продаж матрицы ' . HtmlHelper::getNumberFormat($consolidatedPremiumByMatrix['salaryMatrix']) . ' руб * ' . $textInfoMatrix . ' = ' . HtmlHelper::getNumberFormat($consolidatedPremiumByMatrix['bonusSalaryMatrix']) . ' руб
+ </div>
+ </div>
+
+ <br>';
+} else {
+ echo '<br> Продаж по матрице нет';
+}
+
+echo"<h5>Собранные букеты по матрице за праздники</h5>";
+
+if (!empty($consolidatedPremiumByMatrix) && !empty($consolidatedPremiumByMatrix['makeMatrix'])) {
+
+ $tbl2 = '';
+
+ foreach ($consolidatedPremiumByMatrix['makeMatrix'] as $row) {
+ $tbl2 .= "<tr><td>" . $row["date"] . " </td><td>" . $row["admin_name"] . " </td><td>" . $row["operation"] . " </td><td> " . $row["number"] . " </td><td> " . $row["product_name"] . " </td><td> " . HtmlHelper::getNumberFormat($row["summ"]) . " </td><td>" . HtmlHelper::getNumberFormat($row["bonus"]) . " </td></tr>";
+ }
+
+ echo'
+ <div class="block_info">
+ <span class="btn_toggle_block" >показать список<i class="arrow down"></i></span>
+ <div class="block_body block_body_hide">
+ <table class="salary table table-border">
+ <thead>
+ <th>Дата</th>
+ <th>Сотрудник</th>
+ <th>Операция</th>
+ <th>Название чека</th>
+ <th>Букет</th>
+ <th>Сумма</th>
+ <th>Бонус</th>
+ </thead>
+ <tbody>' . $tbl2 . '</tbody>
+ </table>
+ <p class="p-3">
+ <span>Число чеков ' . count($consolidatedPremiumByMatrix['makeMatrix']) . '</span>
+ </p>
+ </div>
+ <br>
+ <div>
+ Сумма продаж собранных букетов матрицы ' . HtmlHelper::getNumberFormat($consolidatedPremiumByMatrix['salaryMakeMatrix']) . ' руб * ' . $textInfoMatrix . ' = ' . HtmlHelper::getNumberFormat($consolidatedPremiumByMatrix['bonusMakeMatrix']) . ' руб
+ </div>
+ </div>
+
+ <br>';
+} else {
+ echo '<b>Собранных букутов нет</b> <br>';
+}
+
+if (!empty($consolidatedPremiumByMatrix['matrixPrime'])) {
+ echo '<br><h5>Сумма премии магазина за матрицу: <b>' . HtmlHelper::getNumberFormat($consolidatedPremiumByMatrix['matrixPrime']) . ' руб </b></h5>';
+}
+
+
+
+echo '<br><h5>Сумма премии магазина за продажу фокусных позиций и матрицы </h5>';
+echo '<div>'
+ . HtmlHelper::getNumberFormat($consolidatedPremiumByFocusGroups['userSalaryPremiumSum'] ?? 0) .
+ ' руб + '
+ . HtmlHelper::getNumberFormat($consolidatedPremiumByMatrix['matrixPrime'] ?? 0) .
+ ' руб = ' . HtmlHelper::getNumberFormat($consolidatedPremiumByStore) . ' руб </div>';
+echo '<br><h5>Общая сумма премии магазина: <b>' . HtmlHelper::getNumberFormat($consolidatedPremiumByStore) . ' руб </b></h5>';
+echo '<br><h5>Число смен сотрудников, работающих в праздники: ' . DataHelper::ruPlural($adminsHolidayShiftCount, ['смена', 'смены', 'смен']) . '</h5>';
+echo '<br><h5>Премия за одну смену: ' . HtmlHelper::getNumberFormat($onePartHolidayPremium) . ' руб</h5>';
+echo '<br><h5>В праздники вы отработали: ' . DataHelper::ruPlural($personHolidayShiftCount, ['смену', 'смены', 'смен']) . '</h5>';
+echo '<br><h5>Ваша часть премии за продажу фокусных позицый в праздники: <b>' . HtmlHelper::getNumberFormat($personPremiumByStore) . ' руб</b></h5>';
+echo '<br>';
+echo '<br>';
+echo '<br>';
+
+
+/**/
\ No newline at end of file
}
?>
<?php
+$monthlySalaryRow = null;
+if (!empty($administratorOklad) && $isAdministrator) {
+ $monthlySalaryRow = HtmlHelper::getNumberFormat($administratorOklad);
+}
if (!empty($monthlySalary) && array_key_exists('monthly_salary', $monthlySalary) && !$isAdministrator) {
- echo "<br> <b>Оклад : " . HtmlHelper::getNumberFormat($monthlySalary['monthly_salary']) . " руб.</b>";
+ $monthlySalaryRow = HtmlHelper::getNumberFormat($monthlySalary['monthly_salary']);
+}
+
+if (!empty($monthlySalaryRow)) {
+ echo "<br> <b>Оклад : " . $monthlySalaryRow . " руб.</b>";
}
?>
echo " <h3>Сумма продаж по первому блоку премирования </h3>";
echo '<br><h4>Первый блок премирования: продажа фокусных позиций</h4>';
+if (!empty($showHolidayVersion)) {
+ echo '<p><b>Премии за продажу фокусных позиций в мартовские праздники (с 05.03.2024 по 08.03.2024 ) <br> в Блоке премирования магазина</b></p>';
+}
+
$tbl = '';
'teamBonus' => $teamBonus,
]);
}
+if (!empty($adminTeamPayrollTable)) {
+ echo '<br>';
+
+ echo $this->render('_table_team_payroll', [
+ 'teamBonus' => $teamBonus,
+ 'adminTeamPayrollTable' => $adminTeamPayrollTable,
+ ]);
+}
echo '<h5>Командная премия : ' . HtmlHelper::getNumberFormat($teamBonusValue) . ' руб</h5>';
/* @var $arrUsersSalary array */
/* @var $userSalarySum float */
/* @var $tableName string */
+/* @var $sellerShow bool */
use yii_app\helpers\HtmlHelper;
$tbl = '';
foreach ($arrUsersSalary as $row) {
- $tbl .= "<tr><td>" . $row["date"] . " </td><td>" . $row["operation"] . " </td><td> " . $row["number"] . " </td><td>" . HtmlHelper::getNumberFormat($row["bonus"]) . " </td></tr>";
+ $tbl .= "<tr><td>" . $row["date"] . " </td>";
+ if ($sellerShow) {
+ $tbl .= "<td>" . $row["name"] . " </td>";
+ }
+ $tbl .= "<td>" . $row["operation"] . " </td><td> " . $row["number"] . " </td><td>" . HtmlHelper::getNumberFormat($row["bonus"]) . " </td></tr>";
}
- $tbl .= "<tr><td></td><td></td><td></td><td>" . HtmlHelper::getNumberFormat($userSalarySum) . " </td></tr>";
+
+ $tbl .= "<tr>
+ <td></td><td></td><td></td>";
+ if ($sellerShow) {
+ $tbl .= "<td></td>";
+ }
+ $tbl .= "<td>" .HtmlHelper::getNumberFormat($userSalarySum) . " </td></tr>";
+
+ $tblHeader = "<thead>
+ <th>Дата</th>
+ ";
+ if ($sellerShow) {
+ $tblHeader .= "<th>Продавец</th>";
+ }
+ $tblHeader .= " <th>Операция</th>
+ <th>Название</th>
+ <th>Сумма руб.</th>
+ </thead>";
echo'
<div class="block_info">
<span class="btn_toggle_block" >показать список ' . $tableName . '<i class="arrow down"></i></span>
<div class="block_body block_body_hide">
<table class="salary table table-border">
- <thead>
- <th>Дата</th>
- <th>Операция</th>
- <th>Название</th>
- <th>Сумма руб.</th>
- </thead>
+ ' . $tblHeader . '
<tbody>' . $tbl . '</tbody>
</table>
</div>
--- /dev/null
+<?php
+
+
+/* @var $winStoreIdDayChallenge array */
+/* @var $cityStoreNames array */
+/* @var $adminTeamPayrollTable array */
+/* @var $teamBonus array */
+
+use yii\helpers\ArrayHelper;
+
+$this->registerCssFile('/yii_app/css/common/block-info.css');
+$this->registerJsFile('/yii_app/js/common/block-info.js', ['position' => \yii\web\View::POS_END]);
+
+if (!empty($adminTeamPayrollTable)) {
+
+ $tbl = '';
+//
+// 'adminPayDayAll'
+//'payrollVariableDaysAll'
+ /*
+ * $result[$admin['id']]['admin_id'] = $admin['id'];
+ $result[$admin['id']]['admin_name'] = $admin['name'];
+ $result[$admin['id']]['group_name'] = $admin['group_name'];
+ $daysRow = [];
+
+ foreach ($days as $day) {
+ $keyAdminIdDateRow = $admin['id'] . '_' . $day;
+ $payConstantRow = 0;
+ if (array_key_exists($keyAdminIdDateRow, $teamBonusAdminPayDayAll)) {
+ $payConstantRow = ArrayHelper::getValue($teamBonusAdminPayDayAll, $keyAdminIdDateRow);
+ }
+ $payVariableRow = 0;
+
+ if (array_key_exists($keyAdminIdDateRow, $teamBonusPayrollVariableDaysAll)) {
+ $payVariableRow = ArrayHelper::getValue($teamBonusPayrollVariableDaysAll, $keyAdminIdDateRow);
+ }
+ $daysRow[$day] = [
+ 'pay_constant' => $payConstantRow,
+ 'pay_variable' => $payVariableRow,
+ ];
+ * */
+
+ foreach ($adminTeamPayrollTable as $key => $row) {
+// $storeIdKey =array_key_first($row);
+// $rowValue = $row[array_key_first($row)];
+
+
+ $tbl .= "<tr>";
+ $tbl .= "<td>" . $row['admin_name'] . " </td><td>" . $row['group_name'] . " </td>";
+
+ foreach ($row['days'] as $keyDay => $rowDayValue) {
+ $rowPayConstant = $rowDayValue['pay_constant'] ?? '-';
+ $rowPayVariable = $rowDayValue['pay_variable'] ?? '-';
+ $tbl .= "<td>" . $rowPayConstant . " </td><td> " . $rowPayVariable . " </td>";
+ }
+
+ $tbl .= "</tr>";
+ }
+
+ $days = $teamBonus['days'] ?? [];
+ $tblHead = "<tr>";
+ $tblHead .= "<td>Сотрудник</td>";
+ $tblRowTwo = "<tr><td>Дата</td>";
+ foreach ($adminTeamPayrollTable as $key => $row) {
+
+ $tblHead .= "<td colspan='2'>" . $row['admin_name'] . " (" . $row['group_name'] . ") </td>";
+
+ $tblRowTwo .= "<td>Оклад</td>";
+ $tblRowTwo .= "<td>Премия</td>";
+
+ }
+ $tblRowTwo .= "<tr>";
+ $tblHead .= "</tr>";
+
+ $tblRow = "";
+ foreach ($days as $day) {
+ $tblRow .= "<tr>";
+ $tblRow .= "<td>" . $day . "</td>";
+ foreach ($adminTeamPayrollTable as $key => $row) {
+
+
+ if (!empty($row['days'][$day])) {
+ $rowDayValue = $row['days'][$day];
+ $rowPayConstant = $rowDayValue['pay_constant'] ?? '-';
+ $rowPayVariable = $rowDayValue['pay_variable'] ?? '-';
+ $tblRow .= "<td>" . $rowPayConstant . "</td>";
+ $tblRow .= "<td>" . $rowPayVariable . "</td>";
+ }
+ }
+
+ $tblRow .= "</tr>";
+
+ }
+
+
+
+ echo'
+ <div class="block_info">
+ <span class="btn_toggle_block" >Оклады и премии магазина в командном бонусе<i class="arrow down"></i></span>
+ <div class="block_body block_body_hide">
+ <div class="table-responsive">
+ <table class="table table-bordered">
+ <thead>
+ ' . $tblHead . '
+ ' . $tblRowTwo . '
+ </thead>
+ <tbody>
+ ' . $tblRow . '
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <br>
+ </div>
+
+ <br>';
+} else {
+ echo '<br> <br> <b>Нет данных</b> <br>';
+}
\ No newline at end of file
/* @var $sumColumnWages float */
/* @var $teamBonusValue float */
/* @var $teamBonus array */
+/* @var $adminTeamPayrollTable array */
+
+
+/* @var $personRetention float */
+/* @var $personRetentionArray array */
+/* @var $sumPersonRetention float */
+
+/* @var $personPrepaidExpense float */
+/* @var $toPayoff float */
+/* @var $alreadyPay float */
+/* @var $alreadyPaySum float */
+
+/* @var $allowShowPersonRetention bool */
+
+/* @var $showHolidayVersion bool */
+
+/* @var $consolidatedArrUsersSalaryCheck array */
+/* @var $consolidatedPremiumByFocusGroups array */
+/* @var $consolidatedPremiumByMatrix array */
+/* @var $consolidatedPremiumByStore float */
+/* @var $onePartHolidayPremium float */
+/* @var $adminsHolidayShiftCount float */
+/* @var $personPremiumByStore float */
+/* @var $personHolidayShiftCount float */
'normalCostShift' => $normalCostShift,
'monthNameSelect' => $monthNameSelect,
'yearSelect' => $yearSelect,
+ 'administratorOklad' => $administratorOklad,
]); ?>
<?php
'userQualityPremium' => $userQualityPremium,
'teamBonus' => $teamBonus,
'teamBonusValue' => $teamBonusValue,
+ 'adminTeamPayrollTable' => $adminTeamPayrollTable,
+ 'showHolidayVersion' => $showHolidayVersion
]);
?>
+ <?php
+ if ($showHolidayVersion) {
+ echo $this->render('_holiday_table_values', [
+ 'consolidatedArrUsersSalaryCheck' => $consolidatedArrUsersSalaryCheck,
+ 'consolidatedPremiumByFocusGroups' => $consolidatedPremiumByFocusGroups,
+ 'consolidatedPremiumByMatrix' => $consolidatedPremiumByMatrix,
+ 'consolidatedPremiumByStore' => $consolidatedPremiumByStore,
+ 'onePartHolidayPremium' => $onePartHolidayPremium,
+ 'adminsHolidayShiftCount' => $adminsHolidayShiftCount,
+ 'personPremiumByStore' => $personPremiumByStore,
+ 'personHolidayShiftCount' => $personHolidayShiftCount,
+ ]);
+ }
+ ?>
+
<?php
if (!empty($salaryByAdmin)) {
echo "<b><h3> Продажи " . HtmlHelper::getNumberFormat($salaryByAdmin) . " руб </h3></b> ";
<br>
<h4>Сумма окладов и премий за выбранный период <b><?php echo HtmlHelper::getNumberFormat($allTotalAdministrator) ?> руб</b></h4>
+
+ <?php
+
+ if (!empty($personRetention)) {
+ ?>
+ <br>
+
+ <b>Таблица персональных вычетов за выбранный месяц:</b>
+ <table class=" table table-border">
+ <thead>
+ <th>Название</th>
+ <th>Сумма, руб</th>
+ </thead>
+ <?php
+ foreach ($personRetentionArray as $keyName => $value) {
+ ?>
+ <tr>
+ <td><?php echo $keyName ?></td>
+ <td><?php echo HtmlHelper::getNumberFormat($value) ?> </td>
+ </tr><?php
+ }
+ ?>
+ <tfoot>
+ <th></th>
+ <th><?php echo HtmlHelper::getNumberFormat($sumPersonRetention) ?></th>
+ </tfoot>
+
+ </table>
+ <?php
+ }
+ ?>
+
+ <?php
+ if (!empty($allowShowPersonRetention)) {
+ echo $this->render('_already_pay_in_month', [
+ 'toPayoff' => $toPayoff,
+ 'alreadyPay' => $alreadyPay,
+ 'alreadyPaySum' => $alreadyPaySum,
+ ]);
+ }
+ ?>
+ <br>
+
<?php echo $this->render('_disclaimer_info'); ?>
\ No newline at end of file
}
?>
- <?php
- echo $this->render('_cluster_personal_values', [
-// 'adminSumGameBonus' => $adminSumGameBonus,
- 'ratingPerson' => $ratingPerson,
- 'ratingList' => $ratingList,
- 'ratingListSum' => $ratingListSum,
- 'countRatingList' => $countRatingList,
-// 'adminSumGameCountShift' => $adminSumGameCountShift,
-// 'adminSumGameAvgSum' => $adminSumGameAvgSum,
- 'clusterAdminId' => $clusterAdminId,
-// 'adminSumGameBonusTotal' => $adminSumGameBonusTotal,
-// 'adminSumGameCountShiftTotal' => $adminSumGameCountShiftTotal,
-// 'adminSumGameAvgSumTotal' => $adminSumGameAvgSumTotal,
-
-
- 'clusterAdminSumGameBonus' => $clusterAdminSumGameBonus,
- 'clusterAdminAvgSumGameBonus' => $clusterAdminAvgSumGameBonus,
- 'administratorCountInRating' => $administratorCountInRating,
- ]);
- ?>
-
- <br>
-
<?php ;
echo "<hr>";
?>
/* @var $teamBonusValue float */
/* @var $teamBonus array */
+
+/* @var $personRetention float */
+/* @var $personRetentionArray array */
+/* @var $sumPersonRetention float */
+
+/* @var $personPrepaidExpense float */
+/* @var $toPayoff float */
+
+/* @var $alreadyPay float */
+/* @var $alreadyPaySum float */
+
+/* @var $allowShowPersonRetention bool */
+/* @var $showHolidayVersion bool */
+
+/* @var $consolidatedArrUsersSalaryCheck array */
+/* @var $consolidatedPremiumByFocusGroups array */
+/* @var $consolidatedPremiumByMatrix array */
+/* @var $consolidatedPremiumByStore float */
+/* @var $onePartHolidayPremium float */
+/* @var $adminsHolidayShiftCount float */
+/* @var $personPremiumByStore float */
+/* @var $personHolidayShiftCount float */
+
$cabinetName = 'Кабинет флориста';
if ($person) {
'userQualityPremium' => $userQualityPremium,
'teamBonus' => $teamBonus,
'teamBonusValue' => $teamBonusValue,
+ 'showHolidayVersion' => $showHolidayVersion
]);
?>
+ <?php
+ if ($showHolidayVersion) {
+ echo $this->render('_holiday_table_values', [
+ 'consolidatedArrUsersSalaryCheck' => $consolidatedArrUsersSalaryCheck,
+ 'consolidatedPremiumByFocusGroups' => $consolidatedPremiumByFocusGroups,
+ 'consolidatedPremiumByMatrix' => $consolidatedPremiumByMatrix,
+ 'consolidatedPremiumByStore' => $consolidatedPremiumByStore,
+ 'onePartHolidayPremium' => $onePartHolidayPremium,
+ 'adminsHolidayShiftCount' => $adminsHolidayShiftCount,
+ 'personPremiumByStore' => $personPremiumByStore,
+ 'personHolidayShiftCount' => $personHolidayShiftCount,
+ ]);
+ }
+ ?>
<?php
if (!empty($salaryByAdmin)) {
<?php
}
?>
+
<br>
<h4>Сумма окладов и премий за выбранный период <b><?php echo HtmlHelper::getNumberFormat($allTotalFlorist) ?> руб</b>
</h4>
+
+<?php
+
+if (!empty($personRetention)) {
+ ?>
+ <br>
+
+ <b>Таблица персональных вычетов за выбранный месяц:</b>
+ <table class=" table table-border">
+ <thead>
+ <th>Название</th>
+ <th>Сумма, руб</th>
+ </thead>
+ <?php
+ foreach ($personRetentionArray as $keyName => $value) {
+ ?>
+ <tr>
+ <td><?php echo $keyName ?></td>
+ <td><?php echo HtmlHelper::getNumberFormat($value) ?> </td>
+ </tr><?php
+ }
+ ?>
+ <tfoot>
+ <th></th>
+ <th><?php echo HtmlHelper::getNumberFormat($sumPersonRetention) ?></th>
+ </tfoot>
+
+ </table>
+ <?php
+}
+?>
+
+<?php
+if (!empty($allowShowPersonRetention)) {
+ echo $this->render('_already_pay_in_month', [
+ 'toPayoff' => $toPayoff,
+ 'alreadyPay' => $alreadyPay,
+ 'alreadyPaySum' => $alreadyPaySum,
+ ]);
+}
+?>
+ <br>
<?php echo $this->render('_disclaimer_info'); ?>
$this->title = 'Магазины';
$this->params['breadcrumbs'][] = $this->title;
+
+$this->registerJsFile('/js/city-store/index.js', ['position' => \yii\web\View::POS_END]);
+
?>
<div class="city-store-index">
// 'content:ntext',
// 'email:email',
// 'tg_chat_id',
+ [
+ 'label' => 'Телеграм Чат',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ return !empty($model->tg_chat_id) ?
+ Html::button($model->tg_chat_id, ['class' => 'btn btn-link btn-sm', 'onclick' => 'setTgDialog("' . $model->id . '", "' . $model->tg_chat_id . '");']) :
+ Html::button('Настроить', ['class' => 'btn btn-success btn-sm', 'onclick' => 'setTgDialog("' . $model->id . '", "' . $model->tg_chat_id . '");']);
+ }
+ ],
// 'h1',
// 'sprav_id',
// 'images:ntext',
<?php
+use kartik\select2\Select2;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
<?= $form->field($model, 'id') ?>
</div>
<div class="col-4">
- <?= $form->field($model, 'admin_id')->dropDownList(\yii_app\records\Admin::find()->select(['name', 'id'])->indexBy('id')->column(), [
- 'prompt' => '---',
- ]) ?>
+ <?php
+ $adminsWithGroup = \yii_app\records\Admin::find()->select(['name', 'id'])->indexBy('id')->orderBy('name' , SORT_DESC)->all();
+ $admins = [];
+ foreach ($adminsWithGroup as $key => $item) {
+ $admins[$key] = $item['name'] . ' (' . $item['id'] . ')';
+
+ }
+
+ echo $form->field($model, 'admin_id')->widget(Select2::class, [
+ 'data' => $admins,
+ 'language' => 'ru',
+ 'options' => ['placeholder' => '---'],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ]
+ ])?>
</div>
<div class="col-4">
<?= $form->field($model, 'admin_group_id')->dropDownList(\yii_app\records\AdminGroup::find()->select(['name', 'id'])->indexBy('id')->column(), [
* @var $number
* @var $city_stores
* @var $store_traffik
- * @var $sales_products
* @var $equal_days
* @var $arr_work
* @var $date_timetable
* @var $productsArrayServices
* @var $servises
* @var $saleServices
- * @var $checkSellerDiscount
* @var $daysSearchForm
* @var \yii\web\View $this
*/
--- /dev/null
+<?php
+
+$this->registerCssFile('/yii_app/css/infoTable/cabinet.css');
+$this->registerJsFile('/yii_app/js/infoTable/cabinet.js', ['position' => \yii\web\View::POS_END]);
+
+?>
+ <h1>Кабинет</h1>
+<div class="text-row">f8tg9yhujomip,mkonjihbu</div>
\ No newline at end of file
]
])->label(false)); ?>
-<?php/*
+<? /*
<?php PrintBlockHelper::printBlock('Статусы групп уроков', $filterForm->field($filterModel, 'lesson_group_status')
->widget(Select2::class, [
'data' => $lessonGroupStatuses,
?>
</div>
<div class="form-group">
+ <span>Доступна загрузка изображения только в формате jpg и png !</span>
<?= $form->field($modelMatrixErpProperty, 'imageFile')->fileInput(['accept' => 'image/*', 'extension' => ['png','jpg']])->label(false) ?>
</div>
/* @var $yearSelect string */
/* @var $monthSelect string */
/* @var $dateToCabinet string */
+/* @var $lastPacketDate string */
/* @var $allowedPayrollUpdate bool */
/* @var $yearMonthSearchForm yii_app\forms\payroll\YearMonthSearchForm */
$this->title = 'Scheduler Task Logs';
$this->params['breadcrumbs'][] = $this->title;
?>
-<div class="scheduler-task-log-index">
+<div class="scheduler-task-log-index p-8">
<h1><?= Html::encode($this->title) ?></h1>
<?php Pjax::begin(); ?>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
+ <div class="table-responsive">
+ <?= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filterModel' => $searchModel,
+ 'columns' => [
+ ['class' => 'yii\grid\SerialColumn'],
- <?= GridView::widget([
- 'dataProvider' => $dataProvider,
- 'filterModel' => $searchModel,
- 'columns' => [
- ['class' => 'yii\grid\SerialColumn'],
-
- 'id',
- 'task_num',
- 'date_start',
- 'date_stop',
- 'name',
- 'alias',
- 'description:ntext',
- 'result:ntext',
- 'result_number',
- 'error:ntext',
- 'info:ntext',
- 'log:ntext',
- 'date',
- [
- 'class' => ActionColumn::className(),
- 'urlCreator' => function ($action, SchedulerTaskLog $model, $key, $index, $column) {
- return Url::toRoute([$action, 'id' => $model->id]);
- }
- ],
- ],
- ]); ?>
+ 'id',
+ //'task_num',
+ 'date_start',
+ 'date_stop',
+ [
+ 'attribute' => 'status',
+ 'value' => function (SchedulerTaskLog $model) {
+ if ($model->date_start != null && $model->date_stop != null) {
+ return 'Выполнено';
+ }
+ return 'Пропущенно';
+ },
+ 'filter' => \kartik\select2\Select2::widget([
+ 'model' => $searchModel,
+ 'attribute' => 'status',
+ 'data' => $searchModel->statusArray
+ ])
+ ],
+ 'name',
+ //'alias',
+ //'description:ntext',
+ //'result:ntext',
+ //'result_number',
+ 'error:ntext',
+ 'info:ntext',
+ [
+ 'attribute' => 'log',
+ 'value' => function (SchedulerTaskLog $model) {
+ return strlen($model->log) > 400 ? mb_substr($model->log, 0, 400) . "..." : $model->log;
+ },
+ 'contentOptions' => [
+ 'class' => 'w-25'
+ ]
+ ],
+ 'date',
+ [
+ 'class' => ActionColumn::className(),
+ 'urlCreator' => function ($action, SchedulerTaskLog $model, $key, $index, $column) {
+ return Url::toRoute([$action, 'id' => $model->id]);
+ }
+ ],
+ ],
+ ]); ?>
+ </div>
<?php Pjax::end(); ?>
</div>
--- /dev/null
+<?php
+
+use yii\base\DynamicModel;
+use yii\widgets\ActiveForm;
+use kartik\select2\Select2;
+
+use yii_app\helpers\PrintBlockHelper;
+
+/* @var $storeAll array */
+/* @var $products array */
+/* @var $colorsCnt array */
+/* @var $quantity_warehouseman_fact array */
+/* @var $orderId string */
+/* @var $productsMinLot array */
+/* @var $dataFieldsValues array */
+/* @var $storeGroups array */
+/* @var $filterModel DynamicModel */
+/* @var $division_name string */
+/* @var $division_date string */
+/* @var $products_colors array */
+/* @var $dataColor array */
+/* @var $dataHand array */
+
+$this->registerJsFile('/yii_app/js/shipment/division-print-edit.js', ['position' => \yii\web\View::POS_END]);
+
+$storeGroupOptions = [-1 => 'Не выбран'];
+foreach ($storeGroups as $gIndex) {
+ $storeGroupOptions[$gIndex] = $gIndex;
+}
+
+$printOrientationOptions = [
+ 'portrait' => 'Портретная',
+ 'landscape' => 'Альбомная',
+];
+
+?>
+
+<div class="m-5">
+ <h5 class="page-title mb-0 text-primary">Деление по магазинам <?= $division_name ?> Дата деления <?= $division_date ?> id=<?= $orderId ?></h5>
+ <?php $filterForm = ActiveForm::begin(['id' => 'filter-form']); ?>
+ <div class="row">
+ <div class="col-1 text-right">Печатать цвет:</div>
+ <div class="col-1"><?= $filterForm->field($filterModel, 'printColor')->checkbox(['value' => 1, 'uncheckValue' => 0,
+ 'onclick' => '$("#filter-form").get(0).submit();'], false)->label(false) ?></div>
+ <div class="col-2 text-right">Печатать ручных добавок:</div>
+ <div class="col-1"><?= $filterForm->field($filterModel, 'printHand')->checkbox(['value' => '1', 'uncheckValue' => '0',
+ 'onclick' => '$("#filter-form").get(0).submit();'], false)->label(false) ?></div>
+ <div class="col-2 text-right">Показать столбцы итого:</div>
+ <div class="col-1"><?= $filterForm->field($filterModel, 'printSumm')->checkbox(['value' => '1', 'uncheckValue' => '0',
+ 'onclick' => '$("#filter-form").get(0).submit();'], false)->label(false) ?></div>
+ </div>
+ <?php PrintBlockHelper::printBlock('Выберите куст', $filterForm->field($filterModel, 'groupIndex')->widget(Select2::class, [
+ 'data' => $storeGroupOptions,
+ 'language' => 'ru',
+ 'options' => ['placeholder' => 'Куст...'],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ],
+ 'pluginEvents' => [
+ 'change' => 'function(e) {
+ $("#filter-form").get(0).submit();
+ }'
+ ],
+ ])->label(false)); ?>
+ <?php PrintBlockHelper::printBlock('Ориентация', $filterForm->field($filterModel, 'printOrientation')->widget(Select2::class, [
+ 'data' => $printOrientationOptions,
+ 'language' => 'ru',
+ 'options' => ['placeholder' => 'Ориентация...'],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ],
+ 'pluginEvents' => [
+ 'change' => 'function(e) {
+ $("#filter-form").get(0).submit();
+ }'
+ ],
+ ])->label(false)); ?>
+ <?php ActiveForm::end() ?>
+ <div class="col-1">
+ <button id="shipmentPrintButton" class="btn btn-primary btn-lg" onclick="printTable();">Print</button>
+ </div>
+ <div class="table-responsive">
+ <table class="table-hover zak">
+ <thead>
+ <tr class="zg">
+ <th class="td_product">наименование</th>
+ <th><b>мин-ый лот деления шт.</b></th>
+ <?php foreach($storeAll as $store): ?>
+ <?php if ($filterModel->groupIndex == -1 || $store->parent_id == $filterModel->groupIndex): ?>
+ <th><b><?= $store->name ?></b></th>
+ <?php if ($filterModel->groupIndex != -1): ?>
+ <th style="min-width: 40px"></th>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ <th><b>итого</b></th>
+ <th><b>куплено</b></th>
+ <th><b>разница</b></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php
+ $colorsCounter = [];
+ $ostatok = [];
+ ?>
+ <?php foreach($products as $productId => $productName): ?>
+ <?php if (!empty($colorsCnt[$productId]) and $quantity_warehouseman_fact[$productId]["NULL"]["NULL"] > 0): ?>
+ <tr id="tr__<?= $productId ?>" class="trproduct">
+ <td class="td_product producted">
+ <span class="fs-6">
+ <a href="/shipment/divisionPrintEditProduct/?productId=<?= $productId ?>&id=<?= $orderId ?>"
+ target=new><?= $productName ?></a>
+ </span>
+ </td>
+ <td><?= $productsMinLot[$productId] ?></td>
+ <?php $divisionCnt = 0; ?>
+ <?php foreach($storeAll as $store): ?>
+ <?php
+ $value = ceil($dataFieldsValues[$productId][$store->id]["NULL"] ?? 0);
+ $ostatok[$productId][$store->id] = $value;
+ $divisionCnt += $value;
+ if (empty($value)) {
+ $value = "";
+ }
+ ?>
+ <?php if ($filterModel->groupIndex == -1 || $store->parent_id == $filterModel->groupIndex): ?>
+ <td>
+ <?= $value ?>
+ <?php if (!empty($dataHand[$productId][$store->id]['NULL']) && $filterModel->printHand == 1): ?>
+ <sup style="color:green; font-size:0.5rem"><?= intval($dataHand[$productId][$store->id]["NULL"]) ?></sup>
+ <?php endif; ?>
+ </td>
+ <?php if ($filterModel->groupIndex != -1): ?>
+ <td style="min-width: 40px"></td>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ <td><?= intval($divisionCnt) ?></td>
+ <td><?= intval($quantity_warehouseman_fact[$productId]["NULL"]["NULL"]) ?></td>
+ <?php $r2 = $quantity_warehouseman_fact[$productId]["NULL"]["NULL"] - $divisionCnt; ?>
+ <td <?= ($r2 != 0 ? 'class="bg-danger"' : '') ?> ><?= $r2 ?></td>
+ </tr>
+ <?php endif; ?>
+ <?php if ($filterModel->printColor == 1): ?>
+ <?php if (!empty($products_colors[$productId])): ?>
+ <?php foreach($products_colors[$productId] as $colorName): ?>
+ <?php
+ $colorName = trim($colorName);
+ $colorAllCnt = 0;
+ ?>
+ <?php if (!empty($dataColor[$productId][$colorName])): ?>
+ <tr>
+ <td class="tr"><?= $colorName ?>(<?= $dataColor[$productId][$colorName] ?> шт.)</td>
+ <td></td>
+ <?php
+ $colorsCounter[$productId]++;
+ $newHand = [];
+ ?>
+ <?php foreach($storeAll as $store): ?>
+ <?php if ($filterModel->groupIndex == -1 || $store->parent_id == $filterModel->groupIndex): ?>
+ <?php
+ $value = ceil($dataFieldsValues[$productId][$store->id][$colorName] ?? 0);
+ $ostatok[$productId][$store->id] -= $value;
+ $colorAllCnt += $value;
+ ?>
+ <td <?= $value % ($productsMinLot[$productId] ?? 1) != 0 ? 'class="bg-danger"' : '' ?>
+ onclick="ShowInput('division_hand',
+ '<?= $store->id ?>',
+ '<?= $productId ?>',
+ '<?= $colorName ?>',
+ '<?= md5($colorName) ?>',
+ '<?= $productsMinLot[$productId] ?>',
+ '<?= $value ?>')"
+ id="division_hand<?= $store->id ?><?= $productId ?><?= md5($colorName) ?>" >
+ <?= $value ?>
+ </td>
+ <?php if ($filterModel->groupIndex != -1): ?>
+ <td style="min-width: 40px"></td>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ <?php if ($filterModel->printSumm == 1): ?>
+ <?php $difColor = $dataColor[$productId][$colorName] - $colorAllCnt; ?>
+ <td><?= $colorAllCnt ?></td>
+ <td><?= $dataColor[$productId][$colorName] ?></td>
+ <td <?= $difColor != 0 ? 'class="bg-danger"' : '' ?>><?= $difColor ?></td>
+ <?php endif; ?>
+ </tr>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ <?php if (!empty($colorsCounter[$productId])): ?>
+ <tr class="bg-success">
+ <td class="tr">остаток</td>
+ <td></td>
+ <?php foreach($storeAll as $store): ?>
+ <?php if ($filterModel->groupIndex == -1 || $store->parent_id == $filterModel->groupIndex): ?>
+ <?php $value = $ostatok[$productId][$store->id]; ?>
+ <td <?= $value < 0 ? 'class="bg-danger"' : '' ?> ><?= $value ?></td>
+ <?php if ($filterModel->groupIndex != -1): ?>
+ <td style="min-width: 40px"></td>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ <?php if ($filterModel->printSumm == 1): ?>
+ <td></td>
+ <td></td>
+ <td class="bg-danger"></td>
+ <?php endif; ?>
+ </tr>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php if (!empty($colorsCnt[$productId]) and $quantity_warehouseman_fact[$productId]["NULL"]["NULL"] > 0): ?>
+ <?php if ($filterModel->groupIndex == -1): ?>
+ <tr class="trproduct">
+ <td class="td_product"><span class="fs-6"> </span></td>
+ <td class="td_product"><span class="fs-6"> </span></td>
+ <?php foreach($storeAll as $store): ?>
+ <td class="td_product"><span class="fs-6"> </span></td>
+ <?php endforeach; ?>
+ <td class="td_product"><span class="fs-6"> </span></td>
+ <td class="td_product"><span class="fs-6"> </span></td>
+ <td class="td_product"><span class="fs-6"> </span></td>
+ </tr>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ </div>
+</div>
+
+<script>
+ function printTable() {
+ const landscape = '<?= $filterModel->printOrientation ?>' === 'landscape';
+ const css = '@page { ' + (landscape ? 'size: landscape;' : '') + ' margin: 0; } #shipmentPrintButton, #filter-form {display: none;}' +
+ 'a[href]:after { content: "" !important;}',
+ head = document.head || document.getElementsByTagName('head')[0],
+ style = document.createElement('style');
+
+ style.media = 'print';
+ style.appendChild(document.createTextNode(css));
+
+ head.appendChild(style);
+
+ window.print();
+
+ head.removeChild(style)
+ }
+</script>
+
+<style>
+ table tbody tr td {
+ border: 3px solid black !important;
+ }
+
+ table.table tbody tr:hover td {
+ background: #cdcdcd
+ }
+
+ .zak tbody tr:hover td {
+ background: #cdcdcd
+ }
+
+ .zak > thead > tr > th, .zak tr.zg th, .zak tr.zg td {
+ font-size: 0.7rem;
+ min-width: 30px;
+ text-align: center;
+ font-weight: normal;
+ max-height: 60px;
+ overflow: hidden
+ }
+
+ .zak > thead > tr > th b {
+ font-weight: normal;
+ }
+
+ .zak > :not(caption) > * > * {
+ padding: 0.05rem;
+ box-shadow: none;
+ }
+
+ .zak td.fs-5 {
+ text-align: left;
+ padding: 0.3rem 1rem;
+ }
+
+ .zak {
+ border-collapse: collapse;
+ border-spacing: 0;
+ overflow: hidden;
+ }
+
+ .zak th, .zak td {
+ border: 1px solid #e6e6e6;
+ padding: 0.1rem;
+ vertical-align: middle;
+ position: relative;
+ }
+
+ .zak td:hover:before {
+ background-color: #e3e3e3;
+ content: '';
+ height: 100%;
+ left: -5000px;
+ position: absolute;
+ top: 0;
+ width: 10000px;
+ z-index: -2;
+ }
+
+ .zak td:hover:after {
+ background-color: #cdcdcd;
+ content: '';
+ height: 10000px;
+ left: 0;
+ position: absolute;
+ top: -5000px;
+ width: 100%;
+ z-index: -1;
+ }
+
+ .zak tbody td input.form-control {
+ font-size: 0.8rem;
+ min-width: 70px;
+ max-width: 100px;
+ font-weight: bold;
+ border: 0;
+ border-radius: 0;
+ color: #333;
+ padding: 0.2rem;
+ margin: 0;
+ }
+
+ .zak tbody td input.form-control:focus {
+ border: 2px #cd0202 solid;
+ background: #ffccdb
+ }
+
+ .zak td.bg-danger, .zak td.bg-indigo, .zak td.bg-info, .zak tr th.bg-danger, .zak tr th.bg-info, .zak tr th.bg-indigo {
+ color: #fff;
+ }
+
+ table.zak thead th:not(:first-child), table.zak tr.zg th th:not(:first-child) {
+ vertical-align: bottom;
+ line-height: normal;
+ }
+
+ table.zak thead b {
+ writing-mode: vertical-rl;
+ transform: scale(-1);
+ }
+
+ table.zak tr.zg th b, table.zak tr.zg td b {
+ writing-mode: vertical-rl;
+ transform: scale(-1);
+ font-weight: normal;
+ font-size: 0.6rem;
+ }
+
+ .zak tr th .th_p_summ {
+ text-align: center;
+ font-weight: bold;
+ }
+
+ .app-content .side-app {
+ padding: 25px 0.5rem 0 0.5rem;
+ }
+
+ .zak tbody tr td.td_product, .zak td.td_product {
+ tex-align: left;
+ }
+
+ .zak td.td_product:hover {
+ background: #fff;
+ }
+</style>
+<style>
+ .zak tbody tr:hover:not(.no-hover) td {
+ background: #cdcdcd
+ }
+
+ .zak > thead > tr > th, .zak tr.zg th {
+ font-size: 0.7rem;
+ min-width: 30px;
+ max-width: 40px;
+ text-align: center;
+ font-weight: normal;
+ overflow: hidden
+ }
+
+ .zak > thead > tr > th b, .zak > thead > tr > td b {
+ font-weight: normal;
+ }
+
+ .zak > :not(caption) > * > * {
+ padding: 0.05rem;
+ box-shadow: none;
+ }
+
+ .zak td.fs-5 {
+ text-align: left;
+ padding: 0.3rem 1rem;
+ }
+
+ .zak {
+ border-collapse: collapse;
+ border-spacing: 0;
+ overflow: hidden;
+ }
+
+ .zak th, .zak td {
+ border: 1px solid #e6e6e6;
+ padding: 0.1rem;
+ vertical-align: middle;
+ position: relative;
+ }
+
+ table.zak thead th, table.zak tr.zg th th, table.zak tr.zg td td {
+ vertical-align: bottom;
+ line-height: normal;
+ }
+
+ table.zak thead b, table.zak tbody b {
+ writing-mode: vertical-rl;
+ transform: scale(-1);
+ }
+
+ table.zak tr.zg th b, table.zak tr.zg td b {
+ writing-mode: vertical-rl;
+ transform: scale(-1);
+ font-weight: normal;
+ font-size: 0.6rem;
+ }
+
+ .app-content .side-app {
+ padding: 25px 0.5rem 0 0.5rem;
+ }
+
+ .zak tbody tr td.td_product, .zak td.td_product {
+ text-align: right;
+ }
+
+ .zak td.td_product:hover {
+ background: #fff;
+ }
+
+ .zak tr td.pr, .zak tr td.ost {
+ text-align: center;
+ }
+
+ .zak tr td.pr {
+ background: #ddd
+ }
+
+ .zak tr td.ost {
+ background: #e6e6e6
+ }
+
+ .zak td {
+ text-align: center;
+ vertical-align: bottom;
+ }
+
+ .zak td.lf {
+ text-align: left;
+ background: #fff
+ }
+
+ .zak td.tr {
+ text-align: right;
+ }
+
+ .zak td, .zak thead th {
+ color: #000;
+ }
+
+ .zak tr.trproduct td {
+ font-size: 1rem;
+ font-weight: bold;
+ }
+
+ input.greener {
+ border: 2px green solid;
+ }
+
+ input.editColor {
+ width: auto;
+ max-width: 70px;
+ }
+</style>
--- /dev/null
+<?php
+
+
+use yii\grid\ActionColumn;
+use yii\helpers\Url;
+use yii\helpers\Html;
+use yii\grid\GridView;
+use yii\widgets\Pjax;
+use yii_app\records\Dashboard;
+use yii_app\records\StoreOrdersFields;
+use yii_app\records\StoreOrdersStatuses;
+use yii_app\records\StoreOrderStatus;
+use yii_app\services\ShipmentService;
+
+/* @var $this yii\web\View */
+/* @var $bonusConversionCost int */
+
+/* @var $userSalarySalut float */
+/* @var $userSalarySalutPremium float */
+/* @var $storeOrders array */
+/* @var $dozakupka array */
+/* @var $store_orders_statuses array */
+/* @var $dataStoreOrdersFields array */
+/* @var $dostupFields array */
+/* @var $bgFields array */
+/* @var $orders_status_description array */
+/* @var $adminGroups array */
+/* @var $urlActionPart string */
+/* @var $orderId string */
+/* @var $groupId int */
+/* @var $userGroup string */
+/* @var $orderData array */
+/* @var $storeOrderStatusDescription string */
+/* @var $storeOrderStatus string */
+/* @var $storeId ?int */
+/* @var $status_order_id int */
+/* @var $status_edit_dostup array */
+/* @var $store_orders_status_description array */
+/* @var $storesArray array */
+/* @var $storeArr array */
+/* @var $store_orders_statuses array */
+/* @var $statuses_stores_show array */
+/* @var $products_varieties array */
+/* @var $products_class array */
+/* @var $products array */
+/* @var $productsOptions array */
+/* @var $productsColorsArray array */
+/* @var $prov array */
+/* @var $statuses_dostup array */
+/* @var $dostup_fields array */
+/* @var $bg_fields array */
+/* @var $fieldsRows array */
+/* @var $dataTableHeader array */
+/* @var $shipmentService object */
+
+$this->title = 'Заказ товара';
+$this->params['breadcrumbs'][] = $this->title;
+$modul = 'shipment';
+
+
+
+$this->registerCssFile('/yii_app/css/table/table.css', ['position' => \yii\web\View::POS_END]);
+
+?>
+
+
+ <div class="index">
+
+ <h1><?= Html::encode($this->title) ?></h1>
+
+
+
+
+ </div>
+ <div class="alert alert-warning" role="alert"><a href="/shipments/index" class="btn me-2 btn-info">❮ назад в закупки</a>
+
+
+
+ <a href="https://youtu.be/Ol0mWDFYKsw" class="btn me-2 btn-danger" target=new>видео-инструкция новый интерфейс 2</a>
+ <a href="https://youtu.be/4sGW2MqDMgM" class="btn me-2 btn-danger" target=new>видео2</a>
+
+
+ Описание статуса: <?php echo $storeOrderStatusDescription ?> Под кем будем просматривать
+<?php
+foreach ($adminGroups as $gid => $nameGroup) {
+
+ $buttonStyle = '';
+ $urlRow = '/shipment/' . $urlActionPart .'/?id=' . $orderId . '&group_id=' . $gid;
+
+ if ($gid == $groupId) {
+ $buttonStyle = 'btn-success';
+ } else {
+ $buttonStyle = 'btn-outline-info';
+ }
+
+ ?><a href='<?= $urlRow?>' class='m-1 btn btn-sm <?php echo $buttonStyle;?>'><?php echo $nameGroup; ?></a><?php
+
+}
+?>
+
+
+<br>
+<?php
+?>
+
+
+ Дата старта продаж (от этой даты считаем продажи при авто-заказе) <?php echo $orderData['date_start']; ?>
+ Дата деления (от этой даты считаем продажи при делении)<?php echo $orderData['division_date']; ?>
+
+
+
+
+<!--<a href="/shipment/' . $urlActionPart . '/?id=' . $orderId . '&insert=1" class="btn btn-danger me-2">1) подгрузить данные из старого интерфейса</a>-->
+<span onclick="ajaxUpdateFieldsDataTest();" class="btn btn-info me-2">1) TEST!!! поссчитать статистические данные данные</span>
+<span onclick="ajaxUpdateFieldsData();" class="btn btn-info me-2">1) поссчитать статистические данные данные</span>
+<span onclick="ajaxUpdateStep();" class="btn btn-indigo me-2">2) обновить остаток склада</span>
+<span onclick="foreachSalesHand();" class="btn btn-warning me-2"> 3) обновить с распределене остатков склада по ячейкам добавка вручную</span>
+<span onclick="ajaxUploadAutoPurchase();" class="btn btn-warning me-2">автозаказ общий обновить</span>
+
+
+
+
+<span onclick="deleteAll();" class="btn btn-danger me-2">!!!очистить все данные из нового интерфейса!!</span>
+
+
+
+</div>
+
+<a href="/shipment/<?php echo $urlActionPart;?>/?id=<?php echo $orderId ?>'&update=1" class="btn btn-info me-2">обновить данные в таблице</a>
+
+
+<h1 class="page-title mb-0 text-primary">Заказ товара <?php echo $orderData["name"] ?> id=<?php echo $orderId ?>
+<span class="btn btn-lime"><?php echo $storeOrderStatus ?></span> ваша роль <b> <?php echo $userGroup ?></b></h1>';
+
+<?php
+// панель с магазинами
+ShipmentService::showOrderStoresPanel(
+ $status_order_id,
+ $status_edit_dostup,
+ $store_orders_status_description,
+ $storesArray,
+ $storeArr,
+ $storeId,
+ $store_orders_statuses,
+ $statuses_stores_show,
+ $urlActionPart,
+ $orderId,
+ $groupId
+);
+
+//если статус новый то вносим цены по товарам в нужые столбцы - розничная цена
+if (!empty($status_order_id) && $status_order_id == 1) {
+
+
+ ?><a href=\"/shipment/$urlActionPart/?id=$orderId&group_id=$gid&load=purchase_price\" class=\"btn btn-danger me-2\">загрузить розничные цены</a><?php
+
+
+ if (!empty($_REQUEST["load"])) {
+ $data = $db::getRows("SELECT product_id, price FROM `prices` WHERE product_id $whereInProductsId");
+ foreach ($data as $row) {
+ $productsPrices[$row["product_id"]] = $row["price"];
+ }
+ $data_uper = [];
+ foreach ($products as $productId => $nameProduct) {
+ echo "<br>$nameProduct Роз. цена=" . $productsPrices[$productId] . " закуп " . $productsOptions[$productId]["price_zakup"] . " ";
+ $price = $productsPrices[$productId];
+ $data_uper[$productId]["NULL"]["NULL"] = $price;
+
+ $db::sql("
+ UPDATE
+ `store_orders_prices`
+ SET purchase_price='$price'
+ WHERE
+ product_id='$productId'
+ AND
+ order_id='$orderId'
+ AND
+ provider_id=1
+ AND
+ purchase_price!='0.00'"
+ );
+
+ }
+
+//розничная цена
+ insert_store_orders_fields($data_uper, "purchase_price");
+
+
+ $data_uper = [];
+ foreach ($products as $productId => $nameProduct) {
+ $price = $productsOptions[$productId]["price_zakup"];
+ $data_uper[$productId]["NULL"]["NULL"] = $productsOptions[$productId]["price_zakup"];
+ $db::sql("UPDATE `store_orders_prices` SET purchase_price_zakup='$price'
+WHERE product_id='$productId' AND order_id='$orderId' AND provider_id=1 AND purchase_price_zakup!='0.00'");
+ }
+ insert_store_orders_fields($data_uper, "purchase_price_zakup");
+
+//header("Location: /shipment/$urlActionPart/?id=$orderId&group_id=$gid");
+ }
+
+
+}
+
+
+//если выбран магазин то
+if (!empty($store_id)) echo '<input type=hidden name=store_id_id value=' . $store_id . ' id=store_id_id>';
+
+echo '
+<div id=edit_div></div>
+<div class="table-responsive mt-3">
+ <table class="zak">';
+$html = '<thead>
+ <tr class="zg">
+ <th class="text-right">наименование <span onclick="$(\'.trcolors\').toggle();" class="btn btn-sm btn-warning">раскрыть цвета</span>
+
+ <span onclick="$(\'.sorts_flowers\').toggle();" class="btn btn-sm btn-warning">показать сорта</span>
+
+
+<a href="/shipment/statusFieldsSort/?status_id=' . $status_order_id . '" target=new class="btn btn-sm btn-secondary">сортировка столбцов</a>
+
+<a href="/shipment/config/?status_id=' . $status_order_id . '" target=new class="btn btn-sm btn-grey">настройка столбцов</a>
+
+
+</th>';
+$thead = $html; // формируем thead
+$head_td = $html;
+
+
+
+$rowArraySum = [];
+$shipmentService->rowArraySum = [];
+
+
+if (!empty($groupId)) {
+ foreach ($dataStoreOrdersFields as $row) {
+ $dostup = $dostup_fields[$row["id"]];
+ $bg = $bg_fields[$row["id"]];
+ if ($dostup == "edit" or $dostup == "show") {
+
+
+ $html = '<th class="text-center" data-bs-placement="top" data-bs-toggle="tooltip" data-bs-original-title="' . $row["name_full"] . ' ' . $row["name_eng"] . '" onclick="ajaxFieldInfo(' . $row["id"] . ')" style="max-width:90px;">
+ <b>' . $row["name"] . '</b></th>';
+ $thead .= $html;
+ $head_td .= $html;
+ }
+
+ }
+}
+
+$thead .= '</tr></thead>';
+$head_td .= '</tr>';
+echo '' . $thead . '<tbody>';
+
+
+//$FiledsData=getDataFiledsData();
+
+
+// полнограммы по всем магазинам
+if (!empty($store_id)) {
+ $data3 = $db::getRows("SELECT store_id,product_id,quantity FROM store_planogram WHERE color=''
+AND store_id!='' AND quantity>0 AND store_id=?", [$store_id]);
+ foreach ($data3 as $row2) $store_planogramAllStores[$row2["store_id"]][$row2["product_id"]] = $row2["quantity"];
+}
+
+//$data3 = $db::getRows("SELECT * FROM products_class WHERE tip in ('potted','wrap')");
+//$data3 = ProductsClass::find()->andWhere(['tip' => array('potted','wrap')])->asArray()->all();
+
+
+
+
+$trCount = 0;
+foreach ($products as $pid => $name) {
+ if ($trCount == 20) {
+ $trCount = 0;
+ echo $head_td;
+ }
+ $trCount++;
+
+ echo '<tr';
+
+
+ if (!empty($store_id) and empty($store_planogramAllStores[$store_id][$pid])) {
+ echo ' class="bg-danger"';
+ }
+
+
+ if (empty($FiledsData["quantity_warehouseman_fact"][$pid]["NULL"]["NULL"]) and $status_order_id >= 6) {
+// echo ' class="bg-danger"';
+//
+// echo ' style="opacity:0.5"';
+ }
+
+
+ echo '><td class="text-right">';
+//если статус общий то группируем по магазинам
+ if (empty($statuses_stores_show[$status_order_id])) {
+ echo '<span onclick="$(\'.trstores_' . $pid . '\').toggle();" class="btn btn-default btn-sm">+</span>';
+ }
+ echo '' . $name . '';
+
+
+//узнаем категорибю товара
+ $categoryId = $productsOptions[$pid]["parent_id"];
+ $tip = '';
+// по категории узнаем тип товара горшечка или упаковка
+ if (!empty($products_class[$categoryId])) {
+ $tip = $products_class[$categoryId];
+ }
+
+
+ if (array_key_exists($pid, $productsColorsArray)) {
+ if (count($productsColorsArray[$pid]) > 0) {
+ echo '<span onclick="$(\'.trcolors_' . $pid . '\').toggle();" class="btn btn-sm btn-success">+ цвета</span>';
+ }
+ }
+ echo '<input type=hidden name=provider_id[' . $pid . '] value="' . $prov[$pid] . '">';
+ echo '</td>';
+
+
+// if (!empty($store_id)) {
+ foreach ($dataStoreOrdersFields as $row) {
+ $shipmentService->printFieldTd($row["name_eng"], $pid, null);
+ }
+// }
+
+ echo '</tr>';
+
+
+//begin colors
+ if (array_key_exists($pid, $productsColorsArray)) {
+ foreach ($productsColorsArray[$pid] as $color) {
+ $color = trim($color);
+ if (!empty($color)) {
+ echo '<tr class="trcolors trcolors_' . $pid . ' bg-gray-300" style="display:none;"><td class="text-right">' . $name . ' + <span class="btn btn-sm btn-warning me-1">' . $color . '</span>';
+
+ if (!empty($products_varieties[$pid][$color])) {
+ echo '<div class="sorts_flowers" style="display:none;"><br>сорта ';
+ foreach ($products_varieties[$pid][$color] as $k => $var) {
+ echo "<span class=\"btn btn-sm btn-outline-info me-1\">$var</span>";
+ }
+ echo '</div>';
+ }
+
+
+
+ if (!empty($store_id) && !empty($color)) {
+ foreach ($dataStoreOrdersFields as $row) {
+// printFieldTd($row["name_eng"], $pid, null, null);
+ $shipmentService->printFieldTd($row["name_eng"], $pid, $store_id, $color);
+ }
+ }
+
+ echo "</tr>";
+ }
+
+ }
+ }
+//end colors
+
+
+}
+
+
+echo '<tr class="bg-success zg"><td class="text-right"></td>';
+foreach ($dataStoreOrdersFields as $row) {
+ $dostup = $dostup_fields[$row["id"]];
+ $bg = $bg_fields[$row["id"]];
+ if ($dostup == "edit" or $dostup == "show") {
+ echo '<td class="text-center" title="' . $row["name_full"] . ' ' . $row["name_eng"] . '"><b>' . $row["name"] . ' (' . $fieldsRows[$row["name_eng"]]["row_type_sum"] . ')</b></td>';
+ }
+}
+echo '</tr>
+<tr class="bg-success"><td class="text-right">итого -ГО</td>';
+foreach ($dataStoreOrdersFields as $row) {
+ $dostup = $dostup_fields[$row["id"]];
+ if ($dostup == "edit" or $dostup == "show") {
+ $s = "";
+ if ($fieldsRows[$row["name_eng"]]["row_type_sum"] == "amount") {
+ $s = $shipmentService->rowArraySum[$row["id"]] ?? 0;
+ }
+ if ($fieldsRows[$row["name_eng"]]["row_type_sum"] == "avg") {
+ if (!empty($shipmentService->rowArraySum["cnt__" . $row["id"]])) {
+ $s = round($shipmentService->rowArraySum[$row["id"]] ?? 0 / $shipmentService->rowArraySum["cnt__" . $row["id"]]);
+ }
+ }
+
+ echo '<td class="text-center ' . $bg . '"><b>' . $s . '</b></td>';
+ }
+}
+echo '</tr></tbody>';
+echo '</table>
+
+<style>table tr td.bg-lime{background:lime;color:#fff;}</style>';
+/*
+$db::sql("DELETE FROM store_orders_fields_data WHERE field_name='division_auto_need_all' AND order_id='$orderId'");
+
+// суммируем деление и заносим данные в таблицу хранения данных по полям
+foreach($products as $productId => $name) {
+//echo"<br>$name ";
+ $all=0;
+ $division_auto_need_all=0;
+ foreach($storesArrayAll as $storeId => $nameStore) {
+ // echo"<br> <b>$nameStore</b>division_auto_need= ".$FiledsData["division_auto_need"][$productId][$storeId]["NULL"]." ";
+ // $summ=$FiledsData["division_auto_need"][$productId][$storeId]["NULL"] + $FiledsData["division_hand"][$productId][$storeId]["NULL"];
+ $all =$all+$summ;
+ $division_auto_need_all += $FiledsData["division_auto_need"][$productId][$storeId]["NULL"];
+ // if(!empty($summ)) { $data_uper=[];$data_uper[$productId][$storeId]["NULL"]=$summ;insert_store_orders_fields($data_uper,"division_summ");}
+
+
+ }
+
+$field_name="division_auto_need_all";
+//echo" Итого деления потребность + $division_auto_need_all = ".$FiledsData[$field_name][$productId]["NULL"]["NULL"]." division_auto_need_all=$division_auto_need_all ";
+if(!empty($division_auto_need_all)) {
+ $FiledsData["division_auto_need_all"][$productId]["NULL"]["NULL"]=$division_auto_need_all;
+ $data_uper=[];$data_uper[$productId]["NULL"]["NULL"]=$division_auto_need_all;insert_store_orders_fields($data_uper,"division_auto_need_all");}
+
+
+}
+
+//пробегаемся по всем продуктам
+foreach($products as $productId => $name) {
+
+
+$division_auto_need_all=$FiledsData["division_auto_need_all"][$productId]["NULL"]["NULL"];
+$quantity_warehouseman_fact=$FiledsData["quantity_warehouseman_fact"][$productId]["NULL"]["NULL"];
+
+
+echo"<br><b>$name</b> division_auto_need_all=".$FiledsData["division_auto_need_all"][$productId]["NULL"]["NULL"]."
+Сумма потребности =".$division_auto_need_all."
+Сумма получаено по факту ".$quantity_warehouseman_fact."";
+
+$division_ratio=1;
+if($division_auto_need_all > $quantity_warehouseman_fact) {
+$division_ratio=round($quantity_warehouseman_fact/$division_auto_need_all,2);
+
+echo"<font color=red>-меньше!</font>";
+
+echo" применяем коэффициент $division_ratio = ".$FiledsData["division_ratio"][$productId]["NULL"]["NULL"]." ";
+
+}
+
+$data_uper=[];$data_uper[$productId]["NULL"]["NULL"]=$division_ratio;
+insert_store_orders_fields($data_uper,"division_ratio");
+
+
+}
+
+*/
+
+
+echo "<script>
+function ajaxFieldInfo(id){
+ $('#modal-7 .modal-body').html('Загружаем....');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('');
+ $.ajax({
+ url: '/shipments/ajaxFieldInfo/',
+ method: 'post',
+ dataType: 'html',
+ data: {id: id},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }});
+}
+
+function ajaxUpdateFieldsDataTest(){
+ $('#modal-7 .modal-body').html('Test Считаем данные');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('Обновляем данные');
+ $.ajax({
+ url: '/shipments/ajax-update-fields-data-test/',
+ method: 'post',
+ dataType: 'html',
+ data: { id: '2', update:'1'},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }})
+}
+
+function ajaxUpdateFieldsData(){
+ $('#modal-7 .modal-body').html('Считаем данные');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('Обновляем данные');
+ $.ajax({
+ url: '/shipments/ajaxUpdateFieldsData/',
+ method: 'post',
+ dataType: 'html',
+ data: { id: $orderId, update:'1'},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }})
+}
+
+
+function ajaxUpdateStep(){
+ $('#modal-7 .modal-body').html('Считаем данные');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('Обновляем данные');
+ $.ajax({
+ url: '/shipments/ajaxUpdateStep/',
+ method: 'post',
+ dataType: 'html',
+ data: { id: $orderId, update_step:'1'},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }})
+}
+
+
+function ajaxUploadAutoPurchase(){
+ $('#modal-7 .modal-body').html('Считаем данные');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('Обновляем данные');
+ $.ajax({
+ url: '/shipments/ajaxUploadAutoPurchase/',
+ method: 'post',
+ dataType: 'html',
+ data: { id: $orderId, update_step:'1'},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }})
+}
+
+function foreachSalesHand(){
+ $('#modal-7 .modal-body').html('Считаем данные');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('Обновляем данные');
+ $.ajax({
+ url: '/shipments/ajaxUpdateStep/',
+ method: 'post',
+ dataType: 'html',
+ data: { id: $orderId, update_step:'1', foreachSalesHand:'1'},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }})
+}
+
+
+function deleteAll(){
+ const result = confirm('Удаляем данные?');
+
+ if (result) {
+
+ $('#modal-7 .modal-body').html('Удаляем данные');
+jQuery('#modal-7').modal('show', {backdrop: 'static'}); $('#modal-7 .modal-title').text('Удаляем данные');
+ $.ajax({
+ url: '/shipments/ajaxUpdateStep/',
+ method: 'post',
+ dataType: 'html',
+ data: { id: $orderId, deleteAll:'1'},
+ success: function(data){
+ $('#modal-7 .modal-body').html(data);
+ }})
+}
+}
+
+
+</script>";
+
+echo '<!-- MODAL -->
+ <div class="modal fade" id="modal-7">
+ <div class="modal-dialog modal-lg modal-dialog-centered text-center" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h6 class="modal-title">Описание поля</h6><button aria-label="Close" class="btn-close" data-bs-dismiss="modal" type="button"><span aria-hidden="true">×</span></button>
+ </div>
+ <div class="modal-body p-0">
+
+ </div>
+
+ </div>
+</div>
+</div>';
+
+
+//include "templates/bottom.php";
+
+
+
+
+
+
+
+
+
+
+
+/*
+
+--
+
+
+
+--
+
+
+ */
\ No newline at end of file
<?php
-chdir(__DIR__ . '/../../');
-include 'modul/shipment/index.php';
\ No newline at end of file
+use yii\grid\ActionColumn;
+use yii\helpers\Url;
+use yii\helpers\Html;
+use yii\grid\GridView;
+use yii\widgets\Pjax;
+use yii_app\records\Dashboard;
+
+/* @var $this yii\web\View */
+/* @var $bonusConversionCost int */
+
+/* @var $userSalarySalut float */
+/* @var $userSalarySalutPremium float */
+/* @var $storeOrders array */
+/* @var $dozakupka array */
+/* @var $store_orders_statuses array */
+
+$this->title = 'Список закупок';
+$this->params['breadcrumbs'][] = $this->title;
+$modul = 'shipments';
+
+?>
+
+
+<div class="dashboard-index">
+
+ <h1><?= Html::encode($this->title) ?></h1>
+
+
+ <p>
+ <?= Html::a('Создать', ['create'], ['class' => 'btn btn-success']) ?>
+ </p>
+
+
+
+</div>
+<?php
+
+foreach($storeOrders as $row) {
+ ?>
+ <div class="expanel expanel-default">
+ <div class="expanel-heading">
+
+ <span class="btn btn-white btn-light me-1" onclick="$('#external__<?php echo $row["id"]?>').toggle();">показать дозакупки</span>
+ <a href=/<?php echo $modul?>/fields-data/?id=<?php echo $row["id"]?> class="btn btn-default fs-5">
+ <span class="btn btn-outline-info"><?php echo $row["id"]?></span> <?php echo $row["name"]?></a>
+
+
+ <div class="d-inline-block dropdown me-2">
+ <button type="button" class="btn bg-dark-transparent dropdown-toggle" onclick="$(this).parent().children('.dropdown-menu').toggle();">действия</button>
+ <div class="dropdown-menu" style="display:none;">
+ <a class="dropdown-item" href="/shipment/add/?id=<?php echo $row["id"]?>">правка</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/view/?id=<?php echo $row["id"]?>>старый интерфейс</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/view2/?id=<?php echo $row["id"]?>>новый интерфейс</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/fields-data/?id=<?php echo $row["id"]?> >новый интерфейс2</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/division/?id=<?php echo $row["id"]?>>деление</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/purchase/?id=<?php echo $row["id"]?>>цвета для кустовых при заказе</a>
+
+ <a class="dropdown-item" href=/<?php echo $modul?>/divisionPrint/?id=<?php echo $row["id"]?>>деление - печать на складе</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/divisionPrintEdit/?id=<?php echo $row["id"]?>>деление - по цветам</a>
+ </div>
+ </div>
+
+ <a href="/shipment/edit/?id=<?php echo $row["id"]?>" class="btn btn-warning btn-sm me-2"><?php echo $store_orders_statuses[$row["status"]]?></a>
+ <small>дата продаж: <?php echo $row["date_start"]?>, создано <?php echo $row["date_add"]?> <i><?php echo $row["comments"]?></i></small>
+
+
+
+
+ </div>
+
+ <div class="expanel-body" id="external__<?php echo $row["id"] ?>" style="display:none;">
+ <div class="row">
+ <?php
+ if (array_key_exists($row["id"], $dozakupka)) {
+ foreach($dozakupka[$row["id"]] as $rows) {
+
+ ?>
+ <div class="col-12">
+ <div class="ml-4">
+ <a href=/<?php echo $modul?>/fields-data/?id=<?php echo $rows["id"]?> class="btn btn-white fs-6 me-3">
+ <span class="btn btn-outline-info fs-6 me-2"><?php echo $rows["id"]?></span><?php echo $rows["name"]?>
+ <span class="me-2 btn btn-sm bg-warning"><?php echo $store_orders_statuses[$rows["status"]]?></span>
+ </a>
+ <div class="dropdown d-inline-block">
+ <button type="button" class="btn bg-dark-transparent dropdown-toggle" onclick="$(this).parent().children('.dropdown-menu').toggle();">действия </button>
+ <div class="dropdown-menu" style="">
+ <a class="dropdown-item" href="/shipment/add/?id=<?php echo $rows["id"]?>">правка</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/view/?id=<?php echo $rows["id"]?>>старый интерфейс</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/view2/?id=<?php echo $rows["id"]?>>новый интерфейс</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/fields-data/?id=<?php echo $rows["id"]?> >новый интерфейс2</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/division/?id=<?php echo $rows["id"]?>>деление</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/purchase/?id=<?php echo $rows["id"]?>>цвета для кустовых при заказе</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/divisionPrint/?id=<?php echo $rows["id"]?>>деление - печать на складе</a>
+ <a class="dropdown-item" href=/<?php echo $modul?>/divisionPrintEdit/?id=<?php echo $rows["id"]?>>деление - по цветам</a>
+ </div>
+ </div>
+ <i><?php echo $rows["comment"] ?? ''?></i>
+ <table class="table"><tbody></tbody></table>
+ </div>
+ </div>
+ <?php
+ }
+ }
+ ?>
+
+ </div>
+ </div>
+
+
+ </div>
+
+
+
+
+
+<?php
+}
--- /dev/null
+<?php
+
+use yii\widgets\ActiveForm;
+use yii\base\DynamicModel;
+
+use yii_app\helpers\PrintBlockHelper;
+
+use kartik\select2\Select2;
+
+/** @var $products array */
+/** @var $filterModel DynamicModel */
+/** @var $orderStoreSort array */
+/** @var $storeNamesByGuid array */
+/** @var $storePlanogramByStoreGuid array */
+/** @var $salesQuantity array */
+
+$this->registerCssFile('/yii_app/css/customSortable.css');
+$this->registerJsFile('/yii_app/js/Sortable.js', ['position' => \yii\web\View::POS_END]);
+$this->registerJsFile('/yii_app/js/customSortable.js', ['position' => \yii\web\View::POS_END]);
+
+?>
+
+<div class="setDivisionPriority m-5">
+ <?php $filterForm = ActiveForm::begin(['id' => 'filter-form']); ?>
+ <?php PrintBlockHelper::printBlock('Товар', $filterForm->field($filterModel, 'productId')->widget(Select2::class, [
+ 'data' => $products,
+ 'language' => 'ru',
+ 'options' => ['placeholder' => 'Товар...'],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ],
+ 'pluginEvents' => [
+ 'change' => 'function() {
+ $("#filter-form").get(0).submit();
+ }',
+ ]
+ ])->label(false)); ?>
+ <?php ActiveForm::end(); ?>
+ <?php if ($orderStoreSort && $storeNamesByGuid && $storePlanogramByStoreGuid): ?>
+ <div class="row">
+ <div class="col-1"></div>
+ <div class="col-2">Магазин</div>
+ <div class="col-2">Продажи</div>
+ <div class="col-2">Планограмма минимум</div>
+ <div class="col-2">Планограмма максимум</div>
+ </div>
+ <div class="draganddropTable" data-name="stores#<?= $filterModel->productId ?>">
+ <?php foreach ($orderStoreSort as $orderStore): ?>
+ <div class="row">
+ <div class="col-1 drag-handler"></div>
+ <div class="col-2">
+ <?= $storeNamesByGuid[$orderStore->store_id] ?? '---' ?>
+ </div>
+ <div class="col-2">
+ <?= $salesQuantity[$orderStore->store_id] ?? '---' ?>
+ </div>
+ <div class="col-2">
+ <?= $storePlanogramByStoreGuid[$orderStore->store_id]->quantity ?? '---' ?>
+ </div>
+ <div class="col-2">
+ <?= $storePlanogramByStoreGuid[$orderStore->store_id]->quantity_max ?? '---' ?>
+ </div>
+ </div>
+ <?php endforeach; ?>
+ </div>
+ <?php endif; ?>
+</div>
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
+use yii\widgets\Pjax;
use yii_app\forms\timetable\TabelSearchForm;
use yii_app\helpers\HtmlHelper;
use yii_app\records\AdminGroup;
$dates[] = clone $date;
}
?>
+
+<?php Pjax::begin(['id' => 'some_pjax_id']) ?>
+
<div class="table-responsive">
<h3 class="text-center">График сотрудников <?= TabelSearchForm::stores()[$tabelForm->storeId] ?? '' ?> <?= HtmlHelper::getMonth($startDatetime) ?> <?= $startDatetime->format('Y') ?> г.</h3>
<table class="timetable table table-bordered table-striped table-hover">
</table>
<?php } ?>
</div>
+
+<?php Pjax::end() ?>
+
<div class="noprint">
<?php foreach (\yii_app\records\Shift::all() as $shift) { ?>
<br> <b><?= $shift->short_name; ?></b> - <?= $shift->name; ?>
});
}
- document.querySelectorAll('[data-plan-slot-cell]').forEach(function(element) {
- element.addEventListener('click', function (event) {
- event.stopPropagation();
- let params = new URLSearchParams({
- adminId: element.dataset.userId,
- date: element.dataset.date,
- storeId: element.dataset.storeId
+ function planSlotCellActivate() {
+ document.querySelectorAll('[data-plan-slot-cell]').forEach(function (element) {
+ element.addEventListener('click', function (event) {
+ event.stopPropagation();
+ let params = new URLSearchParams({
+ adminId: element.dataset.userId,
+ date: element.dataset.date,
+ storeId: element.dataset.storeId
+ })
+ fetch('/timetable/edit_plan/?' + params, {method: 'get'}).then(response => response.text()).then(function (text) {
+ var intervalTime = setInterval(() => {
+ if ($("#modal-7").css('display') == 'none') {
+ clearInterval(intervalTime);
+ setTimeout(() => planSlotCellActivate(), 2000);
+ $.pjax.reload({container: '#some_pjax_id', async: false});
+ }
+ }, 1000);
+ return showModal({
+ title: 'Добавить сотрудника в смену',
+ body: text,
+ });
+ }).then(initModal)
})
- fetch('/timetable/edit_plan/?' + params, {method: 'get'}).then(response => response.text()).then(function (text) {
- return showModal({
- title: 'Добавить сотрудника в смену',
- body: text,
- });
- }).then(initModal)
})
- })
+ }
+ planSlotCellActivate();
})();
(function() {
if (!empty($lastCheckin)) {\r
if ($lastCheckin->isStart()) {\r
$textButton = 'Закрытие смены';\r
- $textInfo = 'Смена Ñ\83Ñ\81пеÑ\88но закÑ\80Ñ\8bÑ\82иа';\r
+ $textInfo = 'Смена успешно закрыта';\r
$flowersStyleClass = 'closure-flower';\r
$lastCheckinTimeHours = date("d.m.Y H:i", strtotime($lastCheckin->time));\r
$dateTimeHoursInfo = $lastCheckinTimeHours . ' - ' . date("H:i d.m.Y", strtotime($currentCheckin->time));\r
use yii\helpers\ArrayHelper;
use yii_app\records\AdminGroup;
+use yii_app\records\Timetable;
?>
<?php if ($success) { ?>
<?= \yii\helpers\Html::activeHiddenInput($slot, 'tabel'); ?>
<div class="row">
<div class="col-lg-6">
- <?= $form->field($slot, 'shift_id')->dropDownList(ArrayHelper::map(($slot->admin && $slot->admin->adminGroup) ? $slot->admin->adminGroup->shift: [], 'id', 'name')); ?>
+ <?= $form->field($slot, 'shift_id')->dropDownList(ArrayHelper::map(($slot->admin && $slot->admin->adminGroup) ? $slot->admin->adminGroup->shift: [], 'id', 'name'),
+ ['onchange' => '$("#timetableplan-time_start").val(this.value == 1 ? "08:00:00" : "20:00:00"); $("#timetableplan-time_end").val(this.value == 1 ? "20:00:00" : "08:00:00");']); ?>
</div>
<div class="col-lg-6">
<?= $form->field($slot, 'store_id')->dropDownList(\yii_app\forms\timetable\TabelSearchForm::stores()); ?>
</div>
</div>
-<?= $form->field($slot, 'slot_type_id')->dropDownList($slot::slotTypeName()); ?>
+<?php
+
+$salariesDay = array_combine(
+ array_merge([0], Timetable::getSalariesDay()),
+ array_merge(['из окладов'], Timetable::getSalariesDay()),
+);
+if ($slot->d_id == \yii_app\records\Admin::PART_TIME_WORKER_GROUP_ID) {
+ ?>
+ <div class="row">
+ <div class="col-lg-6">
+ <?= $form->field($slot, 'slot_type_id')->dropDownList($slot::slotTypeName()); ?>
+ </div>
+ <div class="col-lg-6">
+ <?= $form->field($slot, 'salary_shift')->dropDownList($salariesDay); ?>
+ </div>
+ </div><?php
+} else {
+ echo $form->field($slot, 'slot_type_id')->dropDownList($slot::slotTypeName());
+}
+?>
+
<?= $form->field($slot, 'comment'); ?>
<?= $form->field($slot, 'status')->dropDownList($slot::statuses()); ?>
-<?= \yii\helpers\Html::submitButton('Сохранить', ['class' => 'btn btn-primary']); ?>
-<?php if ($slot->id) { ?>
-<?= \yii\helpers\Html::a('Удалить', \yii\helpers\Url::to(['/timetable/edit_plan?delete&id=' . $slot->id], ['data-role'=>'delete', 'class' => 'btn'])); ?>
- <?php if (in_array($_SESSION['group_id'], [1, 8]) && !empty($fact)) { /** @TODO Add RBAC */ ?>
- <br>
- <hr>
+<?php
+$session = Yii::$app->session;
+$groupId = (int) $session->get('group_id');
+$numDay = Timetable::getCountDaysAllowEditShift($groupId);
+if (Timetable::getAllowEditShift($slot->date, $numDay)) {
+ ?>
+ <?= \yii\helpers\Html::submitButton('Сохранить.', ['class' => 'btn btn-primary']); ?>
+ <?php if ($slot->id) { ?>
+ <?= \yii\helpers\Html::a('Удалить', \yii\helpers\Url::to(['/timetable/edit_plan?delete&id=' . $slot->id], ['data-role'=>'delete', 'class' => 'btn'])); ?>
+ <?php if (in_array($_SESSION['group_id'], [1, 8]) && !empty($fact)) { /** @TODO Add RBAC */ ?>
+ <br>
+ <hr>
<?= \yii\helpers\Html::a(' <div class="btn btn-danger">Удалить смену и факт </div>', \yii\helpers\Url::to(['/timetable/edit_plan?delete&force&id=' . $slot->id]), ['data-role'=>'delete', 'data-confirm' => 'Удалить?' , 'style' => "color:#fff!important;"]); ?>
+ <?php } ?>
<?php } ?>
-<?php } ?>
+ <?php
+} ?>
<?php $form::end() ?>