You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
10 KiB
289 lines
10 KiB
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace app\service\school_approval;
|
|
|
|
use app\model\school_approval\SchoolApprovalConfig;
|
|
use app\model\school_approval\SchoolApprovalConfigNode;
|
|
use app\model\school_approval\SchoolApprovalParticipants;
|
|
use app\model\school_approval\SchoolApprovalProcess;
|
|
use think\Exception;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 审批流程服务
|
|
* Class SchoolApprovalProcessService
|
|
* @package app\service\school_approval
|
|
*/
|
|
class SchoolApprovalProcessService
|
|
{
|
|
/**
|
|
* 获取审批流程列表
|
|
* @param array $where
|
|
* @param int $page
|
|
* @param int $limit
|
|
* @return array
|
|
*/
|
|
public function getList(array $where = [], int $page = 1, int $limit = 10): array
|
|
{
|
|
$field = 'id, process_name, applicant_id, application_time, current_approver_id, approval_status, approval_time, remarks, created_at, updated_at';
|
|
$order = 'id desc';
|
|
|
|
$list = (new SchoolApprovalProcess())
|
|
->where($where)
|
|
->field($field)
|
|
->order($order)
|
|
->page($page, $limit)
|
|
->select()
|
|
->toArray();
|
|
|
|
$count = (new SchoolApprovalProcess())->where($where)->count();
|
|
|
|
return [
|
|
'list' => $list,
|
|
'count' => $count
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取审批流程详情
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function getInfo(int $id): array
|
|
{
|
|
$info = (new SchoolApprovalProcess())->with(['participants'])->where(['id' => $id])->find();
|
|
if (empty($info)) {
|
|
return [];
|
|
}
|
|
|
|
return $info->toArray();
|
|
}
|
|
|
|
/**
|
|
* 创建审批流程
|
|
* @param array $data
|
|
* @param int $config_id 审批配置ID
|
|
* @return int
|
|
* @throws \Exception
|
|
*/
|
|
public function create(array $data, int $config_id): int
|
|
{
|
|
Db::startTrans();
|
|
try {
|
|
// 获取审批配置详情
|
|
$config_info = (new SchoolApprovalConfigService())->getInfo($config_id);
|
|
if (empty($config_info)) {
|
|
throw new Exception('审批配置不存在');
|
|
}
|
|
|
|
// 创建审批流程
|
|
$process = [
|
|
'process_name' => $data['process_name'],
|
|
'applicant_id' => $data['applicant_id'],
|
|
'application_time' => time(),
|
|
'current_approver_id' => 0, // 初始时为0,后面会更新
|
|
'approval_status' => SchoolApprovalProcess::STATUS_PENDING,
|
|
'remarks' => $data['remarks'] ?? ''
|
|
];
|
|
|
|
$process_id = (new SchoolApprovalProcess())->insertGetId($process);
|
|
|
|
// 创建审批参与人
|
|
$participants = [];
|
|
foreach ($config_info['nodes'] as $sequence => $node) {
|
|
$approver_ids = explode(',', $node['approver_ids']);
|
|
foreach ($approver_ids as $approver_id) {
|
|
$participants[] = [
|
|
'process_id' => $process_id,
|
|
'participant_id' => $approver_id,
|
|
'sequence' => $node['sequence'],
|
|
'status' => SchoolApprovalParticipants::STATUS_PENDING,
|
|
'sign_type' => $node['sign_type']
|
|
];
|
|
}
|
|
}
|
|
|
|
if (!empty($participants)) {
|
|
(new SchoolApprovalParticipants())->insertAll($participants);
|
|
|
|
// 更新当前审批人为第一个审批人
|
|
$first_participant = (new SchoolApprovalParticipants())
|
|
->where(['process_id' => $process_id])
|
|
->order('sequence', 'asc')
|
|
->find();
|
|
|
|
if (!empty($first_participant)) {
|
|
(new SchoolApprovalProcess())->where(['id' => $process_id])
|
|
->update(['current_approver_id' => $first_participant['participant_id']]);
|
|
}
|
|
}
|
|
|
|
Db::commit();
|
|
return $process_id;
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw new Exception($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 审批
|
|
* @param int $process_id 流程ID
|
|
* @param int $approver_id 审批人ID
|
|
* @param string $status 审批状态
|
|
* @param string $remarks 备注
|
|
* @return bool
|
|
* @throws \Exception
|
|
*/
|
|
public function approve(int $process_id, int $approver_id, string $status, string $remarks = ''): bool
|
|
{
|
|
Db::startTrans();
|
|
try {
|
|
// 获取审批流程
|
|
$process_info = (new SchoolApprovalProcess())->where(['id' => $process_id])->find();
|
|
if (empty($process_info)) {
|
|
throw new Exception('审批流程不存在');
|
|
}
|
|
|
|
// 检查是否当前审批人
|
|
if ($process_info['current_approver_id'] != $approver_id) {
|
|
throw new Exception('您不是当前审批人');
|
|
}
|
|
|
|
// 检查流程状态
|
|
if ($process_info['approval_status'] != SchoolApprovalProcess::STATUS_PENDING) {
|
|
throw new Exception('该审批流程已完成');
|
|
}
|
|
|
|
// 获取当前审批节点
|
|
$current_participant = (new SchoolApprovalParticipants())
|
|
->where([
|
|
'process_id' => $process_id,
|
|
'participant_id' => $approver_id,
|
|
'status' => SchoolApprovalParticipants::STATUS_PENDING
|
|
])
|
|
->find();
|
|
|
|
if (empty($current_participant)) {
|
|
throw new Exception('审批节点信息错误');
|
|
}
|
|
|
|
// 更新当前审批人状态
|
|
(new SchoolApprovalParticipants())->where(['id' => $current_participant['id']])
|
|
->update([
|
|
'status' => $status,
|
|
'remarks' => $remarks
|
|
]);
|
|
|
|
// 如果拒绝,直接更新整个流程状态为拒绝
|
|
if ($status == SchoolApprovalParticipants::STATUS_REJECTED) {
|
|
(new SchoolApprovalProcess())->where(['id' => $process_id])
|
|
->update([
|
|
'approval_status' => SchoolApprovalProcess::STATUS_REJECTED,
|
|
'approval_time' => time(),
|
|
'remarks' => $remarks
|
|
]);
|
|
|
|
Db::commit();
|
|
return true;
|
|
}
|
|
|
|
// 检查当前节点是否需要会签
|
|
$same_sequence_participants = (new SchoolApprovalParticipants())
|
|
->where([
|
|
'process_id' => $process_id,
|
|
'sequence' => $current_participant['sequence'],
|
|
'status' => SchoolApprovalParticipants::STATUS_PENDING
|
|
])
|
|
->select();
|
|
|
|
// 如果是会签且还有其他人未审批,则等待
|
|
if ($current_participant['sign_type'] == SchoolApprovalParticipants::SIGN_TYPE_AND && !$same_sequence_participants->isEmpty()) {
|
|
// 不做任何处理,等待其他人审批
|
|
Db::commit();
|
|
return true;
|
|
}
|
|
|
|
// 获取下一个审批节点
|
|
$next_participant = (new SchoolApprovalParticipants())
|
|
->where([
|
|
'process_id' => $process_id,
|
|
'status' => SchoolApprovalParticipants::STATUS_PENDING
|
|
])
|
|
->order('sequence', 'asc')
|
|
->find();
|
|
|
|
if (empty($next_participant)) {
|
|
// 没有下一个审批人,流程结束,标记为已通过
|
|
(new SchoolApprovalProcess())->where(['id' => $process_id])
|
|
->update([
|
|
'approval_status' => SchoolApprovalProcess::STATUS_APPROVED,
|
|
'approval_time' => time()
|
|
]);
|
|
} else {
|
|
// 更新当前审批人为下一个审批人
|
|
(new SchoolApprovalProcess())->where(['id' => $process_id])
|
|
->update(['current_approver_id' => $next_participant['participant_id']]);
|
|
}
|
|
|
|
Db::commit();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw new Exception($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 撤销审批流程
|
|
* @param int $process_id 流程ID
|
|
* @param int $applicant_id 申请人ID
|
|
* @return bool
|
|
* @throws \Exception
|
|
*/
|
|
public function cancel(int $process_id, int $applicant_id): bool
|
|
{
|
|
Db::startTrans();
|
|
try {
|
|
// 获取审批流程
|
|
$process_info = (new SchoolApprovalProcess())->where(['id' => $process_id])->find();
|
|
if (empty($process_info)) {
|
|
throw new Exception('审批流程不存在');
|
|
}
|
|
|
|
// 检查是否申请人
|
|
if ($process_info['applicant_id'] != $applicant_id) {
|
|
throw new Exception('您不是该流程的申请人');
|
|
}
|
|
|
|
// 检查流程状态
|
|
if ($process_info['approval_status'] != SchoolApprovalProcess::STATUS_PENDING) {
|
|
throw new Exception('该审批流程已完成,无法撤销');
|
|
}
|
|
|
|
// 更新流程状态为已拒绝(撤销)
|
|
(new SchoolApprovalProcess())->where(['id' => $process_id])
|
|
->update([
|
|
'approval_status' => SchoolApprovalProcess::STATUS_REJECTED,
|
|
'approval_time' => time(),
|
|
'remarks' => '申请人撤销'
|
|
]);
|
|
|
|
// 更新所有待审批节点为已拒绝
|
|
(new SchoolApprovalParticipants())->where([
|
|
'process_id' => $process_id,
|
|
'status' => SchoolApprovalParticipants::STATUS_PENDING
|
|
])->update([
|
|
'status' => SchoolApprovalParticipants::STATUS_REJECTED,
|
|
'remarks' => '申请人撤销'
|
|
]);
|
|
|
|
Db::commit();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw new Exception($e->getMessage());
|
|
}
|
|
}
|
|
}
|