generated from liutk/owl-admin-base
265 lines
8.3 KiB
PHP
265 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace App\Admin\Services;
|
|
|
|
use App\Enums\{CheckStatus, CheckType};
|
|
use App\Models\Employee;
|
|
use App\Models\Keyword;
|
|
use App\Models\Store;
|
|
use App\Models\Workflow;
|
|
use App\Models\WorkflowCheck;
|
|
use App\Models\WorkflowLog;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class WorkFlowService extends BaseService
|
|
{
|
|
protected array $withRelationships = [];
|
|
|
|
protected string $modelName = Workflow::class;
|
|
|
|
protected string $modelFilterName = '';
|
|
|
|
/**
|
|
* 发起审核申请
|
|
* 1. 待审核 Model 实现 Checkable
|
|
* 2. 生成全部的审核流程
|
|
*
|
|
* @param WorkflowCheck $check 待审核记录
|
|
* @param Employee $user 申请人
|
|
*
|
|
* @return bool true: 成功, false: 失败, $this->getError(): 错误消息
|
|
*/
|
|
public function apply(WorkflowCheck $check, Employee $user)
|
|
{
|
|
if ($check->check_status === CheckStatus::Success) {
|
|
admin_abort('已经审核通过');
|
|
}
|
|
if ($check->check_status === CheckStatus::Processing) {
|
|
admin_abort('正在审核中');
|
|
}
|
|
|
|
$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();
|
|
|
|
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();
|
|
|
|
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]);
|
|
// 自动审核通过
|
|
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;
|
|
}
|
|
$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;
|
|
}
|
|
}
|