增加审批时间轴&&调整采购单
This commit is contained in:
@@ -169,4 +169,33 @@ class ApprovalRecordsController extends BaseController
|
|||||||
return $this->error($e->getMessage());
|
return $this->error($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function approvalTimeline(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$raw = $this->service->serviceApprovalTimeline($request, $request->all());
|
||||||
|
$data = $this->transformData($raw, method_exists($this, 'timelineFormat')
|
||||||
|
? [$this, 'timelineFormat']
|
||||||
|
: null);
|
||||||
|
return $this->success($data);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function timelineFormat($data)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
foreach ($data as $record) {
|
||||||
|
$result[] = [
|
||||||
|
'id' => $record['id'],
|
||||||
|
'name' => $record['approver']['name'],
|
||||||
|
'comment' => $record['comment'],
|
||||||
|
'time' => $record['updated_at']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -43,6 +43,7 @@ class PurchaseOrdersController extends BaseController
|
|||||||
'contract_file' => $contractFile,
|
'contract_file' => $contractFile,
|
||||||
'contract_file_url' => $contractFileUrl,
|
'contract_file_url' => $contractFileUrl,
|
||||||
'status' => $record['status'],
|
'status' => $record['status'],
|
||||||
|
'status_text' => array_flip(\app\common\service\SysDictService::pluckKeyValueByCode('purchase_status'))[$record['status']],
|
||||||
'remark' => $record['remark'],
|
'remark' => $record['remark'],
|
||||||
'created_at' => date('Y-m-d H:i:s', $record['created_at']),
|
'created_at' => date('Y-m-d H:i:s', $record['created_at']),
|
||||||
'updated_at' => date('Y-m-d H:i:s', $record['updated_at']),
|
'updated_at' => date('Y-m-d H:i:s', $record['updated_at']),
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class PurchaseOrders extends Model
|
|||||||
/**
|
/**
|
||||||
* 允许自动填充模型字段
|
* 允许自动填充模型字段
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['id', 'order_no', 'pi_no', 'buyer_id', 'buyer_name', 'contract_file', 'status', 'remark', 'created_at', 'updated_at'];
|
protected $fillable = ['id', 'order_no', 'pi_no', 'buyer_id', 'buyer_name', 'contract_file', 'status', 'remark', 'is_draft', 'created_at', 'updated_at'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 不允许自动填充模型字段
|
* 不允许自动填充模型字段
|
||||||
|
|||||||
@@ -103,14 +103,7 @@ class ApprovalRecordsService
|
|||||||
'approver',
|
'approver',
|
||||||
'instance.flows',
|
'instance.flows',
|
||||||
'instance.initiator',
|
'instance.initiator',
|
||||||
'instance.bizInfo',
|
'instance.bizInfo'
|
||||||
|
|
||||||
// 'instance.bizInfo.items',
|
|
||||||
// 'instance.bizInfo.items.options',
|
|
||||||
// 'instance.bizInfo.items.moneyValues',
|
|
||||||
// 'instance.bizInfo.accounts',
|
|
||||||
// 'instance.bizInfo.moneyValues',
|
|
||||||
// 'instance.bizInfo.salesperson',
|
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -178,4 +171,12 @@ class ApprovalRecordsService
|
|||||||
$result = $service->transferApproval($data['instance_id'], $data['step_index'], $request->user->uid, $data['to_uid'], $data['reason'], 'name');
|
$result = $service->transferApproval($data['instance_id'], $data['step_index'], $request->user->uid, $data['to_uid'], $data['reason'], 'name');
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function serviceApprovalTimeline(Request $request, array $data = [])
|
||||||
|
{
|
||||||
|
$instance = \app\common\model\ApprovalInstances::where('biz_id', $data['id'])->where('flow_type', $data['flow_type'])->first();
|
||||||
|
$result = \app\common\model\ApprovalRecords::where('instance_id', $instance->id)->with('approver')->orderBy('id', 'desc')->get();
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,9 @@ class PurchaseOrdersService
|
|||||||
$data['order_no'] = generateStockNo('CG');
|
$data['order_no'] = generateStockNo('CG');
|
||||||
$data['buyer_id'] = $request->user->uid;
|
$data['buyer_id'] = $request->user->uid;
|
||||||
$data['buyer_name'] = User::where('id', $request->user->uid)->value('name');
|
$data['buyer_name'] = User::where('id', $request->user->uid)->value('name');
|
||||||
|
if ($data['is_draft'] == 0) {
|
||||||
|
$data['status'] = 1;
|
||||||
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,52 +105,6 @@ class PurchaseOrdersService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新采购单
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param array $data
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function serviceUpdate(Request $request, array $data = [], string $scene = 'update')
|
|
||||||
{
|
|
||||||
// 使用事务确保数据一致性
|
|
||||||
return Db::transaction(function () use ($request, $data, $scene) {
|
|
||||||
$data = $this->preProcess(ucfirst($scene), $data, $request);
|
|
||||||
|
|
||||||
// 构建查询条件
|
|
||||||
$config = $this->buildQueryConfig($request, $scene);
|
|
||||||
|
|
||||||
// 更新主表信息
|
|
||||||
$udata = $data;
|
|
||||||
unset($udata['stock_order']);
|
|
||||||
$updated = $this->logicUpdateBy($config, $udata);
|
|
||||||
|
|
||||||
// 获取更新后的数据
|
|
||||||
$order = $this->logicShow($config);
|
|
||||||
|
|
||||||
// 更新采购单明细
|
|
||||||
if (isset($data['stock_order'])) {
|
|
||||||
// 先删除原有的明细
|
|
||||||
PurchaseOrderItems::where('purchase_order_id', $order->id)->delete();
|
|
||||||
|
|
||||||
// 重新创建明细
|
|
||||||
foreach ($data['stock_order'] as $orderData) {
|
|
||||||
foreach ($orderData['stock_items'] as $item) {
|
|
||||||
PurchaseOrderItems::create([
|
|
||||||
'purchase_order_id' => $order->id,
|
|
||||||
'stock_id' => $orderData['stock_orders_id'],
|
|
||||||
'stock_items_id' => $item['stock_order_items_id'],
|
|
||||||
'stock_items_uqid' => $item['unique_id'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->postProcess(ucfirst($scene), $order, ['is_resubmit'=>$data['is_resubmit']]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建查询配置
|
* 构建查询配置
|
||||||
*
|
*
|
||||||
@@ -213,7 +170,7 @@ class PurchaseOrdersService
|
|||||||
*/
|
*/
|
||||||
protected function afterServiceStore($res)
|
protected function afterServiceStore($res)
|
||||||
{
|
{
|
||||||
if ($res->status == 1) {
|
if ($res->is_draft == 0) {
|
||||||
$this->startApproval($res, ['resubmitted'=>0]);
|
$this->startApproval($res, ['resubmitted'=>0]);
|
||||||
}
|
}
|
||||||
return $res;
|
return $res;
|
||||||
@@ -225,6 +182,69 @@ class PurchaseOrdersService
|
|||||||
$appro->start('purchase_orders', 'purchase_orders', $item->id, ['resubmitted'=>0], $item->buyer_id);
|
$appro->start('purchase_orders', 'purchase_orders', $item->id, ['resubmitted'=>0], $item->buyer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function beforeServiceUpdate(array $data, Request $request)
|
||||||
|
{
|
||||||
|
if ($data['is_draft'] == 0) {
|
||||||
|
$data['status'] = 1;
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新采购单
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param array $data
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function serviceUpdate(Request $request, array $data = [], string $scene = 'update')
|
||||||
|
{
|
||||||
|
// 使用事务确保数据一致性
|
||||||
|
return Db::transaction(function () use ($request, $data, $scene) {
|
||||||
|
$data = $this->preProcess(ucfirst($scene), $data, $request);
|
||||||
|
|
||||||
|
// 构建查询条件
|
||||||
|
$config = $this->buildQueryConfig($request, $scene);
|
||||||
|
|
||||||
|
// 更新主表信息
|
||||||
|
$udata = $data;
|
||||||
|
unset($udata['stock_order']);
|
||||||
|
unset($udata['is_resubmit']);
|
||||||
|
unset($udata['approval_desc']);
|
||||||
|
$this->logicUpdateBy($config, $udata);
|
||||||
|
|
||||||
|
// 获取更新后的数据
|
||||||
|
$order = $this->logicShow($config);
|
||||||
|
|
||||||
|
// 更新采购单明细
|
||||||
|
if (isset($data['stock_order'])) {
|
||||||
|
// 先删除原有的明细
|
||||||
|
PurchaseOrderItems::where('purchase_order_id', $order->id)->delete();
|
||||||
|
|
||||||
|
// 重新创建明细
|
||||||
|
foreach ($data['stock_order'] as $orderData) {
|
||||||
|
foreach ($orderData['stock_items'] as $item) {
|
||||||
|
PurchaseOrderItems::create([
|
||||||
|
'purchase_order_id' => $order->id,
|
||||||
|
'stock_id' => $orderData['stock_orders_id'],
|
||||||
|
'stock_items_id' => $item['stock_order_items_id'],
|
||||||
|
'stock_items_uqid' => $item['unique_id'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->postProcess(
|
||||||
|
ucfirst($scene),
|
||||||
|
$order,
|
||||||
|
[
|
||||||
|
'is_resubmit'=>$data['is_resubmit'],
|
||||||
|
'approval_desc'=>$data['approval_desc']
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected function afterServiceUpdate($res, $data)
|
protected function afterServiceUpdate($res, $data)
|
||||||
{
|
{
|
||||||
if ($data['is_resubmit'] == 0 && $res->status == 1) {
|
if ($data['is_resubmit'] == 0 && $res->status == 1) {
|
||||||
@@ -238,10 +258,10 @@ class PurchaseOrdersService
|
|||||||
// 审批服务
|
// 审批服务
|
||||||
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
$appro = new \app\common\utils\approval\service\ApprovalFlowService();
|
||||||
// 重新提交
|
// 重新提交
|
||||||
$appro->resubmit($instance->id, $instance->initiator_id, ['resubmitted'=>1], $data['remark']);
|
$appro->resubmit($instance->id, $instance->initiator_id, ['resubmitted'=>1], $data['approval_desc']);
|
||||||
// 添加到讨论
|
// 添加到讨论
|
||||||
if (!empty($data['remark'])) {
|
if (!empty($data['approval_desc'])) {
|
||||||
$appro->postDiscussion($instance->id, $instance->initiator_id, $data['remark'], false, [], 'name');
|
$appro->postDiscussion($instance->id, $instance->initiator_id, $data['approval_desc'], false, [], 'name');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $res;
|
return $res;
|
||||||
|
|||||||
@@ -808,7 +808,7 @@ class ApprovalFlowService
|
|||||||
* initiator_name?:?string
|
* initiator_name?:?string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
public function getSimpleTimeline(int $instanceId, ?string $userNameColumn = null, string $initiatorPlacement = 'prepend'): array
|
public function getSimpleTimeline2(int $instanceId, ?string $userNameColumn = null, string $initiatorPlacement = 'prepend'): array
|
||||||
{
|
{
|
||||||
// 基础数据
|
// 基础数据
|
||||||
$instance = Db::table('approval_instances')->where('id', $instanceId)->first();
|
$instance = Db::table('approval_instances')->where('id', $instanceId)->first();
|
||||||
@@ -958,6 +958,193 @@ class ApprovalFlowService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getSimpleTimeline(int $instanceId, ?string $userNameColumn = null, string $initiatorPlacement = 'prepend'): array
|
||||||
|
{
|
||||||
|
// 基础数据
|
||||||
|
$instance = Db::table('approval_instances')->where('id', $instanceId)->first();
|
||||||
|
if (!$instance) throw new BusinessException('审批实例未找到');
|
||||||
|
|
||||||
|
$flow = Db::table('approval_flows')->where('type', $instance->flow_type)->first();
|
||||||
|
if (!$flow) throw new BusinessException('审批流程定义未找到');
|
||||||
|
|
||||||
|
$steps = json_decode($flow->steps, true) ?: [];
|
||||||
|
$formData = json_decode($instance->form_data ?? '{}', true) ?: [];
|
||||||
|
$curStep = (int)$instance->current_step;
|
||||||
|
$round = (int)$instance->round;
|
||||||
|
|
||||||
|
// 申请人
|
||||||
|
$initiatorId = (int)$instance->initiator_id;
|
||||||
|
$initiatorName = null;
|
||||||
|
if ($userNameColumn) {
|
||||||
|
$initiatorName = Db::table('user')->where('id', $initiatorId)->value($userNameColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 审批记录(仅当前轮次)
|
||||||
|
$records = Db::table('approval_records as ar')
|
||||||
|
->where('ar.instance_id', $instanceId)
|
||||||
|
->where('ar.round', $round)
|
||||||
|
->orderBy('ar.step_index')
|
||||||
|
->orderByRaw('COALESCE(ar.approved_at, ar.created_at) asc')
|
||||||
|
->select('ar.*')
|
||||||
|
->get()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 一次性拉取姓名,避免 N+1
|
||||||
|
$nameMap = [];
|
||||||
|
if ($userNameColumn && !empty($records)) {
|
||||||
|
$uids = [];
|
||||||
|
foreach ($records as $r) $uids[] = (int)$r->approver_id;
|
||||||
|
$uids = array_values(array_unique($uids));
|
||||||
|
if (!empty($uids)) {
|
||||||
|
$pairs = Db::table('user')->whereIn('id', $uids)->pluck($userNameColumn, 'id')->toArray();
|
||||||
|
foreach ($pairs as $uid => $name) $nameMap[(int)$uid] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录分组
|
||||||
|
$byStep = [];
|
||||||
|
foreach ($records as $r) {
|
||||||
|
$idx = (int)$r->step_index;
|
||||||
|
$byStep[$idx][] = $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
$timeline = [];
|
||||||
|
|
||||||
|
// 可选:发起申请块
|
||||||
|
if ($initiatorPlacement === 'prepend') {
|
||||||
|
$appliedAt = $instance->created_at ?: null;
|
||||||
|
$timeline[] = [
|
||||||
|
'index' => -1,
|
||||||
|
'name' => '发起申请',
|
||||||
|
'type' => '-',
|
||||||
|
'status' => 'submitted',
|
||||||
|
'started_at' => $appliedAt,
|
||||||
|
'finished_at' => $appliedAt,
|
||||||
|
'duration_seconds' => 0,
|
||||||
|
'initiator_id' => $initiatorId,
|
||||||
|
'initiator_name' => $initiatorName,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每一步
|
||||||
|
foreach ($steps as $i => $meta) {
|
||||||
|
$name = $meta['name'] ?? ('Step '.$i);
|
||||||
|
$typeRaw = strtolower($meta['type'] ?? 'all');
|
||||||
|
$type = in_array($typeRaw, ['any','all']) ? $typeRaw : 'all';
|
||||||
|
$condStr = $meta['condition'] ?? null;
|
||||||
|
$condOk = $condStr ? $this->evaluateCondition($condStr, $formData) : true;
|
||||||
|
|
||||||
|
$recs = $byStep[$i] ?? [];
|
||||||
|
$hasRecs = !empty($recs);
|
||||||
|
|
||||||
|
$status = 'pending';
|
||||||
|
$startedAt = null;
|
||||||
|
$finishedAt = null;
|
||||||
|
$durationSec = null;
|
||||||
|
|
||||||
|
// ★ 每一步的“审批意见”(只展示有内容的 comment)
|
||||||
|
$opinions = []; // [{approver_id, approver_name?, action, status, comment, time}...]
|
||||||
|
|
||||||
|
if ($hasRecs) {
|
||||||
|
// 统计时间
|
||||||
|
$minCreated = null;
|
||||||
|
$minApproveAt = null; $maxApproveAt = null;
|
||||||
|
$minRejectAt = null;
|
||||||
|
$maxTimeoutAt = null;
|
||||||
|
$cnt = ['pending'=>0,'approved'=>0,'rejected'=>0,'timeout'=>0];
|
||||||
|
|
||||||
|
foreach ($recs as $rr) {
|
||||||
|
// 收集“审批意见”(非空 comment 都算)
|
||||||
|
$cmt = trim((string)($rr->comment ?? ''));
|
||||||
|
if ($cmt !== '') {
|
||||||
|
$opinions[] = [
|
||||||
|
'approver_id' => (int)$rr->approver_id,
|
||||||
|
'approver_name' => $userNameColumn ? ($nameMap[(int)$rr->approver_id] ?? null) : null,
|
||||||
|
'action' => $rr->action, // approve | reject | null
|
||||||
|
'status' => $rr->status, // approved|rejected|pending|skipped|timeout
|
||||||
|
'comment' => $cmt,
|
||||||
|
'time' => $rr->approved_at ?: $rr->created_at,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rr->created_at && (!$minCreated || $rr->created_at < $minCreated)) $minCreated = $rr->created_at;
|
||||||
|
if ($rr->approved_at) {
|
||||||
|
if ($rr->status === 'approved') {
|
||||||
|
if (!$minApproveAt || $rr->approved_at < $minApproveAt) $minApproveAt = $rr->approved_at;
|
||||||
|
if (!$maxApproveAt || $rr->approved_at > $maxApproveAt) $maxApproveAt = $rr->approved_at;
|
||||||
|
} elseif ($rr->status === 'rejected') {
|
||||||
|
if (!$minRejectAt || $rr->approved_at < $minRejectAt) $minRejectAt = $rr->approved_at;
|
||||||
|
} elseif ($rr->status === 'timeout') {
|
||||||
|
if (!$maxTimeoutAt || $rr->approved_at > $maxTimeoutAt) $maxTimeoutAt = $rr->approved_at;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($cnt[$rr->status])) $cnt[$rr->status]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间升序排序 opinions
|
||||||
|
if (!empty($opinions)) {
|
||||||
|
usort($opinions, function($a, $b) {
|
||||||
|
return strcmp($a['time'] ?? '', $b['time'] ?? '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$startedAt = $minCreated;
|
||||||
|
|
||||||
|
// 总结果(注意:这里按你现在的签名调用,含 round)
|
||||||
|
$outcome = $this->getStepOutcome($instanceId, $round, $i, $type); // 'pending'|'approve'|'reject'
|
||||||
|
if ($outcome === 'reject') {
|
||||||
|
$status = 'rejected';
|
||||||
|
$finishedAt = $minRejectAt;
|
||||||
|
} elseif ($outcome === 'approve') {
|
||||||
|
$status = 'approved';
|
||||||
|
$finishedAt = ($type === 'any') ? $minApproveAt : $maxApproveAt;
|
||||||
|
} else {
|
||||||
|
if ($cnt['timeout'] > 0 && $cnt['approved'] === 0 && $cnt['rejected'] === 0 && $cnt['pending'] === 0) {
|
||||||
|
$status = 'timeout';
|
||||||
|
$finishedAt = $maxTimeoutAt;
|
||||||
|
} else {
|
||||||
|
$status = 'processing';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($startedAt && $finishedAt) {
|
||||||
|
$durationSec = max(0, strtotime($finishedAt) - strtotime($startedAt));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 无记录:根据位置与条件展示
|
||||||
|
if ($i < $curStep) {
|
||||||
|
$status = $condOk ? 'approved' : 'skipped';
|
||||||
|
} elseif ($i === $curStep && $instance->status === 'processing') {
|
||||||
|
$status = 'processing';
|
||||||
|
} else {
|
||||||
|
$status = $condOk ? 'pending' : 'skipped';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = [
|
||||||
|
'index' => (int)$i,
|
||||||
|
'name' => $name,
|
||||||
|
'type' => $type,
|
||||||
|
'status' => $status,
|
||||||
|
'started_at' => $startedAt,
|
||||||
|
'finished_at' => $finishedAt,
|
||||||
|
'duration_seconds' => $durationSec,
|
||||||
|
'opinions' => $opinions, // ★ 这就是每个审批意见
|
||||||
|
];
|
||||||
|
|
||||||
|
// 把申请人信息并到第一步(可选)
|
||||||
|
if ($initiatorPlacement === 'attach' && empty($timeline)) {
|
||||||
|
$row['initiator_id'] = $initiatorId;
|
||||||
|
$row['initiator_name'] = $initiatorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
$timeline[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按业务ID获取“最新进展”的极简状态
|
* 按业务ID获取“最新进展”的极简状态
|
||||||
* - 已完结:直接返回实例最终状态
|
* - 已完结:直接返回实例最终状态
|
||||||
|
|||||||
@@ -319,6 +319,7 @@ Route::group('/admin', function () {
|
|||||||
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']);
|
Route::any('/border', [app\admin\controller\ApprovalRecordsController::class, 'businessOrder']);
|
||||||
Route::any('/transfer', [app\admin\controller\ApprovalRecordsController::class, 'transferApproval']);
|
Route::any('/transfer', [app\admin\controller\ApprovalRecordsController::class, 'transferApproval']);
|
||||||
|
Route::any('/timeline', [app\admin\controller\ApprovalRecordsController::class, 'approvalTimeline']);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group('/stock/order', function () {
|
Route::group('/stock/order', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user