Browse Source

修改审批流

master
王泽彦 10 months ago
parent
commit
6f264d03e2
  1. 192
      niucloud/app/adminapi/controller/school_approval/Config.php
  2. 154
      niucloud/app/adminapi/controller/school_approval/Process.php
  3. 48
      niucloud/app/adminapi/route/school_approval.php
  4. 53
      niucloud/app/model/school_approval/SchoolApprovalConfig.php
  5. 66
      niucloud/app/model/school_approval/SchoolApprovalConfigNode.php
  6. 66
      niucloud/app/model/school_approval/SchoolApprovalParticipants.php
  7. 60
      niucloud/app/model/school_approval/SchoolApprovalProcess.php
  8. 96
      niucloud/app/model/school_approval_config.sql
  9. 185
      niucloud/app/service/school_approval/SchoolApprovalConfigService.php
  10. 289
      niucloud/app/service/school_approval/SchoolApprovalProcessService.php

192
niucloud/app/adminapi/controller/school_approval/Config.php

@ -0,0 +1,192 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\school_approval;
use app\adminapi\controller\BaseAdminApi;
use app\service\school_approval\SchoolApprovalConfigService;
use think\facade\Request;
/**
* 审批流配置控制器
* Class Config
* @package app\adminapi\controller\school_approval
*/
class Config extends BaseAdminApi
{
/**
* @var SchoolApprovalConfigService
*/
protected $service;
public function initialize()
{
parent::initialize();
$this->service = new SchoolApprovalConfigService();
}
/**
* 获取审批流配置列表
*/
public function lists()
{
$page = input('page', 1);
$limit = input('limit', 10);
$status = input('status', '');
$where = [];
if ($status !== '') {
$where[] = ['status', '=', intval($status)];
}
$config_name = input('config_name', '');
if (!empty($config_name)) {
$where[] = ['config_name', 'like', "%{$config_name}%"];
}
$data = $this->service->getList($where, $page, $limit);
return success($data);
}
/**
* 获取审批流配置详情
*/
public function info()
{
$id = input('id', 0);
if (empty($id)) {
return error('参数错误');
}
$info = $this->service->getInfo($id);
if (empty($info)) {
return error('审批流配置不存在');
}
return success($info);
}
/**
* 添加审批流配置
*/
public function add()
{
$data = Request::only(['config_name', 'description', 'status', 'nodes']);
// 验证参数
if (empty($data['config_name'])) {
return error('配置名称不能为空');
}
if (empty($data['nodes']) || !is_array($data['nodes'])) {
return error('至少需要添加一个审批节点');
}
// 验证节点数据
foreach ($data['nodes'] as $node) {
if (empty($node['node_name'])) {
return error('节点名称不能为空');
}
if (empty($node['approver_type'])) {
return error('审批人类型不能为空');
}
if (empty($node['approver_ids'])) {
return error('审批人不能为空');
}
}
// 设置创建人ID
$data['creator_id'] = $this->user_info['uid'];
try {
$config_id = $this->service->add($data);
return success(['id' => $config_id]);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
/**
* 编辑审批流配置
*/
public function edit()
{
$data = Request::only(['id', 'config_name', 'description', 'status', 'nodes']);
// 验证参数
if (empty($data['id'])) {
return error('参数错误');
}
if (empty($data['config_name'])) {
return error('配置名称不能为空');
}
if (empty($data['nodes']) || !is_array($data['nodes'])) {
return error('至少需要添加一个审批节点');
}
// 验证节点数据
foreach ($data['nodes'] as $node) {
if (empty($node['node_name'])) {
return error('节点名称不能为空');
}
if (empty($node['approver_type'])) {
return error('审批人类型不能为空');
}
if (empty($node['approver_ids'])) {
return error('审批人不能为空');
}
}
try {
$result = $this->service->edit($data);
return success($result);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
/**
* 删除审批流配置
*/
public function delete()
{
$id = input('id', 0);
if (empty($id)) {
return error('参数错误');
}
try {
$result = $this->service->delete($id);
return success($result);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
/**
* 修改状态
*/
public function changeStatus()
{
$id = input('id', 0);
$status = input('status', 0);
if (empty($id)) {
return error('参数错误');
}
try {
$result = $this->service->changeStatus($id, $status);
return success($result);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
}

154
niucloud/app/adminapi/controller/school_approval/Process.php

@ -0,0 +1,154 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\school_approval;
use app\adminapi\controller\BaseAdminApi;
use app\service\school_approval\SchoolApprovalProcessService;
use think\facade\Request;
/**
* 审批流程控制器
* Class Process
* @package app\adminapi\controller\school_approval
*/
class Process extends BaseAdminApi
{
/**
* @var SchoolApprovalProcessService
*/
protected $service;
public function initialize()
{
parent::initialize();
$this->service = new SchoolApprovalProcessService();
}
/**
* 获取审批流程列表
*/
public function lists()
{
$page = input('page', 1);
$limit = input('limit', 10);
$status = input('approval_status', '');
$where = [];
if ($status !== '') {
$where[] = ['approval_status', '=', $status];
}
$process_name = input('process_name', '');
if (!empty($process_name)) {
$where[] = ['process_name', 'like', "%{$process_name}%"];
}
// 我发起的审批
$applicant_id = input('applicant_id', 0);
if (!empty($applicant_id)) {
$where[] = ['applicant_id', '=', $applicant_id];
}
// 待我审批的
$approver_id = input('approver_id', 0);
if (!empty($approver_id)) {
$where[] = ['current_approver_id', '=', $approver_id];
$where[] = ['approval_status', '=', 'pending'];
}
$data = $this->service->getList($where, $page, $limit);
return success($data);
}
/**
* 获取审批流程详情
*/
public function info()
{
$id = input('id', 0);
if (empty($id)) {
return error('参数错误');
}
$info = $this->service->getInfo($id);
if (empty($info)) {
return error('审批流程不存在');
}
return success($info);
}
/**
* 创建审批流程
*/
public function create()
{
$data = Request::only(['process_name', 'remarks']);
$config_id = input('config_id', 0);
// 验证参数
if (empty($data['process_name'])) {
return error('流程名称不能为空');
}
if (empty($config_id)) {
return error('请选择审批流配置');
}
// 设置申请人ID
$data['applicant_id'] = $this->user_info['uid'];
try {
$process_id = $this->service->create($data, $config_id);
return success(['id' => $process_id]);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
/**
* 审批
*/
public function approve()
{
$process_id = input('process_id', 0);
$status = input('status', '');
$remarks = input('remarks', '');
if (empty($process_id)) {
return error('参数错误');
}
if (empty($status) || !in_array($status, ['approved', 'rejected'])) {
return error('请选择审批结果');
}
try {
$result = $this->service->approve($process_id, $this->user_info['uid'], $status, $remarks);
return success($result);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
/**
* 撤销审批流程
*/
public function cancel()
{
$process_id = input('process_id', 0);
if (empty($process_id)) {
return error('参数错误');
}
try {
$result = $this->service->cancel($process_id, $this->user_info['uid']);
return success($result);
} catch (\Exception $e) {
return error($e->getMessage());
}
}
}

48
niucloud/app/adminapi/route/school_approval.php

@ -0,0 +1,48 @@
<?php
// +----------------------------------------------------------------------
// | 审批流路由
// +----------------------------------------------------------------------
use think\facade\Route;
// 审批流配置
Route::group('school_approval/config', function () {
// 审批流配置列表
Route::get('lists', 'school_approval.Config/lists');
// 审批流配置详情
Route::get('info', 'school_approval.Config/info');
// 添加审批流配置
Route::post('add', 'school_approval.Config/add');
// 编辑审批流配置
Route::post('edit', 'school_approval.Config/edit');
// 删除审批流配置
Route::post('delete', 'school_approval.Config/delete');
// 修改状态
Route::post('changeStatus', 'school_approval.Config/changeStatus');
})->middleware(
[
app\adminapi\middleware\AdminCheckToken::class,
app\adminapi\middleware\AdminCheckRole::class,
app\adminapi\middleware\AdminLog::class
]
);
// 审批流程
Route::group('school_approval/process', function () {
// 审批流程列表
Route::get('lists', 'school_approval.Process/lists');
// 审批流程详情
Route::get('info', 'school_approval.Process/info');
// 创建审批流程
Route::post('create', 'school_approval.Process/create');
// 审批
Route::post('approve', 'school_approval.Process/approve');
// 撤销审批流程
Route::post('cancel', 'school_approval.Process/cancel');
})->middleware(
[
app\adminapi\middleware\AdminCheckToken::class,
app\adminapi\middleware\AdminCheckRole::class,
app\adminapi\middleware\AdminLog::class
]
);

53
niucloud/app/model/school_approval/SchoolApprovalConfig.php

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace app\model\school_approval;
use think\Model;
/**
* 审批流配置模型
* Class SchoolApprovalConfig
* @package app\model\school_approval
*/
class SchoolApprovalConfig extends Model
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'school_approval_config';
/**
* 自动写入时间戳
* @var bool
*/
protected $autoWriteTimestamp = true;
/**
* 创建时间字段
* @var string
*/
protected $createTime = 'created_at';
/**
* 更新时间字段
* @var string
*/
protected $updateTime = 'updated_at';
/**
* 关联审批流配置节点
* @return \think\model\relation\HasMany
*/
public function nodes()
{
return $this->hasMany(SchoolApprovalConfigNode::class, 'config_id', 'id')->order('sequence', 'asc');
}
}

66
niucloud/app/model/school_approval/SchoolApprovalConfigNode.php

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace app\model\school_approval;
use think\Model;
/**
* 审批流配置节点模型
* Class SchoolApprovalConfigNode
* @package app\model\school_approval
*/
class SchoolApprovalConfigNode extends Model
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'school_approval_config_node';
/**
* 自动写入时间戳
* @var bool
*/
protected $autoWriteTimestamp = true;
/**
* 创建时间字段
* @var string
*/
protected $createTime = 'created_at';
/**
* 更新时间字段
* @var string
*/
protected $updateTime = 'updated_at';
/**
* 审批人类型
*/
const APPROVER_TYPE_USER = 'user'; // 指定用户
const APPROVER_TYPE_ROLE = 'role'; // 指定角色
const APPROVER_TYPE_DEPARTMENT = 'department'; // 指定部门
/**
* 签署类型
*/
const SIGN_TYPE_OR = 'or_sign'; // 或签(一人通过即可)
const SIGN_TYPE_AND = 'and_sign'; // 会签(需全部通过)
/**
* 关联审批流配置
* @return \think\model\relation\BelongsTo
*/
public function config()
{
return $this->belongsTo(SchoolApprovalConfig::class, 'config_id', 'id');
}
}

66
niucloud/app/model/school_approval/SchoolApprovalParticipants.php

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace app\model\school_approval;
use think\Model;
/**
* 审批参与人模型
* Class SchoolApprovalParticipants
* @package app\model\school_approval
*/
class SchoolApprovalParticipants extends Model
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'school_approval_participants';
/**
* 自动写入时间戳
* @var bool
*/
protected $autoWriteTimestamp = true;
/**
* 创建时间字段
* @var string
*/
protected $createTime = 'created_at';
/**
* 更新时间字段
* @var string
*/
protected $updateTime = 'updated_at';
/**
* 审批状态
*/
const STATUS_PENDING = 'pending'; // 待审批
const STATUS_APPROVED = 'approved'; // 已批准
const STATUS_REJECTED = 'rejected'; // 已拒绝
/**
* 签署类型
*/
const SIGN_TYPE_OR = 'or_sign'; // 或签(一人通过即可)
const SIGN_TYPE_AND = 'and_sign'; // 会签(需全部通过)
/**
* 关联审批流程
* @return \think\model\relation\BelongsTo
*/
public function process()
{
return $this->belongsTo(SchoolApprovalProcess::class, 'process_id', 'id');
}
}

60
niucloud/app/model/school_approval/SchoolApprovalProcess.php

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace app\model\school_approval;
use think\Model;
/**
* 审批流程模型
* Class SchoolApprovalProcess
* @package app\model\school_approval
*/
class SchoolApprovalProcess extends Model
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'school_approval_process';
/**
* 自动写入时间戳
* @var bool
*/
protected $autoWriteTimestamp = true;
/**
* 创建时间字段
* @var string
*/
protected $createTime = 'created_at';
/**
* 更新时间字段
* @var string
*/
protected $updateTime = 'updated_at';
/**
* 审批状态
*/
const STATUS_PENDING = 'pending'; // 待审批
const STATUS_APPROVED = 'approved'; // 已批准
const STATUS_REJECTED = 'rejected'; // 已拒绝
/**
* 关联审批参与人
* @return \think\model\relation\HasMany
*/
public function participants()
{
return $this->hasMany(SchoolApprovalParticipants::class, 'process_id', 'id')->order('sequence', 'asc');
}
}

96
niucloud/app/model/school_approval_config.sql

@ -0,0 +1,96 @@
-- ========================
-- 数据库结构增强脚本(MySQL)
-- ========================
-- 1. 会计期间有效性校验
ALTER TABLE financial_accounting_periods
ADD COLUMN status ENUM('active', 'closed', 'locked') DEFAULT 'active' COMMENT '期间状态',
ADD COLUMN validation_date DATE COMMENT '最后验证日期';
-- 2. 预算表(支持多版本)
CREATE TABLE financial_budgets (
budget_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '预算ID',
company_id INT NOT NULL COMMENT '公司ID',
period_id INT NOT NULL COMMENT '会计期间ID',
account_id INT NOT NULL COMMENT '科目ID',
budget_version INT DEFAULT 1 COMMENT '版本号',
planned_amount DECIMAL(18,2) COMMENT '计划金额',
approved_date DATE COMMENT '审批日期',
FOREIGN KEY (company_id) REFERENCES financial_companies(company_id),
FOREIGN KEY (period_id) REFERENCES financial_accounting_periods(period_id),
FOREIGN KEY (account_id) REFERENCES financial_chart_of_accounts(account_id)
) COMMENT='财务预算表';
-- 3. 科目层级管理增强
ALTER TABLE financial_chart_of_accounts
ADD COLUMN path VARCHAR(255) COMMENT '层级路径(如0/1001/)',
ADD COLUMN level INT COMMENT '层级深度';
-- 4. 数据血缘追踪表
CREATE TABLE financial_data_trace (
trace_id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '追踪记录ID',
source_table VARCHAR(50) NOT NULL COMMENT '源表名',
source_id BIGINT NOT NULL COMMENT '源记录ID',
target_table VARCHAR(50) NOT NULL COMMENT '目标表名',
target_id BIGINT NOT NULL COMMENT '目标记录ID',
operation_type ENUM('insert','update','delete') NOT NULL COMMENT '操作类型',
operator VARCHAR(50) COMMENT '操作人',
operation_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间'
) COMMENT='数据操作追踪表';
-- 5. 会计期间重叠检查触发器
DELIMITER //
CREATE TRIGGER trg_check_period_overlap
BEFORE INSERT ON financial_accounting_periods
FOR EACH ROW
BEGIN
IF EXISTS (
SELECT 1 FROM financial_accounting_periods
WHERE company_id = NEW.company_id
AND period_id != NEW.period_id
AND (
(NEW.start_date BETWEEN start_date AND end_date)
OR (NEW.end_date BETWEEN start_date AND end_date)
OR (start_date BETWEEN NEW.start_date AND NEW.end_date)
)
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '会计期间时间重叠';
END IF;
END//
DELIMITER ;
-- 6. 初始化会计期间状态
UPDATE financial_accounting_periods
SET status = CASE
WHEN end_date >= CURDATE() THEN 'active'
WHEN end_date < CURDATE() AND start_date > CURDATE() THEN 'locked'
ELSE 'closed'
END;
-- 7. 创建科目层级维护存储过程
DELIMITER //
CREATE PROCEDURE sp_refresh_account_hierarchy()
BEGIN
UPDATE financial_chart_of_accounts c
LEFT JOIN (
SELECT
a.account_id,
CONCAT(
IFNULL((SELECT CONCAT(path, parent_id, '/') FROM financial_chart_of_accounts
WHERE account_id = a.parent_id), '0/'),
a.account_id, '/'
) AS new_path,
(LENGTH(IFNULL((SELECT path FROM financial_chart_of_accounts
WHERE account_id = a.parent_id), '0/')) - LENGTH(REPLACE(IFNULL(
(SELECT path FROM financial_chart_of_accounts
WHERE account_id = a.parent_id), '0/'), '/', ''))) + 1
AS new_level
FROM financial_chart_of_accounts a
) AS sub ON c.account_id = sub.account_id
SET
c.path = sub.new_path,
c.level = sub.new_level
WHERE c.is_active = TRUE;
END//
DELIMITER ;

185
niucloud/app/service/school_approval/SchoolApprovalConfigService.php

@ -0,0 +1,185 @@
<?php
declare(strict_types=1);
namespace app\service\school_approval;
use app\model\school_approval\SchoolApprovalConfig;
use app\model\school_approval\SchoolApprovalConfigNode;
use think\Exception;
use think\facade\Db;
/**
* 审批流配置服务
* Class SchoolApprovalConfigService
* @package app\service\school_approval
*/
class SchoolApprovalConfigService
{
/**
* 获取审批流配置列表
* @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, config_name, description, status, creator_id, created_at, updated_at';
$order = 'id desc';
$list = (new SchoolApprovalConfig())
->where($where)
->field($field)
->order($order)
->page($page, $limit)
->select()
->toArray();
$count = (new SchoolApprovalConfig())->where($where)->count();
return [
'list' => $list,
'count' => $count
];
}
/**
* 获取审批流配置详情
* @param int $id
* @return array
*/
public function getInfo(int $id): array
{
$info = (new SchoolApprovalConfig())->with(['nodes'])->where(['id' => $id])->find();
if (empty($info)) {
return [];
}
return $info->toArray();
}
/**
* 添加审批流配置
* @param array $data
* @return int
* @throws \Exception
*/
public function add(array $data): int
{
Db::startTrans();
try {
$config = [
'config_name' => $data['config_name'],
'description' => $data['description'] ?? '',
'status' => $data['status'] ?? 1,
'creator_id' => $data['creator_id']
];
$config_id = (new SchoolApprovalConfig())->insertGetId($config);
// 添加节点
if (!empty($data['nodes'])) {
$nodes = [];
foreach ($data['nodes'] as $sequence => $node) {
$nodes[] = [
'config_id' => $config_id,
'node_name' => $node['node_name'],
'approver_type' => $node['approver_type'],
'approver_ids' => is_array($node['approver_ids']) ? implode(',', $node['approver_ids']) : $node['approver_ids'],
'sign_type' => $node['sign_type'] ?? SchoolApprovalConfigNode::SIGN_TYPE_OR,
'sequence' => $sequence + 1
];
}
(new SchoolApprovalConfigNode())->insertAll($nodes);
}
Db::commit();
return $config_id;
} catch (\Exception $e) {
Db::rollback();
throw new Exception($e->getMessage());
}
}
/**
* 编辑审批流配置
* @param array $data
* @return bool
* @throws \Exception
*/
public function edit(array $data): bool
{
Db::startTrans();
try {
$config = [
'config_name' => $data['config_name'],
'description' => $data['description'] ?? '',
'status' => $data['status'] ?? 1
];
(new SchoolApprovalConfig())->where(['id' => $data['id']])->update($config);
// 先删除原有节点
(new SchoolApprovalConfigNode())->where(['config_id' => $data['id']])->delete();
// 添加新节点
if (!empty($data['nodes'])) {
$nodes = [];
foreach ($data['nodes'] as $sequence => $node) {
$nodes[] = [
'config_id' => $data['id'],
'node_name' => $node['node_name'],
'approver_type' => $node['approver_type'],
'approver_ids' => is_array($node['approver_ids']) ? implode(',', $node['approver_ids']) : $node['approver_ids'],
'sign_type' => $node['sign_type'] ?? SchoolApprovalConfigNode::SIGN_TYPE_OR,
'sequence' => $sequence + 1
];
}
(new SchoolApprovalConfigNode())->insertAll($nodes);
}
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
throw new Exception($e->getMessage());
}
}
/**
* 删除审批流配置
* @param int $id
* @return bool
* @throws \Exception
*/
public function delete(int $id): bool
{
Db::startTrans();
try {
// 删除配置
(new SchoolApprovalConfig())->where(['id' => $id])->delete();
// 删除节点
(new SchoolApprovalConfigNode())->where(['config_id' => $id])->delete();
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
throw new Exception($e->getMessage());
}
}
/**
* 修改状态
* @param int $id
* @param int $status
* @return bool
*/
public function changeStatus(int $id, int $status): bool
{
return (new SchoolApprovalConfig())->where(['id' => $id])->update(['status' => $status]) !== false;
}
}

289
niucloud/app/service/school_approval/SchoolApprovalProcessService.php

@ -0,0 +1,289 @@
<?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());
}
}
}
Loading…
Cancel
Save