From f66433e65850db6e19108810521806534b5f4f7a Mon Sep 17 00:00:00 2001 From: panliang <1163816051@qq.com> Date: Tue, 16 Apr 2024 17:01:54 +0800 Subject: [PATCH] =?UTF-8?q?api=20=E5=8D=87=E8=81=8C=E7=94=B3=E8=AF=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Hr/PromotionController.php | 25 +++- .../Services/EmployeePromotionService.php | 60 ++++++--- app/Admin/Services/WorkFlowService.php | 4 + app/Enums/PromotionStatus.php | 4 +- .../Api/Hr/PromotionController.php | 115 ++++++++++++++++++ .../Controllers/Api/WorkflowController.php | 3 +- .../Resources/EmployeePromotionResource.php | 38 ++++++ app/Models/EmployeePromotion.php | 28 +++++ app/Traits/HasCheckable.php | 10 ++ routes/api.php | 8 ++ 10 files changed, 271 insertions(+), 24 deletions(-) create mode 100644 app/Http/Controllers/Api/Hr/PromotionController.php create mode 100644 app/Http/Resources/EmployeePromotionResource.php diff --git a/app/Admin/Controllers/Hr/PromotionController.php b/app/Admin/Controllers/Hr/PromotionController.php index 1597e82..c6db62f 100644 --- a/app/Admin/Controllers/Hr/PromotionController.php +++ b/app/Admin/Controllers/Hr/PromotionController.php @@ -61,6 +61,7 @@ class PromotionController extends AdminController ]), ])) ->columns([ + amisMake()->TableColumn()->name('id')->label(__('employee_promotion.id')), amisMake()->TableColumn()->name('store.title')->label(__('employee_promotion.store_id')), amisMake()->TableColumn()->name('employee.name')->label(__('employee_promotion.employee_id')), amisMake()->TableColumn()->name('job.name')->label(__('employee_promotion.job_id')), @@ -70,9 +71,11 @@ class PromotionController extends AdminController $this->rowActions([ $this->rowShowButton()->visible(Admin::user()->can('admin.hr.promotion.view')), $this->rowEditTypeButton('drawer', 'xl') - ->visible(Admin::user()->can('admin.hr.promotion.update')), + ->visible(Admin::user()->can('admin.hr.promotion.update')) + ->visibleOn('${can_update}'), $this->rowDeleteButton() - ->visible(Admin::user()->can('admin.hr.promotion.delete')), + ->visible(Admin::user()->can('admin.hr.promotion.delete')) + ->visibleOn('${can_update}'), $this->cancelAction()->visibleOn('${promotion_status == '.PromotionStatus::Processing->value.'}'), ]), ]); @@ -102,7 +105,8 @@ class PromotionController extends AdminController amisMake()->SelectControl()->name('job_id')->label(__('employee_promotion.job_id')) ->source(admin_url('api/keywords/tree-list').'?parent_key=job') ->labelField('name') - ->valueField('key'), + ->valueField('key') + ->required(), amisMake()->TextControl()->name('remarks')->label(__('employee_promotion.remarks')), ]); } @@ -119,6 +123,19 @@ class PromotionController extends AdminController ['label' => __('employee_promotion.invitor_id'), 'content' => '${invitor.name}'], ['label' => __('employee_promotion.promotion_status'), 'content' => amisMake()->Mapping()->name('promotion_status')->map(PromotionStatus::options())], ['label' => __('employee_promotion.remarks'), 'content' => '${remarks}'], + ['label' => __('employee_promotion.created_at'), 'content' => '${created_at}', 'span' => 3], + ]); + + $data = amisMake()->Property()->items([ + ['label' => __('employee_promotion.age'), 'content' => '${employee_data.age}'], + ['label' => __('employee_promotion.sex'), 'content' => '${employee_data.sex}'], + ['label' => __('employee_promotion.education'), 'content' => '${employee_data.education}'], + ['label' => __('employee_promotion.first_work_time'), 'content' => '${employee_data.first_work_time}'], + ['label' => __('employee_promotion.work_years'), 'content' => '${employee_data.work_years}'], + ['label' => __('employee_promotion.work_years_in_company'), 'content' => '${employee_data.work_years_in_company}'], + ['label' => __('employee_promotion.comment_self'), 'content' => '${employee_data.comment_self}', 'span' => 3], + ['label' => __('employee_promotion.plans'), 'content' => '${employee_data.plans}', 'span' => 3], + ['label' => __('employee_promotion.reason'), 'content' => '${employee_data.reason}', 'span' => 3], ]); return $this->baseDetail()->id($detailId)->title('')->onEvent([ @@ -129,6 +146,8 @@ class PromotionController extends AdminController ], ])->body([ $detail, + amisMake()->Divider()->title('补充资料'), + $data, amisMake()->Divider(), $this->baseWorkflowLogService($detailId)->id($serviceId), ]); diff --git a/app/Admin/Services/EmployeePromotionService.php b/app/Admin/Services/EmployeePromotionService.php index a75ec5a..a7de825 100644 --- a/app/Admin/Services/EmployeePromotionService.php +++ b/app/Admin/Services/EmployeePromotionService.php @@ -37,6 +37,9 @@ class EmployeePromotionService extends BaseService */ public function apply($model, $data = []) { + if (!$model->canUpdate()) { + return $this->setError('审核中, 无法修改'); + } $validator = Validator::make($data, [ 'age' => ['required'], 'sex' => ['required'], @@ -48,7 +51,7 @@ class EmployeePromotionService extends BaseService 'plans' => ['required'], ]); if ($validator->fails()) { - return $validator->errors()->first(); + return $this->setError($validator->errors()->first()); } $model->update(['employee_data' => $data, 'promotion_status' => PromotionStatus::Invitor]); @@ -65,35 +68,25 @@ class EmployeePromotionService extends BaseService */ public function invitor($model, $data = []) { + if (!$model->canUpdate()) { + return $this->setError('审核中, 无法修改'); + } $validator = Validator::make($data, [ 'reason' => ['required'], ]); if ($validator->fails()) { - return $validator->errors()->first(); + return $this->setError($validator->errors()->first()); } - try { - DB::beginTransaction(); - $attributes = array_merge($model->employee_data, $data); - $model->update(['employee_data' => $data, 'promotion_status' => PromotionStatus::Processing]); - - // 发起审核申请 - $service = WorkflowService::make(); - if ($service->apply($model->workflow, $model->employee) !== true) { - return $this->setError($service->getError()); - } - DB::commit(); - } catch (\Exception $e) { - DB::rollBack(); - - return $this->setError($e->getMessage()); - } + $attributes = array_merge($model->employee_data, $data); + $model->update(['employee_data' => $attributes, 'promotion_status' => PromotionStatus::Processing]); return true; } public function validate($data, $model = null) { + // todo 验证申请人的职位是否重复 $createRules = [ 'store_id' => ['required'], 'employee_id' => ['required'], @@ -108,4 +101,35 @@ class EmployeePromotionService 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; + } + + $model->update($data); + $this->currentModel = $model; + return true; + } + + public function delete(string $ids): mixed + { + $list = $this->query()->with(['workflow'])->whereIn('id', explode(',', $ids))->get(); + foreach ($list as $item) { + if (!$item->canUpdate()) { + return $this->setError($item->promotion_status->text() . ', 无法删除'); + } + $item->delete(); + } + return true; + } } diff --git a/app/Admin/Services/WorkFlowService.php b/app/Admin/Services/WorkFlowService.php index 5184333..6cf7327 100644 --- a/app/Admin/Services/WorkFlowService.php +++ b/app/Admin/Services/WorkFlowService.php @@ -113,6 +113,8 @@ class WorkFlowService extends BaseService 'checked_at' => data_get($options, 'checked_at', now()), ]); + $check->subject->checkFail(); + return true; } @@ -128,6 +130,8 @@ class WorkFlowService extends BaseService 'check_status' => CheckStatus::Cancel, ]); + $check->subject->checkCancel(); + return true; } diff --git a/app/Enums/PromotionStatus.php b/app/Enums/PromotionStatus.php index 794867f..e1bc457 100644 --- a/app/Enums/PromotionStatus.php +++ b/app/Enums/PromotionStatus.php @@ -12,7 +12,7 @@ enum PromotionStatus: int */ case Employee = 1; /** - * 待补充, 等待推荐人填写理由 + * 待推荐, 等待推荐人填写理由 */ case Invitor = 2; /** @@ -32,7 +32,7 @@ enum PromotionStatus: int { return [ self::Employee->value => '待提交', - self::Invitor->value => '待补充', + self::Invitor->value => '待推荐', self::Processing->value => '审核中', self::Success->value => '审核通过', self::Fail->value => '审核不通过', diff --git a/app/Http/Controllers/Api/Hr/PromotionController.php b/app/Http/Controllers/Api/Hr/PromotionController.php new file mode 100644 index 0000000..2709a65 --- /dev/null +++ b/app/Http/Controllers/Api/Hr/PromotionController.php @@ -0,0 +1,115 @@ +guard()->user(); + $list = EmployeePromotion::with(['workflow', 'invitor', 'job']) + ->where('employee_id', $user->id) + ->filter($request->all()) + ->orderBy('id', 'desc') + ->paginate($request->input('per_page')); + + return EmployeePromotionResource::collection($list); + } + + /** + * 推荐列表 + */ + public function inviteList(Request $request) + { + $user = $this->guard()->user(); + $list = EmployeePromotion::with(['workflow', 'employee', 'job']) + ->where('invitor_id', $user->id) + ->filter($request->all()) + ->orderBy('id', 'desc') + ->paginate($request->input('per_page')); + + return EmployeePromotionResource::collection($list); + } + + public function show($id) + { + $info = EmployeePromotion::with(['workflow', 'employee', 'invitor', 'job'])->findOrFail($id); + + return EmployeePromotionResource::make($info); + } + + /** + * 申请人完善资料 + */ + public function applyUpdate($id, Request $request, EmployeePromotionService $service) + { + $user = $this->guard()->user(); + $info = EmployeePromotion::where('employee_id', $user->id)->findOrFail($id); + + if (!$service->apply($info, $request->all())) { + throw new RuntimeException($service->getError()); + } + + return response()->noContent(); + } + + /** + * 推荐人填写 + */ + public function inviteUpdate($id, Request $request, EmployeePromotionService $service) + { + $user = $this->guard()->user(); + $model = EmployeePromotion::with(['workflow', 'employee'])->where('invitor_id', $user->id)->findOrFail($id); + + try { + DB::beginTransaction(); + if (!$service->invitor($model, $request->all())) { + throw new RuntimeException($service->getError()); + } + $workflow = WorkFlowService::make(); + if (!$workflow->apply($model->workflow, $model->employee)) { + throw new RuntimeException($workflow->getError()); + } + + DB::commit(); + return response()->noContent(); + } catch (\Exception $e) { + DB::rollBack(); + throw new RuntimeException($e->getMessage()); + } + } + + public function destroy($id, EmployeePromotionService $service) + { + $user = $this->guard()->user(); + $model = EmployeePromotion::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/WorkflowController.php b/app/Http/Controllers/Api/WorkflowController.php index 85d1102..fc1f4aa 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, HolidayApplyResource, OvertimeApplyResource, AgreementResource}; +use App\Http\Resources\{ReimbursementResource, WorkflowLogResource, EmployeeSignRepairResource, HolidayApplyResource, OvertimeApplyResource, AgreementResource, EmployeePromotionResource}; use App\Enums\CheckStatus; use App\Models\{WorkflowLog, WorkflowCheck}; use Illuminate\Support\Facades\DB; @@ -129,6 +129,7 @@ class WorkflowController extends Controller 'overtime_applies' => OvertimeApplyResource::class, 'agreements' => AgreementResource::class, 'offical_business' => OfficalBusinessResource::class, + 'employee_promotions' => EmployeePromotionResource::class, ]; $resource = data_get($map, $key); if (!$resource) { diff --git a/app/Http/Resources/EmployeePromotionResource.php b/app/Http/Resources/EmployeePromotionResource.php new file mode 100644 index 0000000..96bceb2 --- /dev/null +++ b/app/Http/Resources/EmployeePromotionResource.php @@ -0,0 +1,38 @@ + + */ + 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')), + + 'invitor_id' => $this->invitor_id, + 'invitor' => EmployeeResource::make($this->whenLoaded('invitor')), + 'job_id' => $this->job_id, + 'job' => KeywordResource::make($this->whenLoaded('job')), + + 'promotion_status' => $this->promotion_status, + 'promotion_status_text' => $this->promotion_status->text(), + 'employee_data' => $this->employee_data, + 'created_at' => $this->created_at->timestamp, + + 'workflow_check' => WorkflowCheckResource::make($this->whenLoaded('workflow')), + ]; + } +} diff --git a/app/Models/EmployeePromotion.php b/app/Models/EmployeePromotion.php index 9a5179b..fb981c6 100644 --- a/app/Models/EmployeePromotion.php +++ b/app/Models/EmployeePromotion.php @@ -7,6 +7,7 @@ use App\Traits\HasCheckable; use App\Traits\HasDateTimeFormatter; use EloquentFilter\Filterable; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Casts\Attribute; /** * 员工升职申请 @@ -22,11 +23,38 @@ class EmployeePromotion extends Model 'employee_data' => 'json', ]; + protected $appends = ['can_update']; + public function modelFilter() { return \App\Admin\Filters\EmployeePromotionFilter::class; } + public function checkSuccess() + { + $this->update(['promotion_status' => PromotionStatus::Success]); + } + + public function checkFail() + { + $this->update(['promotion_status' => PromotionStatus::Fail]); + } + + public function checkCancel() + { + $this->update(['promotion_status' => PromotionStatus::Employee]); + } + + public function canUpdate(): bool + { + return in_array($this->promotion_status, [PromotionStatus::Employee, PromotionStatus::Invitor, PromotionStatus::Fail]); + } + + public function getCanUpdateAttribute() + { + return $this->canUpdate(); + } + public function store() { return $this->belongsTo(Store::class, 'store_id'); diff --git a/app/Traits/HasCheckable.php b/app/Traits/HasCheckable.php index b64b3b8..090efae 100644 --- a/app/Traits/HasCheckable.php +++ b/app/Traits/HasCheckable.php @@ -39,6 +39,16 @@ trait HasCheckable } + public function checkFail() + { + + } + + public function checkCancel() + { + + } + public function canUpdate(): bool { return in_array($this->workflow?->check_status, [CheckStatus::None, CheckStatus::Fail, CheckStatus::Cancel]); diff --git a/routes/api.php b/routes/api.php index 861f7d2..96ffa93 100644 --- a/routes/api.php +++ b/routes/api.php @@ -71,6 +71,14 @@ Route::group([ // 出差报备 Route::apiResource('hr/offical-bussiness', \App\Http\Controllers\Api\Hr\OfficalBusinessController::class); + // 升职申请 + Route::get('hr/promotion/apply', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'applyList']); + Route::get('hr/promotion/invite', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'inviteList']); + Route::get('hr/promotion/{id}', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'show']); + Route::post('hr/promotion/{id}/apply', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'applyUpdate']); + Route::post('hr/promotion/{id}/invite', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'inviteUpdate']); + Route::delete('hr/promotion/{id}', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'destroy']); + // 报销管理 Route::apiResource('reimbursements', \App\Http\Controllers\Api\ReimbursementController::class);