|
|
@@ -2094,144 +2094,152 @@ class Synchronization extends Api
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 成品入仓数据同步中间校验接口
|
|
|
- * @desc 逐条工单独立校验,一单一条操作日志
|
|
|
- * 前置校验:先查询【成品入仓】表,校验该工单是否存在末板数据,无末版直接判定同步失败
|
|
|
- * 固定三步校验逻辑:
|
|
|
- * 第一步:查询【工单_印件资料】
|
|
|
- * 第二步:查询【工单_bom资料】提取有效物料
|
|
|
- * 第三步:查询【物料_收发记录】提取已有台账物料
|
|
|
- * 比对第二步物料集合与第三步物料集合:完全一致则同步成功,否则同步失败
|
|
|
- * 无论成功/失败,每条工单单独写入一条操作日志
|
|
|
- * @request POST
|
|
|
- * @body JSON 支持单条对象 / 多条数组批量提交
|
|
|
+ * 成品入仓数据同步中间表
|
|
|
+ * @param int|string $uniqId 成品入仓 UniqId
|
|
|
+ * @param string $insertType 插入类型:新增/修改/删除
|
|
|
+ * @return bool
|
|
|
+ * @throws \Exception 同步失败时抛出,便于调用方提示
|
|
|
*/
|
|
|
- public function syncFinishStockMiddle()
|
|
|
+ public function syncFinishStockMiddle($uniqId, $insertType = '新增')
|
|
|
{
|
|
|
- if (!$this->request->isPost()) {
|
|
|
- return json(['code' => 0, 'msg' => '仅支持POST请求']);
|
|
|
- }
|
|
|
- $jsonStr = file_get_contents('php://input');
|
|
|
- $param = json_decode($jsonStr, true);
|
|
|
- if (!is_array($param)) {
|
|
|
- return json(['code' => 0, 'msg' => 'JSON参数解析失败']);
|
|
|
- }
|
|
|
-
|
|
|
- // 兼容单条、多条入参格式
|
|
|
- $taskList = isset($param[0]) && is_array($param[0]) ? $param : [$param];
|
|
|
- $resultList = [];
|
|
|
- // 循环处理每一条工单
|
|
|
- foreach ($taskList as $item) {
|
|
|
- $gdbh = trim($item['Gdbh'] ?? '');
|
|
|
- $yjno = trim($item['yjno'] ?? '');
|
|
|
- $sysId = $item['sys_id'] ?? '';
|
|
|
- $type = $item['type'] ?? '';
|
|
|
- $syncRq = date('Y-m-d H:i:s');
|
|
|
- // 默认标记为失败
|
|
|
- $status = '同步失败';
|
|
|
- $msg = '';
|
|
|
- $yjmc = '';
|
|
|
- $yjdh = '';
|
|
|
- $wlbmStr = '';
|
|
|
- $bomCodes = [];
|
|
|
-
|
|
|
- try {
|
|
|
- if (empty($gdbh) || empty($yjno)) {
|
|
|
- throw new Exception('工单编号或印件号为空');
|
|
|
- }
|
|
|
+ if (empty($uniqId)) {
|
|
|
+ throw new \Exception('同步失败:UniqId 为空');
|
|
|
+ }
|
|
|
|
|
|
- // 【前置校验】查询成品入仓表,判断该工单是否存在末板数据
|
|
|
- $cprc = Db::name('成品入仓')
|
|
|
- ->where([
|
|
|
- 'jjcp_gdbh' => $gdbh,
|
|
|
- 'jjcp_yjno' => $yjno,
|
|
|
- 'jjcp_smb' => '末 板'
|
|
|
- ])
|
|
|
- ->field('jjcp_gdbh,jjcp_yjno,jjcp_smb,jjcp_cpmc')
|
|
|
- ->find();
|
|
|
- // 未查询到末版数据,直接抛出异常终止当前工单后续流程
|
|
|
- if (empty($cprc)) {
|
|
|
- throw new Exception("工单【{$gdbh}】印件号【{$yjno}】未录入末版数据,无法继续同步");
|
|
|
- }
|
|
|
+ $record = db('成品入仓')->where('UniqId', $uniqId)->find();
|
|
|
+ if (empty($record)) {
|
|
|
+ throw new \Exception('同步失败:未找到成品入仓记录 UniqId=' . $uniqId);
|
|
|
+ }
|
|
|
|
|
|
- // 第一步 查询工单_印件资料
|
|
|
- $yinInfo = Db::name('工单_印件资料')
|
|
|
- ->where([
|
|
|
- 'Yj_Gdbh' => $gdbh,
|
|
|
- 'yj_Yjno' => $yjno
|
|
|
- ])
|
|
|
- ->field('Yj_Gdbh,yj_Yjdh,yj_yjmc,yj_Yjno')
|
|
|
- ->find();
|
|
|
- if (empty($yinInfo)) {
|
|
|
- throw new Exception('工单_印件资料无数据');
|
|
|
- }
|
|
|
- $yjmc = $yinInfo['yj_yjmc'];
|
|
|
- $yjdh = $yinInfo['yj_Yjdh'];
|
|
|
-
|
|
|
- // 第二步 查询工单_bom资料
|
|
|
- $bomCodes = Db::name('工单_bom资料')
|
|
|
- ->where([
|
|
|
- 'BOM_工单编号' => $gdbh,
|
|
|
- 'BOM_产品编号' => $yjdh
|
|
|
- ])
|
|
|
- ->where('BOM_实际用量', '<>', 0)
|
|
|
- ->group('BOM_物料编码')
|
|
|
- ->column('BOM_物料编码');
|
|
|
- if (empty($bomCodes)) {
|
|
|
- throw new Exception('工单_bom资料无有效物料数据');
|
|
|
- }
|
|
|
- $wlbmStr = implode(',', $bomCodes);
|
|
|
-
|
|
|
- // 第三步 查询物料_收发记录
|
|
|
- $receiveCodes = Db::name('物料_收发记录')
|
|
|
- ->whereIn('st_wlbh', $bomCodes)
|
|
|
- ->group('st_wlbh')
|
|
|
- ->column('st_wlbh');
|
|
|
-
|
|
|
- //对比第二步、第三步物料是否完全一致
|
|
|
- $diffCodes = array_diff($bomCodes, $receiveCodes);
|
|
|
- if (!empty($diffCodes)) {
|
|
|
- throw new Exception('物料_收发记录缺失物料:' . implode('、', $diffCodes));
|
|
|
- }
|
|
|
+ // 测试库:database.db8(MySQL);正式库可改为 database.db3(SQL Server)
|
|
|
+ $targetDb = Db::connect(config('database.db8'));
|
|
|
+ $targetTable = 'U8_成品入仓';
|
|
|
|
|
|
- //全部校验通过
|
|
|
- $status = '同步成功';
|
|
|
- $msg = '工单_印件资料、工单_bom资料、物料_收发记录,校验全部一致';
|
|
|
+ $syncTime = date('Y-m-d H:i:s');
|
|
|
+ $isEndBoard = (strpos((string)$record['jjcp_smb'], '末') !== false) ? '末板' : '';
|
|
|
+ $id = 0;
|
|
|
+ $errorMsg = '';
|
|
|
|
|
|
- } catch (Exception $e) {
|
|
|
- // 捕获所有异常,记录失败原因
|
|
|
- $msg = $e->getMessage();
|
|
|
- }
|
|
|
+ try {
|
|
|
+ $maxId = (int)$targetDb->name($targetTable)->max('id');
|
|
|
+ $id = $maxId + 1;
|
|
|
|
|
|
- //插入日志,成功、失败日志
|
|
|
- $logInsert = [
|
|
|
- 'Gdbh' => $gdbh,
|
|
|
- 'wlbm' => $wlbmStr,
|
|
|
- 'yjmc' => $yjmc,
|
|
|
- 'Yjdh' => $yjdh,
|
|
|
- 'Yjno' => $yjno,
|
|
|
- 'sys_id' => $sysId,
|
|
|
- 'sys_rq' => $syncRq,
|
|
|
- 'type' => $type,
|
|
|
- 'status' => $status,
|
|
|
- 'status_msg' => $msg
|
|
|
+ $data = [
|
|
|
+ 'id' => $id, // 主键ID(目标表不自增,按条数递增)
|
|
|
+ 'MESCode' => '000000', // 默认编码
|
|
|
+ 'dDate' => $record['jjcp_sj'], // 入仓日期
|
|
|
+ 'cWhCode' => $record['仓库编号'], // 仓库编码
|
|
|
+ 'cMoCode' => $record['jjcp_gdbh'], // 工单编号
|
|
|
+ 'cMemo' => $record['jjcp_desc'], // 备注
|
|
|
+ 'cInvCode' => $record['jjcp_cpdh'], // 物料编码
|
|
|
+ 'cInvName' => $record['jjcp_cpmc'], // 物料名称
|
|
|
+ 'iQty' => $record['jjcp_sl'], // 数量
|
|
|
+ 'cBatch' => $record['订单编号'], // 批次号
|
|
|
+ 'username' => $record['Sys_id'], // 用户名
|
|
|
+ '是否末版' => $isEndBoard, // 是否末版
|
|
|
+ 'MES插入类型' => $insertType, // 插入类型
|
|
|
+ 'MES传递时间' => $syncTime, // 传递时间
|
|
|
+ 'U8接收时间' => null, // 接收时间为空
|
|
|
+ 'U8接收状态' => '0', // 状态默认 0
|
|
|
+ '印件编码' => $record['jjcp_cpdh'], // 印件编码
|
|
|
+ '印件名称' => $record['jjcp_cpmc'], // 印件名称
|
|
|
+ '成品编码' => $record['成品编码'], // 成品编码
|
|
|
+ '成品名称' => $record['成品名称'], // 成品名称
|
|
|
+ 'UniqId' => $record['UniqId'], // 唯一ID
|
|
|
];
|
|
|
|
|
|
- echo "<pre>";print_r($logInsert);echo "<pre>";
|
|
|
-// Db::name('工单_成品入仓同步操作日志')->insert($logInsert);
|
|
|
+ // 中文字段名不能走 ThinkPHP 命名绑定(PDO 会截断 :data__MES插入类型),改用位置绑定
|
|
|
+ $this->insertFinishStockMiddle($targetDb, $targetTable, $data);
|
|
|
|
|
|
- $resultList[] = [
|
|
|
- '工单编号' => $gdbh,
|
|
|
- '印件号' => $yjno,
|
|
|
- '状态' => $status,
|
|
|
- '说明' => $msg
|
|
|
- ];
|
|
|
+ $this->writeFinishStockSyncLog($record, $uniqId, $insertType, $syncTime, true, '同步成功');
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $errorMsg = $e->getMessage();
|
|
|
+ $this->writeFinishStockSyncLog($record, $uniqId, $insertType, $syncTime, false, $errorMsg);
|
|
|
+ throw new \Exception('同步中间表失败:' . $errorMsg);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 写入成品入仓同步操作日志
|
|
|
+ * 表字段:Gdbh/wlbm/yjmc/Yjdh/Yjno/sys_id/sys_rq/type/status/status_msg/UniqId
|
|
|
+ * @param array $record 成品入仓记录
|
|
|
+ * @param int|string $uniqId
|
|
|
+ * @param string $insertType 新增/修改/删除
|
|
|
+ * @param string $syncTime
|
|
|
+ * @param bool $success
|
|
|
+ * @param string $statusMsg
|
|
|
+ */
|
|
|
+ protected function writeFinishStockSyncLog($record, $uniqId, $insertType, $syncTime, $success, $statusMsg = '')
|
|
|
+ {
|
|
|
+ // 操作人取成品入仓 Sys_id(通常为字符串,如 [272/超级用户])
|
|
|
+ $sysId = $record['Sys_id'] ?? ($record['sys_id'] ?? '');
|
|
|
+
|
|
|
+ $log = [
|
|
|
+ 'Gdbh' => $record['jjcp_gdbh'] ?? '',
|
|
|
+ 'wlbm' => $record['jjcp_cpdh'] ?? '',
|
|
|
+ 'yjmc' => $record['jjcp_cpmc'] ?? '',
|
|
|
+ 'Yjdh' => $record['jjcp_cpdh'] ?? '', // 印件代号
|
|
|
+ 'Yjno' => (int)($record['jjcp_yjno'] ?? 0),
|
|
|
+ 'sys_id' => (string)$sysId, // 操作人
|
|
|
+ 'sys_rq' => $syncTime,
|
|
|
+ 'type' => $insertType,
|
|
|
+ 'status' => $success ? '同步成功' : '同步失败',
|
|
|
+ 'status_msg' => $success ? '' : (string)$statusMsg,
|
|
|
+ 'UniqId' => (int)$uniqId,
|
|
|
+ ];
|
|
|
+
|
|
|
+ try {
|
|
|
+ $maxId = (int)db('工单_成品入仓同步操作日志')->max('id');
|
|
|
+ $log['id'] = $maxId + 1;
|
|
|
+ $sql = db('工单_成品入仓同步操作日志')->fetchSql(true)->insert($log);
|
|
|
+ $result = db()->query($sql);
|
|
|
+ if ($result === false) {
|
|
|
+ throw new \Exception('日志 insert 返回 false');
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 不阻断主流程
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 中间表插入(兼容 MySQL / SQL Server 中文字段,使用位置绑定)
|
|
|
+ * @param \think\db\Connection $targetDb
|
|
|
+ * @param string $table
|
|
|
+ * @param array $data
|
|
|
+ */
|
|
|
+ protected function insertFinishStockMiddle($targetDb, $table, array $data)
|
|
|
+ {
|
|
|
+ $dbType = strtolower((string)$targetDb->getConfig('type'));
|
|
|
+ $isSqlsrv = (strpos($dbType, 'sqlsrv') !== false || strpos($dbType, 'sqlserver') !== false);
|
|
|
+
|
|
|
+ $quote = function ($name) use ($isSqlsrv) {
|
|
|
+ if ($isSqlsrv) {
|
|
|
+ return '[' . str_replace(']', ']]', $name) . ']';
|
|
|
+ }
|
|
|
+ return '`' . str_replace('`', '``', $name) . '`';
|
|
|
+ };
|
|
|
+
|
|
|
+ $fields = [];
|
|
|
+ $placeholders = [];
|
|
|
+ $values = [];
|
|
|
+ foreach ($data as $field => $value) {
|
|
|
+ $fields[] = $quote($field);
|
|
|
+ $placeholders[] = '?';
|
|
|
+ $values[] = $value;
|
|
|
}
|
|
|
|
|
|
- return json([
|
|
|
- 'code' => 1,
|
|
|
- 'msg' => '同步处理完成',
|
|
|
- 'data' => $resultList
|
|
|
- ]);
|
|
|
+ $sql = sprintf(
|
|
|
+ 'INSERT INTO %s (%s) VALUES (%s)',
|
|
|
+ $quote($table),
|
|
|
+ implode(', ', $fields),
|
|
|
+ implode(', ', $placeholders)
|
|
|
+ );
|
|
|
+
|
|
|
+ $result = $targetDb->execute($sql, $values);
|
|
|
+ if ($result === false) {
|
|
|
+ throw new \Exception('中间表 insert 返回 false');
|
|
|
+ }
|
|
|
}
|
|
|
}
|