diff --git a/app/Admin/Controllers/Hr/HolidayController.php b/app/Admin/Controllers/Hr/HolidayController.php index 07cb526..e5ffd91 100644 --- a/app/Admin/Controllers/Hr/HolidayController.php +++ b/app/Admin/Controllers/Hr/HolidayController.php @@ -55,6 +55,7 @@ class HolidayController extends AdminController ]), ])) ->columns([ + amisMake()->TableColumn()->name('id')->label(__('holiday_apply.id')), amisMake()->TableColumn()->name('store.title')->label(__('employee_sign.store_id')), amisMake()->TableColumn()->name('employee.name')->label(__('holiday_apply.employee_id')), amisMake()->TableColumn()->name('type.name')->label(__('holiday_apply.type_id')), @@ -115,7 +116,7 @@ class HolidayController extends AdminController ['label' => __('holiday_apply.store_id'), 'content' => '${store.title}'], ['label' => __('holiday_apply.employee_id'), 'content' => '${employee.name}'], ['label' => __('holiday_apply.type_id'), 'content' => '${type.name}'], - ['label' => __('holiday_apply.date'), 'content' => '${start_at} ${end_at}'], + ['label' => __('holiday_apply.date'), 'content' => [amisMake()->Tag()->label('${start_at}'), amisMake()->Tag()->label('${end_at}')]], ['label' => __('holiday_apply.reason'), 'content' => '${reason}'], ['label' => __('holiday_apply.created_at'), 'content' => '${created_at}'], ['label' => __('workflow_log.check_status'), 'content' => amisMake()->Mapping()->name('workflow.check_status')->map(CheckStatus::options())], diff --git a/app/Admin/Controllers/Hr/SignRepairController.php b/app/Admin/Controllers/Hr/SignRepairController.php index 9ca532b..d801991 100644 --- a/app/Admin/Controllers/Hr/SignRepairController.php +++ b/app/Admin/Controllers/Hr/SignRepairController.php @@ -115,7 +115,7 @@ class SignRepairController extends AdminController ['label' => __('employee_sign_repair.created_at'), 'content' => '${created_at}'], ['label' => __('workflow_log.check_status'), 'content' => amisMake()->Mapping()->name('workflow.check_status')->map(CheckStatus::options())], ['label' => __('workflow_log.checked_at'), 'content' => '${workflow.checked_at}'], - ['label' => __('workflow_log.check_remarks'), 'content' => '${workflow.check_remarks}'], + ['label' => __('workflow_log.remarks'), 'content' => '${workflow.check_remarks}'], ]); return $this->baseDetail()->id($detailId)->title('')->onEvent([ diff --git a/app/Admin/Services/HolidayApplyService.php b/app/Admin/Services/HolidayApplyService.php index 32e2910..7c68e59 100644 --- a/app/Admin/Services/HolidayApplyService.php +++ b/app/Admin/Services/HolidayApplyService.php @@ -34,8 +34,7 @@ class HolidayApplyService extends BaseService public function validate($data, $model = null) { - // 验证申请时间是否重叠 - // todo + // todo 验证申请时间是否重复 $createRules = [ 'employee_id' => ['required'], 'type_id' => ['required'], @@ -51,4 +50,32 @@ class HolidayApplyService extends BaseService return true; } + + public function update($primaryKey, $data): bool + { + $model = $this->query()->whereKey($primaryKey)->firstOrFail(); + if (!$model->canUpdate()) { + return $this->setError('审核中, 无法修改'); + } + $data = $this->resloveData($data, $model); + $validate = $this->validate($data, $model); + if ($validate !== true) { + $this->setError($validate); + + return false; + } + + return $model->update($data); + } + + public function delete(string $ids): mixed + { + $list = HolidayApply::with(['workflow'])->whereIn('id', explode(',', $ids))->get(); + foreach ($list as $item) { + if (!$item->canUpdate()) { + return $this->setError('审核中, 无法删除'); + } + } + return true; + } } diff --git a/app/Http/Controllers/Api/Hr/HolidayController.php b/app/Http/Controllers/Api/Hr/HolidayController.php new file mode 100644 index 0000000..53c705b --- /dev/null +++ b/app/Http/Controllers/Api/Hr/HolidayController.php @@ -0,0 +1,105 @@ +guard()->user(); + $list = HolidayApply::with(['type', 'workflow']) + ->where('employee_id', $user->id) + ->filter($request->all()) + ->orderBy('id', 'desc') + ->paginate($request->input('per_page')); + + return HolidayApplyResource::collection($list); + } + + public function show($id) + { + $info = HolidayApply::with(['type', 'employee', 'store', 'workflow'])->findOrFail($id); + + return HolidayApplyResource::make($info); + } + + public function store(Request $request, HolidayApplyService $service) + { + $user = $this->guard()->user(); + $data = $request->all(); + $data['employee_id'] = $user->id; + + try { + DB::beginTransaction(); + $data = $service->resloveData($data); + $result = $service->validate($data); + if ($result !== true) { + throw new RuntimeException($result); + } + $model = HolidayApply::create($data); + $workflow = WorkFlowService::make(); + if (!$workflow->apply($model->workflow, $user)) { + throw new RuntimeException($workflow->getError()); + } + + DB::commit(); + return response()->noContent(); + } catch (\Exception $e) { + DB::rollBack(); + throw new RuntimeException($e->getMessage()); + } + } + + public function update($id, Request $request, HolidayApplyService $service) + { + $user = $this->guard()->user(); + $model = HolidayApply::where('employee_id', $user->id)->findOrFail($id); + + try { + DB::beginTransaction(); + if (!$service->update($id, $request->all())) { + throw new RuntimeException($service->getError()); + } + $workflow = WorkFlowService::make(); + if (!$workflow->apply($model->workflow, $user)) { + throw new RuntimeException($workflow->getError()); + } + + DB::commit(); + return response()->noContent(); + } catch (\Exception $e) { + DB::rollBack(); + throw new RuntimeException($e->getMessage()); + } + } + + public function destroy($id, HolidayApplyService $service) + { + $user = $this->guard()->user(); + $model = HolidayApply::with(['workflow'])->where('employee_id', $user->id)->findOrFail($id); + + try { + DB::beginTransaction(); + if (!$service->delete($id)) { + throw new RuntimeException($service->getError()); + } + + DB::commit(); + return response()->noContent(); + } catch (\Exception $e) { + DB::rollBack(); + throw new RuntimeException($e->getMessage()); + } + } +} diff --git a/app/Http/Controllers/Api/Hr/SignRepairController.php b/app/Http/Controllers/Api/Hr/SignRepairController.php index 114f5d0..7853512 100644 --- a/app/Http/Controllers/Api/Hr/SignRepairController.php +++ b/app/Http/Controllers/Api/Hr/SignRepairController.php @@ -68,10 +68,10 @@ class SignRepairController extends Controller if (!$model->canUpdate()) { throw new RuntimeException('审核中, 无法修改'); } - + try { DB::beginTransaction(); - $data = $service->resloveData($data, $model); + $data = $service->resloveData($request->all(), $model); $result = $service->validate($data, $model); if ($result !== true) { throw new RuntimeException($result); diff --git a/app/Http/Controllers/Api/WorkflowController.php b/app/Http/Controllers/Api/WorkflowController.php index 89fe5a9..0b4df1d 100644 --- a/app/Http/Controllers/Api/WorkflowController.php +++ b/app/Http/Controllers/Api/WorkflowController.php @@ -4,7 +4,7 @@ namespace App\Http\Controllers\Api; use Illuminate\Http\{Request, Response}; use Illuminate\Database\Eloquent\Relations\Relation; -use App\Http\Resources\{ReimbursementResource, WorkflowLogResource, EmployeeSignRepairResource}; +use App\Http\Resources\{ReimbursementResource, WorkflowLogResource, EmployeeSignRepairResource, HolidayApplyResource}; use App\Enums\CheckStatus; use App\Models\{WorkflowLog, WorkflowCheck}; use Illuminate\Support\Facades\DB; @@ -24,7 +24,14 @@ class WorkflowController extends Controller $resource = $this->mapResource($subjectType); $user = $request->user(); - $query = $model::query()->with(['workflow']) + + $include = ['workflow']; + if ($request->input('include')) { + $explodes = explode(',', $request->input('include')); + $include = array_merge($include, $explodes); + } + + $query = $model::query()->with($include) ->whereHas('workflow', fn($q) => $q->where('check_status', CheckStatus::Processing)) ->whereHas('workflow.logs', fn($q) => $q->own($user)) ->orderBy('created_at', 'desc'); @@ -64,6 +71,26 @@ class WorkflowController extends Controller return WorkflowLogResource::collection($logs); } + public function cancel($id, Request $request, WorkFlowService $workFlowService) + { + $request->validate([ + 'subject_type' => 'required', + ]); + $check = WorkflowCheck::where('subject_type', $request->input('subject_type'))->where('subject_id', $id)->firstOrFail(); + try { + DB::beginTransaction(); + if (!$workFlowService->cancel($check)) { + throw new RuntimeException($workFlowService->getError()); + } + + DB::commit(); + return response('', Response::HTTP_OK); + } catch (\Exception $e) { + DB::rollBack(); + throw new RuntimeException($e->getMessage()); + } + } + public function check($id, Request $request, WorkFlowService $workFlowService) { $request->validate([ @@ -98,6 +125,7 @@ class WorkflowController extends Controller $map = [ 'reimbursements' => ReimbursementResource::class, 'employee_sign_repairs' => EmployeeSignRepairResource::class, + 'holiday_applies' => HolidayApplyResource::class, ]; return data_get($map, $key); } diff --git a/app/Http/Resources/HolidayApplyResource.php b/app/Http/Resources/HolidayApplyResource.php new file mode 100644 index 0000000..f19e670 --- /dev/null +++ b/app/Http/Resources/HolidayApplyResource.php @@ -0,0 +1,37 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + + 'employee_id' => $this->employee_id, + 'employee' => EmployeeResource::make($this->whenLoaded('employee')), + 'store_id' => $this->store_id, + 'store' => StoreResource::make($this->whenLoaded('store')), + + 'type_id' => $this->type_id, + 'type' => KeywordResource::make($this->whenLoaded('type')), + + 'workflow_check' => WorkflowCheckResource::make($this->whenLoaded('workflow')), + + 'start_at' => $this->start_at->timestamp, + 'end_at' => $this->end_at->timestamp, + + 'reason' => $this->reason, + 'created_at' => $this->created_at->timestamp, + ]; + } +} diff --git a/app/Models/HolidayApply.php b/app/Models/HolidayApply.php index cb6ee95..7c74a88 100644 --- a/app/Models/HolidayApply.php +++ b/app/Models/HolidayApply.php @@ -15,16 +15,21 @@ class HolidayApply extends Model { use Filterable, HasCheckable, HasDateTimeFormatter; - protected $fillable = ['store_id', 'employee_id', 'start_at', 'end_at', 'type_id', 'reason']; + protected $guarded = []; protected $casts = [ - 'start_at' => 'date:Y-m-d', - 'end_at' => 'date:Y-m-d', + 'start_at' => 'datetime:Y-m-d H:i', + 'end_at' => 'datetime:Y-m-d H:i', ]; public function modelFilter() { - return App\Admin\Filters\HolidayApplyFilter::class; + return \App\Admin\Filters\HolidayApplyFilter::class; + } + + public function canUpdate(): bool + { + return in_array($this->workflow?->check_status, [CheckStatus::None, CheckStatus::Fail, CheckStatus::Cancel]); } public function store() diff --git a/app/Models/WorkflowLog.php b/app/Models/WorkflowLog.php index 3d4563f..9c4a22a 100644 --- a/app/Models/WorkflowLog.php +++ b/app/Models/WorkflowLog.php @@ -5,6 +5,7 @@ namespace App\Models; use App\Enums\CheckStatus; use App\Enums\CheckType; use Illuminate\Database\Eloquent\Model; +use App\Traits\HasDateTimeFormatter; /** * 审核流水 @@ -16,7 +17,7 @@ class WorkflowLog extends Model protected $casts = [ 'check_type' => CheckType::class, 'check_status' => CheckStatus::class, - 'checked_at' => 'datetime', + 'checked_at' => 'datetime:Y-m-d H:i:s', ]; public function check() diff --git a/routes/api.php b/routes/api.php index e0ef4a1..17f328f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -17,11 +17,11 @@ Route::delete('/auth/logout', [AccessTokenController::class, 'destroy']); // 数据字典 Route::get('keyword', [\App\Http\Controllers\Api\KeywordController::class, 'index']); +// 字典表 +Route::get('keywords', [KeywordController::class, 'index']); Route::group([ 'middleware' => ['auth:api'], ], function () { - // 字典表 - Route::get('keywords', [KeywordController::class, 'index']); // 文件上传 Route::post('fileupload', FileUploadController::class); @@ -59,12 +59,16 @@ Route::group([ // 补卡申请 Route::apiResource('hr/sign-repairs', \App\Http\Controllers\Api\Hr\SignRepairController::class); + // 请假管理 + Route::apiResource('hr/holidays', \App\Http\Controllers\Api\Hr\HolidayController::class); + // 报销管理 Route::apiResource('reimbursements', \App\Http\Controllers\Api\ReimbursementController::class); - + // 审核流程 Route::get('workflow', [\App\Http\Controllers\Api\WorkflowController::class, 'index']); Route::get('workflow/{id}', [\App\Http\Controllers\Api\WorkflowController::class, 'show']); Route::get('workflow/{id}/logs', [\App\Http\Controllers\Api\WorkflowController::class, 'logs']); Route::post('workflow/{id}/check', [\App\Http\Controllers\Api\WorkflowController::class, 'check']); + Route::post('workflow/{id}/cancel', [\App\Http\Controllers\Api\WorkflowController::class, 'cancel']); });