1
This commit is contained in:
@@ -52,4 +52,19 @@ class InvItemController extends BaseController
|
|||||||
$data['manage_user_name'] = User::where('id', $data['manage_user_id'])->value('name');
|
$data['manage_user_name'] = User::where('id', $data['manage_user_id'])->value('name');
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function requisitionList(Request $request){
|
||||||
|
try {
|
||||||
|
$res = $this->service->getList();
|
||||||
|
$result = [];
|
||||||
|
foreach ($res as $value) {
|
||||||
|
$value['company_name'] = Corp::where('id', $value['company_id'])->value('name');
|
||||||
|
$value['manage_user_name'] = User::where('id', $value['manage_user_id'])->value('name');
|
||||||
|
$result[] = $value;
|
||||||
|
}
|
||||||
|
return $this->success($result, '审核列表');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,7 @@ namespace app\admin\controller;
|
|||||||
|
|
||||||
use app\common\controller\BaseController;
|
use app\common\controller\BaseController;
|
||||||
use app\common\traits\crud\CrudControllerTrait;
|
use app\common\traits\crud\CrudControllerTrait;
|
||||||
use app\common\service\InvRequisitionService;
|
use app\admin\service\InvRequisitionService;
|
||||||
use support\Request;
|
|
||||||
|
|
||||||
class InvRequisitionController extends BaseController
|
class InvRequisitionController extends BaseController
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\service;
|
||||||
|
|
||||||
|
use app\common\validate\InvRequisitionValidate;
|
||||||
|
use app\common\traits\crud\CrudServiceTrait;
|
||||||
|
use app\common\model\InvRequisition;
|
||||||
|
|
||||||
|
class InvRequisitionService
|
||||||
|
{
|
||||||
|
|
||||||
|
use CrudServiceTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定当前要操作的模型
|
||||||
|
*/
|
||||||
|
protected string $modelClass = InvRequisition::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证器
|
||||||
|
*/
|
||||||
|
protected $validator = InvRequisitionValidate::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取验证器
|
||||||
|
*/
|
||||||
|
public function getValidator()
|
||||||
|
{
|
||||||
|
return new $this->validator;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
namespace app\common\service;
|
namespace app\common\service;
|
||||||
|
|
||||||
|
use app\common\model\User;
|
||||||
use app\common\validate\InvRequisitionApproveValidate;
|
use app\common\validate\InvRequisitionApproveValidate;
|
||||||
use app\common\traits\crud\CrudServiceTrait;
|
use app\common\traits\crud\CrudServiceTrait;
|
||||||
use app\common\model\InvRequisitionApprove;
|
use app\common\model\InvRequisitionApprove;
|
||||||
|
use support\Db;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
class InvRequisitionApproveService
|
class InvRequisitionApproveService
|
||||||
{
|
{
|
||||||
@@ -29,5 +32,195 @@ class InvRequisitionApproveService
|
|||||||
return new $this->validator;
|
return new $this->validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $flowType
|
||||||
|
* @param string $bizType
|
||||||
|
* @param string $bizId
|
||||||
|
* @param array $formData ['manage_user_id'=>23]//物品管理员
|
||||||
|
* @param int $initiatorId //申请人id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function start(string $flowType, string $bizType, string $bizId, array $formData, int $initiatorId): array
|
||||||
|
{
|
||||||
|
return Db::transaction(function () use ($flowType, $bizType, $bizId, $formData, $initiatorId) {
|
||||||
|
$flow = Db::table('approval_flows')->where('type', $flowType)->where('is_active', 1)->first();
|
||||||
|
if (!$flow) throw new BusinessException("审批流程未找到或已停用: {$flowType}");
|
||||||
|
|
||||||
|
$steps = json_decode($flow->steps, true);
|
||||||
|
if (!is_array($steps) || empty($steps)) throw new BusinessException("流程步骤配置错误");
|
||||||
|
|
||||||
|
// 找首个有效步骤索引(考虑条件)
|
||||||
|
$firstIndex = $this->getNextStepIndex($steps, $formData, -1);
|
||||||
|
if ($firstIndex === null) throw new BusinessException("未找到可执行的审批步骤");
|
||||||
|
$firstStep = $steps[$firstIndex];
|
||||||
|
|
||||||
|
//$now = date('Y-m-d H:i:s');
|
||||||
|
$now = time();
|
||||||
|
|
||||||
|
|
||||||
|
$service = new \app\common\utils\approval\service\ApprovalFlowService();
|
||||||
|
|
||||||
|
// 解析首步审批人(支持 role_id 或 roles.name)
|
||||||
|
$instance = (object)[
|
||||||
|
'initiator_id' => $initiatorId,
|
||||||
|
'form_data'=>json_encode($formData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||||
|
];
|
||||||
|
$approverIds = $service->StetApprovers($firstStep, $instance, true);
|
||||||
|
|
||||||
|
if(empty($approverIds)){
|
||||||
|
throw new BusinessException('未解析到任何审批人');
|
||||||
|
}
|
||||||
|
$uid = array_shift($approverIds);
|
||||||
|
$approver = User::where('id', $uid)->first();
|
||||||
|
|
||||||
|
$approveId = Db::table('inv_requisition_approve')->insertGetId([
|
||||||
|
'requisition_id' => $bizId, //申请单ID
|
||||||
|
'node_type' => $bizType,
|
||||||
|
'approver_id' => $approver->id,
|
||||||
|
'approver_name' => $approver->name,
|
||||||
|
'action' => 0,
|
||||||
|
'comment' => '',
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// foreach ($approverIds as $uid) {
|
||||||
|
// $this->insertApprovalRecord($instance, $firstIndex, $uid);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return ['instance_id' => $approveId];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行审批 */
|
||||||
|
public function approve(int $requisitionId, int $approverId, string $action, string $comment = '')
|
||||||
|
{
|
||||||
|
if (!in_array($action, ['1','2'], true)) { //审批动作:1通过 2驳回
|
||||||
|
throw new BusinessException("无效的审批操作");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Db::transaction(function () use ($requisitionId, $approverId, $action, $comment) {
|
||||||
|
// $instance = Db::table('approval_instances')->where('id', $instanceId)->lockForUpdate()->first();
|
||||||
|
$requisition = Db::table('inv_requisition')->where('id', $requisitionId)->lockForUpdate()->first();
|
||||||
|
if (!$requisition) throw new BusinessException("审批实例未找到");
|
||||||
|
if ($requisition->status !== 'processing') {
|
||||||
|
return ['status' => 'noop', 'msg' => '实例未处理'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//审批流程
|
||||||
|
$flow = Db::table('approval_flows')->where('type', $requisition->flow_type)->first();
|
||||||
|
if (!$flow) throw new BusinessException("审批流程定义未找到");
|
||||||
|
|
||||||
|
$steps = json_decode($flow->steps, true);
|
||||||
|
//$idx = (int)$requisition->current_step;
|
||||||
|
//$step = $steps[$idx] ?? null;
|
||||||
|
//if (!$step) throw new BusinessException("当前步骤配置错误");
|
||||||
|
|
||||||
|
// 找到该用户在本步的 pending 记录(加锁)
|
||||||
|
$pendingRecord = Db::table('inv_requisition_approve')
|
||||||
|
->where('requisition_id', $requisitionId)
|
||||||
|
->where('approver_id', $approverId)
|
||||||
|
->where('action', 0)
|
||||||
|
->lockForUpdate()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$pendingRecord) {
|
||||||
|
// 已处理过?
|
||||||
|
$anyRecord = Db::table('inv_requisition_approve')
|
||||||
|
->where('requisition_id', $requisitionId)
|
||||||
|
->where('approver_id', $approverId)
|
||||||
|
->first();
|
||||||
|
if ($anyRecord && $anyRecord->action > 0) {
|
||||||
|
return ['status' => 'noop', 'msg' => '已处理'];
|
||||||
|
}
|
||||||
|
// 步骤已推进
|
||||||
|
// if ((int)$requisition->current_step !== $idx) {
|
||||||
|
// return ['status' => 'noop', 'msg' => '非当前审批'];
|
||||||
|
// }
|
||||||
|
return ['status' => 'noop', 'msg' => '无待处理记录'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
// 1) 更新当前人的审批记录
|
||||||
|
Db::table('inv_requisition_approve')->where('id', $pendingRecord->id)->update([
|
||||||
|
'action' => $action,
|
||||||
|
'comment' => $comment,
|
||||||
|
'approved_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 2) 已通过步骤与总步数相等则结束审核流程
|
||||||
|
$pass = Db::table('inv_requisition_approve')
|
||||||
|
->where('requisition_id', $requisitionId)
|
||||||
|
->where('approver_id', $approverId)
|
||||||
|
->where('action', 1)
|
||||||
|
->count();
|
||||||
|
if($action == 1){
|
||||||
|
if(count($steps) == $pass){
|
||||||
|
$requisition->status = 12;
|
||||||
|
$requisition->save();
|
||||||
|
return ['status' => 'complete', 'msg' => '已通过'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) 拒绝 => 结束
|
||||||
|
if($action == 2){
|
||||||
|
Db::table('inv_requisition_approve')->where('id', $pendingRecord->id)->update([
|
||||||
|
'action' => $action,
|
||||||
|
'comment' => $comment,
|
||||||
|
'approved_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
if(count($steps) == $pass){
|
||||||
|
$requisition->status = 13;
|
||||||
|
$requisition->save();
|
||||||
|
return ['status' => 'complete', 'msg' => '拒绝'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 4) 通过 => 进入下一步或结束
|
||||||
|
$formData = ['manage_user_id'=>''];
|
||||||
|
|
||||||
|
$nextIndex = $pass;
|
||||||
|
$nextStep = $steps[$nextIndex];
|
||||||
|
$service = new \app\common\utils\approval\service\ApprovalFlowService();
|
||||||
|
|
||||||
|
$instance = (object)[
|
||||||
|
'form_data'=>json_encode($formData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||||
|
];
|
||||||
|
$approverIds = $service->StetApprovers($nextStep, $instance, true);
|
||||||
|
$approver = User::where('id', array_pop($approverIds))->first();
|
||||||
|
Db::table('inv_requisition_approve')->insertGetId([
|
||||||
|
'requisition_id' => $requisitionId, //申请单ID
|
||||||
|
'node_type' => $nextStep['approvers']['initiator_leader'],
|
||||||
|
'approver_id' => $approver->id,
|
||||||
|
'approver_name' => $approver->name,
|
||||||
|
'action' => 0,
|
||||||
|
'comment' => '',
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);;
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// public function insertApprovalRecord()
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/** 获取下一个有效步骤索引 */
|
||||||
|
private function getNextStepIndex(array $steps, array $formData, int $currentStepIndex): ?int
|
||||||
|
{
|
||||||
|
for ($i = $currentStepIndex + 1; $i < count($steps); $i++) {
|
||||||
|
$s = $steps[$i];
|
||||||
|
if (empty($s['condition'])) {
|
||||||
|
return $i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -403,4 +403,8 @@ trait ApprovalResolverTrait
|
|||||||
|
|
||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function StetApprovers(array $step, object $instance, bool $avoidSelf = true){
|
||||||
|
return$this->resolveApprovers($step, $instance, $avoidSelf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -514,6 +514,10 @@ Route::group('/admin', function () {
|
|||||||
Route::any('/item/update', [app\admin\controller\InvItemController::class, 'update']);
|
Route::any('/item/update', [app\admin\controller\InvItemController::class, 'update']);
|
||||||
Route::any('/item/show', [app\admin\controller\InvItemController::class, 'show']);
|
Route::any('/item/show', [app\admin\controller\InvItemController::class, 'show']);
|
||||||
Route::any('/item/destroy', [app\admin\controller\InvItemController::class, 'destroy']);
|
Route::any('/item/destroy', [app\admin\controller\InvItemController::class, 'destroy']);
|
||||||
|
|
||||||
|
Route::group('/requisition', function () {
|
||||||
|
Route::any('/list', [app\admin\controller\InvItemController::class, 'requisitionList']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user