$model = new SumSalaryForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
- $store_id = $model->store_id;
+ $storeId = $model->store_id;
$year = $model->year;
$month = $model->month;
- $records = [];
- $model = new DynamicModel(compact('store_id', 'month', 'year'));
- $model->addRule(['store_id', 'month', 'year'], 'required')
- ->addRule('store_id', 'integer')
- ->addRule('month', 'integer', ['min' => 1, 'max' => 12])
- ->addRule('year', 'integer', ['min' => 2000, 'max' => 2100]);
- if ($model->hasErrors()) {
- return $this->controller->render('error', [
- 'model' => $model,
- 'errors' => $model->errors,
- ]);
- }
+ $model = new DynamicModel(compact('storeId', 'month', 'year'));
+ $model->addRule(['store_id', 'month', 'year'], 'required')
+ ->addRule('store_id', 'integer')
+ ->addRule('month', 'integer', ['min' => 1, 'max' => 12])
+ ->addRule('year', 'integer', ['min' => 2000, 'max' => 2100]);
+
+ if ($model->hasErrors()) {
+ return $this->controller->render('error', [
+ 'model' => $model,
+ 'errors' => $model->errors,
+ ]);
+ }
+
+ $storeId = (int)$storeId;
+ $month = (int)$month;
+ $year = (int)$year;
+
+ $weeks = [
+ ['start' => 1, 'end' => 7],
+ ['start' => 8, 'end' => 14],
+ ['start' => 15, 'end' => 21],
+ ['start' => 22, 'end' => 28],
+ ];
+
+ $lastDayOfMonth = (new DateTime("$year-$month-01"))->format('t');
+
+ // Проверяем, существует ли 29-е число в текущем месяце (для не високосного года в феврале его не будет)
+ if ($lastDayOfMonth > 28) {
+ $weeks[] = ['start' => 29, 'end' => $lastDayOfMonth];
+ }
- $store_id = (int)$store_id;
- $month = (int)$month;
- $year = (int)$year;
+ $dailyPayments = MotivationService::getEmployeePayments($lastDayOfMonth);
- $weeks = [
- ['start' => 1, 'end' => 7],
- ['start' => 8, 'end' => 14],
- ['start' => 15, 'end' => 21],
- ['start' => 22, 'end' => 28],
- ['start' => 29, 'end' => (new DateTime("$year-$month-01"))->format('t')],
- ];
- $results = [];
+ $results = [];
foreach ($weeks as $weekIndex => $week) {
$startDate = sprintf("%s-%02d-%02d", $year, $month, $week['start']);
$endDate = sprintf("%s-%02d-%02d", $year, $month, $week['end']);
- $weeklyRecords = MotivationService::getTimetableFactRecordsByDateAndStore($startDate, $endDate, $store_id);
- $weeklyVacationSum = MotivationService::getVacationsSum($startDate, $endDate, $store_id);
+ $weeklyRecords = MotivationService::getTimetableFactRecordsByDateAndStore($startDate, $endDate, $storeId);
+ $weeklyVacationSum = MotivationService::getVacationsSum($startDate, $endDate, $storeId);
$weeklyTotalSalary = 0.0;
$recordsWithAdditionalData = [];
foreach ($weeklyRecords as $record) {
- $payment = EmployeePayment::find()
- ->where(['admin_id' => $record->admin_id])
- ->orderBy(['date' => SORT_DESC]) // Сортировка по полю date от самой поздней записи к самой ранней
- ->one();
- $dailyPayment = $payment ? $payment->daily_payment : null;
+ $dailyPayment = isset($dailyPayments[$record->admin_id]) ? $dailyPayments[$record->admin_id] : null;
$admin = Admin::findOne(['id' => $record->admin_id]);
$adminName = $admin ? $admin->name : 'Unknown';
$monthlyTotalSalary = 0.0;
- $monthlyRecords = MotivationService::getTimetableFactRecordsByDateAndStore($startOfMonth, $endOfMonth, $store_id);
- $monthlyVacationSum = MotivationService::getVacationsSum($startOfMonth, $endOfMonth, $store_id);
+ $monthlyRecords = MotivationService::getTimetableFactRecordsByDateAndStore($startOfMonth, $endOfMonth, $storeId);
+ $monthlyVacationSum = MotivationService::getVacationsSum($startOfMonth, $endOfMonth, $storeId);
foreach ($monthlyRecords as $record) {
- $payment = EmployeePayment::find()
- ->where(['admin_id' => $record->admin_id])
- ->orderBy(['date' => SORT_DESC]) // Сортировка по полю date от самой поздней записи к самой ранней
- ->one();
- $dailyPayment = $payment ? $payment->daily_payment : null;
+ $dailyPayment = isset($dailyPayments[$record->admin_id]) ? $dailyPayments[$record->admin_id] : null;
$monthlyTotalSalary += !empty($record->salary_shift) ? $record->salary_shift : $dailyPayment;
}
}
foreach ($motivations as $motivation) {
- $store_id = $motivation->store_id;
- $monthlyTotalSalary = MotivationService::calculateTotalSalary($startOfPreviousMonth->format('Y-m-d'), $endOfPreviousMonth->format('Y-m-d'), $store_id);
+ $storeId = $motivation->store_id;
+ $monthlyTotalSalary = MotivationService::calculateTotalSalary($startOfPreviousMonth->format('Y-m-d'), $endOfPreviousMonth->format('Y-m-d'), $storeId);
$idMotivation = MotivationService::saveOrUpdateMotivationValue($motivation->id, 6, 11, "float", $monthlyTotalSalary);
}
$results = [];
foreach ($motivations as $motivation) {
- $store_id = $motivation->store_id;
+ $storeId = $motivation->store_id;
- $records = MotivationService::getTimetableFactRecordsByDateAndStore($startDate, $endDate, $store_id);
- $vacationSum = MotivationService::getVacationsSum($startDate, $endDate, $store_id);
+ $totalSalary = MotivationService::calculateTotalSalary($startDate, $endDate, $storeId);
- $totalSalary = 0.0;
- foreach ($records as $record) {
- $payment = EmployeePayment::find()
- ->where(['admin_id' => $record->admin_id])
- ->orderBy(['date' => SORT_DESC]) // Сортировка по полю date от самой поздней записи к самой ранней
- ->one();
- $dailyPayment = $payment ? $payment->daily_payment : 0.0;
-
- // Если $record->salary_shift имеет значение, учитываем его и не добавляем dailyPayment
- if (!empty($record->salary_shift)) {
- $totalSalary += $record->salary_shift;
- } else {
- $totalSalary += $dailyPayment;
- }
- }
-
- $results[$store_id] = $totalSalary + $vacationSum;
+ $results[$storeId] = $totalSalary;
}
// Записываем информацию в таблицу MotivationValue за текущую неделю
- foreach ($results as $store_id => $totalSalary) {
- $motivation = Motivation::findOne(['store_id' => $store_id, 'year' => $currentYear, 'month' => $currentMonth]);
+ foreach ($results as $storeId => $totalSalary) {
+ $motivation = Motivation::findOne(['store_id' => $storeId, 'year' => $currentYear, 'month' => $currentMonth]);
// Если не найдено соответствующее мотивационное значение, пропустить этот store_id
if ($motivation === null) {
['start' => 8, 'end' => 14],
['start' => 15, 'end' => 21],
['start' => 22, 'end' => 28],
- ['start' => 29, 'end' => (new DateTime("$year-$month-01"))->format('t')] // последняя неделя до конца месяца
];
+ $lastDayOfMonth = (new DateTime("$year-$month-01"))->format('t');
+
+ // Проверяем, существует ли 29-е число в текущем месяце (для не високосного года в феврале его не будет)
+ if ($lastDayOfMonth > 28) {
+ $weeks[] = ['start' => 29, 'end' => $lastDayOfMonth];
+ }
+
foreach ($weeks as $weekIndex => $week) {
$startDate = sprintf("%s-%02d-%02d", $year, $month, $week['start']);
$endDate = sprintf("%s-%02d-%02d", $year, $month, $week['end']);
foreach ($motivations as $motivation) {
- $store_id = $motivation->store_id;
- $totalSalary = MotivationService::calculateTotalSalary($startDate, $endDate, $store_id);
-
-
-
+ $storeId = $motivation->store_id;
+ $totalSalary = MotivationService::calculateTotalSalary($startDate, $endDate, $storeId);
MotivationService::saveOrUpdateMotivationValue($motivation->id, $weekIndex + 1, 11, "float", $totalSalary);
}
}
class MotivationService
{
+
/**
* Получает ассоциативный массив алиасов групп мотивации.
*
*
* @param string $startDate Дата начала периода в формате 'YYYY-MM-DD'.
* @param string $endDate Дата окончания периода в формате 'YYYY-MM-DD'.
- * @param int $store_id Идентификатор магазина.
+ * @param int $storeId Идентификатор магазина.
*
* @return array|null Возвращает массив записей из модели TimetableFactModel, соответствующих условиям,
* или null, если записи не найдены.
*/
- public static function getTimetableFactRecordsByDateAndStore($startDate, $endDate, $store_id)
+ public static function getTimetableFactRecordsByDateAndStore($startDate, $endDate, $storeId)
{
// Делаем запрос к TimetableFactModel
$records = TimetableFactModel::find()
- ->where(['store_id' => $store_id])
+ ->where(['store_id' => $storeId])
->andWhere(['between', 'date_shift', $startDate, $endDate])
->all();
*
* @param string $startDate Дата начала периода в формате 'YYYY-MM-DD'.
* @param string $endDate Дата окончания периода в формате 'YYYY-MM-DD'.
- * @param int $store_id Идентификатор магазина.
+ * @param int $storeId Идентификатор магазина.
*
* @return float Возвращает общую сумму отпускных за указанный период.
* Если записей не найдено, возвращается 0.0.
*/
- public static function getVacationsSum($startDate, $endDate, $store_id):float
+ public static function getVacationsSum($startDate, $endDate, $storeId):float
{
- // Делаем запрос к таблице Timetable для получения записей с slot_type_id = 2
+ // Делаем запрос к таблице Timetable для получения записей с slot_type_id = 2 (Timetable::TIMESLOT_VACATION)
$records = Timetable::find()
- ->where(['store_id' => $store_id])
+ ->where(['store_id' => $storeId])
->andWhere(['between', 'date', $startDate, $endDate])
- ->andWhere(['slot_type_id' => 2])
+ ->andWhere(['slot_type_id' => Timetable::TIMESLOT_VACATION])
->all();
// Проверяем, есть ли записи
return 0.0; // Возвращаем 0, если записей нет
}
-
+ $dailyPayments = self::getEmployeePayments($endDate);
$vacationsSum = 0.0;
foreach ($records as $record) {
- // Находим самую позднюю запись по admin_id
- $payment = EmployeePayment::find()
- ->where(['admin_id' => $record->admin_id])
- ->orderBy(['date' => SORT_DESC])
- ->one();
- $dailyPayment = $payment ? $payment->daily_payment : 0.0;
+ $dailyPayment = isset($dailyPayments[$record->admin_id]) ? $dailyPayments[$record->admin_id] : 0.0;
$vacationsSum += $dailyPayment;
}
-
-
return $vacationsSum;
}
* из всех полученных записей.
*
* @param int $id Идентификатор мотивации (`motivation_id`).
- * @param int $value_id Идентификатор значения (`value_id`).
+ * @param int $valueId Идентификатор значения (`value_id`).
*
* @return float Возвращает сумму всех значений `value_float` для заданного `value_id`.
* Если записи не найдены, возвращается 0.
*/
- public static function getMonthSum($id, $value_id)
+ public static function getMonthSum($id, $valueId)
{
+ $aliases = ['week1', 'week2', 'week3', 'week4', 'week5'];
+ $groupIds = MotivationCostsItem::find()
+ ->select('id')
+ ->where(['alias' => $aliases])
+ ->column();
// Запрос к модели MotivationValue для получения записей с заданными условиями
$records = MotivationValue::find()
- ->where(['motivation_id' => $id, 'value_id' => $value_id])
- ->andWhere(['in', 'motivation_group_id', [1, 2, 3, 4, 5]])
+ ->where(['motivation_id' => $id, 'value_id' => $valueId])
+ ->andWhere(['in', 'motivation_group_id', $groupIds])
->all();
// Получаем массив значений value_float
* (`value_float`, `value_int`, `value_string`) и сохраняет запись.
* Если сохранение успешно, возвращается ID записи. В случае ошибки возвращается `false`.
*
- * @param int $motivation_id Идентификатор мотивации.
- * @param int $group_id Идентификатор группы мотивации.
- * @param int $value_id Идентификатор значения.
- * @param string $value_type Тип значения, который может быть 'float', 'int' или 'string'.
+ * @param int $motivationId Идентификатор мотивации.
+ * @param int $groupId Идентификатор группы мотивации.
+ * @param int $valueId Идентификатор значения.
+ * @param string $valueType Тип значения, который может быть 'float', 'int' или 'string'.
* @param string $value_string Значение, которое нужно сохранить (string).
* @param int $value_int Значение, которое нужно сохранить (int).
* @param float $value_float Значение, которое нужно сохранить (float).
* @return int|false Возвращает ID сохраненной или обновленной записи, либо `false` в случае ошибки.
* @throws \InvalidArgumentException Если передан некорректный тип значения.
*/
- public static function saveOrUpdateMotivationValue($motivation_id, $group_id, $value_id, $value_type, $value)
+ public static function saveOrUpdateMotivationValue($motivationId, $groupId, $valueId, $valueType, $value)
{
// Найти существующую запись
$motivationValue = MotivationValue::findOne([
- 'motivation_id' => $motivation_id,
- 'motivation_group_id' => $group_id,
- 'value_id' => $value_id,
+ 'motivation_id' => $motivationId,
+ 'motivation_group_id' => $groupId,
+ 'value_id' => $valueId,
]);
// Если запись не найдена, создать новую
if ($motivationValue === null) {
$motivationValue = new MotivationValue();
- $motivationValue->motivation_id = $motivation_id;
- $motivationValue->motivation_group_id = $group_id;
- $motivationValue->value_id = $value_id;
- $motivationValue->value_type = $value_type;
+ $motivationValue->motivation_id = $motivationId;
+ $motivationValue->motivation_group_id = $groupId;
+ $motivationValue->value_id = $valueId;
+ $motivationValue->value_type = $valueType;
}
// Установить значение в зависимости от типа
- switch ($value_type) {
+ switch ($valueType) {
case 'float':
$motivationValue->value_float = $value;
break;
$motivationValue->value_string = $value;
break;
default:
- throw new \InvalidArgumentException("Неправильное значение типа: $value_type");
+ throw new \InvalidArgumentException("Неправильное значение типа: $valueType");
}
// Сохранить запись и вернуть id или false
{
$records = self::getTimetableFactRecordsByDateAndStore($startDate, $endDate, $storeId);
$vacationSum = self::getVacationsSum($startDate, $endDate, $storeId);
-
+ $dailyPayments = self::getEmployeePayments($endDate);
$totalSalary = 0.0;
foreach ($records as $record) {
- // Находим самую позднюю запись по admin_id
- $payment = EmployeePayment::find()
- ->where(['admin_id' => $record->admin_id])
- ->orderBy(['date' => SORT_DESC])
- ->one();
- $dailyPayment = $payment ? $payment->daily_payment : 0.0;
+ $dailyPayment = isset($dailyPayments[$record->admin_id]) ? $dailyPayments[$record->admin_id] : 0.0;
if (!empty($record->salary_shift)) {
$totalSalary += $record->salary_shift;
return $totalSalary + $vacationSum;
}
+
+
+ /**
+ * @param $currentDate
+ * @return array
+ */
+ public static function getEmployeePayments($currentDate): array
+ {
+ // Запрос для получения всех записей, но только с учетом последней даты для каждого admin_id
+ $employeePayments = EmployeePayment::find()
+ ->where(['<=', 'date', $currentDate])
+ ->orderBy(['admin_id' => SORT_ASC, 'date' => SORT_DESC])
+ ->all();
+
+ // Преобразование результатов в массив admin_id => daily_payment
+ $dailyPayments = [];
+ foreach ($employeePayments as $payment) {
+ if (!isset($dailyPayments[$payment->admin_id])) {
+ $dailyPayments[$payment->admin_id] = $payment->daily_payment;
+ }
+ }
+ return $dailyPayments;
+ }
}