diff --git a/app/Admin/Controllers/Hr/RestController.php b/app/Admin/Controllers/Hr/RestController.php new file mode 100644 index 0000000..29af702 --- /dev/null +++ b/app/Admin/Controllers/Hr/RestController.php @@ -0,0 +1,63 @@ +baseCRUD() + ->tableLayout('fixed') + ->headerToolbar([ + $this->createButton(true, 'lg'), + ...$this->baseHeaderToolBar(), + ]) + ->bulkActions([]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + amisMake()->TextControl()->name('employee_name')->label(__('employee_sign.employee_id'))->placeholder(__('employee.name') .'/'. __('employee.phone'))->columnRatio(3)->clearable(), + amisMake()->DateRangeControl()->name('date_range')->label(__('employee_sign.date'))->columnRatio(3)->clearable(), + ]), + ])) + ->columns([ + amisMake()->TableColumn()->name('employee.name')->label(__('employee.name')), + // amisMake()->TableColumn()->name('employee.phone')->label(__('employee.phone')), + amisMake()->TableColumn()->name('date')->label(__('employee_sign.date')), + $this->rowActions([ + $this->rowDeleteButton(), + ]), + ]); + + return $this->baseList($crud); + } + + public function form($edit): Form + { + return $this->baseForm()->title('')->body([ + amisMake()->SelectControl()->name('employees')->label(__('employee_sign.employee_id')) + ->source(admin_url('hr/employees?_action=getData&_all=1&employee_status=' . EmployeeStatus::Online->value)) + ->labelField('name') + ->valueField('id') + ->searchable() + ->multiple() + ->joinValues(false) + ->extractValue() + ->required(), + amisMake()->ArrayControl()->name('dates')->label(__('employee_sign.date'))->items([ + amisMake()->DateControl()->name('date')->label('')->valueFormat('YYYY-MM-DD'), + ])->required(), + // amisMake()->DateControl()->name('dates')->label(__('employee_sign.date'))->set('embed', true)->required(), + ]); + } +} diff --git a/app/Admin/Filters/EmployeeRestFilter.php b/app/Admin/Filters/EmployeeRestFilter.php new file mode 100644 index 0000000..33c1d28 --- /dev/null +++ b/app/Admin/Filters/EmployeeRestFilter.php @@ -0,0 +1,34 @@ + [ + 'store_title' => 'title' + ], + 'employee' => [ + 'employee_name' => 'name', + 'employee_search' => 'search', + ] + ]; + + public function employeeId($key) + { + $this->where('employee_id', $key); + } + + public function dateRange($dates) + { + $dates = explode(',', $dates); + $start = Carbon::createFromTimestamp(data_get($dates, 0, time()))->startOfDay(); + $end = Carbon::createFromTimestamp(data_get($dates, 1, time()))->endOfDay(); + $this->whereBetween('date', [$start, $end]); + } +} diff --git a/app/Admin/Services/EmployeeRestService.php b/app/Admin/Services/EmployeeRestService.php new file mode 100644 index 0000000..9f849b6 --- /dev/null +++ b/app/Admin/Services/EmployeeRestService.php @@ -0,0 +1,50 @@ +resloveData($data); + + $validate = $this->validate($data); + if ($validate !== true) { + $this->setError($validate); + + return false; + } + + if (isset($data['employees']) && isset($data['dates'])) { + $dates = array_unique($data['dates']); + $employees = Employee::whereIn('id', $data['employees'])->enable()->get(); + $list = []; + $now = now(); + foreach($employees as $employee) { + foreach ($dates as $date) { + array_push($list, [ + 'date' => $date, + 'employee_id' => $employee->id, + ]); + } + } + EmployeeRest::insert($list); + } else { + $this->modelName::create($data); + } + return true; + } + +} \ No newline at end of file diff --git a/app/Admin/routes.php b/app/Admin/routes.php index 7a87064..493eede 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -1,6 +1,7 @@ post('employees/{id}/leave', [EmployeeController::class, 'leave'])->name('employees.leave'); // 职位管理 $router->resource('jobs', BaseKeywordController::class); + $router->resource('rests', RestController::class); }); diff --git a/app/Enums/SignStatus.php b/app/Enums/SignStatus.php new file mode 100644 index 0000000..738df57 --- /dev/null +++ b/app/Enums/SignStatus.php @@ -0,0 +1,24 @@ +value => '正常', + self::Absent->value => '旷工', + self::Lose->value => '缺卡', + ]; + } + + public function text() + { + return data_get(self::options(), $this->value); + } +} diff --git a/app/Enums/SignType.php b/app/Enums/SignType.php new file mode 100644 index 0000000..67eb7ce --- /dev/null +++ b/app/Enums/SignType.php @@ -0,0 +1,22 @@ +value => '正常打卡', + self::Outside->value => '外勤打卡', + ]; + } + + public function text() + { + return data_get(self::options(), $this->value); + } +} diff --git a/app/Models/EmployeeRest.php b/app/Models/EmployeeRest.php new file mode 100644 index 0000000..1b755a8 --- /dev/null +++ b/app/Models/EmployeeRest.php @@ -0,0 +1,29 @@ + 'date:Y-m-d', + ]; + + public $timestamps = false; + + public function employee() + { + return $this->belongsTo(Employee::class, 'employee_id'); + } +} diff --git a/app/Models/EmployeeSign.php b/app/Models/EmployeeSign.php new file mode 100644 index 0000000..3ac4d55 --- /dev/null +++ b/app/Models/EmployeeSign.php @@ -0,0 +1,37 @@ + 'date:Y-m-d', + 'sign_type' => SignType::class, + 'sign_status' => SignStatus::class, + 'first_time' => 'datetime', + 'last_time' => 'datetime', + ]; + + public function store() + { + return $this->belongsTo(Store::class, 'store_id'); + } + + public function employee() + { + return $this->belongsTo(Employee::class, 'employee_id'); + } +} diff --git a/app/Models/EmployeeSignLog.php b/app/Models/EmployeeSignLog.php new file mode 100644 index 0000000..48133af --- /dev/null +++ b/app/Models/EmployeeSignLog.php @@ -0,0 +1,31 @@ + SignType::class, + 'position' => 'json', + ]; + + public function store() + { + return $this->belongsTo(Store::class, 'store_id'); + } + + public function employee() + { + return $this->belongsTo(Employee::class, 'employee_id'); + } +} diff --git a/app/Models/WorkflowLog.php b/app/Models/WorkflowLog.php index 10ceb97..fd6fa0b 100644 --- a/app/Models/WorkflowLog.php +++ b/app/Models/WorkflowLog.php @@ -2,10 +2,38 @@ namespace App\Models; +use App\Enums\CheckStatus; +use App\Enums\CheckType; use Illuminate\Database\Eloquent\Model; +/** + * 审核流水 + */ class WorkflowLog extends Model { protected $fillable = ['batch_id', 'check_type', 'check_value', 'check_name', 'user_id', 'subject_type', 'subject_id', 'subject_data', 'is_enable', 'check_user_id', 'checked_at', 'remarks', 'check_status', 'sort']; + protected $casts = [ + 'check_type' => CheckType::class, + 'check_status' => CheckStatus::class, + 'is_enable' => 'boolean', + 'subject_data' => 'json', + ]; + + public function user() + { + return $this->belongsTo(Employee::class, 'user_id'); + } + + public function checkUser() + { + return $this->belongsTo(Employee::class, 'check_user_id'); + } + + public function subject() + { + // 定义反向关联 + // $this->morphMany(WorkflowLog::class, 'subject'); + return $this->morphTo(); + } } diff --git a/database/migrations/2024_03_27_113404_create_workflows_table.php b/database/migrations/2024_03_27_113404_create_workflows_table.php index 8f168f7..9923afc 100644 --- a/database/migrations/2024_03_27_113404_create_workflows_table.php +++ b/database/migrations/2024_03_27_113404_create_workflows_table.php @@ -48,5 +48,6 @@ return new class extends Migration public function down(): void { Schema::dropIfExists('workflows'); + Schema::dropIfExists('workflow_logs'); } }; diff --git a/database/migrations/2024_03_27_140744_create_employee_sign_table.php b/database/migrations/2024_03_27_140744_create_employee_sign_table.php new file mode 100644 index 0000000..e0db072 --- /dev/null +++ b/database/migrations/2024_03_27_140744_create_employee_sign_table.php @@ -0,0 +1,75 @@ +id(); + $table->date('date')->comment('日期'); + $table->foreignId('store_id')->comment('门店, stores.id'); + $table->foreignId('employee_id')->comment('员工, employees.id'); + $table->unsignedInteger('sign_type')->default(1)->comment('类别(1: 正常打卡, 2: 外勤)'); + $table->timestamp('first_time')->nullable()->comment('上班打卡时间'); + $table->timestamp('last_time')->nullable()->comment('下班打卡时间'); + $table->unsignedInteger('sign_status')->default(1)->comment('考勤状态(1: 正常, 2: 旷工, 3: 缺卡)'); + $table->timestamps(); + + $table->comment('员工-考勤记录'); + }); + + Schema::create('employee_sign_logs', function (Blueprint $table) { + $table->id(); + $table->foreignId('store_id')->comment('门店, stores.id'); + $table->foreignId('employee_id')->comment('员工, employees.id'); + $table->unsignedInteger('sign_type')->default(1)->comment('类别(1: 正常打卡, 2: 外勤)'); + $table->string('remarks')->nullable()->comment('备注'); + $table->json('position')->comment('打卡位置'); + $table->timestamps(); + + $table->comment('员工-打卡流水'); + }); + + Schema::create('employee_rest_days', function (Blueprint $table) { + $table->id(); + $table->date('date')->comment('日期'); + $table->foreignId('employee_id')->comment('员工, employees.id'); + + $table->comment('员工-休息日'); + }); + + Schema::create('employee_sign_repairs', function (Blueprint $table) { + $table->id(); + $table->date('date')->comment('补卡日期'); + $table->foreignId('store_id')->comment('门店, stores.id'); + $table->foreignId('employee_id')->comment('员工, employees.id'); + $table->string('reason')->comment('补卡原因'); + $table->unsignedInteger('repair_type')->default(1)->comment('上班/下班 补卡'); + + $table->unsignedInteger('check_status')->default(0)->comment('审核状态'); + $table->timestamp('checked_at')->nullable()->comment('审核通过时间'); + + $table->timestamps(); + + $table->comment('员工-补卡申请'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('employee_sign_dates'); + Schema::dropIfExists('employee_sign_logs'); + Schema::dropIfExists('employee_rest_days'); + Schema::dropIfExists('employee_sign_repairs'); + } +}; diff --git a/database/seeders/AdminPermissionSeeder.php b/database/seeders/AdminPermissionSeeder.php index 7b1f9c0..a129b7d 100644 --- a/database/seeders/AdminPermissionSeeder.php +++ b/database/seeders/AdminPermissionSeeder.php @@ -110,6 +110,12 @@ class AdminPermissionSeeder extends Seeder 'uri' => '/hr/jobs?parent_key=job', 'resource' => false ], + 'rests' => [ + 'name' => '休息管理', + 'icon' => '', + 'uri' => '/hr/rests', + 'resource' => true + ], ], ], diff --git a/lang/zh_CN/employee_sign.php b/lang/zh_CN/employee_sign.php new file mode 100644 index 0000000..cbb97b1 --- /dev/null +++ b/lang/zh_CN/employee_sign.php @@ -0,0 +1,17 @@ + 'ID', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + + 'rest' => '休息日', + + 'date' => '日期', + 'store_id' => '门店', + 'employee_id' => '员工', + 'sign_type' => '打卡类型', + 'first_time' => '上班时间', + 'last_time' => '下班时间', + 'sign_status' => '打卡状态', +];