U8ThirtyPartyDatabaseServerService.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. <?php
  2. namespace App\Service;
  3. use Illuminate\Support\Facades\DB;
  4. use Illuminate\Support\Facades\Log;
  5. class U8ThirtyPartyDatabaseServerService extends Service
  6. {
  7. protected $connectionName = 'u8_third_sqlserver';
  8. // Service 内部查询
  9. public function getPendingBills($config, $lastId)
  10. {
  11. try {
  12. $mainTable = $config['main'];
  13. $detailTable = $config['detail'];
  14. $mainKey = $config['main_key'];
  15. $foreignKey = $config['key'];
  16. $whereRaw = $config['whereRaw'];
  17. $main_field = $config['main_field'];
  18. $son_field = $config['son_field'];
  19. $limit = $config['limit'];
  20. // 1. 获取主表
  21. $mainRows = DB::connection($this->connectionName)
  22. ->table($mainTable)
  23. ->lock('WITH(NOLOCK)')
  24. ->where($mainKey, '>', $lastId) // 改用 ID
  25. ->whereRaw($whereRaw)
  26. ->select($main_field)
  27. ->orderBy($mainKey, 'ASC') // 按 ID 排序保证分页连续
  28. ->limit($limit)
  29. ->get();
  30. if ($mainRows->isEmpty()) return [true, []];
  31. if (empty($foreignKey) || empty($son_field)) {
  32. $array = $mainRows->map(function ($item) {
  33. return (array) $item;
  34. })->toArray();
  35. return [true, $array];
  36. }
  37. // 2. 批量获取子表
  38. $mainIds = $mainRows->pluck('id')->toArray();
  39. // $details = DB::connection($this->connectionName)
  40. // ->table($detailTable . ' as detail') // 给子表起别名
  41. // ->leftJoin('Inventory as inv', 'detail.cInvCode', '=', 'inv.cInvCode') // 关联存货表
  42. // ->lock('WITH(NOLOCK)')
  43. // ->whereIn('detail.' . $foreignKey, $mainIds) // 注意这里要指定表别名
  44. // ->select($son_field) // 这里会读取你配置里的新字段
  45. // ->get()
  46. // ->groupBy('id');
  47. $details = DB::connection($this->connectionName)
  48. ->table($detailTable. ' as detail')
  49. ->lock('WITH(NOLOCK)')
  50. ->whereIn($foreignKey, $mainIds)
  51. ->select($son_field)
  52. ->addSelect(DB::raw("ROW_NUMBER() OVER(PARTITION BY detail.{$foreignKey} ORDER BY detail.AutoID) as lineNum"))
  53. ->get()
  54. ->groupBy('id');
  55. // 3. 组合
  56. $result = $mainRows->map(function($main) use ($details, $foreignKey) {
  57. $res = (array)$main;
  58. $mainId = $res['id'];
  59. $res['details'] = isset($details[$mainId])
  60. ? $details[$mainId]->map(function($item) {
  61. return (array)$item; // 强制把子表对象转成数组
  62. })->values()->toArray()
  63. : [];
  64. return $res;
  65. })->toArray();
  66. return [true, $result];
  67. } catch (\Throwable $e) {
  68. Log::channel('apiLog')->info('查询失败', [
  69. "error" => $e->getMessage(),
  70. ]);
  71. return [false, $e->getMessage()];
  72. }
  73. }
  74. public function getBillSingle($config, $id)
  75. {
  76. try {
  77. $mainTable = $config['main'];
  78. $detailTable = $config['detail'];
  79. $mainKey = $config['main_key']; // 比如 ID
  80. $foreignKey = $config['key']; // 比如 id (子表关联主表的字段)
  81. $main_field = $config['main_field'];
  82. $son_field = $config['son_field'];
  83. // 1. 获取主表单条记录
  84. $mainRow = DB::connection($this->connectionName)
  85. ->table($mainTable)
  86. ->lock('WITH(NOLOCK)')
  87. ->where($mainKey, $id) // 精确匹配单据 ID
  88. ->select($main_field)
  89. ->first();
  90. if (!$mainRow) {
  91. return [false, "单据 ID:{$id} 未找到数据"];
  92. }
  93. $result = (array)$mainRow;
  94. // 2. 如果不需要子表,直接返回
  95. if (empty($foreignKey) || empty($son_field)) {
  96. return [true, $result];
  97. }
  98. // 3. 获取该单据对应的子表详情
  99. // 注意:U8 子表通常用 id 关联主表的 ID,这里使用配置中的 $foreignKey
  100. $details = DB::connection($this->connectionName)
  101. ->table($detailTable . ' as detail')
  102. ->lock('WITH(NOLOCK)')
  103. ->where($foreignKey, $id)
  104. ->select($son_field)
  105. // 自动生成行号,按 AutoID 排序
  106. // ->addSelect(DB::raw("ROW_NUMBER() OVER(ORDER BY detail.AutoID) as lineNum"))
  107. ->orderBy('detail.AutoID', 'ASC')
  108. ->get();
  109. // 4. 组合数据
  110. $result['details'] = $details->map(function ($item) {
  111. return (array)$item;
  112. })->toArray();
  113. return [true, $result];
  114. } catch (\Throwable $e) {
  115. Log::channel('apiLog')->info('查询单个单据失败', [
  116. "id" => $id,
  117. "error" => $e->getMessage(),
  118. ]);
  119. return [false, $e->getMessage()];
  120. }
  121. }
  122. public function getArrivalVouchById($orderId)
  123. {
  124. // 1. 获取主表 (PU_ArrivalVouch) 并关联 采购类型表 (PurchaseType)
  125. $main = DB::connection($this->connectionName)
  126. ->table('PU_ArrivalVouch as main')
  127. ->leftJoin('PurchaseType as pt', 'main.cPTCode', '=', 'pt.cPTCode') // 关联采购类型表
  128. ->lock('WITH(NOLOCK)')
  129. ->where('main.ID', $orderId)
  130. ->select([
  131. 'main.ID as id',
  132. 'main.cCode as no',
  133. 'main.cVenCode as supply_code',
  134. 'main.cDepCode as depart_code',
  135. 'main.dDate as order_date',
  136. 'main.cBusType as b_type',
  137. 'main.cPTCode as cg_type',
  138. 'pt.cRdCode as rd_code'
  139. ])
  140. ->first();
  141. if (!$main) return [];
  142. $order = (array)$main;
  143. // 2. 获取子表 (PU_ArrivalVouchs)
  144. $details = DB::connection($this->connectionName)
  145. ->table('PU_ArrivalVouchs as detail')
  146. ->lock('WITH(NOLOCK)')
  147. ->where('ID', $orderId) // 子表里的 ID 关联主表的 ID
  148. ->select([
  149. 'detail.cInvCode',
  150. 'detail.iQuantity',
  151. 'detail.iQuantity as iNNum',
  152. 'detail.iinvexchrate',
  153. 'detail.cBatch',
  154. 'detail.dPDate',
  155. 'detail.dVDate',
  156. 'detail.Autoid as iArrsId',
  157. 'detail.ivouchrowno as iRowNo',
  158. 'detail.iOriTaxCost',
  159. 'detail.iTaxRate',
  160. // 'detail.cordercode',
  161. 'detail.cWhCode',
  162. ])
  163. ->orderBy('detail.ivouchrowno', 'ASC') // 按 U8 原始行号排序
  164. ->get();
  165. // 3. 组合数据并返回
  166. $order['details'] = $details->map(function ($item) {
  167. return (array)$item;
  168. })->toArray();
  169. return $order;
  170. }
  171. /**
  172. * 获取存货档案(带分类名称)
  173. * @param array $config 配置项
  174. * @param mixed $lastId 上次分页的标识(这里用存货编码 cInvCode 或 自动增量标识)
  175. * @return array [bool, items]
  176. */
  177. public function getInventoryData1($config, $lastId = null)
  178. {
  179. try {
  180. $query = DB::connection('u8_third_sqlserver')
  181. ->table('Inventory as main')
  182. ->leftJoin('InventoryClass as sub', 'main.cInvCCode', '=', 'sub.cInvCCode')
  183. ->select([
  184. 'main.cInvCode as product_code',
  185. 'main.cInvName as product_name',
  186. 'main.cInvStd as product_size',
  187. 'main.cInvCCode as product_category_code',
  188. 'sub.cInvCName as product_category_name', // 直接联查分类名
  189. 'main.cComUnitCode as product_unit',
  190. 'main.fOutExcess as out_limit',
  191. 'main.cCurrencyName as common_name',
  192. 'main.fGrossW as grossWeight',
  193. 'main.dModifyDate as upd_time'
  194. ]);
  195. // 分页逻辑
  196. if ($lastId) {
  197. $query->where('main.cInvCode', '>', $lastId);
  198. }
  199. // 基础过滤条件
  200. if (!empty($config['whereRaw'])) {
  201. $query->whereRaw($config['whereRaw']);
  202. }
  203. $items = $query->orderBy('main.cInvCode', 'asc')
  204. ->limit($config['limit'])
  205. ->get();
  206. // 将 Collection 转为数组方便后续处理
  207. $items = json_decode(json_encode($items), true);
  208. return [true, $items];
  209. } catch (\Exception $e) {
  210. Log::channel('apiLog')->error("U8获取存货异常: " . $e->getMessage());
  211. return [false, []];
  212. }
  213. }
  214. public function getInventoryData($config, $lastCode = null)
  215. {
  216. try {
  217. $query = DB::connection('u8_third_sqlserver')
  218. ->table('Inventory as main')
  219. ->leftJoin('InventoryClass as sub', 'main.cInvCCode', '=', 'sub.cInvCCode')
  220. ->leftJoin('ComputationUnit as unit', 'main.cComUnitCode', '=', 'unit.cComUnitCode')
  221. ->select([
  222. 'main.cInvCode as product_code',
  223. 'main.cInvName as product_name',
  224. 'main.cInvStd as product_size',
  225. 'main.cInvCCode as product_category_code',
  226. 'sub.cInvCName as product_category_name', // 直接联查分类名
  227. 'main.cComUnitCode as product_unit',
  228. 'unit.cComUnitName as product_unit_title',
  229. // 'main.fOutExcess as out_limit',
  230. // 'main.cCurrencyName as common_name',
  231. 'main.fGrossW as grossWeight',
  232. // 关键点:将二进制 ufts 转换为 0x... 字符串
  233. DB::raw("master.sys.fn_varbintohexstr(main.pubufts) as ufts_str")
  234. ]);
  235. // 使用 product_code 做分页依据
  236. if ($lastCode) {
  237. $query->where('main.cInvCode', '>', $lastCode);
  238. }
  239. if (!empty($config['whereRaw'])) {
  240. $query->whereRaw($config['whereRaw']);
  241. }
  242. // 必须按编码排序,保证分页不重不漏
  243. $items = $query->orderBy('main.cInvCode', 'asc')
  244. ->limit($config['limit'])
  245. ->get();
  246. return [true, json_decode(json_encode($items), true)];
  247. } catch (\Exception $e) {
  248. Log::channel('apiLog')->error("U8获取存货异常: " . $e->getMessage());
  249. return [false, []];
  250. }
  251. }
  252. //获取单个产品报检单的明细
  253. public function getBjOrder($id){
  254. return DB::connection($this->connectionName)
  255. ->table('QMINSPECTVOUCHERS as detail')
  256. ->lock('WITH(NOLOCK)')
  257. ->where('detail.ID', $id)
  258. ->select('detail.*')
  259. ->get()
  260. ->map(function ($value) {
  261. return (array)$value;
  262. })
  263. ->keyBy('CINVCODE')
  264. ->toArray();
  265. }
  266. /**
  267. * 更新报检单明细
  268. * @param array $update [AutoID => [字段名 => 值], ...]
  269. * @param array $insert [[字段名 => 值], [字段名 => 值], ...]
  270. */
  271. public function updateBjOrder($update, $insert)
  272. {
  273. try {
  274. return DB::connection($this->connectionName)->transaction(function () use ($update, $insert) {
  275. // 1. 处理更新部分
  276. if (!empty($update)) {
  277. foreach ($update as $autoId => $fields) {
  278. DB::connection($this->connectionName)
  279. ->table('QMINSPECTVOUCHERS')
  280. ->where('AUTOID', $autoId)
  281. ->update($fields);
  282. }
  283. }
  284. // 2. 处理插入部分 (拆分行)
  285. if (!empty($insert)) {
  286. // 获取当前单据的最大行号,确保新行号递增
  287. // 注意:这里需要从 $insert 的第一个元素获取 ID,因为它们都属于同一个主表单据
  288. $mainId = $insert[0]['ID'] ?? null;
  289. if ($mainId) {
  290. $maxRowID = DB::connection($this->connectionName)
  291. ->table('QMINSPECTVOUCHERS')
  292. ->max('AUTOID') ?? 0;
  293. foreach ($insert as &$newRow) {
  294. $maxRowID++;
  295. $newRow['AUTOID'] = $maxRowID;
  296. }
  297. // 使用批量插入提高性能
  298. DB::connection($this->connectionName)
  299. ->table('QMINSPECTVOUCHERS')
  300. ->insert($insert);
  301. }
  302. }
  303. });
  304. return [true, ''];
  305. } catch (\Throwable $e) {
  306. return [false, $e->getMessage()];
  307. }
  308. }
  309. public function getJyOrder($id)
  310. {
  311. // 1. 获取表头信息 (主表)
  312. $main = DB::connection($this->connectionName)
  313. ->table('QMCHECKVOUCHER')
  314. ->lock('WITH(NOLOCK)')
  315. ->where('ID', $id)
  316. ->first();
  317. if (!$main) {
  318. return []; // 或者返回空数组 []
  319. }
  320. $main = (array)$main;
  321. return $main;
  322. }
  323. public function getScDetails($id)
  324. {
  325. // 1. 获取表头信息 (主表)
  326. $main = DB::connection($this->connectionName)
  327. ->table('mom_orderdetail')
  328. ->lock('WITH(NOLOCK)')
  329. ->where('MoDid', $id)
  330. ->first();
  331. if (!$main) {
  332. return []; // 或者返回空数组 []
  333. }
  334. $main = (array)$main;
  335. return $main;
  336. }
  337. //获取单个销售订单的信息
  338. public function getXsOrder($id)
  339. {
  340. // 1. 获取销售订单主表信息 (SO_SOMain)
  341. $main = DB::connection($this->connectionName)
  342. ->table('SO_SOMain')
  343. ->lock('WITH(NOLOCK)')
  344. ->where('ID', $id)
  345. ->first();
  346. if (!$main) {
  347. return [];
  348. }
  349. $main = (array)$main;
  350. // 2. 获取销售订单子表信息 (SO_SODetails)
  351. $details = DB::connection($this->connectionName)
  352. ->table('SO_SODetails')
  353. ->lock('WITH(NOLOCK)')
  354. ->where('ID', $id) // 子表通过 ID 关联主表
  355. ->get()
  356. ->map(function ($value) {
  357. return (array)$value;
  358. })
  359. ->toArray();
  360. // 3. 将子表数据放入 details 键中
  361. $main['details'] = $details;
  362. return $main;
  363. }
  364. public function getXsThOrder($id)
  365. {
  366. // 1. 获取销售退货单主表信息 (DispatchList)
  367. $main = DB::connection($this->connectionName)
  368. ->table('DispatchList')
  369. ->lock('WITH(NOLOCK)')
  370. ->where('DLID', $id) // 注意:主键叫 DLID
  371. ->first();
  372. if (!$main) {
  373. return [];
  374. }
  375. $main = (array)$main;
  376. // 2. 获取销售退货单子表信息 (DispatchLists)
  377. $details = DB::connection($this->connectionName)
  378. ->table('DispatchLists')
  379. ->lock('WITH(NOLOCK)')
  380. ->where('DLID', $id) // 通过 DLID 关联
  381. ->get()
  382. ->map(function ($value) {
  383. return (array)$value;
  384. })
  385. ->toArray();
  386. // 3. 将子表数据放入 details 键中
  387. $main['details'] = $details;
  388. return $main;
  389. }
  390. public function getFhOrder($id)
  391. {
  392. // 1. 获取销售发货单主表信息 (DispatchList)
  393. $main = DB::connection($this->connectionName)
  394. ->table('DispatchList')
  395. ->lock('WITH(NOLOCK)')
  396. ->where('DLID', $id) // U8发货单主键通常是 DLID
  397. ->first();
  398. if (!$main) {
  399. return [];
  400. }
  401. $main = (array)$main;
  402. // 2. 获取销售发货单子表信息 (DispatchLists)
  403. $details = DB::connection($this->connectionName)
  404. ->table('DispatchLists') // 注意这里是 DispatchLists
  405. ->lock('WITH(NOLOCK)')
  406. ->where('DLID', $id) // 子表通过 DLID 关联主表
  407. ->get()
  408. ->map(function ($value) {
  409. return (array)$value;
  410. })
  411. ->toArray();
  412. // 3. 将子表数据放入 details 键中
  413. $main['details'] = $details;
  414. return $main;
  415. }
  416. public function getCGDHDetails($id)
  417. {
  418. // 2. 获取采购到货单子表信息 (PU_ArrivalVouchs)
  419. $details = DB::connection($this->connectionName)
  420. ->table('PU_ArrivalVouchs')
  421. ->lock('WITH(NOLOCK)')
  422. ->where('ID', $id) // 通过 ID 关联主表
  423. ->get()
  424. ->map(function ($value) {
  425. return (array)$value;
  426. });
  427. // 3. 将子表数据以 cInvCode 为 Key 进行组织
  428. // 注意:如果一张单据里有重复的存货编码,后面的行会覆盖前面的行
  429. $details = $details->keyBy('cInvCode')->toArray();
  430. return $details;
  431. }
  432. public function getLlSQDetails($id)
  433. {
  434. // 1. 获取领料申请单子表信息 (MaterialAppVouchs)
  435. $details = DB::connection($this->connectionName)
  436. ->table('MaterialAppVouchs') // 领料申请单子表名
  437. ->lock('WITH(NOLOCK)')
  438. ->where('ID', $id) // 通过 ID 关联主表
  439. ->get()
  440. ->map(function ($value) {
  441. return (array)$value;
  442. });
  443. // 2. 将子表数据以 cInvCode 为 Key 进行组织
  444. // 提示:领料申请单中同一存货可能出现在不同行(如:对应不同的生产订单行)
  445. // 如果确定 cInvCode 唯一,可用 keyBy;如果不唯一,建议直接返回数组或 keyBy('AutoID')
  446. $details = $details->keyBy('cInvCode')->toArray();
  447. return $details;
  448. }
  449. public function updateDhOrder($update, $insert)
  450. {
  451. try {
  452. return DB::connection($this->connectionName)->transaction(function () use ($update, $insert) {
  453. // 1. 处理更新部分 (子表: PU_ArrivalVouchs)
  454. if (!empty($update)) {
  455. foreach ($update as $autoId => $fields) {
  456. DB::connection($this->connectionName)
  457. ->table('PU_ArrivalVouchs') // 修正为子表名
  458. ->where('Autoid', $autoId) // U8 习惯大写 A 小写 utoid,但 SQL 不敏感
  459. ->update($fields);
  460. }
  461. }
  462. // 2. 处理插入部分 (拆分行)
  463. if (!empty($insert)) {
  464. $mainId = $insert[0]['ID'] ?? null;
  465. if ($mainId) {
  466. // 获取全表最大 Autoid,确保全局唯一
  467. $maxRowID = DB::connection($this->connectionName)
  468. ->table('PU_ArrivalVouchs') // 修正为子表名
  469. ->max('Autoid') ?? 0;
  470. foreach ($insert as &$newRow) {
  471. $maxRowID++;
  472. $newRow['Autoid'] = $maxRowID;
  473. }
  474. // 使用批量插入
  475. DB::connection($this->connectionName)
  476. ->table('PU_ArrivalVouchs')
  477. ->insert($insert);
  478. }
  479. }
  480. return [true, '']; // 事务成功返回
  481. });
  482. } catch (\Throwable $e) {
  483. // 打印错误堆栈有助于调试
  484. return [false, "修改采购到货单失败: " . $e->getMessage()];
  485. }
  486. }
  487. public function getCgOrder($id)
  488. {
  489. // 1. 获取采购到货单主表信息 (PU_ArrivalVouch)
  490. // 关键:关联键是 ID
  491. $main = DB::connection($this->connectionName)
  492. ->table('PU_ArrivalVouch')
  493. ->lock('WITH(NOLOCK)')
  494. ->where('ID', $id)
  495. ->first();
  496. if (!$main) {
  497. return [];
  498. }
  499. $main = (array)$main;
  500. // 2. 获取采购到货单子表信息 (PU_ArrivalVouchs)
  501. $details = DB::connection($this->connectionName)
  502. ->table('PU_ArrivalVouchs')
  503. ->lock('WITH(NOLOCK)')
  504. ->where('ID', $id) // 子表通过 ID 关联主表
  505. ->get()
  506. ->map(function ($value) {
  507. return (array)$value;
  508. })
  509. ->toArray();
  510. // 3. 将子表数据放入 details 键中
  511. $main['details'] = $details;
  512. return $main;
  513. }
  514. public function getJyOrder2($id)
  515. {
  516. // 关联采购到货单子表 (PU_ArrivalVouchs) 获取金额字段
  517. $order = DB::connection($this->connectionName)
  518. ->table('QMCHECKVOUCHER as qm')
  519. ->leftJoin('PU_ArrivalVouchs as arr', 'qm.SOURCEAUTOID', '=', 'arr.Autoid')
  520. ->select(
  521. 'qm.*',
  522. 'arr.iCost', // 原币无税单价
  523. 'arr.iOriTaxCost', // 原币含税单价
  524. 'arr.iTaxRate' // 税率
  525. )
  526. ->where('qm.ID', $id) // 假设这是检验单主表ID
  527. ->first();
  528. return $order ? (array)$order : [];
  529. }
  530. public function updateLLOrder($update, $insert)
  531. {
  532. try {
  533. return DB::connection($this->connectionName)->transaction(function () use ($update, $insert) {
  534. // 1. 处理更新部分 (子表: MaterialAppVouchs)
  535. if (!empty($update)) {
  536. foreach ($update as $autoId => $fields) {
  537. DB::connection($this->connectionName)
  538. ->table('MaterialAppVouchs') // 领料申请单子表
  539. ->where('autoid', $autoId) // 注意字段名在 U8 里可能是 autoid 或 AutoID
  540. ->update($fields);
  541. }
  542. }
  543. // 2. 处理插入部分 (拆分行/新增行)
  544. if (!empty($insert)) {
  545. // 获取当前领料申请单子表的最大 Autoid,确保手动分配不冲突
  546. $maxRowID = DB::connection($this->connectionName)
  547. ->table('MaterialAppVouchs')
  548. ->max('autoid') ?? 0;
  549. foreach ($insert as &$newRow) {
  550. $maxRowID++;
  551. // U8 的 autoid 通常必须手动指定
  552. $newRow['autoid'] = $maxRowID;
  553. }
  554. // 使用批量插入
  555. DB::connection($this->connectionName)
  556. ->table('MaterialAppVouchs')
  557. ->insert($insert);
  558. }
  559. return [true, ''];
  560. });
  561. } catch (\Throwable $e) {
  562. // 建议记录详细日志
  563. return [false, "修改领料申请单失败: " . $e->getMessage()];
  564. }
  565. }
  566. public function getLLOrder($id)
  567. {
  568. // 关键:关联键是 ID
  569. $main = DB::connection($this->connectionName)
  570. ->table('MaterialAppVouch')
  571. ->lock('WITH(NOLOCK)')
  572. ->where('ID', $id)
  573. ->first();
  574. if (!$main) {
  575. return [];
  576. }
  577. $main = (array)$main;
  578. // 2. 获取采购到货单子表信息 (PU_ArrivalVouchs)
  579. $details = DB::connection($this->connectionName)
  580. ->table('MaterialAppVouchs')
  581. ->lock('WITH(NOLOCK)')
  582. ->where('ID', $id) // 子表通过 ID 关联主表
  583. ->get()
  584. ->map(function ($value) {
  585. return (array)$value;
  586. })
  587. ->toArray();
  588. // 3. 将子表数据放入 details 键中
  589. $main['details'] = $details;
  590. return $main;
  591. }
  592. public function checkInventoryControl($invCodes)
  593. {
  594. if (empty($invCodes)) {
  595. return [false, '存货编码为空'];
  596. }
  597. // 1. 查询存货档案
  598. $list = DB::connection($this->connectionName)
  599. ->table('Inventory')
  600. ->whereIn('cInvCode', $invCodes)
  601. ->select(['cInvCode', 'cInvName', 'bInvBatch', 'bInvQuality'])
  602. ->get();
  603. $noBatch = []; // 未开启批次管理的
  604. $noExpiration = []; // 未开启保质期管理的
  605. $notFound = array_diff($invCodes, $list->pluck('cInvCode')->toArray()); // 数据库中不存在的
  606. foreach ($list as $item) {
  607. // 检查批次管理 (bInvBatch 为 0 表示未开启)
  608. if (empty($item->bInvBatch)) {
  609. $noBatch[] = $item->cInvCode . '(' . $item->cInvName . ')';
  610. }
  611. // 检查保质期管理 (bInvQuality 为 0 表示未开启)
  612. if (empty($item->bInvQuality)) {
  613. $noExpiration[] = $item->cInvCode . '(' . $item->cInvName . ')';
  614. }
  615. }
  616. // 2. 组织提示结果
  617. $messages = [];
  618. if (!empty($noBatch)) {
  619. $messages[] = "【未开启批次管理】: " . implode(', ', $noBatch);
  620. }
  621. if (!empty($noExpiration)) {
  622. $messages[] = "【未开启保质期管理】: " . implode(', ', $noExpiration);
  623. }
  624. if (!empty($notFound)) {
  625. $messages[] = "【档案不存在】: " . implode(', ', $notFound);
  626. }
  627. if (empty($messages)) {
  628. return [true, ''];
  629. }
  630. return [false, implode("\n", $messages)];
  631. }
  632. public function rebuildDhDetails($mainId, $insertData)
  633. {
  634. try {
  635. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  636. // 1. 删除旧明细
  637. DB::connection($this->connectionName)
  638. ->table('PU_ArrivalVouchs')
  639. ->where('ID', $mainId)
  640. ->delete();
  641. // 2. 获取新的起始 Autoid
  642. $maxAutoid = DB::connection($this->connectionName)
  643. ->table('PU_ArrivalVouchs')
  644. ->max('Autoid') ?? 0;
  645. // 3. 分配新 Autoid 并插入
  646. foreach ($insertData as &$row) {
  647. $maxAutoid++;
  648. $row['Autoid'] = $maxAutoid;
  649. }
  650. DB::connection($this->connectionName)
  651. ->table('PU_ArrivalVouchs')
  652. ->insert($insertData);
  653. return [true, ''];
  654. });
  655. } catch (\Throwable $e) {
  656. return [false, "重建明细失败: " . $e->getMessage()];
  657. }
  658. }
  659. public function rebuildLLDetails($mainId, $insertData)
  660. {
  661. try {
  662. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  663. // 1. 删除旧明细 (领料申请单子表)
  664. DB::connection($this->connectionName)
  665. ->table('MaterialAppVouchs')
  666. ->where('ID', $mainId)
  667. ->delete();
  668. // 2. 获取新的起始 autoid
  669. $maxAutoid = DB::connection($this->connectionName)
  670. ->table('MaterialAppVouchs')
  671. ->max('AutoID') ?? 0;
  672. // 3. 分配新 autoid 并插入
  673. foreach ($insertData as &$row) {
  674. $maxAutoid++;
  675. $row['AutoID'] = $maxAutoid;
  676. }
  677. DB::connection($this->connectionName)
  678. ->table('MaterialAppVouchs')
  679. ->insert($insertData);
  680. return [true, ''];
  681. });
  682. } catch (\Throwable $e) {
  683. return [false, "重组领料申请单失败: " . $e->getMessage()];
  684. }
  685. }
  686. public function rebuildBjDetails1($mainId, $insertData)
  687. {
  688. try {
  689. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  690. // 1. 删除旧明细
  691. DB::connection($this->connectionName)
  692. ->table('QMINSPECTVOUCHERS')
  693. ->where('ID', $mainId)
  694. ->delete();
  695. // 2. 获取新的起始 Autoid (报检单通常是 Autoid)
  696. $maxAutoid = DB::connection($this->connectionName)
  697. ->table('QMINSPECTVOUCHERS')
  698. ->max('Autoid') ?? 0;
  699. // 3. 分配新 Autoid
  700. foreach ($insertData as &$row) {
  701. $maxAutoid++;
  702. $row['Autoid'] = $maxAutoid;
  703. }
  704. // 4. 批量插入
  705. DB::connection($this->connectionName)
  706. ->table('QMINSPECTVOUCHERS')
  707. ->insert($insertData);
  708. return [true, ''];
  709. });
  710. } catch (\Throwable $e) {
  711. return [false, "重组报检单失败: " . $e->getMessage()];
  712. }
  713. }
  714. public function rebuildBjDetails($mainId, $insertData)
  715. {
  716. try {
  717. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  718. // 1. 删除旧明细
  719. DB::connection($this->connectionName)
  720. ->table('QMINSPECTVOUCHERS')
  721. ->where('ID', $mainId)
  722. ->delete();
  723. $maxAutoid = DB::connection($this->connectionName)
  724. ->table('QMINSPECTVOUCHERS')
  725. ->max('Autoid') ?? 0;
  726. // 过滤掉不可插入的字段,特别是 UFTS
  727. foreach ($insertData as $key => $row) {
  728. $maxAutoid++;
  729. // 彻底清理:移除 UFTS 字段,防止插入报错及 JSON 转换报错
  730. unset($row['UFTS']);
  731. $row['Autoid'] = $maxAutoid;
  732. $insertData[$key] = $row;
  733. }
  734. // 4. 批量插入
  735. DB::connection($this->connectionName)
  736. ->table('QMINSPECTVOUCHERS')
  737. ->insert($insertData);
  738. return [true, '操作成功'];
  739. });
  740. } catch (\Throwable $e) {
  741. // 这里返回错误信息时,确保不包含二进制内容
  742. return [false, "重组报检单失败: " . $e->getMessage()];
  743. }
  744. }
  745. }