调整ä功能
This commit is contained in:
@@ -36,7 +36,7 @@ class ApprovalRecordsController extends BaseController
|
|||||||
|
|
||||||
'biz_id' => $record['instance']['biz_id'],
|
'biz_id' => $record['instance']['biz_id'],
|
||||||
'biz_desc' => '备货单【'.$record['instance']['bizInfo']['order_no'].'】',
|
'biz_desc' => '备货单【'.$record['instance']['bizInfo']['order_no'].'】',
|
||||||
'biz_type' => $record['instance']['flow_type'],
|
'biz_type' => $record['instance']['biz_type'],
|
||||||
|
|
||||||
'initiator_name' => $record['instance']['initiator']['name'],
|
'initiator_name' => $record['instance']['initiator']['name'],
|
||||||
'initiator_avatar' => $record['instance']['initiator']['avatar'],
|
'initiator_avatar' => $record['instance']['initiator']['avatar'],
|
||||||
@@ -113,7 +113,7 @@ class ApprovalRecordsController extends BaseController
|
|||||||
|
|
||||||
'biz_id' => $record['instance']['biz_id'],
|
'biz_id' => $record['instance']['biz_id'],
|
||||||
'biz_desc' => '业务单号【'.$record['instance']['bizInfo']['order_no'].'】',
|
'biz_desc' => '业务单号【'.$record['instance']['bizInfo']['order_no'].'】',
|
||||||
'biz_type' => $record['instance']['flow_type'],
|
'biz_type' => $record['instance']['biz_type'],
|
||||||
'flow_type' => $record['instance']['flow_type'],
|
'flow_type' => $record['instance']['flow_type'],
|
||||||
|
|
||||||
'initiator_name' => $record['instance']['initiator']['name'],
|
'initiator_name' => $record['instance']['initiator']['name'],
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class StockOrdersController extends BaseController
|
|||||||
if (isset($data['id'])) {
|
if (isset($data['id'])) {
|
||||||
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
||||||
$appro = $appro->getBriefStatusByBiz($data['id'], null, 'name');
|
$appro = $appro->getBriefStatusByBiz($data['id'], null, 'name');
|
||||||
$map = ['processing'=>'审批中','pending'=>'审批中','approved'=>'已通过','rejected'=>'已拒绝','revoked'=>'已撤回'];
|
$map = ['processing'=>'审批中','pending'=>'审批中','approved'=>'已通过','rejected'=>'已拒绝','revoked'=>'已撤回','voided'=>'已作废'];
|
||||||
if ($appro) {
|
if ($appro) {
|
||||||
$data['appro_status'] = [
|
$data['appro_status'] = [
|
||||||
'status' => $appro['status'],
|
'status' => $appro['status'],
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class UserGroupController extends BaseController
|
|||||||
$result = [
|
$result = [
|
||||||
'id' => $record['id'],
|
'id' => $record['id'],
|
||||||
'title' => $record['title'],
|
'title' => $record['title'],
|
||||||
|
'scenario_code' => $record['scenario_code'],
|
||||||
'leader_id' => 0,
|
'leader_id' => 0,
|
||||||
'leader_name' => '',
|
'leader_name' => '',
|
||||||
'sort' => $record['sort'],
|
'sort' => $record['sort'],
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class UserGroupLogic
|
|||||||
$userGroup->title = $data['title'];
|
$userGroup->title = $data['title'];
|
||||||
$userGroup->sort = $data['sort'] ?? 0;
|
$userGroup->sort = $data['sort'] ?? 0;
|
||||||
$userGroup->status = $data['status'];
|
$userGroup->status = $data['status'];
|
||||||
|
$userGroup->scenario_code = $data['scenario_code'] ?? '';
|
||||||
$userGroup->save();
|
$userGroup->save();
|
||||||
|
|
||||||
// 删除所有成员
|
// 删除所有成员
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class ApprovalInstances extends Model
|
|||||||
// ====== ====== ====== 映射业务表 ====== ====== ======
|
// ====== ====== ====== 映射业务表 ====== ====== ======
|
||||||
protected const BIZ_CLASS = [
|
protected const BIZ_CLASS = [
|
||||||
'stock_orders' => \app\common\model\StockOrders::class,
|
'stock_orders' => \app\common\model\StockOrders::class,
|
||||||
|
'stock_orders_nullify' => \app\common\model\StockOrders::class,
|
||||||
'purchase_orders' => \app\common\model\PurchaseOrders::class,
|
'purchase_orders' => \app\common\model\PurchaseOrders::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ class ApprovalInstances extends Model
|
|||||||
|
|
||||||
public function bizInfo()
|
public function bizInfo()
|
||||||
{
|
{
|
||||||
return $this->morphTo('bizInfo', 'biz_type', 'biz_id');
|
return $this->morphTo('bizInfo', 'biz_type', 'biz_id')->withTrashed();
|
||||||
}
|
}
|
||||||
// ====== ====== ====== 映射表业务 ====== ====== ======
|
// ====== ====== ====== 映射表业务 ====== ====== ======
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ namespace app\common\model;
|
|||||||
|
|
||||||
use support\Model;
|
use support\Model;
|
||||||
use app\common\traits\HasMoneyJournal;
|
use app\common\traits\HasMoneyJournal;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class StockOrders extends Model
|
class StockOrders extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The connection name for the model.
|
* The connection name for the model.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class UserGroup extends Model
|
|||||||
/**
|
/**
|
||||||
* 允许自动填充模型字段
|
* 允许自动填充模型字段
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['id', 'title', 'sort', 'status', 'created_at', 'updated_at'];
|
protected $fillable = ['id', 'title', 'scenario_code', 'sort', 'status', 'created_at', 'updated_at'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 不允许自动填充模型字段
|
* 不允许自动填充模型字段
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class ApprovalRecordsService
|
|||||||
$bizInfo = [];
|
$bizInfo = [];
|
||||||
$service = match ($data['flow_type']) {
|
$service = match ($data['flow_type']) {
|
||||||
'stock_orders' => new \app\common\service\StockOrdersService(),
|
'stock_orders' => new \app\common\service\StockOrdersService(),
|
||||||
|
'stock_orders_nullify' => new \app\common\service\StockOrdersService(),
|
||||||
'purchase_orders' => new \app\common\service\PurchaseOrdersService(),
|
'purchase_orders' => new \app\common\service\PurchaseOrdersService(),
|
||||||
default => new \app\common\service\StockOrdersService()
|
default => new \app\common\service\StockOrdersService()
|
||||||
};
|
};
|
||||||
@@ -154,6 +155,14 @@ class ApprovalRecordsService
|
|||||||
'instance.bizInfo.moneyValues',
|
'instance.bizInfo.moneyValues',
|
||||||
'instance.bizInfo.salesperson',
|
'instance.bizInfo.salesperson',
|
||||||
],
|
],
|
||||||
|
'stock_orders_nullify' => [
|
||||||
|
'instance.bizInfo.items',
|
||||||
|
'instance.bizInfo.items.options',
|
||||||
|
'instance.bizInfo.items.moneyValues',
|
||||||
|
'instance.bizInfo.accounts',
|
||||||
|
'instance.bizInfo.moneyValues',
|
||||||
|
'instance.bizInfo.salesperson',
|
||||||
|
],
|
||||||
'purchase_orders' => [
|
'purchase_orders' => [
|
||||||
'instance.bizInfo.items',
|
'instance.bizInfo.items',
|
||||||
'instance.bizInfo.items.stockOrder',
|
'instance.bizInfo.items.stockOrder',
|
||||||
|
|||||||
@@ -410,7 +410,7 @@ class StockOrdersService
|
|||||||
public function approvalNullify($item)
|
public function approvalNullify($item)
|
||||||
{
|
{
|
||||||
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
||||||
$appro->startNullify('stock_orders_nullify', 'stock_orders_nullify', $item->id, [], $item->salesperson_id);
|
$appro->startNullify('stock_orders_nullify', 'stock_orders', $item->id, [], $item->salesperson_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -74,16 +74,16 @@ class WsEvents
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 连接是否满足条件
|
// 连接是否满足条件
|
||||||
// if ($payload['server']['HTTP_ORIGIN'] != 'https://wstool.js.org') {
|
if (getenv('ENVIRONMENT') === 'master' && $payload['server']['HTTP_ORIGIN'] === getenv('MAIN_DOMAIN')) {
|
||||||
// flg('[x] [TOKEN认证] HTTP_ORIGIN不满足条件', false);
|
flg('[x] [TOKEN认证] HTTP_ORIGIN不满足条件', false);
|
||||||
// Gateway::sendToClient($client_id, WsResponse::error(
|
Gateway::sendToClient($client_id, WsResponse::error(
|
||||||
// 'system.auth',
|
'system.auth',
|
||||||
// 1001,
|
1001,
|
||||||
// '[x] [TOKEN认证] HTTP_ORIGIN不满足条件'
|
'[x] [TOKEN认证] HTTP_ORIGIN不满足条件'
|
||||||
// ));
|
));
|
||||||
// Gateway::closeClient($client_id);
|
Gateway::closeClient($client_id);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// 签名检查
|
// 签名检查
|
||||||
if (!isset($payload['get']['token'])) {
|
if (!isset($payload['get']['token'])) {
|
||||||
@@ -99,9 +99,14 @@ class WsEvents
|
|||||||
|
|
||||||
// 解析TOKEN
|
// 解析TOKEN
|
||||||
$user = (new Jwt())->verifyToken($payload['get']['token']);
|
$user = (new Jwt())->verifyToken($payload['get']['token']);
|
||||||
|
|
||||||
// 绑定用户ID
|
// 绑定用户ID
|
||||||
Gateway::bindUid($client_id, $user->uid);
|
Gateway::bindUid($client_id, $user->uid);
|
||||||
|
|
||||||
|
// 绑定SESSION
|
||||||
|
$_SESSION['uid'] = $user->uid;
|
||||||
|
$_SESSION['name'] = $user->uname;
|
||||||
|
|
||||||
// 响应
|
// 响应
|
||||||
Gateway::sendToClient($client_id, WsResponse::success(
|
Gateway::sendToClient($client_id, WsResponse::success(
|
||||||
'system.auth',
|
'system.auth',
|
||||||
@@ -119,6 +124,13 @@ class WsEvents
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function logout(string $client_id)
|
||||||
|
{
|
||||||
|
if ($_SESSION !== null) {
|
||||||
|
var_dump($_SESSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统心跳
|
* 系统心跳
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ namespace app\common\utils\approval\service;
|
|||||||
|
|
||||||
use support\exception\BusinessException;
|
use support\exception\BusinessException;
|
||||||
use support\Db;
|
use support\Db;
|
||||||
|
use support\Log;
|
||||||
|
|
||||||
class ApprovalFlowService
|
class ApprovalFlowService
|
||||||
{
|
{
|
||||||
@@ -174,14 +175,18 @@ class ApprovalFlowService
|
|||||||
$nextIndex = $this->getNextStepIndex($steps, $formData, $idx);
|
$nextIndex = $this->getNextStepIndex($steps, $formData, $idx);
|
||||||
|
|
||||||
if ($nextIndex === null) {
|
if ($nextIndex === null) {
|
||||||
|
$finalStatus = $this->normalizeFinalStatus((string)$instance->flow_type, 'approved');
|
||||||
|
$notifyAction = ($finalStatus === 'voided') ? 'voided' : 'approve';
|
||||||
|
|
||||||
Db::table('approval_instances')->where('id', $instanceId)->update([
|
Db::table('approval_instances')->where('id', $instanceId)->update([
|
||||||
'status' => 'approved',
|
'status' => $finalStatus,
|
||||||
'finished_at' => $now,
|
'finished_at' => $now,
|
||||||
'updated_at' => $now,
|
'updated_at' => $now,
|
||||||
]);
|
]);
|
||||||
$this->onFlowFinalized($instance, 'approved');
|
$this->onFlowFinalized($instance, $finalStatus);
|
||||||
$this->sendNotification([$instance->initiator_id], $instance, 'approve', false);
|
$this->sendNotification([$instance->initiator_id], $instance, $notifyAction, false);
|
||||||
return ['status' => 'completed', 'msg' => '同意'];
|
|
||||||
|
return ['status' => 'completed', 'msg' => ($finalStatus === 'voided' ? '已作废' : '同意')];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 乐观推进 current_step
|
// 乐观推进 current_step
|
||||||
@@ -206,13 +211,16 @@ class ApprovalFlowService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ★ 新增:流程完结后的业务回调(此处处理“作废”落库) */
|
// 流程完结后的业务回调(approved|rejected|revoked|timeout?)
|
||||||
private function onFlowFinalized(object $instance, string $final /* 'approved'|'rejected' */): void
|
private function onFlowFinalized(object $instance, string $final): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
switch ($instance->flow_type) {
|
switch ($instance->flow_type) {
|
||||||
case 'stock_orders': {
|
case 'stock_orders': {
|
||||||
$order = \app\common\model\StockOrders::find($instance->biz_id);
|
$order = \app\common\model\StockOrders::find($instance->biz_id);
|
||||||
|
if (!$order) {
|
||||||
|
throw new BusinessException('订单不存在');
|
||||||
|
}
|
||||||
if ($final === 'approved') {
|
if ($final === 'approved') {
|
||||||
$order->approval_status = 2;
|
$order->approval_status = 2;
|
||||||
$order->save();
|
$order->save();
|
||||||
@@ -225,11 +233,14 @@ class ApprovalFlowService
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'stock_orders_nullify':
|
case 'stock_orders_nullify':
|
||||||
// 仅当作废审批“通过”时,真正把业务单置为作废
|
|
||||||
if ($final === 'approved') {
|
if ($final === 'approved') {
|
||||||
// 这里按你的模型更新,状态字段请替换成你系统实际枚举
|
$final = 'voided';
|
||||||
|
Db::table('approval_instances')->where('id', $instance->id)->update([
|
||||||
|
'status' => 'voided',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (in_array($final, ['voided','approved'], true)) {
|
||||||
$order = \app\common\model\StockOrders::find($instance->biz_id);
|
$order = \app\common\model\StockOrders::find($instance->biz_id);
|
||||||
if ($order && $order->approval_status !== 4) {
|
if ($order && $order->approval_status !== 4) {
|
||||||
$order->approval_status = 4;
|
$order->approval_status = 4;
|
||||||
@@ -237,18 +248,12 @@ class ApprovalFlowService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case 'purchase_orders_nullify':
|
|
||||||
// ...
|
|
||||||
// break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// 非作废流程,无需处理
|
// 非作废流程,无需处理
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
// 避免回写异常影响审批主流程,可按需记录日志
|
Log::error('onFlowFinalized error: '.$e->getMessage());
|
||||||
// logger()->error('onFlowFinalized error: '.$e->getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +367,8 @@ class ApprovalFlowService
|
|||||||
if (!$flow) return;
|
if (!$flow) return;
|
||||||
|
|
||||||
$final = ($flow->timeout_action === 'auto_approve') ? 'approved' : 'rejected';
|
$final = ($flow->timeout_action === 'auto_approve') ? 'approved' : 'rejected';
|
||||||
$finalAction = ($flow->timeout_action === 'auto_approve') ? 'approve' : 'reject';
|
$final = $this->normalizeFinalStatus((string)$instance->flow_type, $final);
|
||||||
|
$finalAction = ($final === 'voided') ? 'voided' : (($final === 'approved') ? 'approve' : 'reject');
|
||||||
|
|
||||||
Db::table('approval_instances')->where('id', $instance->id)->update([
|
Db::table('approval_instances')->where('id', $instance->id)->update([
|
||||||
'status' => $final,
|
'status' => $final,
|
||||||
@@ -490,6 +496,28 @@ class ApprovalFlowService
|
|||||||
$head = $this->getDeptHeadId((int)$val);
|
$head = $this->getDeptHeadId((int)$val);
|
||||||
if ($head) $uids[] = (int)$head;
|
if ($head) $uids[] = (int)$head;
|
||||||
break;
|
break;
|
||||||
|
case 'group_members': {
|
||||||
|
$gid = (int)($val ?? 0);
|
||||||
|
if ($gid <= 0) throw new BusinessException('group_members 需要 group_id');
|
||||||
|
$uids = $this->getGroupMemberIds($gid); // A 方案
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'scenario_leader_of_initiator': {
|
||||||
|
$formData = json_decode($instance->form_data ?? '{}', true) ?: [];
|
||||||
|
$scenario = $val ?? ($formData[$cc['scenario_field']] ?? null);
|
||||||
|
if (!$scenario) throw new BusinessException('缺少业务场景(scenario 或 scenario_field)');
|
||||||
|
|
||||||
|
$mustBelong = array_key_exists('must_belong', $cc) ? (bool)$cc['must_belong'] : true;
|
||||||
|
$preferPrimary = array_key_exists('prefer_primary', $cc) ? (bool)$cc['prefer_primary'] : true;
|
||||||
|
|
||||||
|
$uids = $this->getLeadersByScenarioForInitiator(
|
||||||
|
(int)$instance->initiator_id,
|
||||||
|
(string)$scenario,
|
||||||
|
$mustBelong,
|
||||||
|
$preferPrimary
|
||||||
|
); // B 方案(按场景)
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -553,10 +581,6 @@ class ApprovalFlowService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 聚合本步骤结论(按类型)
|
* 聚合本步骤结论(按类型)
|
||||||
* 返回:'pending' | 'approve' | 'reject'
|
|
||||||
*
|
|
||||||
* any:有 reject => reject;否则有 approve => approve;否则 pending
|
|
||||||
* all:有 reject => reject;有 pending => pending;否则(全 approved 或 approved+skipped/timeout)=> approve
|
|
||||||
*/
|
*/
|
||||||
private function getStepOutcome(int $instanceId, int $round, int $stepIndex, string $type): string
|
private function getStepOutcome(int $instanceId, int $round, int $stepIndex, string $type): string
|
||||||
{
|
{
|
||||||
@@ -566,22 +590,28 @@ class ApprovalFlowService
|
|||||||
->where('step_index', $stepIndex)
|
->where('step_index', $stepIndex)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$pending = 0; $approved = 0; $rejected = 0;
|
$pending = $approved = $rejected = $timeout = $skipped = 0;
|
||||||
foreach ($records as $r) {
|
foreach ($records as $r) {
|
||||||
if ($r->status === 'pending') $pending++;
|
switch ($r->status) {
|
||||||
elseif ($r->status === 'approved') $approved++;
|
case 'pending': $pending++; break;
|
||||||
elseif ($r->status === 'rejected') $rejected++;
|
case 'approved': $approved++; break;
|
||||||
|
case 'rejected': $rejected++; break;
|
||||||
|
case 'timeout': $timeout++; break;
|
||||||
|
case 'skipped': $skipped++; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = strtolower($type);
|
$type = strtolower($type);
|
||||||
if ($type === 'any') {
|
if ($type === 'any') {
|
||||||
if ($rejected > 0) return 'reject';
|
if ($rejected > 0) return 'reject';
|
||||||
if ($approved > 0) return 'approve';
|
if ($approved > 0) return 'approve';
|
||||||
|
// 全为 skipped/timeout 且无 pending/rejected ⇒ 通过
|
||||||
|
if ($pending === 0 && $rejected === 0 && $approved === 0) return 'approve';
|
||||||
return 'pending';
|
return 'pending';
|
||||||
}
|
}
|
||||||
if ($rejected > 0) return 'reject';
|
if ($rejected > 0) return 'reject';
|
||||||
if ($pending > 0) return 'pending';
|
if ($pending > 0) return 'pending';
|
||||||
return $approved > 0 ? 'approve' : 'pending';
|
return 'approve';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭本步其余待办为 skipped */
|
/** 关闭本步其余待办为 skipped */
|
||||||
@@ -637,6 +667,7 @@ class ApprovalFlowService
|
|||||||
'approve' => '已通过',
|
'approve' => '已通过',
|
||||||
'reject' => '已拒绝',
|
'reject' => '已拒绝',
|
||||||
'revoked' => '已撤回',
|
'revoked' => '已撤回',
|
||||||
|
'voided' => '已作废',
|
||||||
];
|
];
|
||||||
$prefix = $isCC ? '【抄送】' : '【审批】';
|
$prefix = $isCC ? '【抄送】' : '【审批】';
|
||||||
$text = $map[$action] ?? $action;
|
$text = $map[$action] ?? $action;
|
||||||
@@ -644,6 +675,10 @@ class ApprovalFlowService
|
|||||||
// 业务标题/内容
|
// 业务标题/内容
|
||||||
$approvalType = array_flip(\app\common\service\SysDictService::pluckKeyValueByCode('approval_type'));
|
$approvalType = array_flip(\app\common\service\SysDictService::pluckKeyValueByCode('approval_type'));
|
||||||
|
|
||||||
|
$flowTxt = $approvalType[$instance->flow_type] ?? (string)$instance->flow_type;
|
||||||
|
$title = $prefix.'审批通知';
|
||||||
|
$content = "{$prefix}你有一条审批 {$text}:类型 {$flowTxt},业务标识 {$instance->biz_id}";
|
||||||
|
|
||||||
switch ($instance->flow_type) {
|
switch ($instance->flow_type) {
|
||||||
case 'stock_orders':
|
case 'stock_orders':
|
||||||
// 备货单
|
// 备货单
|
||||||
@@ -1589,6 +1624,7 @@ class ApprovalFlowService
|
|||||||
->where('status', 'approved')
|
->where('status', 'approved')
|
||||||
->orderByDesc('id')
|
->orderByDesc('id')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$latestApproved) {
|
if (!$latestApproved) {
|
||||||
throw new BusinessException('仅已通过的单据可发起作废');
|
throw new BusinessException('仅已通过的单据可发起作废');
|
||||||
}
|
}
|
||||||
@@ -1603,6 +1639,26 @@ class ApprovalFlowService
|
|||||||
throw new BusinessException('已存在进行中的作废审批');
|
throw new BusinessException('已存在进行中的作废审批');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A. 基于历史“作废流程已通过”的实例拦截
|
||||||
|
$voidApproved = Db::table('approval_instances')
|
||||||
|
->where('flow_type', $voidFlowType)
|
||||||
|
->where('biz_id', $bizId)
|
||||||
|
->whereIn('status', ['approved','voided'])
|
||||||
|
->exists();
|
||||||
|
if ($voidApproved) {
|
||||||
|
throw new BusinessException('该单据已作废,无需重复作废');
|
||||||
|
}
|
||||||
|
|
||||||
|
// B.(可选)直接查业务表状态拦截(若你用 approval_status=4 表示已作废)
|
||||||
|
/*
|
||||||
|
$orderVoided = \app\common\model\StockOrders::where('id', $bizId)
|
||||||
|
->where('approval_status', 4)
|
||||||
|
->exists();
|
||||||
|
if ($orderVoided) {
|
||||||
|
throw new BusinessException('该单据已作废,无需重复作废');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// 4) 计算首步
|
// 4) 计算首步
|
||||||
// 注:作废流程可以有独立条件;若不需要条件,直接第一步
|
// 注:作废流程可以有独立条件;若不需要条件,直接第一步
|
||||||
$formData = array_merge([
|
$formData = array_merge([
|
||||||
@@ -1735,4 +1791,23 @@ class ApprovalFlowService
|
|||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
private function isNullifyFlow(string $flowType): bool
|
||||||
|
{
|
||||||
|
$t = strtolower(trim($flowType));
|
||||||
|
return str_ends_with($t, '_nullify') || in_array($t, [
|
||||||
|
// 所有“作废”类流程的类型
|
||||||
|
'stock_orders_nullify',
|
||||||
|
], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 放到工具方法区
|
||||||
|
private function normalizeFinalStatus(string $flowType, string $final): string
|
||||||
|
{
|
||||||
|
if ($this->isNullifyFlow($flowType) && $final === 'approved') {
|
||||||
|
return 'voided';
|
||||||
|
}
|
||||||
|
return $final;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ class StockOrdersController extends BaseController
|
|||||||
if (isset($data['id'])) {
|
if (isset($data['id'])) {
|
||||||
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
||||||
$appro = $appro->getBriefStatusByBiz($data['id'], null, 'name');
|
$appro = $appro->getBriefStatusByBiz($data['id'], null, 'name');
|
||||||
$map = ['processing'=>'审批中','pending'=>'审批中','approved'=>'已通过','rejected'=>'已拒绝','revoked'=>'已撤回'];
|
$map = ['processing'=>'审批中','pending'=>'审批中','approved'=>'已通过','rejected'=>'已拒绝','revoked'=>'已撤回','voided'=>'已作废'];
|
||||||
if ($appro) {
|
if ($appro) {
|
||||||
$data['appro_status'] = [
|
$data['appro_status'] = [
|
||||||
'status' => $appro['status'],
|
'status' => $appro['status'],
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ return [
|
|||||||
'gateway' => [
|
'gateway' => [
|
||||||
'handler' => Gateway::class,
|
'handler' => Gateway::class,
|
||||||
'listen' => 'websocket://0.0.0.0:' . getenv('GATEWAY_LISTEN'),
|
'listen' => 'websocket://0.0.0.0:' . getenv('GATEWAY_LISTEN'),
|
||||||
'count' => 2,
|
'count' => 3,
|
||||||
'reloadable' => false,
|
'reloadable' => false,
|
||||||
'constructor' => ['config' => [
|
'constructor' => ['config' => [
|
||||||
'lanIp' => '127.0.0.1',
|
'lanIp' => '127.0.0.1',
|
||||||
@@ -22,7 +22,7 @@ return [
|
|||||||
],
|
],
|
||||||
'worker' => [
|
'worker' => [
|
||||||
'handler' => BusinessWorker::class,
|
'handler' => BusinessWorker::class,
|
||||||
'count' => 6,
|
'count' => 2,
|
||||||
'constructor' => ['config' => [
|
'constructor' => ['config' => [
|
||||||
'eventHandler' => plugin\webman\gateway\Events::class,
|
'eventHandler' => plugin\webman\gateway\Events::class,
|
||||||
'name' => 'ChatBusinessWorker',
|
'name' => 'ChatBusinessWorker',
|
||||||
|
|||||||
+4
-1
@@ -330,6 +330,7 @@ Route::group('/admin', function () {
|
|||||||
Route::any('/store', [app\admin\controller\StockOrdersController::class, 'store']);
|
Route::any('/store', [app\admin\controller\StockOrdersController::class, 'store']);
|
||||||
Route::any('/print', [app\admin\controller\StockOrdersController::class, 'print']);
|
Route::any('/print', [app\admin\controller\StockOrdersController::class, 'print']);
|
||||||
Route::any('/detail', [app\admin\controller\StockOrdersController::class, 'detail']);
|
Route::any('/detail', [app\admin\controller\StockOrdersController::class, 'detail']);
|
||||||
|
Route::any('/destroy', [app\admin\controller\StockOrdersController::class, 'destroy']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// crm
|
// crm
|
||||||
@@ -440,7 +441,7 @@ Route::group('/crm', function () {
|
|||||||
Route::any('/user/edit', [app\common\controller\UserController::class, 'edit']);
|
Route::any('/user/edit', [app\common\controller\UserController::class, 'edit']);
|
||||||
Route::any('/user/savePassword', [app\common\controller\UserController::class, 'savePassword']);
|
Route::any('/user/savePassword', [app\common\controller\UserController::class, 'savePassword']);
|
||||||
|
|
||||||
// 基础信息
|
// 备货单
|
||||||
Route::group('/stock/order', function () {
|
Route::group('/stock/order', function () {
|
||||||
Route::any('/list', [app\crm\controller\StockOrdersController::class, 'index']);
|
Route::any('/list', [app\crm\controller\StockOrdersController::class, 'index']);
|
||||||
Route::any('/show', [app\crm\controller\StockOrdersController::class, 'show']);
|
Route::any('/show', [app\crm\controller\StockOrdersController::class, 'show']);
|
||||||
@@ -452,6 +453,7 @@ Route::group('/crm', function () {
|
|||||||
Route::any('/ultimate/approval', [app\crm\controller\StockOrdersController::class, 'ultimateApproval']);
|
Route::any('/ultimate/approval', [app\crm\controller\StockOrdersController::class, 'ultimateApproval']);
|
||||||
Route::any('/nullify/approval', [app\crm\controller\StockOrdersController::class, 'approvalNullify']);
|
Route::any('/nullify/approval', [app\crm\controller\StockOrdersController::class, 'approvalNullify']);
|
||||||
Route::any('/revoke/approval', [app\crm\controller\StockOrdersController::class, 'approvalRevoke']);
|
Route::any('/revoke/approval', [app\crm\controller\StockOrdersController::class, 'approvalRevoke']);
|
||||||
|
Route::any('/destroy', [app\crm\controller\StockOrdersController::class, 'destroy']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 审批记录
|
// 审批记录
|
||||||
@@ -461,6 +463,7 @@ Route::group('/crm', function () {
|
|||||||
Route::any('/action', [app\crm\controller\ApprovalRecordsController::class, 'approve']);
|
Route::any('/action', [app\crm\controller\ApprovalRecordsController::class, 'approve']);
|
||||||
|
|
||||||
Route::any('/todo', [app\admin\controller\ApprovalRecordsController::class, 'todo']);
|
Route::any('/todo', [app\admin\controller\ApprovalRecordsController::class, 'todo']);
|
||||||
|
Route::any('/border', [app\admin\controller\ApprovalRecordsController::class, 'businessOrder']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 汽车颜色
|
// 汽车颜色
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class Events
|
|||||||
|
|
||||||
public static function onClose($client_id)
|
public static function onClose($client_id)
|
||||||
{
|
{
|
||||||
|
self::$wsEvents->logout($client_id);
|
||||||
var_dump('关闭客户端ID:'.$client_id);
|
var_dump('关闭客户端ID:'.$client_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user