getError(): 错误消息 */ public function apply(WorkflowCheck $check, Employee $user) { if ($check->check_status === CheckStatus::Success) { admin_abort('已经审核通过'); } if ($check->check_status === CheckStatus::Processing) { admin_abort('正在审核中'); } $check->update([ 'apply_at' => now(), ]); $workflow = Workflow::where('key', $check->key)->first(); // 没有配置审核流程, 直接通过 if (! $workflow || ! $workflow->config) { $this->success($check); return true; } $jobs = Keyword::where('parent_key', 'job')->get(); $config = collect($workflow->config)->sortBy('sort'); $batchId = $check->logs()->max('batch_id') + 1; $check->update([ 'subject_data' => $check->subject->toArray(), 'check_status' => CheckStatus::Processing, 'employee_id' => $user->id, ]); foreach ($config as $item) { $checkValue = ''; $checkName = ''; // 职位审核 if ($item['type'] == CheckType::Job->value) { // 没有门店, 则跳过 if (! $user->store_id) { continue; } // 所属门店的职位审核 $store = Store::findOrFail($user->store_id); $job = $jobs->firstWhere('key', $item['value']); $checkValue = $store->id.'-'.$job->key; $checkName = $store->title.'-'.$job->name; } // 指定用户审核 elseif ($item['type'] == CheckType::User->value) { $checkUser = Employee::findOrFail($item['value']); $checkValue = $checkUser->id; $checkName = $checkUser->name; } else { admin_abort('未知的审核类型: '.$item['type']); } $check->logs()->create([ 'batch_id' => $batchId, 'check_type' => $item['type'], 'check_value' => $checkValue, 'check_name' => $checkName, 'sort' => $item['sort'], ]); } // 开启第一个审核流程 $this->next($check); return true; } public function success(WorkflowCheck $check, array $options = []) { $check->update([ 'check_status' => CheckStatus::Success, 'checked_at' => data_get($options, 'checked_at', now()), 'check_remarks' => data_get($options, 'remarks'), ]); $check->subject->checkSuccess(); WorkflowCheckSuccess::dispatch($check->withoutRelations()); return true; } public function fail(WorkflowCheck $check, array $options = []) { $check->update([ 'check_status' => CheckStatus::Fail, 'check_remarks' => data_get($options, 'remarks'), 'checked_at' => data_get($options, 'checked_at', now()), ]); // 删除未审核的流程 $check->logs()->where('check_status', CheckStatus::None)->delete(); $check->subject->checkFail(); WorkflowCheckFailed::dispatch($check->withoutRelations()); return true; } /** * 取消审核 * 1. 删除审核的流程 * 2. 更新申请记录的状态 */ public function cancel(WorkflowCheck $check) { $check->logs()->delete(); $check->update([ 'check_status' => CheckStatus::Cancel, 'check_value' => null, 'check_name' => null, 'check_type' => null, ]); $check->subject->checkCancel(); return true; } /** * 审核单个流程 * * @param Employee $user 审核人 * @param WorkflowLog $log 审核流水记录 * @param bool $status 通过/不通过 * @param array $options {remarks: 不通过原因, time: 审核时间(默认当前时间)} * @return bool */ public function check(Employee $user, WorkflowLog $log, $status, $options = []) { if ($log->check_status != CheckStatus::Processing) { admin_abort('不可操作, 等待前面的审核完成'); } if (! $this->authCheck($user, $log)) { admin_abort('没有权限'); } $attributes = ['check_status' => $status ? CheckStatus::Success : CheckStatus::Fail]; $attributes['checked_at'] = data_get($options, 'time', now()); $attributes['remarks'] = data_get($options, 'remarks'); $attributes['check_user_id'] = $user->id; $log->update($attributes); $check = $log->check; $check->update(['check_name' => $user->name]); if ($status) { return $this->next($check); } else { return $this->fail($check, $options); } } /** * 开启下一个审核流程 * * @return bool */ public function next(WorkflowCheck $check) { $log = $check->logs()->where('check_status', CheckStatus::None)->orderBy('sort')->first(); if ($log) { $check->update([ 'check_value' => $log->check_value, 'check_name' => $log->check_name, 'check_type' => $log->check_type, ]); $log->update(['check_status' => CheckStatus::Processing]); WorkflowCheckNext::dispatch($log->withoutRelations()); // 自动审核通过 if ($this->authCheck($check->employee, $log)) { return $this->check($check->employee, $log, true, ['remarks' => '自动审核通过']); } } else { // 没有审核流程了, 审核完成 return $this->success($check); } return true; } /** * 是否有权限审核 * 1. 申请人 == 审核人 * 2. 申请人的 门店+职位 = 审核 门店+职位 */ public function authCheck(Employee $user, WorkflowLog $log) { if ($user->adminUser?->isAdministrator()) { return true; } $checkValue = [$user->id]; if ($user->jobs && $user->jobs->count() > 0) { foreach ($user->jobs as $item) { array_push($checkValue, $user->store_id.'-'.$item->key); } } return in_array($log->check_value, $checkValue); } public function resloveData($data, $model = null) { if (isset($data['config'])) { foreach ($data['config'] as $key => &$item) { if (! $item) { $data['config'] = null; break; } if (! isset($item['value'])) { $item['value'] = match ($item['type']) { CheckType::Job->value => $item['job'], CheckType::User->value => $item['user'], }; } $item['title'] = match ($item['type']) { CheckType::Job->value => CheckType::Job->text(), CheckType::User->value => CheckType::User->text(), }; $item['subTitle'] = match ($item['type']) { CheckType::Job->value => Keyword::where('key', $item['value'])->value('name'), CheckType::User->value => Employee::where('id', $item['value'])->value('name'), }; $item['sort'] = $key + 1; } } return $data; } public function validate($data, $model = null) { $createRules = [ 'key' => ['required', Rule::unique('workflows', 'key')], 'name' => ['required'], 'config' => ['required', 'array'], ]; $updateRules = [ 'key' => [Rule::unique('workflows', 'key')->ignore($model?->id)], ]; $validator = Validator::make($data, $model ? $updateRules : $createRules, [ 'key.unique' => ':input 已经存在', ]); if ($validator->fails()) { return $validator->errors()->first(); } return true; } }