| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742 |
- <?php
- namespace App\Service;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\Log;
- class U8ThirdPartyService extends Service
- {
- const one = 1;
- const two = 2;
- const three = 3;
- const four = 4;
- const five = 5;
- const six = 6;
- const seven = 7;
- const eight = 8;
- const type_all = [
- self::one => '采购入库',
- self::two => '采购退货',
- self::three => '材料出库',
- self::four => '销售出库',
- self::five => '产成品入库',
- self::six => '销售退货',
- self::seven => '其他入',
- self::eight => '其他出',
- ];
- public function settleU8Data($data){
- if(empty($data['type'])) return [false, 'type类型不能为空'];
- if(! isset(self::type_all[$data['type']])) return [false, 'type类型错误'];
- $type = $data['type'];
- list($status, $msg) = $this->getToken();
- // if(! $status) return [false, $msg];
- $data['u8_data'] = $msg;
- if($type == self::one){
- list($status, $msg) = $this->purchaseIn($data);
- }elseif ($type == self::two){
- list($status, $msg) = $this->purchaseReturn($data);
- }elseif ($type == self::three){
- list($status, $msg) = $this->materialOut($data);
- }elseif ($type == self::four){
- list($status, $msg) = $this->saleOut($data);
- }elseif ($type == self::five){
- list($status, $msg) = $this->productIn($data);
- }elseif ($type == self::six){
- list($status, $msg) = $this->saleReturn($data);
- }elseif ($type == self::seven){
- list($status, $msg) = $this->otherIn($data);
- }elseif ($type == self::eight){
- list($status, $msg) = $this->otherOut($data);
- }
- return [$status, $msg];
- }
- public function getToken(){
- $key = "drb_u8_api";
- $config = config('wms.drb');
- // 1. 自检网络通畅
- list($bool, $msg) = $this->checkNetworkStatus($config['api_host'], $config['api_port']);
- if (!$bool) return [false, "网络连接失败: " . $msg];
- $host = $config['api_host'] . ":" . $config['api_port'];
- // 2. 尝试从缓存获取
- $token = Cache::get($key);
- if (! $token) {
- // 3. 缓存失效,请求新 Token
- $url = $host . "/api/System/GetToken";
- $date = date("Y-m-d");
- $json = [
- "U8DbName" => $config['database'],
- "sUserId" => $config['user_id'],
- "sPassword" => $config['user_password'],
- "LoginDateTime" => $date,
- "bPersist" => true
- ];
- $header = ['Content-Type:application/json'];
- // 调用你的 POST 辅助函数
- list($status, $result) = $this->post_helper1($url, json_encode($json), $header);
- if (!$status) return [false, "用友token获取失败: " . $result];
- if (!isset($result['code'])) return [false, '获取用友登录信息失败: 响应格式异常'];
- if ($result['code'] != 0) return [false, "U8错误: " . ($result['msg'] ?? '未知错误')];
- $token = $result['data']['Token'] ?? "";
- if (empty($token)) return [false, "接口返回的 Token 为空"];
- // 30分钟 = 1800秒
- Cache::put($key, $token, now()->addMinutes(30));
- }
- return [true, ['host' => $host, 'token' => $token]];
- }
- public function purchaseIn1($data){
- if(empty($data['orderId'])) return [false, '采购到货单ID不能为空'];
- if(empty($data['orderNo'])) return [false, '采购到货单单号不能为空'];
- if(empty($data['detail'])) return [false, '表体信息detail不能为空'];
- //获取采购到货单明细
- $service = new U8ThirtyPartyDatabaseServerService();
- $details_map = $service->getCGDHDetail1s($data['orderId']);
- if(empty($details_map)) return [false, '采购到货单明细不存在'];
- $existingLineNums = array_column($data['detail'], 'lineNum');
- $maxLineNum = empty($existingLineNums) ? 0 : max($existingLineNums);
- $body = [];
- $seenLineNums = []; // 用于记录已经处理过的原始行号
- foreach ($data['detail'] as $key => $value) {
- if(empty($value['lineNum'])) return [false, '行号不能为空'];
- if(! is_numeric($value['lineNum'])) return [false, '行号错误'];
- if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- if(empty($value['productDate']) || ! $this->validateProductDate($value['productDate'])) return [false, '生产日期为空或格式错误'];
- if(empty($value['failureDate']) || ! $this->validateProductDate($value['failureDate'])) return [false, '失效日期为空或格式错误'];
- if(empty($value['lot'])) return [false, '批号不能为空'];
- if(empty($value['iQuantity']) || ! is_numeric($value['iQuantity'])) return [false, '存货数量错误'];
- $currentLineNum = $value['lineNum'];
- // 2. 判断行号是否重复
- if (in_array($currentLineNum, $seenLineNums)) {
- $maxLineNum++;
- $currentLineNum = $maxLineNum;
- $editProp = 'A'; // 或者根据你的需求设为空或其他标志
- $o_tmp = $details_map[$value['materialCode']] ?? [];
- } else {
- $seenLineNums[] = $currentLineNum;
- $editProp = 'M';
- }
- // 3. 组织最终数据
- $body[] = [
- 'ivouchrowno' =>$currentLineNum,
- 'dPDate' => $value['productDate'],
- 'dVDate' => $value['failureDate'],
- 'cBatch' => $value['lot'],
- 'iQuantity' => $value['iQuantity'],
- 'editprop' => $editProp,
- ];
- }
- //调用所需
- $host = $data['u8_data']['host'];
- $token = $data['u8_data']['token'];
- //采购到货单弃审
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/PuArrVouch/UnVerify";
- $json = [
- "VouchId" => $data['orderId'],
- ];
- $json = json_encode($json);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '采购到货单弃审失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- //采购到货单编辑并审核
- $url = $host . "/api/PuArrVouch/Update";
- $json_final[] = [
- "Inum" => "PuArrVouch",
- "data" =>[
- "iHead" => [
- "cCode" => $data['orderNo'],
- "IsVerify" => true,
- "debug" => true,
- ],
- "iBody" => $body,
- ],
- ];
- $json = json_encode($json_final);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '采购到货单编辑并审核失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- /**
- * 采购到货单拆行/更新处理
- */
- public function purchaseIn($data)
- {
- if (empty($data['orderId'])) return [false, '采购到货单ID不能为空'];
- if (empty($data['orderNo'])) return [false, '采购到货单单号不能为空'];
- if (empty($data['detail'])) return [false, '表体信息detail不能为空'];
- // 1. 获取到货单明细
- $service = new U8ThirtyPartyDatabaseServerService();
- $result = $service->getCGDHDetails($data['orderId']);
- if (empty($result)) return [false, '采购到货单明细不存在'];
- // 取出第一行作为模板,保留 ID, cCode 等主表关联信息
- $templateRow = reset($result);
- $mainId = $templateRow['ID'];
- // 2. 存货管控校验(批次/保质期)
- list($status, $msg) = $service->checkInventoryControl(array_column($data['detail'], 'materialCode'));
- if (!$status) return [false, $msg];
- $insertData = [];
- $rowNo = 1;
- foreach ($data['detail'] as $value) {
- if (!isset($result[$value['materialCode']])) continue;
- $map = $result[$value['materialCode']]; // 获取原始行信息(单价、税率等)
- // 计算单价
- $oldQty = (float)($map['iQuantity'] ?? 0);
- if ($oldQty <= 0) continue;
- $unitPrice = (float)$map['iOriSum'] / $oldQty;
- $unitMoney = (float)$map['iOriMoney'] / $oldQty;
- $unitLocalSum = (float)$map['iSum'] / $oldQty;
- $unitLocalMoney = (float)$map['iMoney'] / $oldQty;
- $newQty = (float)$value['iQuantity'];
- // 组织新行数据
- $newRow = $map;
- // 清理旧行主键和业务累积状态(关键!)
- unset($newRow['Autoid']);
- $newRow['fInspectQuantity'] = 0; // 已报检量清零
- $newRow['fValidQuantity'] = 0; // 合格量清零
- $newRow['iQuantity'] = $newQty;
- $newRow['ivouchrowno'] = $rowNo++; // 重新排序行号
- // 填充计算后的金额和批次日期
- $newRow['iOriMoney'] = round($unitMoney * $newQty, 2);
- $newRow['iOriSum'] = round($unitPrice * $newQty, 2);
- $newRow['iOriTaxPrice'] = round(($unitPrice - $unitMoney) * $newQty, 2);
- $newRow['iMoney'] = round($unitLocalMoney * $newQty, 2);
- $newRow['iSum'] = round($unitLocalSum * $newQty, 2);
- $newRow['iTaxPrice'] = round(($unitLocalSum - $unitLocalMoney) * $newQty, 2);
- $newRow['cBatch'] = $value['lot'];
- $newRow['dPDate'] = $this->formatAndValidateDate($value['productDate']);
- $newRow['dVDate'] = $this->formatAndValidateDate($value['failureDate']);
- $insertData[] = $newRow;
- }
- // 3. 执行数据库操作:先删后插
- list($status, $msg) = $service->rebuildDhDetails($mainId, $insertData);
- if (!$status) return [false, $msg];
- //查询采购到货单
- $order = $service->getCgOrder($data['orderId']);
- if(empty($order)) return [false, '采购到货单不存在'];
- //生成来料报检单
- $inspect = [
- "Inum" => "ArrInspect",
- "Data" => [
- "iHead" => [
- // 注意:这里使用的是主表的 ID
- "CSOURCEID" => $order['ID'],
- "CDEPCODE" => $order['cDepCode'],
- "DDATE" => date("Y-m-d"),
- "CCHECKTYPECODE" => 'ARR',
- ],
- "iBody" => []
- ]
- ];
- foreach ($order['details'] as $item) {
- $qty = (float)($item['iQuantity'] ?? 0);
- if ($qty <= 0) continue;
- $inspect["Data"]["iBody"][] = [
- "SOURCEAUTOID" => $item['Autoid'],
- "ITESTSTYLE" => 0,
- "CINVCODE" => $item['cInvCode'],
- "FCHANGRATE" => (float)($item['iInvExchRate'] ?? 0),
- "FQUANTITY" => $qty,
- "CBATCH" => $item['cBatch'],
- 'DPRODATE' => $item['dPDate'],
- 'DVDATE' => $item['dVDate'],
- ];
- }
- // 4. 封装成数组返回
- $final_data = [$inspect];
- //调用所需
- $host = $data['u8_data']['host'];
- $token = $data['u8_data']['token'];
- //报检单
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/QmArr/ArrInspectAdd";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '报检单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function materialOut($data)
- {
- if (empty($data['orderId'])) return [false, '领料申请单ID不能为空'];
- if (empty($data['orderNo'])) return [false, '领料申请单单号不能为空'];
- if (empty($data['warehouseCode'])) return [false, '仓库不能为空'];
- if (empty($data['detail'])) return [false, '表体信息detail不能为空'];
- // 1. 获取领料申请单明细
- $service = new U8ThirtyPartyDatabaseServerService();
- $result = $service->getLlSQDetails($data['orderId']);
- if (empty($result)) return [false, '领料申请单明细不存在'];
- // 取出第一行作为模板,获取主表 ID
- $templateRow = reset($result);
- $mainId = $templateRow['ID'];
- // 2. 存货管控校验(批次/保质期)
- list($status, $msg) = $service->checkInventoryControl(array_column($data['detail'], 'materialCode'));
- if (!$status) return [false, $msg];
- $insertData = [];
- $rowNo = 1;
- foreach ($data['detail'] as $value) {
- if (!isset($result[$value['materialCode']])) continue;
- // 获取原始行(保留生产订单关联 morderdid、仓库 cwhcode 等信息)
- $map = $result[$value['materialCode']];
- $newQty = (float)$value['iQuantity'];
- // 组织新行数据
- $newRow = $map;
- // 清理主键
- unset($newRow['AutoID']);
- $newRow['iQuantity'] = $newQty; // 申请数量
- $newRow['irowno'] = $rowNo++; // 重新排序行号
- $newRow['cBatch'] = $value['lot']; // 批号
- // 生产日期与失效日期 (U8 领料申请单通常字段名为 dMadeDate 和 dVDate 或 dmadedate)
- $newRow['dMadeDate'] = !empty($value['productDate']) ? $this->formatAndValidateDate($value['productDate']) : null;
- $newRow['dVDate'] = !empty($value['failureDate']) ? $this->formatAndValidateDate($value['failureDate']) : null;
- $insertData[] = $newRow;
- }
- // 3. 执行数据库操作:先删后插
- list($status, $msg) = $service->rebuildLLDetails($mainId, $insertData);
- if (!$status) return [false, $msg];
- //查询领料申请单
- $order = $service->getLLOrder($data['orderId']);
- if(empty($order)) return [false, '领料单不存在'];
- //仓库区分出入库类别
- if($data['warehouseCode'] == "01"){
- $cRdCode = "0201";
- }else{
- $cRdCode = "0203";
- }
- $materialOut = [
- "Inum" => "MaterialOut",
- "Data" => [
- "iHead" => [
- "IsVerify" => true,
- "cWhCode" => $data['warehouseCode'], // 仓库
- "cVouchType" => "11",
- "cRdCode" => $cRdCode, // 出入库类别
- "cDepCode" => $order['cDepCode'], // 领用部门
- "cSource" => "领料申请单",
- "cBusCode" => $order['cCode'], // 领料申请单单号
- "cBusType" => "领料",
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- ],
- "iBody" => []
- ]
- ];
- foreach ($order['details'] as $index => $item) {
- // 这里的数量取值要对应你 getLLOrder 查出来的字段名,通常是 fQty
- $qty = $item['iQuantity'];
- if ($qty <= 0) continue;
- $materialOut["Data"]["iBody"][] = [
- "iRowNo" => $index + 1,
- "cInvCode" => $item['cInvCode'],
- "cBatch" => $item['cBatch'], // 批号
- "iQuantity" => $qty, // 实际出库数量
- "iNQuantity" => $qty, // 实收数量
- "iinvexchrate" => (float)($item['iinvexchrate'] ?? 1),
- "iMaIDs" => $item['AutoID'],
- "dMadeDate" => $item['dMadeDate'], // 生产日期
- "dVDate" => $item['dVDate'], // 失效日期
- ];
- }
- // 封装成数组返回
- $final_data = [$materialOut];
- //调用所需
- $host = $data['u8_data']['host'];
- $token = $data['u8_data']['token'];
- //材料出库单
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/MaterialOut/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '材料出库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function materialOut1($data){
- if(empty($data['orderId'])) return [false, '领料申请单ID不能为空'];
- if(empty($data['orderNo'])) return [false, '领料申请单单号不能为空'];
- if(empty($data['detail'])) return [false, '表体信息detail不能为空'];
- $body = [];
- foreach ($data['detail'] as $key => $value){
- if(empty($value['lineNum'])) return [false, '行号不能为空'];
- if(! is_numeric($value['lineNum'])) return [false, '行号错误'];
- if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- if(empty($value['productDate']) || ! $this->validateProductDate($value['productDate'])) return [false, '生产日期为空或格式错误'];
- if(empty($value['failureDate']) || ! $this->validateProductDate($value['failureDate'])) return [false, '失效日期为空或格式错误'];
- if(empty($value['lot'])) return [false, '批号不能为空'];
- $body[] = [
- 'ivouchrowno' => $value['lineNum'],
- 'dPDate' => $value['productDate'],
- 'dVDate' => $value['failureDate'],
- 'cBatch' => $value['lot'],
- 'editprop' => 'M',
- ];
- }
- //调用所需
- $host = $data['u8_data']['host'];
- $token = $data['u8_data']['token'];
- //采购到货单弃审
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/PuArrVouch/UnVerify";
- $json = [
- "VouchId" => $data['orderId'],
- ];
- $json = json_encode($json);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '采购到货单弃审失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- //采购到货单编辑并审核
- $url = $host . "/api/PuArrVouch/Update";
- $json_final[] = [
- "Inum" => "PuArrVouch",
- "data" =>[
- "iHead" => [
- "cCode" => $data['orderNo'],
- "IsVerify" => true,
- "debug" => true,
- ],
- "iBody" => $body,
- ],
- ];
- $json = json_encode($json_final);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '采购到货单编辑并审核失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function purchaseReturn($data){
- if(empty($data['orderId'])) return [false, '采购退货单ID不能为空'];
- // 1. 获取到货单(退货单)及明细
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getArrivalVouchById($data['orderId']);
- if(empty($order)) return [false, '采购退货单数据不存在'];
- // 获取 Token 相关信息
- $host = $data['u8_data']['host'] ?? "";
- $token = $data['u8_data']['token'] ?? "";
- // 2. 组织单一仓库的红字采购入库单
- $iBody = [];
- foreach ($order['details'] as $index => $item) {
- // 强制转为负数,生成红字入库单
- $qty = abs((float)$item['iQuantity']) * -1;
- $iBody[] = [
- "iRowNo" => $index + 1,
- "cInvCode" => $item['cInvCode'],
- "cBatch" => $item['cBatch'] ?? '',
- "iinvexchrate" => (float)($item['iinvexchrate'] ?? 1),
- "iQuantity" => $qty, // 负数
- "iNQuantity" => $qty, // 负数
- "iArrsId" => $item['iArrsId'],
- "dMadeDate" => $item['dPDate'],
- "dVDate" => $item['dVDate'],
- "iTaxRate" => $item['iTaxRate'] ?? 0,
- "iTaxUnitPrice"=> $item['iOriTaxCost'] ?? 0,
- ];
- }
- if(empty($iBody)) return [false, '表体明细为空'];
- $final_data = [
- [
- "Inum" => "PurchaseIn",
- "Data" => [
- "iHead" => [
- "IsVerify" => true,
- "bIsRedVouch" => true, // 必须为红字
- "bCalPrice" => true, // 自动计算金额
- "cWhCode" => "01",
- "cRdCode" => $order['rd_code'],
- "cDepCode" => $order['depart_code'],
- "cARVCode" => $order['no'], // 关联来源单号
- "cSource" => "采购到货单", // 即使是退货单,参照来源也写这个
- "cBusType" => "普通采购",
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- "iExchRate"=> 1,
- ],
- "iBody" => $iBody
- ]
- ]
- ];
- // 3. 调用 API
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- $url = $host . "/api/PurchaseIn/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '红字采购入库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function productIn($data){
- if(empty($data['orderId'])) return [false, '产品报检单ID不能为空'];
- if(empty($data['orderNo'])) return [false, '产品报检单单号不能为空'];
- if(empty($data['detail'])) return [false, '表体信息detail不能为空'];
- // 1. 获取报检单明细 (建议 getBjOrder 返回以 cInvCode 为 key 的数组)
- $service = new U8ThirtyPartyDatabaseServerService();
- $result = $service->getBjOrder($data['orderId']);
- if (empty($result)) return [false, '报检单明细不存在'];
- // 取出第一行作为模板,获取主表 ID
- $templateRow = reset($result);
- $mainId = $templateRow['ID'];
- // 2. 存货管控校验(批次/保质期)
- list($status, $msg) = $service->checkInventoryControl(array_column($data['detail'], 'materialCode'));
- if (!$status) return [false, $msg];
- $insertData = [];
- $rowNo = 1;
- foreach ($data['detail'] as $value) {
- if (!isset($result[$value['materialCode']])) continue;
- // 获取原始行(保留来源单据关联,如采购到货单行 AutoID 等)
- $map = $result[$value['materialCode']];
- $newQty = (float)$value['iQuantity'];
- // 组织新行数据
- $newRow = $map;
- // 清理子表主键
- unset($newRow['AUTOID']);
- // --- 核心字段修正 (报检单子表字段通常为大写) ---
- $newRow['FQUANTITY'] = $newQty; // 报检数量
- $newRow['CBATCH'] = $value['lot']; // 批号
- // 报检单的日期字段通常是 DPRODATE (生产日期) 和 DVDATE (失效日期)
- $newRow['DPRODATE'] = !empty($value['productDate']) ? $this->formatAndValidateDate($value['productDate']) : null;
- $newRow['DVDATE'] = !empty($value['failureDate']) ? $this->formatAndValidateDate($value['failureDate']) : null;
- $insertData[] = $newRow;
- }
- // 3. 执行数据库操作:先删后插
- list($status, $msg) = $service->rebuildBjDetails($mainId, $insertData);
- if (!$status) return [false, $msg];
- // $service = new U8ThirtyPartyDatabaseServerService();
- // $result = $service->getBjOrder($data['orderId']);
- //
- // $tmp = $update = $insert = [];
- // foreach ($data['detail'] as $key => $value) {
- // if(empty($value['lineNum'])) return [false, '行号不能为空'];
- // if(! is_numeric($value['lineNum'])) return [false, '行号错误'];
- // if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- // if(empty($value['productDate'])) return [false, '生产日期不能为空'];
- // $return = $this->formatAndValidateDate($value['productDate']);
- // if(! $return) return [false, '生产日期格式错误'];
- // $productDate = $return;
- // if(empty($value['failureDate'])) return [false, '失效日期不能为空'];
- // $return = $this->formatAndValidateDate($value['failureDate']);
- // if(! $return) return [false, '生产日期格式错误'];
- // $failureDate= $return;
- // if(empty($value['lot'])) return [false, '批号不能为空'];
- // if(empty($value['iQuantity']) || ! is_numeric($value['iQuantity'])) return [false, '存货数量错误'];
- //
- // if(isset($result[$value['materialCode']])){
- // $map = $result[$value['materialCode']];
- // $update_detail = [
- // 'CBATCH' => $value['lot'],
- // 'FQUANTITY' => $value['iQuantity'],
- // 'DPRODATE' => $productDate,
- // 'DVDATE' => $failureDate,
- // ];
- // if(! isset($tmp[$value['materialCode']])){
- // $update[$map['AUTOID']] = $update_detail;
- // $tmp[$value['materialCode']] = $value['materialCode'];
- // }else{
- // $map['AUTOID'] = null;
- // $insert[] = array_merge($map, $update_detail);
- // }
- // }
- // }
- //
- // list($status,$msg) = $service->checkInventoryControl(array_values(array_column($data['detail'],'materialCode')));
- // if(! $status) return [false, $msg];
- //
- // list($status, $msg) = $service->updateBjOrder($update, $insert);
- // if(! $status) return [false, $msg];
- return [true, ''];
- }
- public function saleOut1($data){
- if(empty($data['orderId'])) return [false, '销售订单ID不能为空'];
- if(empty($data['orderNo'])) return [false, '销售订单号不能为空'];
- if(empty($data['detail'])) return [false, '表体信息detail不能为空'];
- //获取销售订单信息
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getXsOrder($data['orderId']);
- if(empty($order)) return [false, '销售订单不存在'];
- $detail_map = [];
- foreach ($data['detail'] as $key => $value) {
- if(empty($value['lineNum'])) return [false, '行号不能为空'];
- if(! is_numeric($value['lineNum'])) return [false, '行号错误'];
- if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- if(empty($value['productDate'])) return [false, '生产日期不能为空'];
- $return = $this->formatAndValidateDate($value['productDate']);
- if(! $return) return [false, '生产日期格式错误'];
- $productDate = $return;
- if(empty($value['failureDate'])) return [false, '失效日期不能为空'];
- $return = $this->formatAndValidateDate($value['failureDate']);
- if(! $return) return [false, '生产日期格式错误'];
- $failureDate= $return;
- if(empty($value['lot'])) return [false, '批号不能为空'];
- if(empty($value['iQuantity']) || ! is_numeric($value['iQuantity'])) return [false, '存货数量错误'];
- $detail_map[$value['materialCode']][] = [
- 'productDate' => $productDate,
- 'failureDate' => $failureDate,
- 'lot' => $value['lot'],
- 'iQuantity' => $value['iQuantity'],
- ];
- }
- // 2. 组织发货单 (DispatchList) 结构
- $tmp = [
- "Inum" => "DispatchList",
- "Data" => [
- "iHead" => [
- "cBusType" => $order['cBusType'], // 业务类型
- "cVouchType" => "05", // 销售发货单类型
- "cSTCode" => $order['cSTCode'], // 销售类型
- "cDepCode" => $order['cDepCode'], // 部门
- "IsVerify" => true, // 是否自动审核
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- "bCalPrice" => true, // 由接口计算价格
- "PriceCalKey" => "iTaxUnitPrice", // 以含税单价为准计算
- "cSoCode" => $order['cSOCode'], // 销售订单号
- "cCusCode" => $order['cCusCode'], // 客户编码
- "cinvoicecompany" => $order['cCusCode'], // 开票单位(通常取客户编码)
- ],
- "iBody" => []
- ]
- ];
- // 3. 遍历销售订单明细组织表体
- $key = 0; // 初始化行号计数器
- foreach ($order['details'] as $index => $item) {
- // 销售订单存货可能拆分出多行
- $p_t = $detail_map[$item['cInvCode']] ?? [];
- if(empty($p_t)) continue;
- foreach ($p_t as $value){
- $key++; // 每进入一次内层循环,行号加 1
- $tmp["Data"]["iBody"][] = [
- "iRowNo" => $key, // 直接使用累加后的 key
- "cWhCode" => "06",
- "iQuantity" => $value['iQuantity'],
- "iSOsID" => $item['iSOsID'],
- "cBatch" => $value['lot'],
- "dMDate" => $value['productDate'],
- "dvDate" => $value['failureDate'],
- "iTaxUnitPrice" => $item['iTaxUnitPrice'],
- "iTaxRate" => $item['iTaxRate'],
- ];
- }
- }
- // 4. 封装成数组返回
- $final_data = [$tmp];
- //调用所需
- $host = $data['u8_data']['host'];
- $token = $data['u8_data']['token'];
- //销售发货单
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/Dispatch/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '销售发货单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- $first = $result['data'][0];
- $id = $first['VouchId'];
- // $id = 1000000882;
- $fhOrder = $service->getFhOrder($id);
- if(empty($fhOrder)) return [false, '销售发货单获取失败'];
- // 2. 初始化销售出库单结构
- $saleOut = [
- "Inum" => "SaleOut",
- "Data" => [
- "iHead" => [
- "IsVerify" => true, // 自动审核
- "cWhCode" => "06", // 仓库编码
- "cRdCode" => "0299", // 出入库类别编码
- "cVouchType" => "32", // 单据类型编码
- "cMemo" => "接口生成",
- "cSource" => "发货单",
- "cSTCode" => $fhOrder['cSTCode'], // 销售类型
- "DLCode" => $fhOrder['cDLCode'], // 关联的发货单号
- "cDepCode" => $fhOrder['cDepCode'], // 部门
- "dDate" => date("Y-m-d"), // 出库日期
- ],
- "iBody" => []
- ]
- ];
- // 3. 遍历发货单明细组织表体
- foreach ($fhOrder['details'] as $index => $item) {
- // 计算待出库数量 (总发货数 - 已出库数)
- $qty = (float)($item['iQuantity'] ?? 0);
- $outQty = (float)($item['fOutQuantity'] ?? 0);
- $pendingQty = $qty - $outQty;
- // 如果该行已全部出库,则跳过(可选逻辑)
- if ($pendingQty <= 0) continue;
- $saleOut["Data"]["iBody"][] = [
- "iRowNo" => $index + 1,
- "cInvCode" => $item['cInvCode'] ?? "",
- "cPosition" => $item['cPosition'] ?? "", // 货位
- "cBatch" => $item['cBatch'] ?? "", // 批号
- "iinvexchrate" => (float)($item['iExchRate'] ?? 1), // 换算率
- "iQuantity" => $pendingQty, // 本次出库数量
- "iNQuantity" => $pendingQty, // 对应实收数量
- "iDLsID" => $item['iDLsID'], // 核心:发货单子表ID
- "dMadeDate" => $item['dMDate'], // 生产
- "dVDate" => $item['dvDate'], // 失效
- "iUnitCost" => (float)($item['iUnitPrice'] ?? 0), // 无税单价
- "iPrice" => round((float)($item['iUnitPrice'] ?? 0) * $pendingQty, 2), // 无税金额
- ];
- }
- // 4. 封装成数组
- $final_data = [$saleOut];
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/SaleOut/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '销售出库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function saleOut($data){
- if(empty($data['orderId'])) return [false, '销售订单ID不能为空'];
- if(empty($data['orderNo'])) return [false, '销售订单号不能为空'];
- if(empty($data['detail'])) return [false, '表体信息detail不能为空'];
- //获取销售订单信息
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getXsOrder($data['orderId']);
- if(empty($order)) return [false, '销售订单不存在'];
- $orderItemMap = [];
- foreach ($order['details'] as $detail) {
- // 这里的 iTaxUnitPrice 是订单里的含税单价
- $orderItemMap[$detail['cInvCode']] = [
- 'iTaxUnitPrice' => $detail['iTaxUnitPrice'] ?? 0,
- 'iTaxRate' => $detail['iTaxRate'] ?? 13,
- 'iUnitPrice' => $detail['iUnitPrice'] ?? 0,
- ];
- }
- $detail_map = [];
- foreach ($data['detail'] as $key => $value) {
- if(empty($value['lineNum'])) return [false, '行号不能为空'];
- if(! is_numeric($value['lineNum'])) return [false, '行号错误'];
- if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- if(empty($value['productDate'])) return [false, '生产日期不能为空'];
- $return = $this->formatAndValidateDate($value['productDate']);
- if(! $return) return [false, '生产日期格式错误'];
- $productDate = $return;
- if(empty($value['failureDate'])) return [false, '失效日期不能为空'];
- $return = $this->formatAndValidateDate($value['failureDate']);
- if(! $return) return [false, '生产日期格式错误'];
- $failureDate= $return;
- if(empty($value['lot'])) return [false, '批号不能为空'];
- if(empty($value['iQuantity']) || ! is_numeric($value['iQuantity'])) return [false, '存货数量错误'];
- $detail_map[$value['materialCode']][] = [
- 'productDate' => $productDate,
- 'failureDate' => $failureDate,
- 'lot' => $value['lot'],
- 'iQuantity' => $value['iQuantity'],
- ];
- }
- // 2. 组织发货单 (DispatchList) 结构
- $tmp = [
- "Inum" => "DispatchList",
- "Data" => [
- "iHead" => [
- "cVouchType" => "05",
- "cSTCode" => $order['cSTCode'] ?? "01",
- "cDepCode" => $order['cDepCode'] ?? "01",
- "IsVerify" => true,
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- "bCalPrice" => false,
- "PriceCalKey" => "iSum",
- "iExchRate" => $order['iExchRate'] ?? 1,
- "cexch_name" => $order['cexch_name'] ?? "人民币",
- "cCusCode" => $order['cCusCode'],
- "iTaxRate" => $order['iTaxRate'] ?? 13,
- "cinvoicecompany" => $order['cCusCode'],
- ],
- "iBody" => []
- ]
- ];
- // 3. 组织表体
- $rowKey = 0;
- foreach ($detail_map as $invCode => $items) {
- // 获取该存货在订单里的价格信息
- $priceInfo = $orderItemMap[$invCode];
- foreach ($items as $value) {
- $rowKey++;
- $quantity = $value['iQuantity'];
- $unitPrice = $priceInfo['iTaxUnitPrice']; // 直接使用订单里的含税单价
- // 计算价税合计:数量 * 含税单价
- $sum = round($quantity * $unitPrice, 2);
- $tmp["Data"]["iBody"][] = [
- "iRowNo" => $rowKey,
- "cInvCode" => $invCode,
- "iTaxRate" => $priceInfo['iTaxRate'],
- "cWhCode" => "06",
- "iQuantity" => $quantity,
- "iSum" => $sum, // 总金额
- "iMoney" => $sum,
- "cBatch" => $value['lot'],
- "dMDate" => $value['productDate'],
- "dvDate" => $value['failureDate'],
- "iTaxUnitPrice" => $unitPrice, // 含税单价
- "iUnitPrice" => $priceInfo['iUnitPrice'], // 原订单无税单价
- ];
- }
- }
- // 4. 封装成数组返回
- $final_data = [$tmp];
- //调用所需
- $host = $data['u8_data']['host'];
- $token = $data['u8_data']['token'];
- //销售发货单
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/Dispatch/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '销售发货单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- $first = $result['data'][0];
- $id = $first['VouchId'];
- // $id = 1000000882;
- $fhOrder = $service->getFhOrder($id);
- if(empty($fhOrder)) return [false, '销售发货单获取失败'];
- // 2. 初始化销售出库单结构
- $saleOut = [
- "Inum" => "SaleOut",
- "Data" => [
- "iHead" => [
- "IsVerify" => true, // 自动审核
- "cWhCode" => "06", // 仓库编码
- "cRdCode" => "0299", // 出入库类别编码
- "cVouchType" => "32", // 单据类型编码
- "cMemo" => "接口生成",
- "cSource" => "发货单",
- "cSTCode" => $fhOrder['cSTCode'], // 销售类型
- "DLCode" => $fhOrder['cDLCode'], // 关联的发货单号
- "cDepCode" => $fhOrder['cDepCode'], // 部门
- "dDate" => date("Y-m-d"), // 出库日期
- ],
- "iBody" => []
- ]
- ];
- // 3. 遍历发货单明细组织表体
- foreach ($fhOrder['details'] as $index => $item) {
- // 计算待出库数量 (总发货数 - 已出库数)
- $qty = (float)($item['iQuantity'] ?? 0);
- $outQty = (float)($item['fOutQuantity'] ?? 0);
- $pendingQty = $qty - $outQty;
- // 如果该行已全部出库,则跳过(可选逻辑)
- if ($pendingQty <= 0) continue;
- $saleOut["Data"]["iBody"][] = [
- "iRowNo" => $index + 1,
- "cInvCode" => $item['cInvCode'] ?? "",
- "cPosition" => $item['cPosition'] ?? "", // 货位
- "cBatch" => $item['cBatch'] ?? "", // 批号
- "iinvexchrate" => (float)($item['iExchRate'] ?? 1), // 换算率
- "iQuantity" => $pendingQty, // 本次出库数量
- "iNQuantity" => $pendingQty, // 对应实收数量
- "iDLsID" => $item['iDLsID'], // 核心:发货单子表ID
- "dMadeDate" => $item['dMDate'], // 生产
- "dVDate" => $item['dvDate'], // 失效
- "iUnitCost" => (float)($item['iUnitPrice'] ?? 0), // 无税单价
- "iPrice" => round((float)($item['iUnitPrice'] ?? 0) * $pendingQty, 2), // 无税金额
- ];
- }
- // 4. 封装成数组
- $final_data = [$saleOut];
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/SaleOut/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url,$json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '销售出库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function otherIn($data) {
- // 1. 基础校验
- if (empty($data['warehouseCode'])) return [false, '仓库编码不能为空'];
- if (empty($data['detail'])) return [false, '明细数据不能为空'];
- $iBody = [];
- foreach ($data['detail'] as $key => $value) {
- if(empty($value['lineNum'])) return [false, '行号不能为空'];
- if(! is_numeric($value['lineNum'])) return [false, '行号错误'];
- if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- if(empty($value['productDate'])) return [false, '生产日期不能为空'];
- $return = $this->formatAndValidateDate($value['productDate']);
- if(! $return) return [false, '生产日期格式错误'];
- $productDate = $return;
- if(empty($value['failureDate'])) return [false, '失效日期不能为空'];
- $return = $this->formatAndValidateDate($value['failureDate']);
- if(! $return) return [false, '生产日期格式错误'];
- $failureDate= $return;
- if(empty($value['lot'])) return [false, '批号不能为空'];
- if(empty($value['iQuantity']) || ! is_numeric($value['iQuantity'])) return [false, '存货数量错误'];
- $iBody[] = [
- "iRowNo" => $key + 1,
- "cInvCode" => $value['materialCode'], // 存货编码
- "cBatch" => $value['lot'] ?? "", // 批号
- "iQuantity" => $value['iQuantity'],
- "iinvexchrate" => 0,
- "iNum" => 0,
- "dMadeDate" => $productDate, // 生产日期
- "dVDate" => $failureDate, // 失效日期
- ];
- }
- // 2. 组织表头 (iHead)
- $iHead = [
- "cWhCode" => $data['warehouseCode'], // 仓库编码
- "cRdCode" => "0109", // 收发类别 其他入
- "cDepCode" => "", // 部门
- "IsVerify" => ! isset($data['IsVerify']) ?? false, // 是否自动审核
- "cMemo" => "接口生成",
- "dDate" => $data['dDate'] ?? date("Y-m-d"), // 单据日期
- ];
- // 4. 封装成要求的数组结构
- $final_data = [
- [
- "Inum" => "OtherIn",
- "Data" => [
- "iHead" => $iHead,
- "iBody" => $iBody
- ]
- ]
- ];
- // 5. 准备发送请求
- $host = $data['u8_data']['host'] ?? "";
- $token = $data['u8_data']['token'] ?? "";
- $url = $host . "/api/OtherIn/Add";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- // 执行提交 (假设你已经定义了 post_helper1)
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '其他入库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, $result];
- }
- public function otherOut($data) {
- // 1. 基础校验
- if (empty($data['warehouseCode'])) return [false, '仓库编码不能为空'];
- if (empty($data['detail'])) return [false, '明细数据不能为空'];
- $iBody = [];
- foreach ($data['detail'] as $key => $value) {
- if(empty($value['materialCode'])) return [false, '存货编码不能为空'];
- // 格式化生产日期
- $productDate = null;
- if(!empty($value['productDate'])){
- $productDate = $this->formatAndValidateDate($value['productDate']);
- if(!$productDate) return [false, '生产日期格式错误'];
- }
- // 格式化失效日期
- $failureDate = null;
- if(!empty($value['failureDate'])){
- $failureDate = $this->formatAndValidateDate($value['failureDate']);
- if(!$failureDate) return [false, '失效日期格式错误'];
- }
- if(empty($value['iQuantity']) || !is_numeric($value['iQuantity'])) return [false, '存货数量错误'];
- $iBody[] = [
- "iRowNo" => $key + 1,
- "cInvCode" => $value['materialCode'], // 存货编码
- "cBatch" => $value['lot'] ?? "", // 批号
- "iQuantity" => $value['iQuantity'],
- "iinvexchrate" => 0,
- "dMadeDate" => $productDate, // 生产日期
- "dVDate" => $failureDate, // 失效日期
- ];
- }
- // 2. 组织表头 (iHead)
- $iHead = [
- "cWhCode" => $data['warehouseCode'], // 仓库编码
- "cRdCode" => "0209", // 收发类别:其他出库
- "cDepCode" => "", // 部门
- "IsVerify" => isset($data['IsVerify']) ?? false, // 是否自动审核
- "cMemo" => "接口生成",
- "dDate" => $data['dDate'] ?? date("Y-m-d"), // 单据日期
- ];
- // 4. 封装成要求的数组结构 - Inum 改为 OtherOut
- $final_data = [
- [
- "Inum" => "OtherOut",
- "Data" => [
- "iHead" => $iHead,
- "iBody" => $iBody
- ]
- ]
- ];
- // 5. 准备发送请求
- $host = $data['u8_data']['host'] ?? "";
- $token = $data['u8_data']['token'] ?? "";
- // 地址改为 OtherOut
- $url = $host . "/api/OtherOut/Add";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- // 执行提交
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, "网络请求失败: " . $result];
- if(! isset($result['code'])) return [false, '其他出库单生成失败'];
- if($result['code'] != 0) return [false, "U8错误: " . $result['msg']];
- return [true, $result];
- }
- public function saleReturn1($data) {
- if(empty($data['orderId'])) return [false, '销售退货单ID不能为空'];
- // 1. 获取销售退货单/订单信息
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getXsThOrder($data['orderId']);
- if(empty($order)) return [false, '销售退货单信息不存在'];
- $iBody = [];
- foreach ($order['details'] as $key => $value) {
- // 确保数量为负数(红字单据要求)
- $qty = (float)($value['iQuantity'] ?? 0);
- $redQty = $qty > 0 ? -$qty : $qty;
- $iBody[] = [
- "iRowNo" => $key + 1,
- "cInvCode" => $value['cInvCode'], // 存货编码
- "cPosition" => $value['cPosition'] ?? "", // 货位
- "cBatch" => $value['cBatch'] ?? "", // 批号
- "iinvexchrate" => (float)($value['iinvexchrate'] ?? 1),
- "iQuantity" => $redQty, // 红字数量
- "iNQuantity" => $redQty, // 实退数量
- "iNum" => (float)($value['iNum'] ?? 0),
- "iNNum" => (float)($value['iNum'] ?? 0),
- // 核心关联:如果是参照发货单退货,需要 iDLsID (发货单子表Autoid)
- "iDLsID" => $value['iDLsID'] ?? 0,
- "dMadeDate" => $value['dMDate'], // 生产日期
- "dVDate" => $value['dvDate'], // 失效日期
- ];
- }
- // 2. 组织表头 (iHead)
- $iHead = [
- "IsVerify" => $data['IsVerify'] ?? false, // 是否自动审核
- "bIsRedVouch" => true, // 核心:必须为 true (红字单据)
- "cWhCode" => $order['cWhCode'], // 仓库
- "cRdCode" => $order['cRdCode'], // 收发类别(如:销售出库/退货)
- "cMemo" => "接口生成",
- "cSource" => "发货单", // 来源类型
- "cSTCode" => $order['cSTCode'], // 销售类型
- "DLCode" => $order['cDLCode'], // 关联的发货单号
- "dDate" => date("Y-m-d"), // 单据日期
- ];
- // 3. 封装成 SaleOut 结构
- $final_data = [
- [
- "Inum" => "SaleOut",
- "Data" => [
- "iHead" => $iHead,
- "iBody" => $iBody
- ]
- ]
- ];
- // 4. 发送请求
- $host = $data['u8_data']['host'] ?? "";
- $token = $data['u8_data']['token'] ?? "";
- $url = $host . "/api/SaleOut/Add";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '红字销售出库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, $result];
- }
- public function saleReturn($data) {
- if(empty($data['orderId'])) return [false, '销售退货单ID不能为空'];
- // 1. 获取销售退货单信息 (DispatchList & DispatchLists)
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getXsThOrder($data['orderId']);
- if(empty($order)) return [false, '销售退货单信息不存在'];
- // --- 核心修改:按仓库分组 ---
- $groupDetails = [];
- foreach ($order['details'] as $item) {
- $whCode = $item['cWhCode'] ?? $order['cWhCode']; // 优先取明细里的仓库,没有则取主表的
- $groupDetails[$whCode][] = $item;
- }
- $final_data = [];
- // 2. 遍历每个仓库分组,生成各自的单据
- foreach ($groupDetails as $whCode => $details) {
- $iBody = [];
- foreach ($details as $index => $value) {
- $qty = (float)($value['iQuantity'] ?? 0);
- $redQty = $qty > 0 ? -$qty : $qty; // 强制红字
- $iBody[] = [
- "iRowNo" => $index + 1,
- "cInvCode" => $value['cInvCode'],
- "cPosition" => $value['cPosition'] ?? "",
- "cBatch" => $value['cBatch'] ?? "",
- "iinvexchrate" => (float)($value['iinvexchrate'] ?? 1),
- "iQuantity" => $redQty,
- "iNQuantity" => $redQty,
- "iNum" => (float)($value['iNum'] ?? 0),
- "iNNum" => (float)($value['iNum'] ?? 0),
- "iDLsID" => $value['iDLsID'] ?? 0, // 关键:关联发货单行ID
- "dMadeDate" => $value['dMDate'] ?? null,
- "dVDate" => $value['dvDate'] ?? null,
- ];
- }
- // 组织该单据的表头
- $iHead = [
- "IsVerify" => true,
- "bIsRedVouch" => true,
- "cWhCode" => $whCode, // 当前分组的仓库
- "cRdCode" => "0204",
- "cMemo" => "接口生成",
- "cSource" => "发货单",
- "cSTCode" => $order['cSTCode'],
- "DLCode" => $order['cDLCode'] ?? "",
- "dDate" => date("Y-m-d"),
- ];
- // 放入大数组
- $final_data[] = [
- "Inum" => "SaleOut",
- "Data" => [
- "iHead" => $iHead,
- "iBody" => $iBody
- ]
- ];
- }
- // 3. 发送请求
- $host = $data['u8_data']['host'] ?? "";
- $token = $data['u8_data']['token'] ?? "";
- $url = $host . "/api/SaleOut/Add";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(!$status) return [false, $result];
- if(!isset($result['code'])) return [false, '红字销售出库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, $result];
- }
- //检验单生成产成品入库单
- public function productInByZj1($data){
- $record = $data['record'];
- $payload = $data['payload'];
- $id = $record['u8_id'];
- $type = $data['type'];
- if($type == 1){
- $num = $payload['hg_quantity'];
- }else{
- $num = $payload['rb_quantity'];
- }
- //获取单据 产品检验单
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getJyOrder($id);
- if(empty($order)) return [false, '产品检验单不存在'];
- //获取单据 生产订单子表
- $product_detail = $service->getScDetails($order['SOURCEID']);
- if(empty($product_detail)) return [false, '生产订单子表数据不存在'];
- //u8 token
- list($status, $msg) = $this->getToken();
- if(! $status) return [false, $msg];
- $tmp = [
- "Inum" => "ProductIn",
- "Data" => [
- "iHead" => [
- "IsVerify" => true,
- "cWhCode" => "06", // 产成品库
- "cRdCode" => '0103', // 入库类别 产成品入库
- "cDepCode" => $order['CINSPECTDEPCODE'] ?? '', // 部门
- "cMemo" => "接口生成",
- "cSource" => "产品检验单",
- "cBusType" => "成品入库",
- "cMPoCode" => $order['SOURCECODE'], // 生产订单号
- "cChkCode" => $order['CCHECKCODE'], // 检验单号
- "dDate" => date("Y-m-d"),
- "bIsRedVouch" => false, // 如果是红字入库请设为true
- "bCalPrice" => true, // 是否由接口计算金额
- ],
- "iBody" => []
- ]
- ];
- //一个检验单只有一行
- $tmp["Data"]["iBody"][] = [
- "iRowNo" => 1,
- "cInvCode" => $order['cInvCode'] ?? '',
- "cAssUnit" => $order['CUNITID'] ?? '',
- "cPosition" => $order['cPosition'] ?? '',
- "cBatch" => $order['cBatch'] ?? '',
- "iinvexchrate" => $order['FCHANGRATE'] ?? 0,
- "iQuantity" => $num, // 数量
- "iNQuantity" => $product_detail['Qty'], // 生产订单产品数量
- "iMPoIds" => $order['SOURCEAUTOID'] ?? 0, // 生产订单子表ID
- "dMadeDate" => $order['DPRODATE'] ?? '', // 生产日期
- "iMassDate" => $order['IMASSDATE'], // 保质期
- "cMassUnit" => $order['CMASSUNIT'], // 保质期单位
- "dVDate" => $order['DVDATE'] ?? '', // 失效日期
- ];
- $final_data = [$tmp];
- //调用所需
- $host = $msg['host'] ?? "";
- $token = $msg['token'] ?? "";
- //产成品入库单生成
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/ProductIn/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '产成品入库单生成并审核失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function productInByZj($data){
- $record = $data['record'];
- $payload = $data['payload'];
- $id = $record['u8_id'];
- $type = $data['type'];
- // 确定入库数量
- $num = ($type == 1) ? $payload['hg_quantity'] : $payload['rb_quantity'];
- // 1. 获取检验单数据(用于提取物料、批次、仓库等基本信息,即便不参照也需要这些数据)
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getJyOrder($id);
- if(empty($order)) return [false, '产品检验单不存在'];
- // 2. 获取 U8 Token
- list($status, $msg) = $this->getToken();
- if(! $status) return [false, $msg];
- // 3. 组织产成品入库单 (不参照模式)
- $tmp = [
- "Inum" => "ProductIn",
- "Data" => [
- "iHead" => [
- "IsVerify" => true, // 自动审核
- "cWhCode" => $order['CWHCODE'] ?? "06", // 产成品库
- "cRdCode" => '0103', // 产成品入库类别编码 (根据U8实际修改,通常为12)
- "cDepCode" => $order['CINSPECTDEPCODE'],
- "cMemo" => "接口生成",
- "cSource" => "库存", // 关键:设为库存即为手动入库
- "cBusType" => "成品入库",
- "dDate" => date("Y-m-d"),
- "bIsRedVouch" => false,
- "bCalPrice" => true,
- ],
- "iBody" => [
- [
- "iRowNo" => 1,
- "cInvCode" => $order['CINVCODE'] ?? '',
- "cBatch" => $order['CBATCH'] ?? '',
- "iinvexchrate" => $order['FCHANGRATE'] ?? 0,
- "iQuantity" => $num, // 入库数量
- "iNQuantity" => $num, // 保持一致
- "dMadeDate" => $order['DPRODATE'] ?? '', // 生产日期
- "dVDate" => $order['DVDATE'] ?? '', // 失效日期
- ]
- ]
- ]
- ];
- $final_data = [$tmp];
- // 4. 调用接口
- $host = $msg['host'] ?? "";
- $token = $msg['token'] ?? "";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- $url = $host . "/api/ProductIn/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '产成品入库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- //检验单生成其他入库单
- public function otherInByZj($data){
- $record = $data['record'];
- $payload = $data['payload'];
- $id = $record['u8_id'];
- $num = $payload['hg_not_quantity'];
- //获取单据 检验单
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getJyOrder($id);
- if(empty($order)) return [false, '检验单不存在'];
- //u8 token
- list($status, $msg) = $this->getToken();
- if(! $status) return [false, $msg];
- $tmp = [
- "Inum" => "OtherIn",
- "Data" => [
- "iHead" => [
- "IsVerify" => true,
- "cWhCode" => "53", // 成品不良品库
- "cRdCode" => '0109', // 入库类别 其他入库
- "cDepCode" => '', // 部门
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- ],
- "iBody" => []
- ]
- ];
- //一个检验单只有一行
- $tmp["Data"]["iBody"][] = [
- "iRowNo" => 1,
- "cInvCode" => $order['CINVCODE'] ?? '',
- "cAssUnit" => $order['CUNITID'] ?? '',
- "cPosition" => $order['cPosition'] ?? '',
- "cBatch" => $order['CBATCH'] ?? '',
- "iinvexchrate" => $order['FCHANGRATE'] ?? 0,
- "iQuantity" => $num, // 数量
- "dMadeDate" => $order['DPRODATE'] ?? '', // 生产日期
- "dVDate" => $order['DVDATE'] ?? '',
- ];
- $final_data = [$tmp];
- //调用所需
- $host = $msg['host'] ?? "";
- $token = $msg['token'] ?? "";
- //产成品入库单生成
- $header = ["Authorization: {$token}",'Content-Type:application/json'];
- $url = $host . "/api/OtherIn/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '其他入库单生成并审核失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- //检验单生产采购入库单
- public function purchaseInByZj1($data)
- {
- $record = $data['record'];
- $payload = $data['payload'];
- $id = $record['u8_id']; // 这里的 ID 应该是检验单主表的 ID
- $type = $data['type'];
- if($type == 1){
- $num = $payload['hg_quantity'];
- }else{
- $num = $payload['rb_quantity'];
- }
- // 1. 获取检验单明细 (需要包含来源到货单子表ID: SOURCEAUTOID)
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getJyOrder2($id);
- if(empty($order)) return [false, '检验单不存在'];
- // 2. 获取 U8 Token
- list($status, $msg) = $this->getToken();
- if(! $status) return [false, $msg];
- // 3. 组织采购入库单 (PurchaseIn) 结构
- $tmp = [
- "Inum" => "PurchaseIn",
- "Data" => [
- "iHead" => [
- "IsVerify" => true, // 自动审核
- "bCalPrice" => true, // 自动计算价格
- "cWhCode" => $order['CWHCODE'], // 仓库编码
- "cRdCode" => "0101", // 入库类别:原材料采购入库
- "cSource" => "来料检验单", // 来源
- "cBusType" => "普通采购",
- "cChkCode" => $order['CCHECKCODE'] ?? '', // 关联检验单号
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- ],
- "iBody" => []
- ]
- ];
- // 4. 组织表体
- $tmp["Data"]["iBody"][] = [
- "iRowNo" => 1,
- "cInvCode" => $order['CINVCODE'] ?? '',
- "cPosition" => $order['cPosition'] ?? '',
- "cBatch" => $order['CBATCH'],
- "iinvexchrate" => (float)($order['FCHANGRATE'] ?? 1),
- "iQuantity" => $num, // 应收数量(入库数量)
- "iNQuantity" => $num, // 实收数量
- "iArrsId" => $order['SOURCEAUTOID'], // 子表id
- "dMadeDate" => $order['DPRODATE'], // 生产日期
- "dVDate" => $order['DVDATE'], // 失效日期
- "iUnitCost" => $order['iCost'] ?? 0,
- "iPrice" => round(($order['iCost'] ?? 0) * $num, 2),
- "iTaxUnitPrice"=> $order['iOriTaxCost'] ?? 0,
- "iSum" => round(($order['iOriTaxCost'] ?? 0) * $num, 2),
- "iTaxRate" => $order['iTaxRate'] ?? 0,
- ];
- $final_data = [$tmp];
- // 5. 调用 API
- $host = $msg['host'] ?? "";
- $token = $msg['token'] ?? "";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- $url = $host . "/api/PurchaseIn/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '采购入库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function purchaseInByZj($data)
- {
- $record = $data['record'];
- $payload = $data['payload'];
- $type = $data['type'];
- // 确定入库数量
- $num = ($type == 1) ? $payload['hg_quantity'] : $payload['rb_quantity'];
- // 1. 获取基础数据 (即使不参照,我们也需要从检验单拿到物料、仓库、供应商等基本信息)
- $service = new U8ThirtyPartyDatabaseServerService();
- $order = $service->getJyOrder2($record['u8_id']);
- if(empty($order)) return [false, '检验单不存在'];
- // 2. 获取 U8 Token
- list($status, $msg) = $this->getToken();
- if(! $status) return [false, $msg];
- // 3. 组织采购入库单 (不参照模式)
- $tmp = [
- "Inum" => "PurchaseIn",
- "Data" => [
- "iHead" => [
- "IsVerify" => true, // 自动审核
- "bCalPrice" => true, // 自动计算价格
- "PriceCalKey" => "iOriTaxCost", // 以含税单价为准计算
- "cWhCode" => "01", // 仓库
- "cVenCode" => $order['CVENCODE'], // 供应商(不参照时必填)
- "cPTCode" => "01", // 采购类型:委外或普通
- "cRdCode" => "0101", // 入库类别编码
- "cDepCode" => $order['CDEPCODE'] ?? '', // 部门
- "cBusType" => "普通采购",
- "cSource" => "库存", // 设为库存即为不参照模式
- "cMemo" => "接口生成",
- "dDate" => date("Y-m-d"),
- "cExch_Name" => "人民币",
- "iExchRate" => 1,
- ],
- "iBody" => [
- [
- "iRowNo" => 1,
- "cInvCode" => $order['CINVCODE'],
- "cPosition" => $order['CPOSITION'] ?? '',
- "cBatch" => $order['CBATCH'] ?? '',
- "iQuantity" => $num, // 数量
- "iNQuantity" => $num, // 实收数量
- "iOriTaxCost" => $order['iOriTaxCost'], // 含税单价
- "iTaxRate" => $order['iTaxRate'], // 税率
- "dMadeDate" => $order['DPRODATE'], // 生产日期
- "dVDate" => $order['DVDATE'], // 失效日期
- // 注意:不参照时,不要传 iArrsId
- ]
- ]
- ]
- ];
- $final_data = [$tmp];
- // 4. 调用 API
- $host = $msg['host'] ?? "";
- $token = $msg['token'] ?? "";
- $header = ["Authorization: {$token}", 'Content-Type:application/json'];
- $url = $host . "/api/PurchaseIn/Add";
- $json = json_encode($final_data);
- list($status, $result) = $this->post_helper1($url, $json, $header, 30);
- if(! $status) return [false, $result];
- if(! isset($result['code'])) return [false, '采购入库单生成失败'];
- if($result['code'] != 0) return [false, $result['msg']];
- return [true, ''];
- }
- public function post_helper1($url, $data, $header = [], $timeout = 20){
- Log::channel('apiLog')->info('POST', ["api" => $url , "param" => json_decode($data,true) ,"header" => $header]);
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_ENCODING, '');
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
- curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
- curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
- if(!is_null($data)) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
- $r = curl_exec($ch);
- if ($r === false) {
- // 获取错误号
- $errorNumber = curl_errno($ch);
- // 获取错误信息
- $errorMessage = curl_error($ch);
- $message = "cURL Error #{$errorNumber}: {$errorMessage}";
- Log::channel('apiLog')->info('POST结果', ["message" => $message ]);
- return [false, $message];
- }
- curl_close($ch);
- $return = json_decode($r, true);
- unset($r);
- Log::channel('apiLog')->info('POST结果', ["message" => $return ]);
- return [true, $return];
- }
- function validateProductDate($dateStr) {
- // SQL Server 常用的 datetime 格式包含 .v (毫秒)
- // 注意:这里的格式必须严格对应 " 2025-12-13 00:00:00.000"
- // 如果字符串开头有空格,格式字符串里也要留空格
- $format = 'Y-m-d H:i:s.v';
- $d = \DateTime::createFromFormat($format, $dateStr);
- // 检查是否转换成功,并且转换后的格式与原字符串完全一致
- return $d && $d->format($format) === $dateStr;
- }
- /**
- * 校验并格式化日期
- * 如果日期合法,返回格式化后的字符串;如果不合法,返回 false
- */
- public function formatAndValidateDate($dateStr) {
- try {
- // DateTime 构造函数会自动识别多种日期格式
- // trim($dateStr) 用于去除可能存在的首尾空格
- $d = new \DateTime(trim($dateStr));
- // 统一转换为 SQL Server 喜欢的格式: 2026-03-11 00:00:00.000
- return $d->format('Y-m-d H:i:s.v');
- } catch (\Exception $e) {
- // 如果传入的字符串无法解析为日期,会抛出异常
- return false;
- }
- }
- }
|