generated from liutk/owl-admin-base
227 lines
7.7 KiB
PHP
227 lines
7.7 KiB
PHP
<?php
|
|
|
|
namespace App\Admin\Services;
|
|
|
|
use App\Enums\{CheckType, CheckStatus};
|
|
use App\Models\{Employee, Store, Keyword, Workflow, WorkflowLog};
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Validation\Rule;
|
|
use App\Contracts\Checkable;
|
|
|
|
class WorkFlowService extends BaseService
|
|
{
|
|
protected array $withRelationships = [];
|
|
|
|
protected string $modelName = Workflow::class;
|
|
|
|
protected string $modelFilterName = '';
|
|
|
|
/**
|
|
* 发起审核申请
|
|
* 1. 待审核 Model 实现 Checkable
|
|
* 2. 生成全部的审核流程
|
|
*
|
|
* @param Checkable $subject 待审核记录
|
|
* @param Employee $user 申请人
|
|
*
|
|
* @return boolean true: 成功, false: 失败, $this->getError(): 错误消息
|
|
*/
|
|
public function apply(Checkable $subject, Employee $user)
|
|
{
|
|
if ($subject->check_status === CheckStatus::Success->value) {
|
|
return $this->setError('已经审核通过');
|
|
}
|
|
if ($subject->check_status === CheckStatus::Processing->value) {
|
|
return $this->setError('正在审核中');
|
|
}
|
|
|
|
$workflow = Workflow::where('key', $subject->getCheckKey())->first();
|
|
// 没有配置审核流程, 直接通过
|
|
if (!$workflow || !$workflow->config) {
|
|
$subject->checkSuccess();
|
|
return true;
|
|
}
|
|
$jobs = Keyword::where('parent_key', 'job')->get();
|
|
$config = collect($workflow->config)->sortBy('sort');
|
|
$batchId = WorkflowLog::where('subject_type', $subject->getMorphClass())->where('subject_id', $subject->id)->max('batch_id') + 1;
|
|
$subjectData = $subject->toArray();
|
|
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;
|
|
}
|
|
// 指定用户审核
|
|
else if ($item['type'] == CheckType::User->value) {
|
|
$checkUser = Employee::findOrFail($item['value']);
|
|
$checkValue = $checkUser->id;
|
|
$checkName = $checkUser->name;
|
|
} else {
|
|
return $this->setError('未知的审核类型: ' . $item['type']);
|
|
break;
|
|
}
|
|
$subject->workflows()->create([
|
|
'batch_id' => $batchId,
|
|
'check_type' => $item['type'],
|
|
'check_value' => $checkValue,
|
|
'check_name' => $checkName,
|
|
'user_id' => $user->id,
|
|
'subject_data' => $subjectData,
|
|
'sort' => $item['sort']
|
|
]);
|
|
}
|
|
$subject->checkApply();
|
|
// 开启第一个审核流程
|
|
$this->next($subject);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 取消审核
|
|
* 1. 删除未审核的流程
|
|
* 2. 更新申请记录的状态
|
|
*
|
|
*/
|
|
public function cancel(Checkable $subject)
|
|
{
|
|
$subject->workflows()->whereIn('check_status', [CheckStatus::None, CheckStatus::Processing])->delete();
|
|
$subject->checkCancel();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 审核单个流程
|
|
*
|
|
* @param Employee $user 审核人
|
|
* @param WorkflowLog $log 审核流水记录
|
|
* @param boolean $status 通过/不通过
|
|
* @param array $options {remarks: 不通过原因, time: 审核时间(默认当前时间)}
|
|
* @return boolean
|
|
*/
|
|
public function check(Employee $user, WorkflowLog $log, $status, $options = [])
|
|
{
|
|
if ($log->check_status != CheckStatus::Processing) {
|
|
return $this->setError('不可操作, 等待前面的审核完成');
|
|
}
|
|
if (!$this->authCheck($user, $log)) {
|
|
return $this->setError('没有权限');
|
|
}
|
|
$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);
|
|
|
|
$subject = $log->subject;
|
|
// 审核未通过, 删除剩下的流程
|
|
if (!$status) {
|
|
WorkflowLog::where('subject_type', $log->subject_type)->where('subject_id', $log->subject_id)->where('check_status', CheckStatus::None)->delete();
|
|
$subject->checkFail($options);
|
|
return true;
|
|
}
|
|
|
|
return $this->next($subject);
|
|
}
|
|
|
|
/**
|
|
* 开启下一个审核流程
|
|
*
|
|
* @param Checkable $subject
|
|
* @return boolean
|
|
*/
|
|
public function next(Checkable $subject)
|
|
{
|
|
$log = $subject->workflows()->where('check_status', CheckStatus::None)->orderBy('sort')->first();
|
|
if ($log) {
|
|
$log->update(['check_status' => CheckStatus::Processing]);
|
|
// 申请人自动审核通过
|
|
if ($this->authCheck($subject->employee, $log)) {
|
|
return $this->check($subject->employee, $log, true);
|
|
}
|
|
} else {
|
|
// 没有审核流程了
|
|
$subject->checkSuccess();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 员工是否有权限审核
|
|
*/
|
|
public function authCheck(Employee $user, WorkflowLog $log)
|
|
{
|
|
if ($user->adminUser?->isAdministrator()) {
|
|
return true;
|
|
}
|
|
if ($log->check_type == CheckType::User && $log->check_value == $user->id) {
|
|
return true;
|
|
} else if ($log->check_type == CheckType::Job) {
|
|
$jobs = $user->jobs;
|
|
foreach($jobs as $job) {
|
|
if ($log->check_value == $user->store_id . '-' . $job->key) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function resloveData($data, $model = null)
|
|
{
|
|
if (isset($data['config'])) {
|
|
foreach ($data['config'] as $key => &$item) {
|
|
if (!$item) {
|
|
$data['config'] = null;
|
|
break;
|
|
}
|
|
$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['job'])->value('name'),
|
|
CheckType::User->value => Employee::where('id', $item['user'])->value('name'),
|
|
};
|
|
$item['value'] = match ($item['type']) {
|
|
CheckType::Job->value => $item['job'],
|
|
CheckType::User->value => $item['user'],
|
|
};
|
|
$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;
|
|
}
|
|
}
|