--- /dev/null
+<?php
+
+namespace yii_app\actions\timetable;
+
+use app\records\TimetableFactModel;
+use Yii;
+use yii\base\Action;
+use yii\base\DynamicModel;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Json;
+use yii_app\records\Admin;
+use yii_app\records\AdminCheckin;
+use yii_app\records\AdminDevice;
+use yii_app\records\AdminGroup;
+use yii_app\records\CityStore;
+use yii_app\records\EmployeePayment;
+use yii_app\records\Shift;
+use yii_app\records\Timetable;
+
+class AddFactHandAction extends Action
+{
+ public function run() {
+ $action = Yii::$app->request->post('action');
+
+ $model = DynamicModel::validateData([
+ 'admin_id' => 0, 'store_id' => 0, 'shift_id' => 0, 'plan_id' => null,
+ 'tabel' => null, 'admin_group_id' => null, 'timetable_fact_id' => null, 'shift_start' => null, 'shift_end' => null
+ ],
+ [
+ [['admin_id', 'store_id', 'shift_id', 'shift_start', 'shift_end'], 'required'],
+ [['plan_id', 'tabel', 'admin_group_id', 'timetable_fact_id'], 'safe']
+ ]);
+
+ $allowAdd = false;
+ if (Yii::$app->request->isPost && $model->load(Yii::$app->request->post())) {
+ if ($model->validate()) {
+ $allowAdd = true;
+ if (in_array($action, ['createFact', 'createFactOpenShift', 'createFactCloseShift'])) {
+
+ $checkInIds = [];
+ foreach (range(0,1) as $index) {
+ if ($index == 0 && $action == 'createFactCloseShift') {
+ continue;
+ }
+ if ($index == 1 && $action == 'createFactOpenShift') {
+ continue;
+ }
+ $checkIn = new AdminCheckin;
+ $checkIn->admin_id = $model->admin_id;
+ if (!empty($model->plan_id)) {
+ $checkIn->plan_id = $model->plan_id;
+ }
+ $checkIn->store_id = $model->store_id;
+ $checkIn->ball = 5;
+ $checkIn->comment = "Ручное добавление чекина";
+ $checkIn->d_id = $model->admin_group_id;
+ $checkIn->date = date('Y-m-d', strtotime($model->shift_start));
+ $checkIn->time = [$model->shift_start, $model->shift_end][$index];
+ $checkIn->lat = null;
+ $checkIn->lon = null;
+ $checkIn->photo = 'images/next.png';
+ $checkIn->device_id = AdminDevice::findOne(['admin_id' => $model->admin_id])->id ?? 0;
+ $checkIn->type_id = in_array($model->shift_id, [5, 8]) ? AdminCheckin::TYPE_APPEAR :
+ [AdminCheckin::TYPE_START, AdminCheckin::TYPE_END][$index];
+ $checkIn->status = 0;
+ $checkIn->save();
+ if ($checkIn->getErrors()) {
+ throw new \Exception(Json::encode($checkIn->getErrors()));
+ }
+ $checkInIds[$index] = $checkIn->id;
+ }
+
+ if (in_array($action, ['createFact', 'createFactOpenShift'])) {
+ $timetableFactModel = new TimetableFactModel;
+ $timetableFactModel->admin_id = $model->admin_id;
+ $timetableFactModel->store_id = $model->store_id;
+ $timetableFactModel->admin_group_id = $model->admin_group_id;
+ $timetableFactModel->d_id = $model->admin_group_id;
+ $timetableFactModel->date_shift = date('Y-m-d', strtotime($model->shift_start));
+ $timetableFactModel->date_start = $timetableFactModel->date_shift;
+ $timetableFactModel->date_end = date('Y-m-d', strtotime($model->shift_end));
+ $timetableFactModel->is_opening = false;
+ $timetableFactModel->is_close = true;
+ if (!empty($model->tabel)) {
+ $timetableFactModel->tabel = $model->tabel;
+ }
+ $timetableFactModel->shift_id = $model->shift_id;
+ $timetableFactModel->admin_id_add = Yii::$app->user->id;
+ $timetableFactModel->time_start = date("H:i:s", strtotime($model->shift_start));
+ $timetableFactModel->time_end = date("H:i:s", strtotime($model->shift_end));
+ $timetableFactModel->work_time = min(abs(strtotime($timetableFactModel->date_end
+ . $timetableFactModel->time_end) + 600 - strtotime($timetableFactModel->date_start
+ . $timetableFactModel->time_start)) / 3600, TimetableFactModel::WORK_HOURS_TIME);
+
+ $timetableFactModel->salary_shift = !empty($salary = EmployeePayment::findOne(['admin_id' => $model->admin_id])) ? $salary->daily_payment : null;
+ $timetableFactModel->price_hour = $timetableFactModel->salary_shift / ($timetableFactModel->d_id == AdminGroup::GROUP_ADMINISTRATORS ? 8 : 12);
+ $timetableFactModel->date_add = date('Y-m-d H:i:s');
+ $timetableFactModel->status = AdminCheckin::TYPE_END;
+ $timetableFactModel->checkin_start_id = $checkInIds[0];
+ if ($action == 'createFact') {
+ $timetableFactModel->checkin_end_id = $checkInIds[1];
+ }
+ }
+ if ($action == 'createFactCloseShift') {
+ $timetableFactModel = TimetableFactModel::findOne($model->timetable_fact_id);
+ $timetableFactModel->checkin_end_id = $checkInIds[1];
+ }
+ $timetableFactModel->save();
+ if ($timetableFactModel->getErrors()) {
+ throw new \Exception(Json::encode($timetableFactModel->getErrors()));
+ }
+
+ return $this->controller->redirect('/timetable/add-fact-hand');
+ }
+ } else {
+ $adm = Admin::findOne($model->admin_id);
+ if ($adm) {
+ $model->admin_group_id = $adm->group_id;
+ }
+ }
+ }
+
+ $adminArr = [];
+ foreach (Admin::find()->with('adminGroup')->orderBy(['id' => SORT_ASC])->all() as $admin) {
+ if ($admin->group_id > 0) {
+ $adminArr[] = ['id' => $admin->id, 'name' => $admin->name, 'groupName' => $admin->adminGroup->name ?? "Другие"];
+ }
+ }
+ $admins = ArrayHelper::map($adminArr, 'id', 'name', 'groupName');
+ $stores = ArrayHelper::map(CityStore::find()->all(), 'id', 'name');
+ $shifts = ArrayHelper::map(Shift::find()->all(), 'id', 'name');
+ $adminGroups = ArrayHelper::map(AdminGroup::find()->all(), 'id', 'name');
+ foreach ($adminGroups as $key => $name) {
+ if (!in_array($key, AdminGroup::getGroupsForEmployeeOnCashbox())) {
+ unset($adminGroups[$key]);
+ }
+ }
+
+ $timetables = null;
+ $checkIns = null;
+ $timetableFacts = null;
+
+ if ($allowAdd) {
+ $timetables = Timetable::find()->where([
+ 'or',
+ [
+ 'and',
+ ['<=', 'datetime_start', date('Y-m-d H:i:s', strtotime("+6 hour", strtotime($model->shift_start)))],
+ ['>=', 'datetime_end', date('Y-m-d H:i:s', strtotime("+6 hour", strtotime($model->shift_start)))],
+ ],
+ [
+ 'and',
+ ['<=', 'datetime_start', date('Y-m-d H:i:s', strtotime("-6 hour", strtotime($model->shift_end)))],
+ ['>=', 'datetime_end', date('Y-m-d H:i:s', strtotime("-6 hour", strtotime($model->shift_end)))],
+ ],
+ [
+ 'and',
+ ['>=', 'datetime_start', date('Y-m-d H:i:s', strtotime("+6 hour", strtotime($model->shift_start)))],
+ ['<=', 'datetime_end', date('Y-m-d H:i:s', strtotime("-6 hour", strtotime($model->shift_end)))],
+ ],
+ ])->andWhere(['admin_id' => $model->admin_id])->all();
+
+ $checkIns = AdminCheckin::find()->where(['admin_id' => $model->admin_id])
+ ->andWhere([
+ 'and',
+ ['>=', 'time', date('Y-m-d H:i:s', strtotime("-6 hour", strtotime($model->shift_start)))],
+ ['<=', 'time', date('Y-m-d H:i:s', strtotime("+6 hour", strtotime($model->shift_end)))],
+ ])->all();
+
+ $timetableFacts = TimetableFactModel::find()->where(['admin_id' => $model->admin_id])
+ ->andWhere(['>=', 'date_shift', date('Y-m-d', strtotime($model->shift_start))])
+ ->andWhere(['<=', 'date_shift', date('Y-m-d', strtotime($model->shift_end))])
+ ->all();
+ }
+
+ return $this->controller->render('add-fact-hand', compact('model', 'admins', 'stores',
+ 'shifts', 'allowAdd', 'timetables', 'checkIns', 'timetableFacts', 'adminGroups'));
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+use dosamigos\datetimepicker\DateTimePicker;
+use \yii\helpers\Html;
+use \yii\widgets\ActiveForm;
+use \yii\base\DynamicModel;
+
+/** @var $model DynamicModel */
+/** @var $admins array */
+/** @var $stores array */
+/** @var $shifts array */
+/** @var $allowAdd bool */
+/** @var $timetables array */
+/** @var $checkIns array */
+/** @var $timetableFacts array */
+/** @var $adminGroups array */
+
+?>
+
+<div class="timetableAddFactHand m-5">
+
+ <?php $form = ActiveForm::begin(['enableClientScript' => false]) ?>
+
+ <div class="row">
+ <div class="col-12">
+ Сотрудник: <div style="display:inline-block"><?= $form->field($model, 'admin_id')->dropDownList($admins)->label(false) ?></div>
+ Магазин: <div style="display:inline-block"><?= $form->field($model, 'store_id')->dropDownList($stores)->label(false) ?></div>
+ Тип смены: <div style="display:inline-block"><?= $form->field($model, 'shift_id')->dropDownList($shifts)->label(false) ?></div>
+ <br>
+ <span style="text-decoration: underline; color: blue;" title="Выберите кликом из Смены (/timetable/fact, /timetable/plan):">plan_id</span>: <div style="display:inline-block"><?= $form->field($model, 'plan_id')->textInput(['type' => 'number'])->label(false) ?></div>
+ <span style="text-decoration: underline; color: blue;" title="Выберите кликом из Смены (/timetable/fact, /timetable/plan):">tabel</span>: <div style="display:inline-block"><?= $form->field($model, 'tabel')->textInput(['type' => 'number'])->label(false) ?></div>
+ <span style="text-decoration: underline; color: blue;" title="Выберите кликом из Смены (/timetable/fact, /timetable/plan):">admin_group_id</span>: <div style="display:inline-block"><?= $form->field($model, 'admin_group_id')->dropDownList($adminGroups)->label(false) ?></div>
+ <br>
+ Начало смены: <div style="display:inline-block"><?= $form->field($model, 'shift_start')->widget(DateTimePicker::class, [
+ 'language' => 'ru',
+ 'template' => '{input}',
+ 'clientOptions' => [
+ 'autoclose' => true,
+ 'format' => 'Y-m-d H:i:s',
+ 'todayBtn' => true
+ ],
+ ])->label(false) ?></div>
+ Конец смены: <div style="display:inline-block"><?= $form->field($model, 'shift_end')->widget(DateTimePicker::class, [
+ 'language' => 'ru',
+ 'template' => '{input}',
+ 'clientOptions' => [
+ 'autoclose' => true,
+ 'format' => 'Y-m-d H:i:s',
+ 'todayBtn' => true
+ ],
+ ])->label(false) ?></div>
+ <br>
+ <?= Html::submitButton('Показать смены и чекины', ['class' => 'btn btn-secondary btn-sm', 'name' => 'action', 'value' => 'showShiftsAndCheckins'])?>
+ <?php if ($allowAdd): ?>
+ <?= Html::submitButton('Создать факт и чикины', ['class' => 'btn btn-danger btn-sm', 'name' => 'action', 'value' => 'createFact'])?>
+ <?= Html::submitButton('Создать факт и чикин (открыть смену)', ['class' => 'btn btn-danger btn-sm', 'name' => 'action', 'value' => 'createFactOpenShift'])?>
+ <span style="text-decoration: underline; color: blue;" title="Выберите кликом из Смены-Факта (/timetable-fact):">timetable_fact_id</span>: <div style="display:inline-block"><?= $form->field($model, 'timetable_fact_id')->textInput(['type' => 'number'])->label(false) ?></div>
+ <?= Html::submitButton('Создать чикин (закрыть смену)', ['class' => 'btn btn-danger btn-sm', 'name' => 'action', 'value' => 'createFactCloseShift'])?>
+ <?php endif; ?>
+ </div>
+ </div>
+
+ <?php ActiveForm::end() ?>
+
+ <?php if ($allowAdd): ?>
+ Смены-Факты (/timetable-fact):
+ <table id="timetableFacts" class="m-5">
+ <thead>
+ <tr>
+ <th>timetable_fact_id</th>
+ <th>Магазин</th>
+ <th>День смены</th>
+ <th>Начала смены</th>
+ <th>Конец смены</th>
+ <th>Чекин старт id</th>
+ <th>Чекин конец id</th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($timetableFacts as $timetableFact): ?>
+ <tr>
+ <td style="text-decoration: underline; color: blue;" onclick="document.querySelector('#dynamicmodel-timetable_fact_id').value = this.innerHTML"><?= $timetableFact->id ?></td>
+ <td><?= $stores[$timetableFact->store_id] ?? '' ?></td>
+ <td><?= $timetableFact->date_shift ?></td>
+ <td><?= $timetableFact->time_start ?></td>
+ <td><?= $timetableFact->time_end ?></td>
+ <td><?= $timetableFact->checkin_start_id ?></td>
+ <td><?= $timetableFact->checkin_end_id ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ Смены (/timetable/fact, /timetable/plan):
+ <table id="timetables" class="m-5">
+ <thead>
+ <tr>
+ <th>id</th>
+ <th>План/Факт</th>
+ <th>admin_group_id</th>
+ <th>Магазин</th>
+ <th>Начала смены</th>
+ <th>Конец смены</th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($timetables as $timetable): ?>
+ <tr>
+ <td style="text-decoration: underline; color: blue;" onclick="document.querySelector('#dynamicmodel-<?= empty($timetable->plan_id) ? 'plan_id' : 'tabel' ?>').value = this.innerHTML"><?= $timetable->id ?></td>
+ <td><?= $timetable->tabel == 0 ? 'План' : 'Факт'?></td>
+ <td style="text-decoration: underline; color: blue;" onclick="document.querySelector('#dynamicmodel-admin_group_id').value = this.innerHTML"><?= $timetable->admin_group_id ?></td>
+ <td><?= $stores[$timetable->store_id] ?? '' ?></td>
+ <td><?= $timetable->datetime_start ?></td>
+ <td><?= $timetable->datetime_end ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ Чекины:
+ <table id="checkIns" class="m-5">
+ <thead>
+ <tr>
+ <th>id</th>
+ <th>plan_id</th>
+ <th>type_id</th>
+ <th>Время</th>
+ <th>Магазин</th>
+ <th>Фото</th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($checkIns as $checkIn): ?>
+ <tr>
+ <td><?= $checkIn->id ?></td>
+ <td><?= $checkIn->plan_id ?></td>
+ <td><?= $checkIn->type_id == 1 ? 'Старт' : ($checkIn->type_id == 2 ? 'Конец' : 'Появление') ?></td>
+ <td><?= $checkIn->time ?></td>
+ <td><?= $stores[$checkIn->store_id] ?? '' ?></td>
+ <td><?php \yii_app\helpers\ImageHelper::drawImage($checkIn->photo, 100) ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ <script>
+ $(document).ready(() => {
+ const options = {
+ info: false,
+ paging: false,
+ searching: false,
+ language: data_table_language
+ };
+ $("#timetableFacts").DataTable(options);
+ $("#timetables").DataTable(options);
+ $("#checkIns").DataTable(options);
+ });
+ </script>
+ <?php endif; ?>
+</div>