U8ThirtyPartyDatabaseServerService.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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. 'main.bFree1 as param_one',
  233. 'main.bFree2 as param_two',
  234. // 关键点:将二进制 ufts 转换为 0x... 字符串
  235. DB::raw("master.sys.fn_varbintohexstr(main.pubufts) as ufts_str")
  236. ]);
  237. // 使用 product_code 做分页依据
  238. if ($lastCode) {
  239. $query->where('main.cInvCode', '>', $lastCode);
  240. }
  241. if (!empty($config['whereRaw'])) {
  242. $query->whereRaw($config['whereRaw']);
  243. }
  244. // 必须按编码排序,保证分页不重不漏
  245. $items = $query->orderBy('main.cInvCode', 'asc')
  246. ->limit($config['limit'])
  247. ->get();
  248. return [true, json_decode(json_encode($items), true)];
  249. } catch (\Exception $e) {
  250. Log::channel('apiLog')->error("U8获取存货异常: " . $e->getMessage());
  251. return [false, []];
  252. }
  253. }
  254. //获取单个产品报检单的明细
  255. public function getBjOrder($id){
  256. return DB::connection($this->connectionName)
  257. ->table('QMINSPECTVOUCHERS as detail')
  258. ->lock('WITH(NOLOCK)')
  259. ->where('detail.ID', $id)
  260. ->select('detail.*')
  261. ->get()
  262. ->map(function ($value) {
  263. return (array)$value;
  264. })
  265. ->keyBy('CINVCODE')
  266. ->toArray();
  267. }
  268. /**
  269. * 更新报检单明细
  270. * @param array $update [AutoID => [字段名 => 值], ...]
  271. * @param array $insert [[字段名 => 值], [字段名 => 值], ...]
  272. */
  273. public function updateBjOrder($update, $insert)
  274. {
  275. try {
  276. return DB::connection($this->connectionName)->transaction(function () use ($update, $insert) {
  277. // 1. 处理更新部分
  278. if (!empty($update)) {
  279. foreach ($update as $autoId => $fields) {
  280. DB::connection($this->connectionName)
  281. ->table('QMINSPECTVOUCHERS')
  282. ->where('AUTOID', $autoId)
  283. ->update($fields);
  284. }
  285. }
  286. // 2. 处理插入部分 (拆分行)
  287. if (!empty($insert)) {
  288. // 获取当前单据的最大行号,确保新行号递增
  289. // 注意:这里需要从 $insert 的第一个元素获取 ID,因为它们都属于同一个主表单据
  290. $mainId = $insert[0]['ID'] ?? null;
  291. if ($mainId) {
  292. $maxRowID = DB::connection($this->connectionName)
  293. ->table('QMINSPECTVOUCHERS')
  294. ->max('AUTOID') ?? 0;
  295. foreach ($insert as &$newRow) {
  296. $maxRowID++;
  297. $newRow['AUTOID'] = $maxRowID;
  298. }
  299. // 使用批量插入提高性能
  300. DB::connection($this->connectionName)
  301. ->table('QMINSPECTVOUCHERS')
  302. ->insert($insert);
  303. }
  304. }
  305. });
  306. return [true, ''];
  307. } catch (\Throwable $e) {
  308. return [false, $e->getMessage()];
  309. }
  310. }
  311. public function getJyOrder($id)
  312. {
  313. // 1. 获取表头信息 (主表)
  314. $main = DB::connection($this->connectionName)
  315. ->table('QMCHECKVOUCHER')
  316. ->lock('WITH(NOLOCK)')
  317. ->where('ID', $id)
  318. ->first();
  319. if (!$main) {
  320. return []; // 或者返回空数组 []
  321. }
  322. $main = (array)$main;
  323. return $main;
  324. }
  325. public function getScDetails($id)
  326. {
  327. // 1. 获取表头信息 (主表)
  328. $main = DB::connection($this->connectionName)
  329. ->table('mom_orderdetail')
  330. ->lock('WITH(NOLOCK)')
  331. ->where('MoDid', $id)
  332. ->first();
  333. if (!$main) {
  334. return []; // 或者返回空数组 []
  335. }
  336. $main = (array)$main;
  337. return $main;
  338. }
  339. //获取单个销售订单的信息
  340. public function getXsOrder($id)
  341. {
  342. // 1. 获取销售订单主表信息 (SO_SOMain)
  343. $main = DB::connection($this->connectionName)
  344. ->table('SO_SOMain')
  345. ->lock('WITH(NOLOCK)')
  346. ->where('ID', $id)
  347. ->first();
  348. if (!$main) {
  349. return [];
  350. }
  351. $main = (array)$main;
  352. // 2. 获取销售订单子表信息 (SO_SODetails)
  353. $details = DB::connection($this->connectionName)
  354. ->table('SO_SODetails')
  355. ->lock('WITH(NOLOCK)')
  356. ->where('ID', $id) // 子表通过 ID 关联主表
  357. ->get()
  358. ->map(function ($value) {
  359. return (array)$value;
  360. })
  361. ->toArray();
  362. // 3. 将子表数据放入 details 键中
  363. $main['details'] = $details;
  364. return $main;
  365. }
  366. public function getXsThOrder($id)
  367. {
  368. // 1. 获取销售退货单主表信息 (DispatchList)
  369. $main = DB::connection($this->connectionName)
  370. ->table('DispatchList')
  371. ->lock('WITH(NOLOCK)')
  372. ->where('DLID', $id) // 注意:主键叫 DLID
  373. ->first();
  374. if (!$main) {
  375. return [];
  376. }
  377. $main = (array)$main;
  378. // 2. 获取销售退货单子表信息 (DispatchLists)
  379. $details = DB::connection($this->connectionName)
  380. ->table('DispatchLists')
  381. ->lock('WITH(NOLOCK)')
  382. ->where('DLID', $id) // 通过 DLID 关联
  383. ->get()
  384. ->map(function ($value) {
  385. return (array)$value;
  386. })
  387. ->toArray();
  388. // 3. 将子表数据放入 details 键中
  389. $main['details'] = $details;
  390. return $main;
  391. }
  392. public function getFhOrder($id)
  393. {
  394. // 1. 获取销售发货单主表信息 (DispatchList)
  395. $main = DB::connection($this->connectionName)
  396. ->table('DispatchList')
  397. ->lock('WITH(NOLOCK)')
  398. ->where('DLID', $id) // U8发货单主键通常是 DLID
  399. ->first();
  400. if (!$main) {
  401. return [];
  402. }
  403. $main = (array)$main;
  404. // 2. 获取销售发货单子表信息 (DispatchLists)
  405. $details = DB::connection($this->connectionName)
  406. ->table('DispatchLists') // 注意这里是 DispatchLists
  407. ->lock('WITH(NOLOCK)')
  408. ->where('DLID', $id) // 子表通过 DLID 关联主表
  409. ->get()
  410. ->map(function ($value) {
  411. return (array)$value;
  412. })
  413. ->toArray();
  414. // 3. 将子表数据放入 details 键中
  415. $main['details'] = $details;
  416. return $main;
  417. }
  418. public function getCGDHDetails($id)
  419. {
  420. // 2. 获取采购到货单子表信息 (PU_ArrivalVouchs)
  421. $details = DB::connection($this->connectionName)
  422. ->table('PU_ArrivalVouchs')
  423. ->lock('WITH(NOLOCK)')
  424. ->where('ID', $id) // 通过 ID 关联主表
  425. ->get()
  426. ->map(function ($value) {
  427. return (array)$value;
  428. });
  429. // 3. 将子表数据以 cInvCode 为 Key 进行组织
  430. // 注意:如果一张单据里有重复的存货编码,后面的行会覆盖前面的行
  431. $details = $details->keyBy('cInvCode')->toArray();
  432. return $details;
  433. }
  434. public function getLlSQDetails($id)
  435. {
  436. // 1. 获取领料申请单子表信息 (MaterialAppVouchs)
  437. $details = DB::connection($this->connectionName)
  438. ->table('MaterialAppVouchs') // 领料申请单子表名
  439. ->lock('WITH(NOLOCK)')
  440. ->where('ID', $id) // 通过 ID 关联主表
  441. ->get()
  442. ->map(function ($value) {
  443. return (array)$value;
  444. });
  445. // 2. 将子表数据以 cInvCode 为 Key 进行组织
  446. // 提示:领料申请单中同一存货可能出现在不同行(如:对应不同的生产订单行)
  447. // 如果确定 cInvCode 唯一,可用 keyBy;如果不唯一,建议直接返回数组或 keyBy('AutoID')
  448. $details = $details->keyBy('cInvCode')->toArray();
  449. return $details;
  450. }
  451. public function updateDhOrder($update, $insert)
  452. {
  453. try {
  454. return DB::connection($this->connectionName)->transaction(function () use ($update, $insert) {
  455. // 1. 处理更新部分 (子表: PU_ArrivalVouchs)
  456. if (!empty($update)) {
  457. foreach ($update as $autoId => $fields) {
  458. DB::connection($this->connectionName)
  459. ->table('PU_ArrivalVouchs') // 修正为子表名
  460. ->where('Autoid', $autoId) // U8 习惯大写 A 小写 utoid,但 SQL 不敏感
  461. ->update($fields);
  462. }
  463. }
  464. // 2. 处理插入部分 (拆分行)
  465. if (!empty($insert)) {
  466. $mainId = $insert[0]['ID'] ?? null;
  467. if ($mainId) {
  468. // 获取全表最大 Autoid,确保全局唯一
  469. $maxRowID = DB::connection($this->connectionName)
  470. ->table('PU_ArrivalVouchs') // 修正为子表名
  471. ->max('Autoid') ?? 0;
  472. foreach ($insert as &$newRow) {
  473. $maxRowID++;
  474. $newRow['Autoid'] = $maxRowID;
  475. }
  476. // 使用批量插入
  477. DB::connection($this->connectionName)
  478. ->table('PU_ArrivalVouchs')
  479. ->insert($insert);
  480. }
  481. }
  482. return [true, '']; // 事务成功返回
  483. });
  484. } catch (\Throwable $e) {
  485. // 打印错误堆栈有助于调试
  486. return [false, "修改采购到货单失败: " . $e->getMessage()];
  487. }
  488. }
  489. public function getCgOrder($id)
  490. {
  491. // 1. 获取采购到货单主表信息 (PU_ArrivalVouch)
  492. // 关键:关联键是 ID
  493. $main = DB::connection($this->connectionName)
  494. ->table('PU_ArrivalVouch')
  495. ->lock('WITH(NOLOCK)')
  496. ->where('ID', $id)
  497. ->first();
  498. if (!$main) {
  499. return [];
  500. }
  501. $main = (array)$main;
  502. // 2. 获取采购到货单子表信息 (PU_ArrivalVouchs)
  503. $details = DB::connection($this->connectionName)
  504. ->table('PU_ArrivalVouchs')
  505. ->lock('WITH(NOLOCK)')
  506. ->where('ID', $id) // 子表通过 ID 关联主表
  507. ->get()
  508. ->map(function ($value) {
  509. return (array)$value;
  510. })
  511. ->toArray();
  512. // 3. 将子表数据放入 details 键中
  513. $main['details'] = $details;
  514. return $main;
  515. }
  516. public function getJyOrder2($id)
  517. {
  518. // 关联采购到货单子表 (PU_ArrivalVouchs) 获取金额字段
  519. $order = DB::connection($this->connectionName)
  520. ->table('QMCHECKVOUCHER as qm')
  521. ->leftJoin('PU_ArrivalVouchs as arr', 'qm.SOURCEAUTOID', '=', 'arr.Autoid')
  522. ->select(
  523. 'qm.*',
  524. 'arr.iCost', // 原币无税单价
  525. 'arr.iOriTaxCost', // 原币含税单价
  526. 'arr.iTaxRate' // 税率
  527. )
  528. ->where('qm.ID', $id) // 假设这是检验单主表ID
  529. ->first();
  530. return $order ? (array)$order : [];
  531. }
  532. public function updateLLOrder($update, $insert)
  533. {
  534. try {
  535. return DB::connection($this->connectionName)->transaction(function () use ($update, $insert) {
  536. // 1. 处理更新部分 (子表: MaterialAppVouchs)
  537. if (!empty($update)) {
  538. foreach ($update as $autoId => $fields) {
  539. DB::connection($this->connectionName)
  540. ->table('MaterialAppVouchs') // 领料申请单子表
  541. ->where('autoid', $autoId) // 注意字段名在 U8 里可能是 autoid 或 AutoID
  542. ->update($fields);
  543. }
  544. }
  545. // 2. 处理插入部分 (拆分行/新增行)
  546. if (!empty($insert)) {
  547. // 获取当前领料申请单子表的最大 Autoid,确保手动分配不冲突
  548. $maxRowID = DB::connection($this->connectionName)
  549. ->table('MaterialAppVouchs')
  550. ->max('autoid') ?? 0;
  551. foreach ($insert as &$newRow) {
  552. $maxRowID++;
  553. // U8 的 autoid 通常必须手动指定
  554. $newRow['autoid'] = $maxRowID;
  555. }
  556. // 使用批量插入
  557. DB::connection($this->connectionName)
  558. ->table('MaterialAppVouchs')
  559. ->insert($insert);
  560. }
  561. return [true, ''];
  562. });
  563. } catch (\Throwable $e) {
  564. // 建议记录详细日志
  565. return [false, "修改领料申请单失败: " . $e->getMessage()];
  566. }
  567. }
  568. public function getLLOrder($id)
  569. {
  570. // 关键:关联键是 ID
  571. $main = DB::connection($this->connectionName)
  572. ->table('MaterialAppVouch')
  573. ->lock('WITH(NOLOCK)')
  574. ->where('ID', $id)
  575. ->first();
  576. if (!$main) {
  577. return [];
  578. }
  579. $main = (array)$main;
  580. // 2. 获取采购到货单子表信息 (PU_ArrivalVouchs)
  581. $details = DB::connection($this->connectionName)
  582. ->table('MaterialAppVouchs')
  583. ->lock('WITH(NOLOCK)')
  584. ->where('ID', $id) // 子表通过 ID 关联主表
  585. ->get()
  586. ->map(function ($value) {
  587. return (array)$value;
  588. })
  589. ->toArray();
  590. // 3. 将子表数据放入 details 键中
  591. $main['details'] = $details;
  592. return $main;
  593. }
  594. public function checkInventoryControl($invCodes)
  595. {
  596. if (empty($invCodes)) {
  597. return [false, '存货编码为空'];
  598. }
  599. // 1. 查询存货档案
  600. $list = DB::connection($this->connectionName)
  601. ->table('Inventory')
  602. ->whereIn('cInvCode', $invCodes)
  603. ->select(['cInvCode', 'cInvName', 'bInvBatch', 'bInvQuality'])
  604. ->get();
  605. $noBatch = []; // 未开启批次管理的
  606. $noExpiration = []; // 未开启保质期管理的
  607. $notFound = array_diff($invCodes, $list->pluck('cInvCode')->toArray()); // 数据库中不存在的
  608. foreach ($list as $item) {
  609. // 检查批次管理 (bInvBatch 为 0 表示未开启)
  610. if (empty($item->bInvBatch)) {
  611. $noBatch[] = $item->cInvCode . '(' . $item->cInvName . ')';
  612. }
  613. // 检查保质期管理 (bInvQuality 为 0 表示未开启)
  614. if (empty($item->bInvQuality)) {
  615. $noExpiration[] = $item->cInvCode . '(' . $item->cInvName . ')';
  616. }
  617. }
  618. // 2. 组织提示结果
  619. $messages = [];
  620. if (!empty($noBatch)) {
  621. $messages[] = "【未开启批次管理】: " . implode(', ', $noBatch);
  622. }
  623. if (!empty($noExpiration)) {
  624. $messages[] = "【未开启保质期管理】: " . implode(', ', $noExpiration);
  625. }
  626. if (!empty($notFound)) {
  627. $messages[] = "【档案不存在】: " . implode(', ', $notFound);
  628. }
  629. if (empty($messages)) {
  630. return [true, ''];
  631. }
  632. return [false, implode("\n", $messages)];
  633. }
  634. public function rebuildDhDetails($mainId, $insertData)
  635. {
  636. try {
  637. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  638. // 1. 删除旧明细
  639. DB::connection($this->connectionName)
  640. ->table('PU_ArrivalVouchs')
  641. ->where('ID', $mainId)
  642. ->delete();
  643. // 2. 获取新的起始 Autoid
  644. $maxAutoid = DB::connection($this->connectionName)
  645. ->table('PU_ArrivalVouchs')
  646. ->max('Autoid') ?? 0;
  647. // 3. 分配新 Autoid 并插入
  648. foreach ($insertData as &$row) {
  649. $maxAutoid++;
  650. $row['Autoid'] = $maxAutoid;
  651. }
  652. DB::connection($this->connectionName)
  653. ->table('PU_ArrivalVouchs')
  654. ->insert($insertData);
  655. return [true, ''];
  656. });
  657. } catch (\Throwable $e) {
  658. return [false, "重建明细失败: " . $e->getMessage()];
  659. }
  660. }
  661. public function rebuildLLDetails($mainId, $insertData)
  662. {
  663. try {
  664. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  665. // 1. 删除旧明细 (领料申请单子表)
  666. DB::connection($this->connectionName)
  667. ->table('MaterialAppVouchs')
  668. ->where('ID', $mainId)
  669. ->delete();
  670. // 2. 获取新的起始 autoid
  671. $maxAutoid = DB::connection($this->connectionName)
  672. ->table('MaterialAppVouchs')
  673. ->max('AutoID') ?? 0;
  674. // 3. 分配新 autoid 并插入
  675. foreach ($insertData as &$row) {
  676. $maxAutoid++;
  677. $row['AutoID'] = $maxAutoid;
  678. }
  679. DB::connection($this->connectionName)
  680. ->table('MaterialAppVouchs')
  681. ->insert($insertData);
  682. return [true, ''];
  683. });
  684. } catch (\Throwable $e) {
  685. return [false, "重组领料申请单失败: " . $e->getMessage()];
  686. }
  687. }
  688. public function rebuildBjDetails1($mainId, $insertData)
  689. {
  690. try {
  691. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  692. // 1. 删除旧明细
  693. DB::connection($this->connectionName)
  694. ->table('QMINSPECTVOUCHERS')
  695. ->where('ID', $mainId)
  696. ->delete();
  697. // 2. 获取新的起始 Autoid (报检单通常是 Autoid)
  698. $maxAutoid = DB::connection($this->connectionName)
  699. ->table('QMINSPECTVOUCHERS')
  700. ->max('Autoid') ?? 0;
  701. // 3. 分配新 Autoid
  702. foreach ($insertData as &$row) {
  703. $maxAutoid++;
  704. $row['Autoid'] = $maxAutoid;
  705. }
  706. // 4. 批量插入
  707. DB::connection($this->connectionName)
  708. ->table('QMINSPECTVOUCHERS')
  709. ->insert($insertData);
  710. return [true, ''];
  711. });
  712. } catch (\Throwable $e) {
  713. return [false, "重组报检单失败: " . $e->getMessage()];
  714. }
  715. }
  716. public function rebuildBjDetails($mainId, $insertData)
  717. {
  718. try {
  719. return DB::connection($this->connectionName)->transaction(function () use ($mainId, $insertData) {
  720. // 1. 删除旧明细
  721. DB::connection($this->connectionName)
  722. ->table('QMINSPECTVOUCHERS')
  723. ->where('ID', $mainId)
  724. ->delete();
  725. $maxAutoid = DB::connection($this->connectionName)
  726. ->table('QMINSPECTVOUCHERS')
  727. ->max('Autoid') ?? 0;
  728. // 过滤掉不可插入的字段,特别是 UFTS
  729. foreach ($insertData as $key => $row) {
  730. $maxAutoid++;
  731. // 彻底清理:移除 UFTS 字段,防止插入报错及 JSON 转换报错
  732. unset($row['UFTS']);
  733. $row['Autoid'] = $maxAutoid;
  734. $insertData[$key] = $row;
  735. }
  736. // 4. 批量插入
  737. DB::connection($this->connectionName)
  738. ->table('QMINSPECTVOUCHERS')
  739. ->insert($insertData);
  740. return [true, '操作成功'];
  741. });
  742. } catch (\Throwable $e) {
  743. // 这里返回错误信息时,确保不包含二进制内容
  744. return [false, "重组报检单失败: " . $e->getMessage()];
  745. }
  746. }
  747. }