From: Aleksey Filippov Date: Fri, 29 Dec 2023 08:36:45 +0000 (+0300) Subject: правки X-Git-Tag: 1.1~194^2~2 X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=12c4ec4687eb88cdd31e132d2dd4222df768964d;p=erp24_rep%2Fyii-erp24%2F.git правки --- diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index d9d401bc..050409b8 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -6,7 +6,7 @@ RUN apk add --update --no-cache \ RUN apk add --no-cache zlib libpng icu \ && apk add --no-cache --virtual .deps zlib-dev libpng-dev icu-dev \ - && docker-php-ext-install -j$(nproc) gd mysqli pdo pdo_mysql intl calendar opcache \ + && docker-php-ext-install -j$(nproc) gd mysqli pdo pdo_mysql intl calendar mbstring opcache \ && apk del .deps RUN apk --no-cache --update --repository http://dl-cdn.alpinelinux.org/alpine/v$ALPINE_VERSION/main/ add \ @@ -21,7 +21,7 @@ RUN wget https://getcomposer.org/installer \ #add xdebug RUN apk add --no-cache $PHPIZE_DEPS \ - && pecl install xdebug \ + && pecl install xdebug-3.1.6 \ && docker-php-ext-enable xdebug \ && apk del $PHPIZE_DEPS WORKDIR /www diff --git a/erp24/forms/EmployeePaymentSearch.php b/erp24/forms/EmployeePaymentSearch.php new file mode 100755 index 00000000..36e96c10 --- /dev/null +++ b/erp24/forms/EmployeePaymentSearch.php @@ -0,0 +1,73 @@ + $query, + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + // grid filtering conditions + $query->andFilterWhere([ + 'id' => $this->id, + 'admin_id' => $this->admin_id, + 'admin_group_id' => $this->admin_group_id, + 'date' => $this->date, + 'monthly_salary' => $this->monthly_salary, + 'daily_payment' => $this->daily_payment, + 'creator_id' => $this->creator_id, + ]); + + return $dataProvider; + } +} diff --git a/erp24/forms/MultipleUploadForm.php b/erp24/forms/MultipleUploadForm.php new file mode 100644 index 00000000..04075602 --- /dev/null +++ b/erp24/forms/MultipleUploadForm.php @@ -0,0 +1,36 @@ + 'png, jpg', 'maxFiles' => 10, 'skipOnEmpty' => false], + ]; + } + + public function upload() + { + if ($this->validate()) { + foreach ($this->imageFiles as $file) { + + $test = 33; +// $file->saveAs('uploads/' . $file->baseName . '.' . $file->extension); + } + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/erp24/forms/UploadImageForm.php b/erp24/forms/UploadImageForm.php new file mode 100644 index 00000000..c80ae72e --- /dev/null +++ b/erp24/forms/UploadImageForm.php @@ -0,0 +1,38 @@ + false, 'extensions' => 'jpg, png'], + ]; + } + public function upload($entity, $entity_id) { + if ($this->validate()) { + $target_dir = 'uploads/' . Yii::$app->user->id . '/' . date("Y") . "/" . date("m") . "/" . date("d"); + if (!is_dir($target_dir)) { + mkdir($target_dir, 0777, true); + } + $targetFile = $target_dir . "/" . rand(1000, 9999) . $this->image->baseName . '.' . $this->image->extension; + $this->image->saveAs($targetFile); + + $fileRecord = new Files; + $fileRecord->created_at = date("Y-m-d H:i:s"); + $fileRecord->entity_id = $entity_id; + $fileRecord->entity = $entity; + $fileRecord->file_type = 'image'; + $fileRecord->url = '/' . $targetFile; + $fileRecord->save(); + + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/erp24/forms/device/AddDeviceForm.php b/erp24/forms/device/AddDeviceForm.php new file mode 100755 index 00000000..03035f3f --- /dev/null +++ b/erp24/forms/device/AddDeviceForm.php @@ -0,0 +1,91 @@ +device = new AdminDesktop(); + } + public function rules(): array + { + return [ + [['storeId'], 'integer'], + [['name'], 'string'], + [['name'], 'default', 'value' => 'Рабочий ПК'], + [['storeId'], 'in', 'range' => array_keys(self::stores())], + [['typeId'], 'in', 'range' => array_keys(AdminDesktop::deviceTypes())], + ]; + } + + public function attributeLabels() + { + return [ + 'storeId' => 'Магазин', + 'typeId' => 'Тип устройства', + 'name' => 'Название устройства', + ]; + } + public static function stores() : array + { + return CityStore::find() + ->select(['name', 'id']) + ->indexBy('id') + ->cache(3600) + ->column(); + } + public static function devices() + { + return AdminDesktop::deviceTypes(); + } + + public function getStoreName() + { + return self::stores()[$this->storeId] ?? 'вне магазинов'; + } + + public function save(): bool + { + if (!$this->validate()) { + return false; + } + $this->device->name = $this->name; + $this->device->store_id = $this->storeId; + $this->device->date_add = date('Y-m-d H:i:s'); + $this->device->type_id = $this->typeId; + $this->device->device_info = \Yii::$app->getRequest()->getUserAgent(); + $this->device->lasttime = date('Y-m-d H:i:s'); + $this->device->keygen = \Yii::$app->getSecurity()->generateRandomString(); + $this->device->ip = \Yii::$app->getRequest()->getRemoteIP(); + $this->device->admin_id = $_SESSION['admin_id']; + if (!$this->device->save()) { + $this->addErrors($this->device->getErrors()); + return false; + } + return true; + } + + /** + * @return AdminDesktop + */ + public function getDevice() + { + return $this->device; + } +} \ No newline at end of file diff --git a/erp24/forms/device/SelectDeviceForm.php b/erp24/forms/device/SelectDeviceForm.php new file mode 100755 index 00000000..67f88413 --- /dev/null +++ b/erp24/forms/device/SelectDeviceForm.php @@ -0,0 +1,49 @@ + array_keys(self::devices())], + ]; + } + + public static function devices() + { + static $all = []; + if ($all) { + return $all; + } + return $all = AdminDesktop::find()->indexBy('id')->all(); + } + + public function attributeLabels() + { + return [ + 'id' => 'Устройство', + ]; + } + + /** + * @return array|\yii\db\ActiveRecord|null + */ + public function getDevice() + { + return AdminDesktop::find()->andWhere(['id' => $this->id])->one(); + } +} \ No newline at end of file diff --git a/erp24/forms/infoTable/ChartManagementForm.php b/erp24/forms/infoTable/ChartManagementForm.php new file mode 100644 index 00000000..76feb8ec --- /dev/null +++ b/erp24/forms/infoTable/ChartManagementForm.php @@ -0,0 +1,46 @@ + date("Y-m-d", strtotime('today -14 day'))], + ['date_end', 'default', 'value' => date("Y-m-d", strtotime('now'))], + ['mode_select_matrix_category', 'default', 'value' => 0], + ['mode_group', 'default', 'value' => 0], + ['date_start', 'validateDate'], + ]; + } + + public function attributeLabels() + { + return [ + 'date_start' => 'Дата начала', + 'date_end' => 'Дата окончания', + 'mode_select_matrix_category' => 'Определить категории матрицы' + ]; + } + + public function validateDate() + { + if (strtotime($this->date_start) > strtotime($this->date_end)) { + $this->addError('date_start', 'Дата начала не может быть больше даты окончания'); + $this->addError('date_end', 'Дата окончания не может быть меньше даты начала'); + } + } +} \ No newline at end of file diff --git a/erp24/forms/infoTable/Charts.php b/erp24/forms/infoTable/Charts.php new file mode 100644 index 00000000..fc80bd09 --- /dev/null +++ b/erp24/forms/infoTable/Charts.php @@ -0,0 +1,39 @@ + date("Y-m-d", strtotime('first day of this month'))], + ['date_end', 'default', 'value' => date("Y-m-d", strtotime('last day of this month'))], + ['date_start', 'validateDate'], + ]; + } + + public function attributeLabels() + { + return [ + 'date_start' => 'Дата начала', + 'date_end' => 'Дата окончания' + ]; + } + + public function validateDate() + { + if (strtotime($this->date_start) > strtotime($this->date_end)) { + $this->addError('date_start', 'Дата начала не может быть больше даты окончания'); + $this->addError('date_end', 'Дата окончания не может быть меньше даты начала'); + } + } +} \ No newline at end of file diff --git a/erp24/forms/infoTable/YearWeekSearchForm.php b/erp24/forms/infoTable/YearWeekSearchForm.php new file mode 100644 index 00000000..34e54316 --- /dev/null +++ b/erp24/forms/infoTable/YearWeekSearchForm.php @@ -0,0 +1,40 @@ +year = date("Y", strtotime(date("Y-m-d",time()))); + + $this->week = date("W", strtotime(date("Y-m-d",time()))); + } + + + public function attributeLabels() + { + return [ + 'year' => 'Год', + 'week' => 'Неделя', + 'store_id' => 'Магазин', + ]; + } + +} \ No newline at end of file diff --git a/erp24/forms/lesson/LessonForm.php b/erp24/forms/lesson/LessonForm.php new file mode 100755 index 00000000..6ba21beb --- /dev/null +++ b/erp24/forms/lesson/LessonForm.php @@ -0,0 +1,36 @@ +year = date("Y", strtotime(date("Y-m-d",time()) . $modifier)); + + $this->month = date("m", strtotime(date("Y-m-d",time()) . $modifier)); + } + + + public function attributeLabels() + { + return [ + 'year' => 'Год', + 'month' => 'Месяц', + 'dateFrom' => 'dateFrom', + 'store_id' => 'Магазин', + ]; + } + +} \ No newline at end of file diff --git a/erp24/forms/planStore/AddPlanStore.php b/erp24/forms/planStore/AddPlanStore.php new file mode 100644 index 00000000..d6c8e353 --- /dev/null +++ b/erp24/forms/planStore/AddPlanStore.php @@ -0,0 +1,52 @@ + 'Январь', + 'Февраль', + 'Март', + 'Апрель', + 'Май', + 'Июнь', + 'Июль', + 'Август', + 'Сентябрь', + 'Октябрь', + 'Ноябрь', + 'Декабрь' + ]; + public function rules() + { + return [ + [['store_id', 'year', 'month'], 'required'], + [['store_id', 'year', 'month'], 'integer'], + ['date_str', 'string'] + ]; + } + + public function attributeLabels() + { + return [ + 'store_id' => 'Магазин', + 'date_str' => 'Дата' + ]; + } + + public function updateDate () { + $this->year = intval(date('Y', strtotime($this->date_str))); + $this->month = intval(date('m', strtotime($this->date_str))); + } +} \ No newline at end of file diff --git a/erp24/forms/support/TaskSupportCreateForm.php b/erp24/forms/support/TaskSupportCreateForm.php new file mode 100755 index 00000000..9855cd1f --- /dev/null +++ b/erp24/forms/support/TaskSupportCreateForm.php @@ -0,0 +1,30 @@ + 255], + [['name'], 'string', 'min' => 3], + [['entity_id', 'function_entity_id'], 'string', 'max' => 36], + [['files'], 'file', 'skipOnEmpty' => true, 'maxFiles' => 20], + ]; + } + + public function attributeLabels() + { + return [ + 'description' => 'Описание', + 'entity_type' => 'Тип сущности', + 'entity_id' => 'Магазин', + 'name' => 'Название' + ]; + } +} \ No newline at end of file diff --git a/erp24/forms/timetable/AddForm.php b/erp24/forms/timetable/AddForm.php new file mode 100755 index 00000000..8ce1dcf4 --- /dev/null +++ b/erp24/forms/timetable/AddForm.php @@ -0,0 +1,146 @@ + array_keys(self::stores())], + [['date'], 'date', 'format' => 'php:Y-m-d'], + [['timeStart', 'timeEnd', 'adminIds'], 'required'], + [['timeStart', 'timeEnd'], 'date', 'format' => 'php:H:i:s'], + [['shiftId'], 'in', 'range' => array_keys(Shift::all())], + [['adminIds'], 'each', 'rule' => ['in', 'range' => array_keys(self::admins())]], + [['slotTypeId'], 'in', 'range' => array_keys(Timetable::slotTypeName())], + ]; + } + + public function attributeLabels() + { + return [ + 'adminIds' => 'Пользователи', + 'storeId' => 'Магазин', + 'timeStart' => 'Время начала', + 'timeEnd' => 'Время конца', + 'shiftId' => 'Смена', + 'slotTypeId' => 'Тип занятости', + ]; + } + public static function stores() : array + { + return CityStore::find() + ->select(['name', 'id']) + ->andWhere(['visible' => 1]) + ->indexBy('id') + ->cache(3600) + ->column(); + } + + public function getShift(): Shift + { + return Shift::all()[$this->shiftId]; + } + + public static function admins() + { + return Admin::find() + ->with('adminGroup') + ->andWhere([ + 'group_id' => array_keys(AdminGroup::groupsWithShift()), + ]) + ->orderBy([ + 'group_id' => SORT_ASC, + 'name' => SORT_ASC + ]) + ->indexBy('id') + ->all() + ; + } + + public static function minutes(): array + { + return [0, 10, 20, 30, 40, 50]; + } + + public function getStoreName() + { + return self::stores()[$this->storeId] ?? 'вне магазинов'; + } + + public function save(): bool + { + if (!$this->validate()) { + return false; + } + $start = new \DateTime($this->date . ' ' .$this->timeStart); + $end = new \DateTime($this->date . ' ' .$this->timeEnd); + $minStart = new \DateTime($this->date . ' ' .$this->shift->start_time); + // shift crosses midnight + if ($start < $minStart) { + $start->modify('+1 day'); + } + if ($end < $minStart) { + $end->modify('+1 day'); + } + + /** @var Admin[] $admins */ + $admins = Admin::find() + ->with('adminGroup') + ->andWhere(['id' => $this->adminIds]) + ->indexBy('id') + ->all(); + + $trx = TimetablePlan::getDb()->beginTransaction(); + foreach ($this->adminIds as $adminId) { + $timeTable = new TimetablePlan([ + 'shift_id' => $this->shiftId, + 'store_id' => $this->storeId, + 'date' => $this->date, + 'admin_id' => $adminId, + 'd_id' => $admins[$adminId]->adminGroup->id, + 'admin_id_add' => $_SESSION['admin_id'], + 'time_start' => $this->timeStart, + 'time_end' => $this->timeEnd, + 'datetime_start' => $start->format('Y-m-d H:i:s'), + 'datetime_end' => $end->format('Y-m-d H:i:s'), + 'slot_type_id' => $this->slotTypeId, + 'comment' => $this->comment, + 'status' => 0, + ]); + if (!$timeTable->save()) { + $this->addError('adminIds', implode("\n", $timeTable->getFirstErrors())); + $trx->rollBack(); + return false; + } + } + $trx->commit(); + return true; + } +} \ No newline at end of file diff --git a/erp24/forms/timetable/HolidaySearch.php b/erp24/forms/timetable/HolidaySearch.php new file mode 100755 index 00000000..6b225e10 --- /dev/null +++ b/erp24/forms/timetable/HolidaySearch.php @@ -0,0 +1,35 @@ + 'php:Y-m-d'], + [['dateFrom'], 'default', 'value' => function () { + return date('Y-01-01'); + }], + [['dateTo'], 'default', 'value' => function () { + return date('Y-12-31'); + }], + ]; + } + + public function attributeLabels() + { + return [ + 'dateFrom' => 'Дата начала', + 'dateTo' => 'Дата конца', + ]; + } + +} \ No newline at end of file diff --git a/erp24/forms/timetable/IndexForm.php b/erp24/forms/timetable/IndexForm.php new file mode 100755 index 00000000..d5dfbaac --- /dev/null +++ b/erp24/forms/timetable/IndexForm.php @@ -0,0 +1,49 @@ + array_keys(self::stores())], + [['start', 'end'], 'date', 'format' => 'php:Y-m-d'], + [['start'], 'default', 'value' => date('Y-m-d', strtotime('-1 day'))], + [['end'], 'default', 'value' => date('Y-m-d', strtotime('+7 day'))], + ]; + } + + public function attributeLabels() + { + return [ + 'store_id' => 'Магазин', + 'start' => 'Дата начала', + 'end' => 'Дата конца', + ]; + } + public static function stores() : array + { + return CityStore::find() + ->select(['name', 'id']) + ->andWhere(['visible' => 1]) + ->indexBy('id') + ->cache(3600) + ->column(); + } + + public function getStoreName() + { + return self::stores()[$this->store_id] ?? 'вне магазинов'; + } + +} \ No newline at end of file diff --git a/erp24/forms/timetable/StartForm.php b/erp24/forms/timetable/StartForm.php new file mode 100755 index 00000000..3345973a --- /dev/null +++ b/erp24/forms/timetable/StartForm.php @@ -0,0 +1,251 @@ +type_id == AdminCheckin::TYPE_START; + } + + public function isEnd() + { + return $this->type_id == AdminCheckin::TYPE_END; + } + + public function isAppear() + { + return $this->type_id == AdminCheckin::TYPE_APPEAR; + } + + public static function ratings() + { + return [ + 2 => 'Неудовлетворительно', + 3 => 'Удовлетворительно', + 4 => 'Хорошо', + 5 => 'Отлично', + ]; + } + + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'admin_id' => 'ID пользователя', + 'type_id' => 'Открытие/закрытие смены', + 'date' => 'Дата смены', + 'time' => 'Время', + 'store_id' => 'Место', + 'checkin_id' => 'ID отметки / открытия / закрытия смены', + 'ball' => 'Оценка', + 'comment' => 'Комментарий', + 'photo' => 'Селфи', + 'd_id' => 'Должность', + 'status' => 'Статус проверки', + 'replaced_admin_id' => 'Заменяемый сотрудник', + 'gps' => 'Координаты', + ]; + } + + public function init() + { + $this->checkinModel = new AdminCheckin(); + } + + public function rules(): array + { + return [ + [['id', 'admin_id', 'replaced_admin_id', 'plan_id', 'checkin_id', 'store_id', 'type_id', 'd_id', 'ball', 'status'], 'integer'], + [['comment', 'date'], 'string'], + [['lat', 'lon'], 'number'], + [['admin_id', 'replaced_admin_id'], 'exist', 'targetClass' => Admin::class, 'targetAttribute' => 'id'], + [['admin_id', 'store_id', 'device_id', 'type_id', 'd_id', 'ball', 'date'], 'required'], + [['d_id'], 'exist', 'targetClass' => AdminGroup::class, 'targetAttribute' => 'id'], + [['store_id'], function() { + $targetAdminId = $this->replaced_admin_id ?: $this->admin_id; + /** @var Admin $targetAdmin */ + $targetAdmin = Admin::find()->andWhere(['id' => $targetAdminId])->one(); + if (!in_array($this->store_id, $targetAdmin->getStoreIds())) { + $this->addError('store_id', 'У пользователя нет доступа к этому магазину'); + } + }], + [['status'], 'required', 'requiredValue' => AdminCheckin::STATUS_PENDING], + [['photo'], 'required', 'message' => 'Смена не может быть открыта без селфи'], + [['photo'], 'file', 'mimeTypes' => ['image/jpeg'], 'message' => 'Неправильный формат файла'], + [['store_id'], 'required', 'message' => 'Смена не может быть открыта без указания магазина'], + [['time'], function () { + $maxShiftDuration = max(ArrayHelper::getColumn(Shift::all(), 'duration')); + /** @var AdminCheckin $lastCheckin */ + $lastCheckin = AdminCheckin::find() + ->andWhere(['admin_id' => $this->admin_id]) + ->andWhere(['>', 'time', date('Y-m-d H:i:s', strtotime("-$maxShiftDuration hour"))]) + ->orderBy(['time' => SORT_DESC]) + ->limit(1) + ->one(); + if (!$lastCheckin) { + return; + } + if ($lastCheckin->type_id == $this->type_id) { + if ($this->isStart()) { + $this->addError('time', 'Смена уже открывалась'); + } else { + $this->addError('time', 'Смена уже закрывалась'); + } + } + }], + [['admin_id'], function () { + /** @TODO check for power admins */ + if ($this->admin_id != $_SESSION['admin_id']) { + $this->addError('admin_id', 'Неправильный пользователь'); + } + }], + [['device_id'], function () { + /** @var AdminDesktop $device */ + $device = AdminDesktop::find()->andWhere(['id' => $this->device_id])->one(); + if (!$device) { + $this->addError('device_id', 'Неправильный идентификатор устройства'); + } + if ($device->keygen != $_COOKIE['device_key']) { + $this->addError('device_id', 'Переданный идентификатор не совпадает с привязанным устройством'); + } + }], + [['plan_id'], function () { + if (!$this->plan_id) { + return; + } + /** @var TimetablePlan $plan */ + $plan = TimetablePlan::find()->andWhere(['id' => $this->plan_id])->one(); + if (!$plan) { + $this->addError('plan_id', 'Неправильный номер записи плана'); + } + if (!$plan->isWorkSlot()) { + $this->addError('plan_id', 'Нерабочий день по плану'); + } + if ($this->date != $plan->date) { + $this->addError('date', 'Дата открытия не совпадает с планом'); + } + $targetAdminId = $this->replaced_admin_id ?: $this->admin_id; + if ($targetAdminId != $plan->admin_id) { + $this->addError($this->replaced_admin_id ? 'replaced_admin_id' : 'admin_id', 'Выбран неправильный пользователь в плане'); + } + if ($this->d_id != $plan->d_id) { + $this->addError('d_id', 'Выбранная должность не совпадает с планом'); + } + if ($this->date != $plan->date) { + $this->addError('date', 'Дата не совпадает с планом'); + } + }], + ]; + } + + public function beforeValidate() + { + $this->time = date('Y-m-d H:i:s'); + return parent::beforeValidate(); + } + + public function save() + { + if (!$this->validate()) { + return false; + } + $filePath = $this->generateFilePath(); + if ($this->hasErrors()) { + parent::afterValidate(); + return false; + } + + if (!$this->photo->saveAs($filePath)) { + $this->addError('photo', 'Невозможно загрузить файл фотографии'); + parent::afterValidate(); + return false; + } + + $attributes = ['photo' => $filePath] + $this->getAttributes(); + $this->checkinModel->setAttributes($attributes); + if (!$this->checkinModel->save()) { + $this->addErrors($this->checkinModel->getErrors()); + return false; + } + return true; + } + + private function generateFilePath(): string + { + $Y = date("Y"); + $m = date("m"); + if (!is_dir("data/admin/$Y/$m")) { + mkdir("data/admin/$Y/$m", 0777, true); + } + $fileName = $_SESSION["admin_id"] . '-' . date("YmdHis") . '.jpg'; + return "data/admin/$Y/$m/$fileName"; + } + + public function getStore() + { + return CityStore::find() + ->andWhere(['id' => $this->store_id]) + ->one() + ; + } + + /** + * @return TimetablePlan + */ + public function getPlanSlot() + { + if (!$this->planSlotModel) { + $this->planSlotModel = TimetablePlan::find()->andWhere(['id' => $this->plan_id])->one(); + } + return $this->planSlotModel; + } + +} \ No newline at end of file diff --git a/erp24/forms/timetable/TabelSearchForm.php b/erp24/forms/timetable/TabelSearchForm.php new file mode 100755 index 00000000..cd303466 --- /dev/null +++ b/erp24/forms/timetable/TabelSearchForm.php @@ -0,0 +1,147 @@ + array_keys(self::stores())], + [['adminGroupId'], 'in', 'range' => array_keys(AdminGroup::groupsWithShift())], + [['start', 'end'], 'date', 'format' => 'php:Y-m-d'], + [['status'], 'in' ,'range' => array_keys(Timetable::statuses())], + [['start'], 'default', 'value' => date('Y-m-01', strtotime('next month midnight'))], + [['end'], 'default', 'value' => date('Y-m-t', strtotime('next month midnight'))], + ]; + } + + public function attributeLabels() + { + return [ + 'storeId' => 'Магазин', + 'start' => 'Дата начала', + 'end' => 'Дата конца', + 'adminGroupId' => 'Группа работников', + ]; + } + + public static function stores() : array + { + $stores = CityStore::find() + ->select(['name', 'id']) + ->andWhere(['id' => $_SESSION["store_arr_dostup"]]) + ->indexBy('id') + ->cache(3600) + ->column(); + natsort($stores); + return $stores; + } + + public static function adminGroups(): array + { + static $groups; + if (isset($groups)) { + return $groups; + } + return \Yii::$app->getCache()->getOrSet('admin_groups_with_shifts', function () { + return AdminGroup::find() + ->with(['shift']) + ->andWhere(['NOT IN', 'id', [1, 2, -1]]) + ->indexBy('id') + ->all(); + }); + } + + /** + * @return Admin[] + */ + public function admins() + { + $adminQuery = Admin::find() + ->select(['id', 'name', 'group_id', 'store_arr', 'avatarka']) + ->with(['adminGroup' => function (ActiveQuery $q) { + return $q->select(['id', 'name']); + }]) + ->with('adminGroup.shift') + ->andWhere([ + 'group_id' => array_keys(AdminGroup::groupsWithShift()) + ]) + ->andFilterWhere(['group_id' => $this->adminGroupId]) + ->orderBy(['group_id' => SORT_ASC, 'name' => SORT_ASC]) + ->indexBy('id'); + if ($this->storeId) { + $adminQuery + ->andWhere(new Expression('FIND_IN_SET(:store_id, store_arr)', ['store_id' => (int) $this->storeId])); + } + return $adminQuery->all(); + } + + public function search($tabel) + { + $classes = [ + Timetable::TABLE_PLAN => TimetablePlan::class, + Timetable::TABLE_FACT => TimetableFact::class, + ]; + if (!isset($classes[$tabel])) { + throw new \Exception('Unknown type'); + } + /** @var TimetablePlan | TimetableFact $class */ + $class = $classes[$tabel]; + return $class::find() + ->andWhere([ + 'admin_group_id' => array_keys(AdminGroup::groupsWithShift()), + 'store_id' => array_keys(self::stores()), + ]) + ->andFilterWhere([ + 'admin_group_id' => $this->adminGroupId, + 'store_id' => $this->storeId, + 'status' => $this->status, + ]) + ->andFilterWhere(['>=', 'date', $this->start]) + ->andFilterWhere(['<=', 'date', $this->end]) + ; + } + + public function holidays() + { + return $this->validate(['start', 'end'], false) ? Holiday::find() + ->andFilterWhere(['>=', 'date', $this->start]) + ->andFilterWhere(['<=', 'date', $this->end]) + ->all() : [] + ; + } + + public function getDates(): array + { + $startDatetime = new \DateTime($this->start); + $endDatetime = new \DateTime($this->end); + + $dates = []; + for ($date = clone $startDatetime; $date <= $endDatetime; $date->modify('+1 day')) { + $dates[] = clone $date; + } + + return $dates; + } +} \ No newline at end of file diff --git a/erp24/forms/timetable/TabelSearchFormFact.php b/erp24/forms/timetable/TabelSearchFormFact.php new file mode 100755 index 00000000..40be10f7 --- /dev/null +++ b/erp24/forms/timetable/TabelSearchFormFact.php @@ -0,0 +1,124 @@ + array_keys(self::stores())], + [['adminGroupId'], 'in', 'range' => array_keys(AdminGroup::groupsWithShift())], + [['start', 'end'], 'date', 'format' => 'php:Y-m-d'], + [['status'], 'in' ,'range' => array_keys(Timetable::statuses())], + [['status'], 'default' ,'value' => Timetable::STATUS_PENDING], + [['start'], 'default', 'value' => date('Y-m-d', strtotime('-7 day'))], + [['end'], 'default', 'value' => date('Y-m-d', strtotime('+1 day'))], + ]; + } + + public function attributeLabels() + { + return [ + 'storeId' => 'Магазин', + 'start' => 'Дата начала', + 'end' => 'Дата конца', + 'adminGroupId' => 'Группа работников', + 'status' => 'Статус проверки', + ]; + } + + public static function stores() : array + { + return CityStore::find() + ->select(['name', 'id']) + ->andWhere(['id' => $_SESSION["store_arr_dostup"]]) + ->indexBy('id') + ->cache(3600) + ->column(); + } + + public static function adminGroups(): array + { + static $groups; + if (isset($groups)) { + return $groups; + } + return \Yii::$app->getCache()->getOrSet('admin_groups_with_shifts', function () { + return AdminGroup::find() + ->with(['shift']) + ->andWhere(['NOT IN', 'id', [1, 2, -1]]) + ->indexBy('id') + ->all(); + }); + } + + /** + * @return Admin[] + */ + public function admins() + { + $adminQuery = Admin::find() + ->select(['id', 'name', 'group_id', 'store_arr']) + ->with(['adminGroup' => function (ActiveQuery $q) { + return $q->select(['id', 'name']); + }]) + ->with('adminGroup.shift') + ->andWhere([ + 'group_id' => array_keys(AdminGroup::groupsWithShift()) + ]) + ->andFilterWhere(['group_id' => $this->adminGroupId]) + ->orderBy(['group_id' => SORT_ASC, 'name' => SORT_ASC]) + ->indexBy('id'); + if ($this->storeId) { + $adminQuery + ->andWhere(new Expression('FIND_IN_SET(:store_id, store_arr)', ['store_id' => (int) $this->storeId])); + } + return $adminQuery->all(); + } + + public function search($tabel) + { + $classes = [ + Timetable::TABLE_PLAN => TimetablePlan::class, + Timetable::TABLE_FACT => TimetableFact::class, + ]; + if (!isset($classes[$tabel])) { + throw new \Exception('Unknown type'); + } + /** @var TimetablePlan | TimetableFact $class */ + $class = $classes[$tabel]; + return $class::find() + ->andWhere([ + 'admin_group_id' => array_keys(AdminGroup::groupsWithShift()), + 'store_id' => array_keys(self::stores()), + ]) + ->andFilterWhere([ + 'admin_group_id' => $this->adminGroupId, + 'store_id' => $this->storeId, + 'status' => $this->status, + ]) + ->andFilterWhere(['>=', 'date', $this->start]) + ->andFilterWhere(['<=', 'date', $this->end]) + ; + } +} \ No newline at end of file diff --git a/erp24/forms/writeOffsErp/WriteOffsForm.php b/erp24/forms/writeOffsErp/WriteOffsForm.php new file mode 100644 index 00000000..346e49f1 --- /dev/null +++ b/erp24/forms/writeOffsErp/WriteOffsForm.php @@ -0,0 +1,34 @@ + 'Магазин', + ]; + } + +} \ No newline at end of file diff --git a/erp24/forms/writeOffsErp/WriteOffsProductsForm.php b/erp24/forms/writeOffsErp/WriteOffsProductsForm.php new file mode 100644 index 00000000..43d0818c --- /dev/null +++ b/erp24/forms/writeOffsErp/WriteOffsProductsForm.php @@ -0,0 +1,111 @@ +select('quantity') + ->andWhere([ + 'product_id' => $productGuid, + 'store_id' => $storeGuid, //'quantity' + ])->asArray() + + ->scalar(); + + + return $productCount; + } + + /** + * {@inheritdoc} + */ + public function rules() + { + return [ + [['product_id', 'quantity'], 'required'], + [['store_id', 'cause_id'], 'integer'], + [['quantity'], 'number'], + [['product_id'], 'string', 'max' => 36], + ['quantity', 'compare', 'compareValue' => 0, 'operator' => '>'], + ['product_id', 'custom_function_validation'], + ]; + } + public function custom_function_validation($attribute, $params) + { + if (empty($this->quantity) || empty($this->store_id)) { + $errorText = 'Проверка по наличию товара под списание в магазине не пройдена'; + $this->addError($attribute, $errorText); + } else { + $resultCheck = self::checkProductBalance($this->$attribute, $this->store_id, $this->quantity); + + if (!empty($resultCheck)) { + $this->addError($attribute, $resultCheck); + } + } + + } + + +/** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'product_id' => 'Товар', + 'cause_id' => 'Причина списания', + 'quantity' => 'Количество', + ]; + } + +} \ No newline at end of file diff --git a/erp24/models/LoginForm.php b/erp24/models/LoginForm.php index e86786f6..f68ba61a 100644 --- a/erp24/models/LoginForm.php +++ b/erp24/models/LoginForm.php @@ -103,6 +103,8 @@ class LoginForm extends Model $_SESSION['dostup_area'] = []; $group = AdminGroup::findOne($user->group_id); $_SESSION['admin_group_name'] = $group->name ?? "Какая-то..."; + $_SESSION['name_group_admin'] = $group->name ?? "Какая-то..."; + $_SESSION['status_dostup_arr'] = []; $_SESSION['admin_group_add_arr'] = []; @@ -123,7 +125,6 @@ class LoginForm extends Model $_SESSION['manager_id'] = $user->manager_id ?? null; $_SESSION['content_dostup'] = $user->content_dostup ?? null; - $_SESSION['name_group_admin'] = "Пользователь"; } /** diff --git a/erp24/tests/functional/PageListCest.php b/erp24/tests/functional/PageListCest.php new file mode 100644 index 00000000..c9a1e607 --- /dev/null +++ b/erp24/tests/functional/PageListCest.php @@ -0,0 +1,13 @@ +amLoggedInAs(\app\models\User::findByUsername('admin')); + $I->amOnPage('/info-table/shift-sales'); + $I->see('Login', 'h1'); + } + +} \ No newline at end of file diff --git a/erp24/tests/unit/models/UserTest.php b/erp24/tests/unit/models/UserTest.php index 28986cbb..697e1459 100644 --- a/erp24/tests/unit/models/UserTest.php +++ b/erp24/tests/unit/models/UserTest.php @@ -3,13 +3,14 @@ namespace tests\unit\models; use app\models\User; +use yii_app\records\Admin; class UserTest extends \Codeception\Test\Unit { public function testFindUserById() { - verify($user = User::findIdentity(100))->notEmpty(); - verify($user->username)->equals('admin'); + verify($user = Admin::findIdentity(1))->notEmpty(); + verify($user->login_user)->equals('root'); verify(User::findIdentity(999))->empty(); } diff --git a/erp24/views/layouts/api2_menu.php b/erp24/views/layouts/api2_menu.php index 2f5389a3..18e16f09 100644 --- a/erp24/views/layouts/api2_menu.php +++ b/erp24/views/layouts/api2_menu.php @@ -4,4 +4,4 @@ $this->registerJS(" var ADMIN_ID = " . (Yii::$app->user->id ?? 0) . "; ", \yii\web\View::POS_BEGIN, 'api2_menu_init_global_vars'); -//$this->registerJsFile('/js/site/get_menu.js', ['position' => \yii\web\View::POS_END]); +$this->registerJsFile('/js/site/get_menu.js', ['position' => \yii\web\View::POS_END]); diff --git a/erp24/web/favicon.ico b/erp24/web/favicon.ico index 580ed732..a62770a9 100644 Binary files a/erp24/web/favicon.ico and b/erp24/web/favicon.ico differ