|
|
@@ -197,31 +197,176 @@ class Procuremen extends Backend
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 左侧菜单
|
|
|
+ * 从 ERP 库拉取外发工序池(与 api/procuremen/getprocuremen 一致),并尽力写入 Redis
|
|
|
+ *
|
|
|
+ * @return array<int, array<string, mixed>>
|
|
|
+ */
|
|
|
+ protected function procuremenFetchErpPoolFromDb(): array
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $startTime = date('Y-m-d 00:00:00', strtotime('-1 year'));
|
|
|
+ $endTime = date('Y-m-d 23:59:59');
|
|
|
+ $list = Db::table('scydgy')
|
|
|
+ ->alias('a')
|
|
|
+ ->join('mcyd b', 'b.ICYDID = a.ICYDID AND b.iStatus >= 10', 'inner')
|
|
|
+ ->field('a.ID, b.CCYDH, b.CYJMC, b.CCLBMMC, a.CDXMC, a.CGYBH, a.CGYMC, a.CDW, a.NGZL, b.CDF, a.cGzzxMc, a.MBZ, a.bwjg, a.iStatus, a.dStamp, b.dputrecord, b.cywyxm')
|
|
|
+ ->where([
|
|
|
+ 'a.bwjg' => 1,
|
|
|
+ 'a.iEndBz' => 0,
|
|
|
+ 'a.iType' => 0,
|
|
|
+ 'a.iStatus' => 10,
|
|
|
+ ])
|
|
|
+ ->where('a.dStamp', '>=', $startTime)
|
|
|
+ ->where('a.dStamp', '<=', $endTime)
|
|
|
+ ->order('a.dStamp', 'desc')
|
|
|
+ ->select();
|
|
|
+ if (!is_array($list)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ $redis = redis();
|
|
|
+ $payload = [
|
|
|
+ 'code' => 200,
|
|
|
+ 'msg' => 'success',
|
|
|
+ 'data' => $list,
|
|
|
+ ];
|
|
|
+ $redis->set('procuremen_redis', json_encode($payload, JSON_UNESCAPED_UNICODE));
|
|
|
+ $this->procuremenRedisCache = $list;
|
|
|
+ } catch (\Throwable $e) {
|
|
|
+ }
|
|
|
+
|
|
|
+ return $list;
|
|
|
+ } catch (\Throwable $e) {
|
|
|
+ Log::write('外发列表拉取 ERP 数据失败:' . $e->getMessage(), 'error');
|
|
|
+
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Redis 为空时从库补一份缓存(同请求内只尝试一次)
|
|
|
+ *
|
|
|
+ * @return array<int, array<string, mixed>>
|
|
|
+ */
|
|
|
+ protected function procuremenEnsureRedisPool(): array
|
|
|
+ {
|
|
|
+ $pool = $this->ProcuremenRedis();
|
|
|
+ if (is_array($pool) && $pool !== []) {
|
|
|
+ return $pool;
|
|
|
+ }
|
|
|
+ static $warmed = false;
|
|
|
+ if ($warmed) {
|
|
|
+ return is_array($pool) ? $pool : [];
|
|
|
+ }
|
|
|
+ $warmed = true;
|
|
|
+
|
|
|
+ return $this->procuremenFetchErpPoolFromDb();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从工序行提取年月(与列表筛选一致:dputrecord 优先,回退 dStamp 等)
|
|
|
+ *
|
|
|
+ * @param array<string, mixed> $row
|
|
|
+ */
|
|
|
+ protected function procuremenRowYearMonth(array $row, string $primary = 'dputrecord'): ?string
|
|
|
+ {
|
|
|
+ $t = $this->procuremenRowListSortTime($row, $primary);
|
|
|
+ if ($t === '' || !preg_match('/^([12]\d{3})-(\d{1,2})/', $t, $m)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ $mo = (int)$m[2];
|
|
|
+ if ($mo < 1 || $mo > 12) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $m[1] . '-' . str_pad((string)$mo, 2, '0', STR_PAD_LEFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param array<int, array{year:string, months:array}> $sidebar
|
|
|
+ * @return array<int, array{year:string, months:array}>
|
|
|
+ */
|
|
|
+ protected function ensureProcuremenSidebarHasYm(array $sidebar, string $ym): array
|
|
|
+ {
|
|
|
+ $ym = trim($ym);
|
|
|
+ if (!preg_match('/^\d{4}-\d{2}$/', $ym)) {
|
|
|
+ return $sidebar;
|
|
|
+ }
|
|
|
+ foreach ($sidebar as $block) {
|
|
|
+ if (!is_array($block) || empty($block['months']) || !is_array($block['months'])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ foreach ($block['months'] as $item) {
|
|
|
+ if (is_array($item) && ($item['ym'] ?? '') === $ym) {
|
|
|
+ return $sidebar;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $y = substr($ym, 0, 4);
|
|
|
+ $mo = (int)substr($ym, 5, 2);
|
|
|
+ $sidebar[] = [
|
|
|
+ 'year' => $y,
|
|
|
+ 'months' => [['ym' => $ym, 'label' => $mo . '月']],
|
|
|
+ ];
|
|
|
+
|
|
|
+ return $this->buildYearMonthSidebar($this->flattenProcuremenSidebarYms($sidebar));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param array<int, array{year:string, months:array}> $sidebar
|
|
|
+ * @return string[]
|
|
|
+ */
|
|
|
+ protected function flattenProcuremenSidebarYms(array $sidebar): array
|
|
|
+ {
|
|
|
+ $yms = [];
|
|
|
+ foreach ($sidebar as $block) {
|
|
|
+ if (!is_array($block) || empty($block['months']) || !is_array($block['months'])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ foreach ($block['months'] as $item) {
|
|
|
+ if (!is_array($item)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $ym = trim((string)($item['ym'] ?? ''));
|
|
|
+ if (preg_match('/^\d{4}-\d{2}$/', $ym)) {
|
|
|
+ $yms[$ym] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return array_keys($yms);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 左侧菜单(外发初选:Redis/ERP 工序按提交日期分组;与列表月份筛选字段一致)
|
|
|
*/
|
|
|
protected function GetIndexYearMonths()
|
|
|
{
|
|
|
$ymSet = [];
|
|
|
- //获取此方法调用缓存数据
|
|
|
- foreach ($this->ProcuremenRedis() as $r) {
|
|
|
+ $pool = $this->procuremenEnsureRedisPool();
|
|
|
+ foreach ($pool as $r) {
|
|
|
if (!is_array($r)) {
|
|
|
continue;
|
|
|
}
|
|
|
- $ds = trim((string)($r['dputrecord'] ?? ''));
|
|
|
- if ($ds === '' || stripos($ds, '0000-00-00') === 0) {
|
|
|
- continue;
|
|
|
+ $ym = $this->procuremenRowYearMonth($r, 'dputrecord');
|
|
|
+ if ($ym !== null) {
|
|
|
+ $ymSet[$ym] = true;
|
|
|
}
|
|
|
- if (!preg_match('/^([12]\d{3})-(\d{1,2})-(\d{1,2})/', $ds, $m)) {
|
|
|
+ }
|
|
|
+ foreach ($this->loadPickManualOrderRows() as $r) {
|
|
|
+ if (!is_array($r)) {
|
|
|
continue;
|
|
|
}
|
|
|
- $mo = (int)$m[2];
|
|
|
- if ($mo < 1 || $mo > 12) {
|
|
|
- continue;
|
|
|
+ $ym = $this->procuremenRowYearMonth($r, 'dputrecord');
|
|
|
+ if ($ym !== null) {
|
|
|
+ $ymSet[$ym] = true;
|
|
|
}
|
|
|
- $ymSet[$m[1] . '-' . str_pad((string)$mo, 2, '0', STR_PAD_LEFT)] = true;
|
|
|
}
|
|
|
|
|
|
$ymList = array_keys($ymSet);
|
|
|
+ if ($ymList === []) {
|
|
|
+ $ymList[] = $this->resolveProcuremenDefaultYm('pick');
|
|
|
+ }
|
|
|
|
|
|
return $this->buildYearMonthSidebar($ymList);
|
|
|
}
|
|
|
@@ -285,15 +430,10 @@ class Procuremen extends Backend
|
|
|
if (!is_array($r)) {
|
|
|
continue;
|
|
|
}
|
|
|
- $t = $this->procuremenRowListSortTime($r, 'pick_time');
|
|
|
- if ($t === '' || !preg_match('/^([12]\d{3})-(\d{1,2})/', $t, $m)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- $mo = (int)$m[2];
|
|
|
- if ($mo < 1 || $mo > 12) {
|
|
|
- continue;
|
|
|
+ $ym = $this->procuremenRowYearMonth($r, 'pick_time');
|
|
|
+ if ($ym !== null) {
|
|
|
+ $ymSet[$ym] = true;
|
|
|
}
|
|
|
- $ymSet[$m[1] . '-' . str_pad((string)$mo, 2, '0', STR_PAD_LEFT)] = true;
|
|
|
}
|
|
|
}
|
|
|
} catch (\Throwable $e) {
|
|
|
@@ -502,11 +642,11 @@ class Procuremen extends Backend
|
|
|
$indexPhpRoot = $rootTrue . '/index.php';
|
|
|
}
|
|
|
$this->view->assign('procuremenRedisApi', $indexPhpRoot . '/api/procuremen/getprocuremen');
|
|
|
- $this->view->assign('defaultYm', $this->resolveProcuremenDefaultYm($stage));
|
|
|
- $this->view->assign(
|
|
|
- 'sidebarYearMonths',
|
|
|
- $stage === 'pick' ? $this->GetIndexYearMonths() : $this->GetIssuedOrderYearMonths($stage)
|
|
|
- );
|
|
|
+ $defaultYm = $this->resolveProcuremenDefaultYm($stage);
|
|
|
+ $sidebar = $stage === 'pick' ? $this->GetIndexYearMonths() : $this->GetIssuedOrderYearMonths($stage);
|
|
|
+ $sidebar = $this->ensureProcuremenSidebarHasYm($sidebar, $defaultYm);
|
|
|
+ $this->view->assign('defaultYm', $defaultYm);
|
|
|
+ $this->view->assign('sidebarYearMonths', $sidebar);
|
|
|
$this->view->assign('procuremenStage', $stage);
|
|
|
$this->view->assign('procuremenPageTitle', $pageTitle);
|
|
|
}
|
|
|
@@ -617,7 +757,7 @@ class Procuremen extends Backend
|
|
|
$this->loadPurchaseOrderRowsForListStage('confirm', $ym, $applyMonthRange)
|
|
|
);
|
|
|
} else {
|
|
|
- $pool = $this->ProcuremenRedis();
|
|
|
+ $pool = $this->procuremenEnsureRedisPool();
|
|
|
if (!is_array($pool)) {
|
|
|
$pool = [];
|
|
|
}
|
|
|
@@ -642,7 +782,6 @@ class Procuremen extends Backend
|
|
|
return json([
|
|
|
'total' => 0,
|
|
|
'rows' => [],
|
|
|
- 'msg' => '暂无缓存数据',
|
|
|
]);
|
|
|
}
|
|
|
}
|
|
|
@@ -697,6 +836,22 @@ class Procuremen extends Backend
|
|
|
}
|
|
|
$dir = $ord === 1 ? SORT_ASC : SORT_DESC;
|
|
|
array_multisort($sortKeys, $dir, SORT_NUMERIC, $filtered);
|
|
|
+ } elseif ($sortField === 'CCYDH') {
|
|
|
+ usort($filtered, function ($a, $b) use ($ord) {
|
|
|
+ $sa = trim((string)($a['CCYDH'] ?? ''));
|
|
|
+ $sb = trim((string)($b['CCYDH'] ?? ''));
|
|
|
+ if ($sa === $sb) {
|
|
|
+ return ((int)($a['ID'] ?? 0) <=> (int)($b['ID'] ?? 0)) * $ord;
|
|
|
+ }
|
|
|
+ if ($sa === '') {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if ($sb === '') {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return strcmp($sa, $sb) * $ord;
|
|
|
+ });
|
|
|
} else {
|
|
|
usort($filtered, function ($a, $b) use ($sortField, $ord) {
|
|
|
$va = $a[$sortField] ?? null;
|
|
|
@@ -901,10 +1056,11 @@ class Procuremen extends Backend
|
|
|
'rows' => $rows,
|
|
|
]);
|
|
|
} catch (\Throwable $e) {
|
|
|
+ Log::write('外发列表加载异常:' . $e->getMessage(), 'error');
|
|
|
+
|
|
|
return json([
|
|
|
'total' => 0,
|
|
|
'rows' => [],
|
|
|
- 'msg' => $e->getMessage(),
|
|
|
]);
|
|
|
}
|
|
|
}
|
|
|
@@ -2999,6 +3155,44 @@ class Procuremen extends Backend
|
|
|
return ($ts !== false && $ts > 0) ? date('Y-m-d', $ts) : $s;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 供应商是否已在手机端填写单价或交货日期(任一有值即视为已操作)
|
|
|
+ */
|
|
|
+ protected function detailRowSupplierOperated(array $r): bool
|
|
|
+ {
|
|
|
+ $am = $r['amount'] ?? null;
|
|
|
+ $okAmt = $am !== null && $am !== '' && !(is_string($am) && trim($am) === '');
|
|
|
+ $dv = isset($r['delivery']) ? trim((string)$r['delivery']) : '';
|
|
|
+ $okDel = $dv !== '' && !preg_match('/^0000-00-00/i', $dv);
|
|
|
+
|
|
|
+ return $okAmt || $okDel;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详情供应商表「操作时间」:仅手机端填写单价/交期后展示,不用下发明细的 createtime
|
|
|
+ */
|
|
|
+ protected function resolveDetailSupplierOperTime(array $r): string
|
|
|
+ {
|
|
|
+ if (!$this->detailRowSupplierOperated($r)) {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ $t = $this->formatProcuremenDetailTime($r['updatetime'] ?? null);
|
|
|
+ if ($t !== '') {
|
|
|
+ return $t;
|
|
|
+ }
|
|
|
+ foreach (['delivery_createtime', 'deliverycreatetime'] as $col) {
|
|
|
+ if (!isset($r[$col]) || $r[$col] === '' || $r[$col] === null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $t = $this->formatProcuremenDetailTime($r[$col]);
|
|
|
+ if ($t !== '') {
|
|
|
+ return $t;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 供应商已接单:金额与交货日期均已填写(与列表汇总逻辑一致)
|
|
|
*/
|
|
|
@@ -3156,7 +3350,7 @@ class Procuremen extends Backend
|
|
|
if (!is_array($dr) || !$this->detailRowSupplierAccepted($dr)) {
|
|
|
continue;
|
|
|
}
|
|
|
- $t = $this->formatProcuremenDetailTime($dr['updatetime'] ?? $dr['createtime'] ?? null);
|
|
|
+ $t = $this->resolveDetailSupplierOperTime($dr);
|
|
|
if ($t !== '' && ($supplierTime === '' || strcmp($t, $supplierTime) < 0)) {
|
|
|
$supplierTime = $t;
|
|
|
}
|
|
|
@@ -3419,6 +3613,7 @@ class Procuremen extends Backend
|
|
|
}
|
|
|
$r['delivery_ymd'] = $this->formatDeliveryYmd($r['delivery'] ?? null);
|
|
|
$r['is_void'] = is_array($r) && $this->isPurchaseOrderDetailVoid($r);
|
|
|
+ $r['oper_time_text'] = $this->resolveDetailSupplierOperTime($r);
|
|
|
}
|
|
|
unset($r);
|
|
|
|
|
|
@@ -4176,10 +4371,7 @@ class Procuremen extends Backend
|
|
|
$groupHas = true;
|
|
|
}
|
|
|
}
|
|
|
- $ct = $d['createtime_text'] ?? '';
|
|
|
- if ($ct === '' && isset($d['createtime'])) {
|
|
|
- $ct = $this->formatProcuremenDetailTime($d['createtime'] ?? null);
|
|
|
- }
|
|
|
+ $ct = $this->resolveDetailSupplierOperTime($d);
|
|
|
$lines[] = [
|
|
|
'cgymc' => $gymcBySid[$sid] ?? trim((string)($d['CGYMC'] ?? '')),
|
|
|
'unit_price_text' => $amountNum !== null ? $this->formatProcuremenMoneyDisplay($amountNum) : trim((string)($d['amount'] ?? '')),
|
|
|
@@ -4187,7 +4379,7 @@ class Procuremen extends Backend
|
|
|
'delivery_ymd' => $d['delivery_ymd'] ?? $this->formatDeliveryYmd($d['delivery'] ?? null),
|
|
|
'status' => (int)($d['status'] ?? 0),
|
|
|
'is_void' => $isVoid,
|
|
|
- 'createtime_text' => $ct,
|
|
|
+ 'oper_time_text' => $ct,
|
|
|
];
|
|
|
};
|
|
|
foreach ($orderedSids as $sid) {
|
|
|
@@ -4210,7 +4402,7 @@ class Procuremen extends Backend
|
|
|
'lines' => $lines,
|
|
|
'line_count' => count($lines),
|
|
|
'total_text' => $groupHas ? $this->formatProcuremenMoneyDisplay($groupTotal) : '',
|
|
|
- 'has_total' => $groupHas,
|
|
|
+ 'has_total' => count($lines) > 0,
|
|
|
];
|
|
|
}
|
|
|
usort($supplierGroups, function ($a, $b) {
|