|
|
@@ -746,6 +746,19 @@ class Procuremen extends Backend
|
|
|
->whereRaw('(status_name IS NULL OR TRIM(status_name) = \'\' OR status_name <> \'' . ProcuremenStatus::POD_VOID . '\')');
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @param array<string, mixed> $detailRow
|
|
|
+ */
|
|
|
+ protected function isActivePurchaseOrderDetailRow(array $detailRow): bool
|
|
|
+ {
|
|
|
+ if (ProcuremenStatus::isPodVoid($detailRow['status'] ?? '')) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ $statusName = trim((string)($detailRow['status_name'] ?? ''));
|
|
|
+
|
|
|
+ return $statusName === '' || $statusName !== ProcuremenStatus::POD_VOID;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 废弃退回初选:下发明细标记归档,不物理删除
|
|
|
*
|
|
|
@@ -1278,7 +1291,7 @@ class Procuremen extends Backend
|
|
|
ProcuremenStatus::wflowPendingApprovalValues()
|
|
|
))
|
|
|
->whereOr(function ($q1) {
|
|
|
- $q1->whereIn('status', ProcuremenStatus::poCompletedValues());
|
|
|
+ $q1->whereRaw(ProcuremenStatus::sqlPoCompleted('status'));
|
|
|
})
|
|
|
->whereOr(function ($q2) {
|
|
|
$q2->whereNotNull('pick_time')
|
|
|
@@ -1494,6 +1507,69 @@ class Procuremen extends Backend
|
|
|
];
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 初选行对应的 purchase_order 与是否应从初选列表隐藏
|
|
|
+ *
|
|
|
+ * @return array{po:?array<string,mixed>, hidden:bool}
|
|
|
+ */
|
|
|
+ protected function resolvePickRowPoContext(int $sid): array
|
|
|
+ {
|
|
|
+ $po = null;
|
|
|
+ try {
|
|
|
+ $found = Db::table('purchase_order')->where('scydgy_id', $sid)->find();
|
|
|
+ if (is_array($found)) {
|
|
|
+ $po = $found;
|
|
|
+ }
|
|
|
+ } catch (\Throwable $e) {
|
|
|
+ }
|
|
|
+ $hideSet = $this->loadPickHiddenScydgySet();
|
|
|
+
|
|
|
+ return ['po' => $po, 'hidden' => isset($hideSet[$sid])];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初选删除前校验(已删除幂等跳过;已下发/已完结禁止)
|
|
|
+ */
|
|
|
+ protected function assertPickRowCanDelete(int $sid, array $row): void
|
|
|
+ {
|
|
|
+ $ctx = $this->resolvePickRowPoContext($sid);
|
|
|
+ $po = $ctx['po'];
|
|
|
+ if (is_array($po) && $this->isPurchaseOrderSoftDeleted($po['mod_rq'] ?? null)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (is_array($po)) {
|
|
|
+ if (ProcuremenStatus::isPoCompleted($po['status'] ?? '')) {
|
|
|
+ throw new \InvalidArgumentException('该工序已完结,无法删除');
|
|
|
+ }
|
|
|
+ if (ProcuremenStatus::wflowAtLeastConfirm($po['wflow_status'] ?? '')) {
|
|
|
+ throw new \InvalidArgumentException('该工序已下发或进入后续流程,无法删除');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($ctx['hidden']) {
|
|
|
+ $ccydh = trim((string)($row['CCYDH'] ?? ''));
|
|
|
+ $label = $ccydh !== '' ? $ccydh : ('工序' . $sid);
|
|
|
+ throw new \InvalidArgumentException('订单号「' . $label . '」已下发或已进入后续流程,无法删除');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初选直接完结前校验
|
|
|
+ */
|
|
|
+ protected function assertPickRowCanComplete(int $sid, array $row): void
|
|
|
+ {
|
|
|
+ $ctx = $this->resolvePickRowPoContext($sid);
|
|
|
+ $po = $ctx['po'];
|
|
|
+ if (is_array($po) && ProcuremenStatus::isPoCompleted($po['status'] ?? '')) {
|
|
|
+ throw new \Exception($this->formatProcuremenRowLabel($row) . '已完结,无需重复操作');
|
|
|
+ }
|
|
|
+ if (is_array($po) && $this->isPurchaseOrderSoftDeleted($po['mod_rq'] ?? null)) {
|
|
|
+ throw new \Exception($this->formatProcuremenRowLabel($row) . '已删除,无法完结');
|
|
|
+ }
|
|
|
+ if ($ctx['hidden'] || (is_array($po) && ProcuremenStatus::wflowAtLeastConfirm($po['wflow_status'] ?? ''))) {
|
|
|
+ throw new \Exception($this->formatProcuremenRowLabel($row) . '已下发或进入后续流程,不能直接完结');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 协助初选列表软删除(mod_rq 记删除时间;ERP 行无记录则插入 purchase_order)
|
|
|
*/
|
|
|
@@ -1503,25 +1579,13 @@ class Procuremen extends Backend
|
|
|
if (!$this->isValidScydgyRowId($sid)) {
|
|
|
throw new \InvalidArgumentException('无效的行主键');
|
|
|
}
|
|
|
- $hideSet = $this->loadPickHiddenScydgySet();
|
|
|
- if ($sid > 0 && isset($hideSet[$sid])) {
|
|
|
- throw new \InvalidArgumentException('订单号「' . trim((string)($row['CCYDH'] ?? '')) . '」已下发或已进入后续流程,无法删除');
|
|
|
+ $this->assertPickRowCanDelete($sid, $row);
|
|
|
+ $po = $this->resolvePickRowPoContext($sid)['po'];
|
|
|
+ if (is_array($po) && $this->isPurchaseOrderSoftDeleted($po['mod_rq'] ?? null)) {
|
|
|
+ return;
|
|
|
}
|
|
|
- if ($sid < 0) {
|
|
|
- try {
|
|
|
- $po = Db::table('purchase_order')->where('scydgy_id', $sid)->find();
|
|
|
- if (is_array($po)) {
|
|
|
- if (ProcuremenStatus::wflowAtLeastConfirm($po['wflow_status'] ?? '')) {
|
|
|
- throw new \InvalidArgumentException('手工新增工序已下发,无法删除');
|
|
|
- }
|
|
|
- if ($this->isPurchaseOrderSoftDeleted($po['mod_rq'] ?? null)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (\InvalidArgumentException $e) {
|
|
|
- throw $e;
|
|
|
- } catch (\Throwable $e) {
|
|
|
- }
|
|
|
+ if ($sid < 0 && is_array($po) && ProcuremenStatus::wflowAtLeastConfirm($po['wflow_status'] ?? '')) {
|
|
|
+ throw new \InvalidArgumentException('手工新增工序已下发,无法删除');
|
|
|
}
|
|
|
|
|
|
$now = date('Y-m-d H:i:s');
|
|
|
@@ -2003,7 +2067,7 @@ class Procuremen extends Backend
|
|
|
}
|
|
|
$byCompany = [];
|
|
|
foreach ($details as $d) {
|
|
|
- if (!is_array($d)) {
|
|
|
+ if (!is_array($d) || !$this->isActivePurchaseOrderDetailRow($d)) {
|
|
|
continue;
|
|
|
}
|
|
|
$cn = trim((string)($d['company_name'] ?? ''));
|
|
|
@@ -2121,7 +2185,7 @@ class Procuremen extends Backend
|
|
|
{
|
|
|
$out = [];
|
|
|
foreach ($details as $d) {
|
|
|
- if (!is_array($d)) {
|
|
|
+ if (!is_array($d) || !$this->isActivePurchaseOrderDetailRow($d)) {
|
|
|
continue;
|
|
|
}
|
|
|
$sid = (int)($d['scydgy_id'] ?? 0);
|
|
|
@@ -2677,6 +2741,7 @@ class Procuremen extends Backend
|
|
|
}
|
|
|
$finishRaw = $this->request->post('finish', '1');
|
|
|
$asComplete = ($finishRaw === '1' || $finishRaw === 1 || $finishRaw === true);
|
|
|
+ $poIdLog = null;
|
|
|
|
|
|
try {
|
|
|
// 获取工序行 ID,对应 purchase_order.scydgy_id;有则改、无则插
|
|
|
@@ -2685,6 +2750,10 @@ class Procuremen extends Backend
|
|
|
throw new \Exception($this->formatProcuremenRowLabel($row) . '数据不完整,请刷新列表后重试');
|
|
|
}
|
|
|
|
|
|
+ if ($asComplete) {
|
|
|
+ $this->assertPickRowCanComplete($ids, $row);
|
|
|
+ }
|
|
|
+
|
|
|
$exists = Db::table('purchase_order')->where('scydgy_id', $ids)->find();
|
|
|
|
|
|
$data = [
|
|
|
@@ -2737,7 +2806,6 @@ class Procuremen extends Backend
|
|
|
} catch (\Throwable $e) {
|
|
|
$this->error($e->getMessage());
|
|
|
}
|
|
|
- $poIdLog = null;
|
|
|
try {
|
|
|
$rpo = Db::table('purchase_order')->where('scydgy_id', $ids)->find();
|
|
|
if (is_array($rpo)) {
|
|
|
@@ -2772,6 +2840,7 @@ class Procuremen extends Backend
|
|
|
$poIdLog
|
|
|
);
|
|
|
}
|
|
|
+ $this->pickHiddenScydgySetCache = null;
|
|
|
$this->success("操作成功");
|
|
|
}
|
|
|
|
|
|
@@ -2846,6 +2915,9 @@ class Procuremen extends Backend
|
|
|
if (!$this->request->isPost() || !$this->request->isAjax()) {
|
|
|
$this->error(__('Invalid parameters'));
|
|
|
}
|
|
|
+ if (!$this->hasProcuremenPerm(['purchaseconfirmpick', 'purchaseConfirmPick'])) {
|
|
|
+ $this->error(__('You have no permission'));
|
|
|
+ }
|
|
|
|
|
|
$batchRaw = trim((string)$this->request->post('order_picks_json', ''));
|
|
|
if ($batchRaw !== '') {
|
|
|
@@ -2889,6 +2961,7 @@ class Procuremen extends Backend
|
|
|
} catch (\Throwable $e) {
|
|
|
$this->error($e->getMessage());
|
|
|
}
|
|
|
+ $this->pickHiddenScydgySetCache = null;
|
|
|
$this->success('操作成功', '', $result);
|
|
|
}
|
|
|
|
|
|
@@ -2949,6 +3022,7 @@ class Procuremen extends Backend
|
|
|
$this->error($msg !== '' ? $msg : '提交失败');
|
|
|
}
|
|
|
|
|
|
+ $this->pickHiddenScydgySetCache = null;
|
|
|
$this->success('操作成功', '', ['batch' => $results]);
|
|
|
}
|
|
|
|
|
|
@@ -5679,6 +5753,7 @@ class Procuremen extends Backend
|
|
|
$this->error($e->getMessage());
|
|
|
}
|
|
|
|
|
|
+ $this->pickHiddenScydgySetCache = null;
|
|
|
$this->success('已删除 ' . $done . ' 条工序');
|
|
|
}
|
|
|
|
|
|
@@ -6403,6 +6478,9 @@ class Procuremen extends Backend
|
|
|
if (!$this->request->isPost() || !$this->request->isAjax()) {
|
|
|
$this->error(__('Invalid parameters'));
|
|
|
}
|
|
|
+ if (!$this->hasProcuremenPerm(['purchaseapprovalreject', 'purchaseApprovalReject'])) {
|
|
|
+ $this->error(__('You have no permission'));
|
|
|
+ }
|
|
|
|
|
|
$batchRaw = trim((string)$this->request->post('order_picks_json', ''));
|
|
|
$decoded = json_decode($batchRaw, true);
|
|
|
@@ -6410,6 +6488,7 @@ class Procuremen extends Backend
|
|
|
$this->error('提交数据无效');
|
|
|
}
|
|
|
|
|
|
+ $done = 0;
|
|
|
Db::startTrans();
|
|
|
try {
|
|
|
foreach ($decoded as $item) {
|
|
|
@@ -6421,6 +6500,10 @@ class Procuremen extends Backend
|
|
|
continue;
|
|
|
}
|
|
|
$this->runPurchaseApprovalRejectForSid($sid);
|
|
|
+ $done++;
|
|
|
+ }
|
|
|
+ if ($done < 1) {
|
|
|
+ throw new \Exception('所选订单均不在待审批状态');
|
|
|
}
|
|
|
Db::commit();
|
|
|
} catch (\Throwable $e) {
|
|
|
@@ -6428,6 +6511,7 @@ class Procuremen extends Backend
|
|
|
$this->error($e->getMessage() !== '' ? $e->getMessage() : '驳回失败');
|
|
|
}
|
|
|
|
|
|
+ $this->pickHiddenScydgySetCache = null;
|
|
|
$this->success('已驳回并退回「协助审批下发」');
|
|
|
}
|
|
|
|
|
|
@@ -6436,6 +6520,10 @@ class Procuremen extends Backend
|
|
|
*/
|
|
|
protected function runPurchaseApprovalRejectForSid(int $sid): void
|
|
|
{
|
|
|
+ $poRow = ProcuremenGuard::loadPurchaseOrderOrFail($sid, '未找到订单');
|
|
|
+ ProcuremenGuard::assertWflowPendingApproval($poRow, '该订单不在待审批状态,无法驳回');
|
|
|
+ ProcuremenGuard::assertNotCompleted($poRow, '订单已完结,无法驳回');
|
|
|
+
|
|
|
$allIds = $this->purchaseOrderDetail($sid);
|
|
|
if ($allIds === []) {
|
|
|
throw new \Exception('未找到下发明细');
|