ProcessDataJob.php 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. <?php
  2. namespace App\Jobs;
  3. use App\Model\DDEmployee;
  4. use App\Model\Inventory;
  5. use App\Model\Record;
  6. use App\Model\U8State;
  7. use App\Model\Vendor;
  8. use App\Service\U8DatabaseServerService;
  9. use Illuminate\Bus\Queueable;
  10. use Illuminate\Contracts\Queue\ShouldQueue;
  11. use Illuminate\Foundation\Bus\Dispatchable;
  12. use Illuminate\Queue\InteractsWithQueue;
  13. use Illuminate\Queue\SerializesModels;
  14. use Symfony\Component\Console\Output\ConsoleOutput;
  15. use Symfony\Component\Console\Output\OutputInterface;
  16. class ProcessDataJob implements ShouldQueue
  17. {
  18. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  19. protected $data;
  20. public $timeout = 30;
  21. public function __construct($data)
  22. {
  23. //record表
  24. $this->data = $data;
  25. }
  26. public function handle()
  27. {
  28. try {
  29. list($bool, $msg) = $this->syncApprovedRecords($this->data);
  30. if(! $bool) $this->finalDo($msg, $this->data);
  31. } catch (\Throwable $e) {
  32. $this->finalDo("异常:" . $e->getMessage());
  33. $this->delete();
  34. }
  35. }
  36. private function finalDo($msg, $record){
  37. Record::where('id', $record['id'])
  38. ->update(['result' => $msg]);
  39. }
  40. private function syncApprovedRecords($record)
  41. {
  42. try {
  43. $LoginType = $record['login_type'];
  44. $database = $record['database'];
  45. $service = new U8DatabaseServerService(['zt_database' => $database]);
  46. if ($service->error) return [false, $service->error];
  47. $time = date("Y-m-d H:i:s");
  48. $time1 = date("Y-m-d 00:00:00");
  49. if($record['del_time'] == 2){
  50. $type = $record['type'];
  51. $order_number = $record['order_number'];
  52. $system_name = "system";
  53. $name = DDEmployee::where('userid', $record['userid'])->where('login_type', $LoginType)->value('name');
  54. if(! empty($name)) $system_name = $name;
  55. if($type == Record::type_one){
  56. $service->db->table("PO_Pomain")
  57. ->where("cPOID", $order_number)
  58. ->update([
  59. "cVerifier" => $system_name,
  60. "iverifystateex" => 1,
  61. "cState" => 1,
  62. "cAuditTime" => $time . ".000",
  63. "cAuditDate" => $time1 . ".000",
  64. ]);
  65. }elseif($type == Record::type_two){
  66. $service->db->table("PU_AppVouch")
  67. ->where("cCode", $order_number)
  68. ->update([
  69. "cVerifier" => $system_name,
  70. "cAuditTime" => $time . ".000",
  71. "cAuditDate" => $time1 . ".000",
  72. ]);
  73. }elseif($type == Record::type_three){
  74. $service->db->table("RdRecord01")
  75. ->where("cCode", $order_number)
  76. ->update([
  77. "cHandler" => $system_name,
  78. "dnverifytime" => $time . ".000",
  79. "dVeriDate" => $time1 . ".000",
  80. ]);
  81. }elseif($type == Record::type_four){
  82. list($status, $msg) = $this->inventoryAddToU8($record, $name, $service->db);
  83. if(! $status) return [false, $msg];
  84. }elseif($type == Record::type_five){
  85. list($status, $msg) = $this->vendorAddToU8($record, $name, $service->db);
  86. if(! $status) return [false, $msg];
  87. }
  88. // 更新本地数据 通过状态
  89. Record::where("id", $record['id'])->update(['del_time' => 3]);
  90. // 更新状态为 通过状态
  91. U8State::updateOrCreate(
  92. ['order_number' => $record['order_number'], 'login_type' => $record['login_type'], 'type' => $record['type']],
  93. ['state' => U8State::state_one]
  94. );
  95. }
  96. $service->close();
  97. } catch (\Throwable $e) {
  98. return [false, $e->getMessage()];
  99. }
  100. return [true, ''];
  101. }
  102. public function inventoryAddToU81($data, $service){
  103. $inventory = Inventory::where('del_time', 0)
  104. ->where('order_number', $data['order_number'])
  105. ->where('login_type', $data['login_type'])
  106. ->first();
  107. if(empty($inventory)) return [false, '存货记录不存在或已被删除'];
  108. $inventory = $inventory->toArray();
  109. $title = $inventory['title'];
  110. $category_code = $inventory['category_code'];
  111. if(! empty($data['code'])){
  112. //用户传入
  113. $no = $inventory['code'];
  114. $flag_title = "重填";
  115. }else{
  116. //生成编码
  117. list($status, $msg) = $this->generate('inventory',$category_code, $service);
  118. if(! $status) return [false, $msg];
  119. $no = $msg;
  120. $flag_title = "重试";
  121. }
  122. $inventoryData = [
  123. 'cInvCode' => $no,
  124. 'cInvName' => $title,
  125. 'cInvCCode' => $category_code,
  126. 'cInvStd' => $inventory['size'] ?? null, // 规格型号
  127. 'bSale' => $inventory['bSale'], //内销
  128. 'bExpSale' => $inventory['bExpSale'], //外销
  129. 'bPurchase' => $inventory['bPurchase'], // 采购
  130. 'bSelf' => $inventory['bSelf'], // 自制
  131. 'bComsume' => $inventory['bComsume'], // 生产耗材
  132. 'iGroupType' => $inventory['unit_group_type'], // 计量单位组类别
  133. 'cGroupCode' => $inventory['unit_group_code'], //计量单位组
  134. 'cComUnitCode' => $inventory['unit_code'], // 主计量单位
  135. 'cShopUnit' => $inventory['unit_code'], // 零售计量单位
  136. 'iImpTaxRate' => $inventory['iImpTaxRate'], // 进项税率
  137. 'iTaxRate' => $inventory['iTaxRate'], // 销项税率
  138. 'dSDate' => date("Y-m-d 00:00:00.000"), // 启用日期
  139. 'cEnterprise' => $inventory['vendor_code_title'] ?? null,
  140. 'iSupplyType' => '0', // 供应类型
  141. 'fConvertRate' => '1.0', // 转换因子
  142. 'bInTotalCost' => '1', // 成本累计否
  143. 'cPlanMethod' => 'R',
  144. 'cSRPolicy' => 'PE',
  145. 'bBomMain' => '0', // 允许BOM母件
  146. 'bBomSub' => '0', // 允许BOM子件
  147. 'bProductBill' => '0', // 允许生产订单
  148. 'iPlanDefault' => '1',
  149. 'iAllocatePrintDgt' => '4',
  150. 'bService' => '0',
  151. 'bAccessary' => '0',
  152. 'iInvAdvance' => '0.0',
  153. 'bInvQuality' => '0',
  154. 'bInvBatch' => '0',
  155. 'bInvEntrust' => '0',
  156. 'bInvOverStock' => '0',
  157. 'bFree1' => '0',
  158. 'bFree2' => '0',
  159. 'bInvType' => '0',
  160. 'bFree3' => '0',
  161. 'bFree4' => '0',
  162. 'bFree5' => '0',
  163. 'bFree6' => '0',
  164. 'bFree7' => '0',
  165. 'bFree8' => '0',
  166. 'bFree9' => '0',
  167. 'bFree10' => '0',
  168. 'cCreatePerson' => 'demo',
  169. 'cModifyPerson' => 'demo', // 变更
  170. 'dModifyDate' => date("Y-m-d H:i:s.000"),
  171. 'bFixExch' => '0',
  172. 'bTrack' => '0',
  173. 'bSerial' => '0',
  174. 'bBarCode' => '0',
  175. 'bSolitude' => '0',
  176. 'bSpecialties' => '0',
  177. 'bPropertyCheck' => '0',
  178. 'iRecipeBatch' => '0',
  179. 'bPromotSales' => '0',
  180. 'bPlanInv' => '0',
  181. 'bProxyForeign' => '0',
  182. 'bATOModel' => '0',
  183. 'bCheckItem' => '0',
  184. 'bPTOModel' => '0',
  185. 'bEquipment' => '0',
  186. 'bMPS' => '0',
  187. 'bROP' => '0',
  188. 'bRePlan' => '0',
  189. 'bBillUnite' => '0',
  190. 'bCutMantissa' => '0',
  191. 'bConfigFree1' => '0',
  192. 'bConfigFree2' => '0',
  193. 'bConfigFree3' => '0',
  194. 'bConfigFree4' => '0',
  195. 'bConfigFree5' => '0',
  196. 'bConfigFree6' => '0',
  197. 'bConfigFree7' => '0',
  198. 'bConfigFree8' => '0',
  199. 'bConfigFree9' => '0',
  200. 'bConfigFree10' => '0',
  201. 'bPeriodDT' => '0',
  202. 'bOutInvDT' => '0',
  203. 'bBackInvDT' => '0',
  204. 'bDTWarnInv' => '0',
  205. 'bImportMedicine' => '0',
  206. 'bFirstBusiMedicine' => '0',
  207. 'bForeExpland' => '0',
  208. 'bInvModel' => '0',
  209. 'bKCCutMantissa' => '0',
  210. 'bReceiptByDT' => '0',
  211. 'bCheckBSATP' => '0',
  212. 'bCheckFree1' => '0',
  213. 'bCheckFree2' => '0',
  214. 'bCheckFree3' => '0',
  215. 'bCheckFree4' => '0',
  216. 'bCheckFree5' => '0',
  217. 'bCheckFree6' => '0',
  218. 'bCheckFree7' => '0',
  219. 'bCheckFree8' => '0',
  220. 'bCheckFree9' => '0',
  221. 'bCheckFree10' => '0',
  222. 'iCheckATP' => '0',
  223. 'bPiece' => '0',
  224. 'bSrvItem' => '0',
  225. 'bSrvFittings' => '0',
  226. 'bSpecialOrder' => '0',
  227. 'bTrackSaleBill' => '0',
  228. 'bCheckBatch' => '0',
  229. 'bMngOldpart' => '0',
  230. ];
  231. $inventorySubData = [
  232. 'cInvSubCode' => $no,
  233. 'iSurenessType' => '1',
  234. 'bIsAttachFile' => '0',
  235. 'bInByProCheck' => '1',
  236. 'iRequireTrackStyle' => '0',
  237. 'iExpiratDateCalcu' => '0',
  238. 'iBOMExpandUnitType' => '1',
  239. 'iDrawType' => $inventory['iDrawType'] ?? 0, // 领用方式
  240. 'fInvCIQExch' => $inventory['customs_change_rate'] ?? 1, // 海关换算率
  241. 'bInvKeyPart' => '1',
  242. 'iAcceptEarlyDays' => '999',
  243. 'dInvCreateDatetime' => date("Y-m-d H:i:s.000"),
  244. 'bPUQuota' => '0',
  245. 'bInvROHS' => '0',
  246. 'bPrjMat' => '0',
  247. 'bInvAsset' => '0',
  248. 'bSrvProduct' => '0',
  249. 'iAcceptDelayDays' => '0',
  250. 'bSCkeyProjections' => '0',
  251. 'iSupplyPeriodType' => '1',
  252. 'iAvailabilityDate' => '1',
  253. 'bImport' => '0',
  254. 'bCheckSubitemCost' => '1',
  255. 'fRoundFactor' => '0.0',
  256. 'bConsiderFreeStock' => '1',
  257. 'bSuitRetail' => '0',
  258. 'bFeatureMatch' => '0',
  259. 'bProduceByFeatureAllocate' => '0',
  260. 'bMaintenance' => '0',
  261. 'iMaintenanceCycleUnit' => '0',
  262. 'bCoupon' => '0',
  263. 'bStoreCard' => '0',
  264. 'bProcessProduct' => '0',
  265. 'bProcessMaterial' => '0',
  266. // 所有的价格自由项默认设为 '0'
  267. 'bPurPriceFree1' => '0', 'bPurPriceFree2' => '0', 'bPurPriceFree3' => '0', 'bPurPriceFree4' => '0', 'bPurPriceFree5' => '0',
  268. 'bPurPriceFree6' => '0', 'bPurPriceFree7' => '0', 'bPurPriceFree8' => '0', 'bPurPriceFree9' => '0', 'bPurPriceFree10' => '0',
  269. 'bOMPriceFree1' => '0', 'bOMPriceFree2' => '0', 'bOMPriceFree3' => '0', 'bOMPriceFree4' => '0', 'bOMPriceFree5' => '0',
  270. 'bOMPriceFree6' => '0', 'bOMPriceFree7' => '0', 'bOMPriceFree8' => '0', 'bOMPriceFree9' => '0', 'bOMPriceFree10' => '0',
  271. 'bSalePriceFree1' => '0', 'bSalePriceFree2' => '0', 'bSalePriceFree3' => '0', 'bSalePriceFree4' => '0', 'bSalePriceFree5' => '0',
  272. 'bSalePriceFree6' => '0', 'bSalePriceFree7' => '0', 'bSalePriceFree8' => '0', 'bSalePriceFree9' => '0', 'bSalePriceFree10' => '0',
  273. // 所有的控制自由项默认设为 '0'
  274. 'bControlFreeRange1' => '0', 'bControlFreeRange2' => '0', 'bControlFreeRange3' => '0', 'bControlFreeRange4' => '0', 'bControlFreeRange5' => '0',
  275. 'bControlFreeRange6' => '0', 'bControlFreeRange7' => '0', 'bControlFreeRange8' => '0', 'bControlFreeRange9' => '0', 'bControlFreeRange10' => '0',
  276. // 所有的批次属性默认设为 '0'
  277. 'bBatchProperty1' => '0', 'bBatchProperty2' => '0', 'bBatchProperty3' => '0', 'bBatchProperty4' => '0', 'bBatchProperty5' => '0',
  278. 'bBatchProperty6' => '0', 'bBatchProperty7' => '0', 'bBatchProperty8' => '0', 'bBatchProperty9' => '0', 'bBatchProperty10' => '0',
  279. 'bBondedInv' => '0',
  280. 'bBatchCreate' => '0',
  281. ];
  282. try {
  283. $service->beginTransaction();
  284. $exists = $service->table('Inventory')
  285. ->where('cInvCode', $inventoryData['cInvCode'])
  286. ->lockForUpdate() // 锁定该行,防止并发冲突
  287. ->exists();
  288. if ($exists) return [false, '存货编码已存在,请' . $flag_title];
  289. $service->table('Inventory')->insert($inventoryData);
  290. $service->table('Inventory_sub')->insert($inventorySubData);
  291. $service->commit();
  292. } catch (\Throwable $exception) {
  293. $service->rollBack();
  294. return [false, "创建用友失败: " . $exception->getMessage()];
  295. }
  296. return [true, ''];
  297. }
  298. public function inventoryAddToU82($data, $username, $service)
  299. {
  300. // 1. 获取本地存货记录
  301. $inventory = Inventory::where('del_time', 0)
  302. ->where('order_number', $data['order_number'])
  303. ->where('login_type', $data['login_type'])
  304. ->first();
  305. if (empty($inventory)) {
  306. return [false, '本地存货记录不存在或已被删除'];
  307. }
  308. $inventory = $inventory->toArray();
  309. // 2. 提取核心属性变量并转换为布尔/整数
  310. $bSale = (int)($inventory['bSale'] ?? 0); // 销售(内销)
  311. $bExpSale = (int)($inventory['bExpSale'] ?? 0); // 外销
  312. $bPurchase = (int)($inventory['bPurchase'] ?? 0); // 采购
  313. $bSelf = (int)($inventory['bSelf'] ?? 0); // 自制
  314. $bComsume = (int)($inventory['bComsume'] ?? 0); // 生产耗用
  315. $bProxy = (int)($inventory['bProxy'] ?? 0); // 委外 (若数据库无此字段,建议默认0)
  316. // --- 用友业务规则动态计算开始 ---
  317. // 2.1 计划默认属性 (iPlanDefault)
  318. // 规则:自制=1, 委外=2, 采购=3, 计划品=4。优先级:自制 > 委外 > 采购
  319. $iPlanDefault = 0;
  320. if ($bSelf) {
  321. $iPlanDefault = 1;
  322. } elseif ($bProxy) {
  323. $iPlanDefault = 2;
  324. } elseif ($bPurchase) {
  325. $iPlanDefault = 3;
  326. }
  327. // 2.2 允许BOM母件 (bBomMain)
  328. // 规则:自制、委外、计划品等默认为1;纯采购件默认为0
  329. $bBomMain = ($bSelf || $bProxy) ? 1 : 0;
  330. // 2.3 允许BOM子件 (bBomSub)
  331. // 规则:只要涉及到生产消耗或采购,通常都允许作为子件
  332. $bBomSub = ($bSelf || $bProxy || $bPurchase || $bComsume) ? 1 : 0;
  333. // 2.4 允许生产订单 (bProductBill)
  334. // 规则:只有“自制”属性为“是”时,才允许下达生产订单
  335. $bProductBill = $bSelf ? 1 : 0;
  336. // 2.5 计划方法 (cPlanMethod) 和 成本相关 (bInTotalCost)
  337. // 规则:如果非内外销且非生产耗用,但勾选了BOM子件,属于辅助性物料,不计算MRP
  338. $cPlanMethod = 'R'; // R: MRP/MPS计算
  339. $bInTotalCost = 1; // 默认参与成本累计
  340. if (!$bSale && !$bExpSale && !$bComsume && $bBomSub) {
  341. $cPlanMethod = 'N'; // N: 不计算
  342. $bInTotalCost = 0;
  343. }
  344. // --- 用友业务规则动态计算结束 ---
  345. // 3. 编码生成或使用传入编码
  346. $category_code = $inventory['category_code'];
  347. if (!empty($data['code'])) {
  348. $no = $data['code'];
  349. $flag_title = "重填";
  350. } else {
  351. // 调用编码生成器 (假设方法名为 generate)
  352. list($status, $msg) = $this->generate('inventory', $category_code, $service);
  353. if (!$status) {
  354. return [false, "生成存货编码失败: " . $msg];
  355. }
  356. $no = $msg;
  357. $flag_title = "重试";
  358. }
  359. // 4. 构建 Inventory 主表数据
  360. $inventoryData = [
  361. 'cInvCode' => $no,
  362. 'cInvName' => $inventory['title'],
  363. 'cInvCCode' => $category_code,
  364. 'cInvStd' => $inventory['size'] ?? null, // 规格型号
  365. 'bSale' => $bSale,
  366. 'bExpSale' => $bExpSale,
  367. 'bPurchase' => $bPurchase,
  368. 'bSelf' => $bSelf,
  369. 'bComsume' => $bComsume,
  370. 'bProxyForeign' => $bProxy, // 委外
  371. 'iGroupType' => $inventory['unit_group_type'],
  372. 'cGroupCode' => $inventory['unit_group_code'],
  373. 'cComUnitCode' => $inventory['unit_code'], // 主计量单位
  374. 'cShopUnit' => $inventory['unit_code'], // 零售单位
  375. 'iImpTaxRate' => $inventory['iImpTaxRate'], // 进项税率
  376. 'iTaxRate' => $inventory['iTaxRate'], // 销项税率
  377. 'dSDate' => date("Y-m-d 00:00:00.000"), // 启用日期
  378. 'cEnterprise' => $inventory['vendor_code_title'] ?? null,
  379. 'iSupplyType' => '0', // 领料方式:领用
  380. 'fConvertRate' => '1.0', // 转换因子
  381. 'bInTotalCost' => $bInTotalCost, // 动态计算
  382. 'cPlanMethod' => $cPlanMethod, // 动态计算
  383. 'cSRPolicy' => 'PE', // 供需政策:PE
  384. 'bBomMain' => $bBomMain, // 动态计算
  385. 'bBomSub' => $bBomSub, // 动态计算
  386. 'bProductBill' => $bProductBill, // 动态计算
  387. 'iPlanDefault' => $iPlanDefault, // 动态计算
  388. 'iAllocatePrintDgt' => '4',
  389. 'bService' => '0',
  390. 'bAccessary' => '0',
  391. 'iInvAdvance' => '0.0',
  392. 'bInvQuality' => '0',
  393. 'bInvBatch' => '0',
  394. 'bInvEntrust' => '0',
  395. 'bInvOverStock' => '0',
  396. 'cCreatePerson' => $username,
  397. 'dModifyDate' => date("Y-m-d H:i:s.000"),
  398. 'bPlanInv' => '0',
  399. 'bATOModel' => '0',
  400. 'bPTOModel' => '0',
  401. 'bMPS' => ($iPlanDefault == 1 || $iPlanDefault == 2) ? '1' : '0', // 只有自制委外才可能作为MPS件
  402. 'bROP' => '0',
  403. 'bRePlan' => '0',
  404. 'bCutMantissa' => '0',
  405. 'bCheckBSATP' => '0',
  406. 'iCheckATP' => '0',
  407. // 以下为大量自由项/控制位字段,默认设为 0
  408. 'bFree1' => '0', 'bFree2' => '0', 'bFree3' => '0', 'bFree4' => '0', 'bFree5' => '0',
  409. 'bFree6' => '0', 'bFree7' => '0', 'bFree8' => '0', 'bFree9' => '0', 'bFree10' => '0',
  410. 'bConfigFree1' => '0', 'bConfigFree2' => '0', 'bConfigFree3' => '0', 'bConfigFree4' => '0',
  411. 'bConfigFree5' => '0', 'bConfigFree6' => '0', 'bConfigFree7' => '0', 'bConfigFree8' => '0',
  412. 'bConfigFree9' => '0', 'bConfigFree10' => '0',
  413. ];
  414. // 5. 构建 Inventory_sub 表数据
  415. $inventorySubData = [
  416. 'cInvSubCode' => $no,
  417. 'iSurenessType' => '1',
  418. 'bIsAttachFile' => '0',
  419. 'bInByProCheck' => '1',
  420. 'iRequireTrackStyle' => '0',
  421. 'iExpiratDateCalcu' => '0',
  422. 'iBOMExpandUnitType' => '1', // BOM展开单位:主计量
  423. 'iDrawType' => $inventory['iDrawType'] ?? 0, // 领用方式
  424. 'fInvCIQExch' => $inventory['customs_change_rate'] ?? 1,
  425. 'bInvKeyPart' => '1',
  426. 'iAcceptEarlyDays' => '999',
  427. 'dInvCreateDatetime' => date("Y-m-d H:i:s.000"),
  428. 'bPUQuota' => '0',
  429. 'bInvROHS' => '0',
  430. 'bPrjMat' => '0',
  431. 'bInvAsset' => '0',
  432. 'bSrvProduct' => '0',
  433. 'iAcceptDelayDays' => '0',
  434. 'bSCkeyProjections' => '0',
  435. 'iSupplyPeriodType' => '1', // 供应期间类型:天
  436. 'iAvailabilityDate' => '1', // 第一需求日
  437. 'bImport' => '0',
  438. 'bCheckSubitemCost' => '1',
  439. 'fRoundFactor' => '0.0',
  440. 'bConsiderFreeStock' => '1',
  441. 'bSuitRetail' => '0',
  442. 'bFeatureMatch' => '0',
  443. 'bProduceByFeatureAllocate' => '0',
  444. 'bMaintenance' => '0',
  445. 'iMaintenanceCycleUnit' => '0',
  446. 'bCoupon' => '0',
  447. 'bStoreCard' => '0',
  448. 'bProcessProduct' => '0',
  449. 'bProcessMaterial' => '0',
  450. // 自由项价格控制全部设为 0
  451. 'bPurPriceFree1' => '0', 'bOMPriceFree1' => '0', 'bSalePriceFree1' => '0',
  452. 'bControlFreeRange1' => '0', 'bBatchProperty1' => '0',
  453. 'bBondedInv' => '0',
  454. 'bBatchCreate' => '0',
  455. ];
  456. // 6. 执行数据库同步(使用事务)
  457. try {
  458. $service->beginTransaction();
  459. // 检查存货编码是否冲突
  460. $exists = $service->table('Inventory')
  461. ->where('cInvCode', $no)
  462. ->lockForUpdate()
  463. ->exists();
  464. if ($exists) {
  465. $service->rollBack();
  466. return [false, '存货编码 [' . $no . '] 在用友系统中已存在,请' . $flag_title];
  467. }
  468. // 插入主表和从表
  469. $service->table('Inventory')->insert($inventoryData);
  470. $service->table('Inventory_sub')->insert($inventorySubData);
  471. $service->commit();
  472. } catch (\Throwable $exception) {
  473. $service->rollBack();
  474. return [false, "同步用友数据库失败: " . $exception->getMessage()];
  475. }
  476. return [true, '同步成功'];
  477. }
  478. public function vendorAddToU82($data, $username,$service){
  479. $vendor = Vendor::where('del_time', 0)
  480. ->where('order_number', $data['order_number'])
  481. ->where('login_type', $data['login_type'])
  482. ->first();
  483. if(empty($vendor)) return [false, '供应商记录不存在或已被删除'];
  484. $vendor = $vendor->toArray();
  485. if(! empty($vendor['code'])){
  486. //用户传入
  487. $no = $vendor['code'];
  488. $flag_title = "重填";
  489. }else{
  490. //生成编码
  491. list($status, $msg) = $this->generate('vendor','', $service);
  492. if(! $status) return [false, $msg];
  493. $no = $msg;
  494. $flag_title = "重试";
  495. }
  496. $vendorData = [
  497. 'cVenCode' => $no,
  498. 'cVenName' => $vendor['title'],
  499. 'cVenAbbName' => $vendor['easy_title'],
  500. 'cVCCode' => $vendor['category_code'],
  501. 'dVenDevDate' => date("Y-m-d 00:00:00.000"),
  502. 'iVenDisRate' => '0.0',
  503. 'iVenCreLine' => '0.0',
  504. 'iVenCreDate' => '0',
  505. 'cVenHeadCode' => $no,
  506. 'iAPMoney' => '0.0',
  507. 'iLastMoney' => '0.0',
  508. 'iLRMoney' => '0.0',
  509. 'iFrequency' => '0',
  510. 'bVenTax' => '1',
  511. 'cCreatePerson' => $username,
  512. 'cModifyPerson' => $username,
  513. 'dModifyDate' => date("Y-m-d H:i:s.000"),
  514. 'iGradeABC' => '-1',
  515. 'bLicenceDate' => '0',
  516. 'bBusinessDate' => '0',
  517. 'bProxyDate' => '0',
  518. 'bPassGMP' => '0',
  519. 'bVenCargo' => '1', // 采购
  520. 'bProxyForeign' => '0', // 委外
  521. 'bVenService' => '0', // 服务
  522. 'bVenOverseas' => '0', // 国外
  523. 'cVenExch_name' => '人民币',
  524. 'iVenGSPType' => '0',
  525. 'iVenGSPAuth' => '-1',
  526. 'bVenAccPeriodMng' => '0',
  527. 'bVenHomeBranch' => '0',
  528. 'dVenCreateDatetime' => date("Y-m-d H:i:s.000"),
  529. 'bIsVenAttachFile' => '0',
  530. 'bRetail' => '0',
  531. ];
  532. try {
  533. $service->beginTransaction();
  534. $exists = $service->table('Vendor')
  535. ->where('cVenCode', $vendorData['cVenCode'])
  536. ->lockForUpdate() // 锁定该行,防止并发冲突
  537. ->exists();
  538. if ($exists) return [false, '供应商编码已存在,请' . $flag_title];
  539. $service->table('Vendor')->insert($vendorData);
  540. $service->commit();
  541. } catch (\Throwable $exception) {
  542. $service->rollBack();
  543. return [false, "创建供应商失败: " . $exception->getMessage()];
  544. }
  545. return [true, ''];
  546. }
  547. public function generate2($type, $classCode = "", $service)
  548. {
  549. try {
  550. // 1. 确定对象映射
  551. $cardNumber = ($type === 'inventory') ? 'inventory' : 'Vendor';
  552. $cardNumber_name = ($type === 'inventory') ? '存货' : '供应商';
  553. $table = ($type === 'inventory') ? 'Inventory' : 'Vendor';
  554. $codeField = ($type === 'inventory') ? 'cInvCode' : 'cVenCode';
  555. // 2. 获取 U8 规则定义
  556. $rule = $service->table('VoucherNumber')
  557. ->where('CardNumber', $cardNumber)
  558. ->first();
  559. if (!$rule) return [false, "未找到 {$cardNumber_name} 的规则定义"];
  560. /**
  561. * 3. 动态解析前缀 (Prefix1, Prefix2, Prefix3)
  562. * U8 的规则通常存放在 PrefixRule 或 Prefix 字段中
  563. */
  564. $prefix = "";
  565. for ($i = 1; $i <= 3; $i++) {
  566. $ruleField = "Prefix{$i}Rule";
  567. $valField = "Prefix{$i}";
  568. // 检查规则描述
  569. $ruleDesc = $rule->$ruleField ?? ''; // 例如 "存货分类编码" 或 "GYS"
  570. $staticVal = $rule->$valField ?? '';
  571. if (str_contains($ruleDesc, '分类') || str_contains($staticVal, '分类')) {
  572. // 如果规则提到“分类”,则填入传入的分类编码
  573. $prefix .= $classCode;
  574. } elseif (!empty($ruleDesc)) {
  575. // 如果规则是具体的字符(如 "GYS"),直接拼接
  576. $prefix .= $ruleDesc;
  577. } elseif (!empty($staticVal) && $staticVal !== '手工输入' && $staticVal !== '存货分类编码') {
  578. // 如果静态值不是提示语,则作为前缀
  579. $prefix .= $staticVal;
  580. }
  581. }
  582. // 4. 获取流水号配置 (Glide)
  583. $glideLen = $rule->GlideLen > 0 ? $rule->GlideLen : 4;
  584. $startNum = $rule->iStartNumber ?? 1;
  585. // 5. 查找当前最大编码
  586. $expectedLen = strlen($prefix) + $glideLen;
  587. $lastCode = $service->table($table)
  588. ->where($codeField, 'like', $prefix . '%')
  589. ->whereRaw("LEN($codeField) = $expectedLen")
  590. ->orderBy($codeField, 'desc')
  591. ->value($codeField);
  592. // 6. 生成编码
  593. if (!$lastCode) {
  594. // 初始:前缀 + 起始值补零
  595. $finalCode = $prefix . str_pad($startNum, $glideLen, '0', STR_PAD_LEFT);
  596. } else {
  597. // 截取流水号自增
  598. $lastSerial = substr($lastCode, -$glideLen);
  599. $nextSerial = ++$lastSerial;
  600. // 溢出检查
  601. if (strlen($nextSerial) > $glideLen) {
  602. return [false, "流水号已溢出"];
  603. }
  604. $finalCode = $prefix . str_pad($nextSerial, $glideLen, '0', STR_PAD_LEFT);
  605. }
  606. return [true, $finalCode];
  607. } catch (\Throwable $e) {
  608. return [false, "生成失败: " . $e->getMessage()];
  609. }
  610. }
  611. /**
  612. * 将存货信息同步到用友 U8 系统
  613. * @param array $data 包含 order_number 和 login_type 等关键参数
  614. * @param string $username 当前操作人
  615. * @param object $service 用友数据库连接实例 (DB Service)
  616. * @return array [bool, string]
  617. */
  618. public function inventoryAddToU83($data, $username, $service)
  619. {
  620. // 1. 获取本地存货记录
  621. $inventory = Inventory::where('del_time', 0)
  622. ->where('order_number', $data['order_number'])
  623. ->where('login_type', $data['login_type'])
  624. ->first();
  625. if (empty($inventory)) {
  626. return [false, '本地存货记录不存在或已被删除'];
  627. }
  628. $inventory = $inventory->toArray();
  629. // 2. 提取核心属性变量并转换为布尔/整数
  630. $bSale = (int)($inventory['bSale'] ?? 0); // 销售(内销)
  631. $bExpSale = (int)($inventory['bExpSale'] ?? 0); // 外销
  632. $bPurchase = (int)($inventory['bPurchase'] ?? 0); // 采购
  633. $bSelf = (int)($inventory['bSelf'] ?? 0); // 自制
  634. $bComsume = (int)($inventory['bComsume'] ?? 0); // 生产耗用
  635. $bProxy = (int)($inventory['bProxy'] ?? 0); // 委外
  636. // --- 用友业务规则动态计算 ---
  637. $iPlanDefault = $bSelf ? 1 : ($bProxy ? 2 : ($bPurchase ? 3 : 0));
  638. $bBomMain = ($bSelf || $bProxy) ? 1 : 0;
  639. $bBomSub = ($bSelf || $bProxy || $bPurchase || $bComsume) ? 1 : 0;
  640. $bProductBill = $bSelf ? 1 : 0;
  641. $cPlanMethod = 'R';
  642. $bInTotalCost = 1;
  643. if (!$bSale && !$bExpSale && !$bComsume && $bBomSub) {
  644. $cPlanMethod = 'N';
  645. $bInTotalCost = 0;
  646. }
  647. // 3. 编码生成逻辑
  648. $category_code = $inventory['category_code'];
  649. $serialInfo = null;
  650. if (!empty($data['code'])) {
  651. $no = $data['code'];
  652. $flag_title = "重填";
  653. } else {
  654. list($status, $res) = $this->generate('inventory', $category_code, $service);
  655. if (!$status) return [false, "生成存货编码失败: " . $res];
  656. $no = $res['finalCode'];
  657. $serialInfo = $res;
  658. $flag_title = "重试";
  659. }
  660. // 4. 构建 Inventory 主表数据 (还原所有原始字段)
  661. $inventoryData = [
  662. 'cInvCode' => $no,
  663. 'cInvName' => $inventory['title'],
  664. 'cInvCCode' => $category_code,
  665. 'cInvStd' => $inventory['size'] ?? null,
  666. 'bSale' => $bSale,
  667. 'bExpSale' => $bExpSale,
  668. 'bPurchase' => $bPurchase,
  669. 'bSelf' => $bSelf,
  670. 'bComsume' => $bComsume,
  671. 'bProxyForeign' => $bProxy,
  672. 'iGroupType' => $inventory['unit_group_type'],
  673. 'cGroupCode' => $inventory['unit_group_code'],
  674. 'cComUnitCode' => $inventory['unit_code'],
  675. 'cShopUnit' => $inventory['unit_code'],
  676. 'iImpTaxRate' => $inventory['iImpTaxRate'],
  677. 'iTaxRate' => $inventory['iTaxRate'],
  678. 'dSDate' => date("Y-m-d 00:00:00.000"),
  679. 'cEnterprise' => $inventory['vendor_code_title'] ?? null,
  680. 'iSupplyType' => '0',
  681. 'fConvertRate' => '1.0',
  682. 'bInTotalCost' => $bInTotalCost,
  683. 'cPlanMethod' => $cPlanMethod,
  684. 'cSRPolicy' => 'PE',
  685. 'bBomMain' => $bBomMain,
  686. 'bBomSub' => $bBomSub,
  687. 'bProductBill' => $bProductBill,
  688. 'iPlanDefault' => $iPlanDefault,
  689. 'iAllocatePrintDgt' => '4',
  690. 'bService' => '0',
  691. 'bAccessary' => '0',
  692. 'iInvAdvance' => '0.0',
  693. 'bInvQuality' => '0',
  694. 'bInvBatch' => '0',
  695. 'bInvEntrust' => '0',
  696. 'bInvOverStock' => '0',
  697. 'cCreatePerson' => $username,
  698. 'dModifyDate' => date("Y-m-d H:i:s.000"),
  699. 'bPlanInv' => '0',
  700. 'bATOModel' => '0',
  701. 'bPTOModel' => '0',
  702. 'bMPS' => ($iPlanDefault == 1 || $iPlanDefault == 2) ? '1' : '0',
  703. 'bROP' => '0',
  704. 'bRePlan' => '0',
  705. 'bCutMantissa' => '0',
  706. 'bCheckBSATP' => '0',
  707. 'iCheckATP' => '0',
  708. 'bFree1' => '0', 'bFree2' => '0', 'bFree3' => '0', 'bFree4' => '0', 'bFree5' => '0',
  709. 'bFree6' => '0', 'bFree7' => '0', 'bFree8' => '0', 'bFree9' => '0', 'bFree10' => '0',
  710. 'bConfigFree1' => '0', 'bConfigFree2' => '0', 'bConfigFree3' => '0', 'bConfigFree4' => '0',
  711. 'bConfigFree5' => '0', 'bConfigFree6' => '0', 'bConfigFree7' => '0', 'bConfigFree8' => '0',
  712. 'bConfigFree9' => '0', 'bConfigFree10' => '0',
  713. ];
  714. // 5. 构建 Inventory_sub 表数据
  715. $inventorySubData = [
  716. 'cInvSubCode' => $no,
  717. 'iSurenessType' => '1',
  718. 'bIsAttachFile' => '0',
  719. 'bInByProCheck' => '1',
  720. 'iRequireTrackStyle' => '0',
  721. 'iExpiratDateCalcu' => '0',
  722. 'iBOMExpandUnitType' => '1',
  723. 'iDrawType' => $inventory['iDrawType'] ?? 0,
  724. 'fInvCIQExch' => $inventory['customs_change_rate'] ?? 1,
  725. 'bInvKeyPart' => '1',
  726. 'iAcceptEarlyDays' => '999',
  727. 'dInvCreateDatetime' => date("Y-m-d H:i:s.000"),
  728. 'bPUQuota' => '0',
  729. 'bInvROHS' => '0',
  730. 'bPrjMat' => '0',
  731. 'bInvAsset' => '0',
  732. 'bSrvProduct' => '0',
  733. 'iAcceptDelayDays' => '0',
  734. 'bSCkeyProjections' => '0',
  735. 'iSupplyPeriodType' => '1',
  736. 'iAvailabilityDate' => '1',
  737. 'bImport' => '0',
  738. 'bCheckSubitemCost' => '1',
  739. 'fRoundFactor' => '0.0',
  740. 'bConsiderFreeStock' => '1',
  741. 'bSuitRetail' => '0',
  742. 'bFeatureMatch' => '0',
  743. 'bProduceByFeatureAllocate' => '0',
  744. 'bMaintenance' => '0',
  745. 'iMaintenanceCycleUnit' => '0',
  746. 'bCoupon' => '0',
  747. 'bStoreCard' => '0',
  748. 'bProcessProduct' => '0',
  749. 'bProcessMaterial' => '0',
  750. 'bPurPriceFree1' => '0', 'bOMPriceFree1' => '0', 'bSalePriceFree1' => '0',
  751. 'bControlFreeRange1' => '0', 'bBatchProperty1' => '0',
  752. 'bBondedInv' => '0',
  753. 'bBatchCreate' => '0',
  754. ];
  755. // 6. 执行同步
  756. try {
  757. $service->beginTransaction();
  758. $exists = $service->table('Inventory')->where('cInvCode', $no)->lockForUpdate()->exists();
  759. if ($exists) {
  760. $service->rollBack();
  761. return [false, '存货编码 [' . $no . '] 在用友系统中已存在,请' . $flag_title];
  762. }
  763. $service->table('Inventory')->insert($inventoryData);
  764. $service->table('Inventory_sub')->insert($inventorySubData);
  765. // 更新流水号表
  766. if ($serialInfo) {
  767. $service->table('VoucherHistory')->updateOrInsert(
  768. ['CardNumber' => 'inventory', 'cContent' => '存货分类编码', 'cSeed' => $category_code],
  769. ['cNumber' => $serialInfo['serial']]
  770. );
  771. }
  772. $service->commit();
  773. } catch (\Throwable $exception) {
  774. $service->rollBack();
  775. return [false, "同步用友数据库失败: " . $exception->getMessage()];
  776. }
  777. return [true, '同步成功'];
  778. }
  779. public function inventoryAddToU8($data, $username, $service)
  780. {
  781. // 1. 获取本地存货记录
  782. $inventory = Inventory::where('del_time', 0)
  783. ->where('order_number', $data['order_number'])
  784. ->where('login_type', $data['login_type'])
  785. ->first();
  786. if (empty($inventory)) {
  787. return [false, '本地存货记录不存在或已被删除'];
  788. }
  789. $inventory = $inventory->toArray();
  790. // 2. 提取核心属性变量
  791. $bSale = (int)($inventory['bSale'] ?? 0);
  792. $bExpSale = (int)($inventory['bExpSale'] ?? 0);
  793. $bPurchase = (int)($inventory['bPurchase'] ?? 0);
  794. $bSelf = (int)($inventory['bSelf'] ?? 0);
  795. $bComsume = (int)($inventory['bComsume'] ?? 0);
  796. $bProxy = (int)($inventory['bProxy'] ?? 0);
  797. // --- 用友业务规则动态计算 ---
  798. $iPlanDefault = $bSelf ? 1 : ($bProxy ? 2 : ($bPurchase ? 3 : 0));
  799. $bBomMain = ($bSelf || $bProxy) ? 1 : 0;
  800. $bBomSub = ($bSelf || $bProxy || $bPurchase || $bComsume) ? 1 : 0;
  801. $bProductBill = $bSelf ? 1 : 0;
  802. $cPlanMethod = 'R';
  803. $bInTotalCost = 1;
  804. if (!$bSale && !$bExpSale && !$bComsume && $bBomSub) {
  805. $cPlanMethod = 'N';
  806. $bInTotalCost = 0;
  807. }
  808. // 3. 编码生成逻辑
  809. $category_code = $inventory['category_code'];
  810. $serialInfo = null;
  811. if (!empty($data['code'])) {
  812. $no = $data['code'];
  813. $flag_title = "重填";
  814. } else {
  815. list($status, $res) = $this->generate('inventory', $category_code, $service);
  816. if (!$status) return [false, "生成存货编码失败: " . $res];
  817. $no = $res['finalCode'];
  818. $serialInfo = $res;
  819. $flag_title = "重试";
  820. }
  821. // 4. 构建 Inventory 主表数据
  822. $inventoryData = [
  823. 'cInvCode' => $no,
  824. 'cInvName' => $inventory['title'],
  825. 'cInvCCode' => $category_code,
  826. 'cInvStd' => $inventory['size'] ?? null,
  827. 'bSale' => $bSale,
  828. 'bExpSale' => $bExpSale,
  829. 'bPurchase' => $bPurchase,
  830. 'bSelf' => $bSelf,
  831. 'bComsume' => $bComsume,
  832. 'bProxyForeign' => $bProxy,
  833. 'iGroupType' => $inventory['unit_group_type'],
  834. 'cGroupCode' => $inventory['unit_group_code'],
  835. 'cComUnitCode' => $inventory['unit_code'],
  836. 'cShopUnit' => $inventory['unit_code'],
  837. 'iImpTaxRate' => $inventory['iImpTaxRate'],
  838. 'iTaxRate' => $inventory['iTaxRate'],
  839. 'dSDate' => date("Y-m-d 00:00:00.000"),
  840. 'cEnterprise' => $inventory['vendor_code_title'] ?? null,
  841. 'iSupplyType' => '0',
  842. 'fConvertRate' => '1.0',
  843. 'bInTotalCost' => $bInTotalCost,
  844. 'cPlanMethod' => $cPlanMethod,
  845. 'cSRPolicy' => 'PE',
  846. 'bBomMain' => $bBomMain,
  847. 'bBomSub' => $bBomSub,
  848. 'bProductBill' => $bProductBill,
  849. 'iPlanDefault' => $iPlanDefault,
  850. 'iAllocatePrintDgt' => '4',
  851. 'bService' => '0',
  852. 'bAccessary' => '0',
  853. 'iInvAdvance' => '0.0',
  854. 'bInvQuality' => '0',
  855. 'bInvBatch' => '0',
  856. 'bInvEntrust' => '0',
  857. 'bInvOverStock' => '0',
  858. 'cCreatePerson' => $username,
  859. 'dModifyDate' => date("Y-m-d H:i:s.000"),
  860. 'bPlanInv' => '0',
  861. 'bATOModel' => '0',
  862. 'bPTOModel' => '0',
  863. 'bMPS' => ($iPlanDefault == 1 || $iPlanDefault == 2) ? '1' : '0',
  864. 'bROP' => '0',
  865. 'bRePlan' => '0',
  866. 'bCutMantissa' => '0',
  867. 'bCheckBSATP' => '0',
  868. 'iCheckATP' => '0',
  869. 'bFree1' => '0', 'bFree2' => '0', 'bFree3' => '0', 'bFree4' => '0', 'bFree5' => '0',
  870. 'bFree6' => '0', 'bFree7' => '0', 'bFree8' => '0', 'bFree9' => '0', 'bFree10' => '0',
  871. 'bConfigFree1' => '0', 'bConfigFree2' => '0', 'bConfigFree3' => '0', 'bConfigFree4' => '0',
  872. 'bConfigFree5' => '0', 'bConfigFree6' => '0', 'bConfigFree7' => '0', 'bConfigFree8' => '0',
  873. 'bConfigFree9' => '0', 'bConfigFree10' => '0',
  874. ];
  875. // 5. 构建 Inventory_sub 表数据
  876. $inventorySubData = [
  877. 'cInvSubCode' => $no,
  878. 'iSurenessType' => '1',
  879. 'bIsAttachFile' => '0',
  880. 'bInByProCheck' => '1',
  881. 'iRequireTrackStyle' => '0',
  882. 'iExpiratDateCalcu' => '0',
  883. 'iBOMExpandUnitType' => '1',
  884. 'iDrawType' => $inventory['iDrawType'] ?? 0,
  885. 'fInvCIQExch' => $inventory['customs_change_rate'] ?? 1,
  886. 'bInvKeyPart' => '1',
  887. 'iAcceptEarlyDays' => '999',
  888. 'dInvCreateDatetime' => date("Y-m-d H:i:s.000"),
  889. 'bPUQuota' => '0',
  890. 'bInvROHS' => '0',
  891. 'bPrjMat' => '0',
  892. 'bInvAsset' => '0',
  893. 'bSrvProduct' => '0',
  894. 'iAcceptDelayDays' => '0',
  895. 'bSCkeyProjections' => '0',
  896. 'iSupplyPeriodType' => '1',
  897. 'iAvailabilityDate' => '1',
  898. 'bImport' => '0',
  899. 'bCheckSubitemCost' => '1',
  900. 'fRoundFactor' => '0.0',
  901. 'bConsiderFreeStock' => '1',
  902. 'bSuitRetail' => '0',
  903. 'bFeatureMatch' => '0',
  904. 'bProduceByFeatureAllocate' => '0',
  905. 'bMaintenance' => '0',
  906. 'iMaintenanceCycleUnit' => '0',
  907. 'bCoupon' => '0',
  908. 'bStoreCard' => '0',
  909. 'bProcessProduct' => '0',
  910. 'bProcessMaterial' => '0',
  911. 'bPurPriceFree1' => '0', 'bOMPriceFree1' => '0', 'bSalePriceFree1' => '0',
  912. 'bControlFreeRange1' => '0', 'bBatchProperty1' => '0',
  913. 'bBondedInv' => '0',
  914. 'bBatchCreate' => '0',
  915. ];
  916. // 6. 执行同步
  917. try {
  918. $service->beginTransaction();
  919. $exists = $service->table('Inventory')->where('cInvCode', $no)->lockForUpdate()->exists();
  920. if ($exists) {
  921. $service->rollBack();
  922. return [false, '存货编码 [' . $no . '] 在用友系统中已存在,请' . $flag_title];
  923. }
  924. // --- 核心插入操作 ---
  925. $service->table('Inventory')->insert($inventoryData);
  926. $service->table('Inventory_sub')->insert($inventorySubData);
  927. // --- 新增:插入 bas_part 表 ---
  928. // 1. 获取 U8 内部最大 PartId (或者从 bas_part_seq 获取,这里采用最大值+1的简易方案)
  929. $maxPartId = $service->table('bas_part')->max('PartId');
  930. $newPartId = (int)$maxPartId + 1;
  931. $basPartData = [
  932. 'PartId' => $newPartId,
  933. 'InvCode' => $no,
  934. 'Free1' => '', 'Free2' => '', 'Free3' => '', 'Free4' => '', 'Free5' => '',
  935. 'Free6' => '', 'Free7' => '', 'Free8' => '', 'Free9' => '', 'Free10' => '',
  936. 'SafeQty' => null,
  937. 'MinQty' => null,
  938. 'MulQty' => null,
  939. 'FixQty' => null,
  940. 'bVirtual' => 1, // 默认非虚仓,如果是虚拟件请改为 1
  941. 'DrawCode' => null,
  942. 'LLC' => 0, // 低层码,新增时默认为 0,U8全检时会更新
  943. 'iSurenessType' => 1, // 对应 Inventory_sub 的设置
  944. 'RoundingFactor' => '0',
  945. 'FreeStockFlag' => '0',
  946. 'bFreeStop' => '0'
  947. ];
  948. $service->table('bas_part')->insert($basPartData);
  949. // 更新流水号表
  950. if ($serialInfo) {
  951. $service->table('VoucherHistory')->updateOrInsert(
  952. ['CardNumber' => 'inventory', 'cContent' => '存货分类编码', 'cSeed' => $category_code],
  953. ['cNumber' => $serialInfo['serial']]
  954. );
  955. }
  956. $service->commit();
  957. } catch (\Throwable $exception) {
  958. $service->rollBack();
  959. return [false, "同步用友数据库失败: " . $exception->getMessage()];
  960. }
  961. return [true, '同步成功'];
  962. }
  963. /**
  964. * U8 供应商新增 (全量版)
  965. */
  966. public function vendorAddToU8($data, $username, $service)
  967. {
  968. $vendor = Vendor::where('del_time', 0)
  969. ->where('order_number', $data['order_number'])
  970. ->where('login_type', $data['login_type'])
  971. ->first();
  972. if (empty($vendor)) return [false, '供应商记录不存在或已被删除'];
  973. $vendor = $vendor->toArray();
  974. $serialInfo = null;
  975. if (!empty($vendor['code'])) {
  976. $no = $vendor['code'];
  977. $flag_title = "重填";
  978. } else {
  979. list($status, $res) = $this->generate('vendor', '', $service);
  980. if (!$status) return [false, $res];
  981. $no = $res['finalCode'];
  982. $serialInfo = $res;
  983. $flag_title = "重试";
  984. }
  985. $vendorData = [
  986. 'cVenCode' => $no,
  987. 'cVenName' => $vendor['title'],
  988. 'cVenAbbName' => $vendor['easy_title'],
  989. 'cVCCode' => $vendor['category_code'],
  990. 'dVenDevDate' => date("Y-m-d 00:00:00.000"),
  991. 'iVenDisRate' => '0.0',
  992. 'iVenCreLine' => '0.0',
  993. 'iVenCreDate' => '0',
  994. 'cVenHeadCode' => $no,
  995. 'iAPMoney' => '0.0',
  996. 'iLastMoney' => '0.0',
  997. 'iLRMoney' => '0.0',
  998. 'iFrequency' => '0',
  999. 'bVenTax' => '1',
  1000. 'cCreatePerson' => $username,
  1001. 'cModifyPerson' => $username,
  1002. 'dModifyDate' => date("Y-m-d H:i:s.000"),
  1003. 'iGradeABC' => '-1',
  1004. 'bLicenceDate' => '0',
  1005. 'bBusinessDate' => '0',
  1006. 'bProxyDate' => '0',
  1007. 'bPassGMP' => '0',
  1008. 'bVenCargo' => '1',
  1009. 'bProxyForeign' => '0',
  1010. 'bVenService' => '0',
  1011. 'bVenOverseas' => '0',
  1012. 'cVenExch_name' => '人民币',
  1013. 'iVenGSPType' => '0',
  1014. 'iVenGSPAuth' => '-1',
  1015. 'bVenAccPeriodMng' => '0',
  1016. 'bVenHomeBranch' => '0',
  1017. 'dVenCreateDatetime' => date("Y-m-d H:i:s.000"),
  1018. 'bIsVenAttachFile' => '0',
  1019. 'bRetail' => '0',
  1020. ];
  1021. try {
  1022. $service->beginTransaction();
  1023. $exists = $service->table('Vendor')->where('cVenCode', $no)->lockForUpdate()->exists();
  1024. if ($exists) {
  1025. $service->rollBack();
  1026. return [false, '供应商编码已存在,请' . $flag_title];
  1027. }
  1028. $service->table('Vendor')->insert($vendorData);
  1029. // 更新流水号表
  1030. if ($serialInfo) {
  1031. $service->table('VoucherHistory')->updateOrInsert(
  1032. ['CardNumber' => 'Vendor', 'cContent' => NULL, 'cSeed' => NULL],
  1033. ['cNumber' => $serialInfo['serial']]
  1034. );
  1035. }
  1036. $service->commit();
  1037. } catch (\Throwable $exception) {
  1038. $service->rollBack();
  1039. return [false, "创建供应商失败: " . $exception->getMessage()];
  1040. }
  1041. return [true, '同步成功'];
  1042. }
  1043. /**
  1044. * 编码生成器 (增加流水数据返回)
  1045. */
  1046. public function generate($type, $classCode = "", $service)
  1047. {
  1048. try {
  1049. $cardNumber = ($type === 'inventory') ? 'inventory' : 'Vendor';
  1050. $table = ($type === 'inventory') ? 'Inventory' : 'Vendor';
  1051. $codeField = ($type === 'inventory') ? 'cInvCode' : 'cVenCode';
  1052. $rule = $service->table('VoucherNumber')->where('CardNumber', $cardNumber)->first();
  1053. if (!$rule) return [false, "未找到规则定义"];
  1054. $prefix = "";
  1055. for ($i = 1; $i <= 3; $i++) {
  1056. $ruleField = "Prefix{$i}Rule";
  1057. $valField = "Prefix{$i}";
  1058. $ruleDesc = $rule->$ruleField ?? '';
  1059. $staticVal = $rule->$valField ?? '';
  1060. if (str_contains($ruleDesc, '分类') || str_contains($staticVal, '分类')) {
  1061. $prefix .= $classCode;
  1062. } elseif (!empty($ruleDesc) && !in_array($ruleDesc, ['手工输入', '无'])) {
  1063. $prefix .= $ruleDesc;
  1064. }
  1065. }
  1066. $glideLen = $rule->GlideLen ?: 4;
  1067. $startNum = $rule->iStartNumber ?: 1;
  1068. $lastCode = $service->table($table)
  1069. ->where($codeField, 'like', $prefix . '%')
  1070. ->whereRaw("LEN($codeField) = " . (strlen($prefix) + $glideLen))
  1071. ->orderBy($codeField, 'desc')
  1072. ->value($codeField);
  1073. $nextSerial = (!$lastCode) ? (int)$startNum : (int)substr($lastCode, -$glideLen) + 1;
  1074. $finalCode = $prefix . str_pad($nextSerial, $glideLen, '0', STR_PAD_LEFT);
  1075. return [true, [
  1076. 'finalCode' => $finalCode,
  1077. 'prefix' => $prefix,
  1078. 'serial' => $nextSerial
  1079. ]];
  1080. } catch (\Throwable $e) {
  1081. return [false, "生成失败: " . $e->getMessage()];
  1082. }
  1083. }
  1084. protected function echoMessage(OutputInterface $output)
  1085. {
  1086. //输出消息
  1087. $output->writeln(json_encode($this->data));
  1088. }
  1089. }