|
|
@@ -104,7 +104,7 @@ class U8ThirdPartyService extends Service
|
|
|
/**
|
|
|
* 采购到货单拆行/更新处理
|
|
|
*/
|
|
|
- public function purchaseIn($data)
|
|
|
+ public function purchaseIn1($data)
|
|
|
{
|
|
|
if (empty($data['orderId'])) return [false, '采购到货单ID不能为空'];
|
|
|
if (empty($data['orderNo'])) return [false, '采购到货单单号不能为空'];
|
|
|
@@ -119,10 +119,6 @@ class U8ThirdPartyService extends Service
|
|
|
$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;
|
|
|
|
|
|
@@ -229,6 +225,258 @@ class U8ThirdPartyService extends Service
|
|
|
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();
|
|
|
+ list($status, $result) = $service->getCGDHDetails($data['orderId']);
|
|
|
+ if (! $status) return [false, $result];
|
|
|
+
|
|
|
+ // ==================== 核心修改:前置全单 bGsp 类型强一致性校验 ====================
|
|
|
+ $hasInspect = false; // 是否存在需要检验的行 (bGsp = 1)
|
|
|
+ $hasNoInspect = false; // 是否存在不需要检验的行 (bGsp = 0)
|
|
|
+
|
|
|
+ foreach ($result as $item) {
|
|
|
+ if (isset($item['bGsp']) && (int)$item['bGsp'] === 1) {
|
|
|
+ $hasInspect = true;
|
|
|
+ } else {
|
|
|
+ $hasNoInspect = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 只要同时存在【检验】和【免检】,直接在这里拦截,后面任何多余的计算和数据库操作都不执行
|
|
|
+ if ($hasInspect && $hasNoInspect) {
|
|
|
+ return [false, '该采购到货单中同时存在【检验】与【免检】的存货,无法混合处理,请拆单或修正单据中存货属性。'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果明细为空,直接返回
|
|
|
+ if (!$hasInspect && !$hasNoInspect) {
|
|
|
+ return [false, '未找到有效的明细数据进行处理'];
|
|
|
+ }
|
|
|
+ // ==========================================================================
|
|
|
+
|
|
|
+ // 取出第一行作为模板,保留 ID, cCode 等主表关联信息
|
|
|
+ $templateRow = reset($result);
|
|
|
+ $mainId = $templateRow['ID'];
|
|
|
+
|
|
|
+ $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'] = !empty($value['lot']) ? $value['lot'] : null;
|
|
|
+ $newRow['dPDate'] = !empty($value['productDate']) ? $this->formatAndValidateDate($value['productDate']) : null;
|
|
|
+ $newRow['dVDate'] = !empty($value['failureDate']) ? $this->formatAndValidateDate($value['failureDate']) : null;
|
|
|
+ $newRow['cFree1'] = !empty($value['param_one']) ? $value['param_one'] : null;
|
|
|
+ $newRow['cFree2'] = !empty($value['param_two']) ? $value['param_two'] : null;
|
|
|
+
|
|
|
+ $insertData[] = $newRow;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 执行数据库操作:先删后插
|
|
|
+ list($status, $msg) = $service->rebuildDhDetails($mainId, $insertData);
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+
|
|
|
+ // 查询采购到货单(获取最新插入并带有最新 Autoid 的明细数据)
|
|
|
+ list($status, $order) = $service->getCgOrder($data['orderId']);
|
|
|
+ if(! $status) return [false, $order];
|
|
|
+
|
|
|
+ // ==================== 整单分流处理 ====================
|
|
|
+ $host = $data['u8_data']['host'];
|
|
|
+ $token = $data['u8_data']['token'];
|
|
|
+ $header = ["Authorization: {$token}", 'Content-Type:application/json'];
|
|
|
+
|
|
|
+ if ($hasInspect) {
|
|
|
+ // -------------- 全单走:来料报检单 --------------
|
|
|
+ $inspectBody = [];
|
|
|
+ foreach ($order['details'] as $item) {
|
|
|
+ $qty = (float)($item['iQuantity'] ?? 0);
|
|
|
+ if ($qty <= 0) continue;
|
|
|
+
|
|
|
+ $inspectBody[] = [
|
|
|
+ "SOURCEAUTOID" => $item['Autoid'],
|
|
|
+ "ITESTSTYLE" => 0,
|
|
|
+ "CINVCODE" => $item['cInvCode'],
|
|
|
+ "FCHANGRATE" => (float)($item['iInvExchRate'] ?? 0),
|
|
|
+ "FQUANTITY" => $qty,
|
|
|
+ "CBATCH" => $item['cBatch'],
|
|
|
+ 'DPRODATE' => $item['dPDate'],
|
|
|
+ 'DVDATE' => $item['dVDate'],
|
|
|
+ 'cFree1' => $item['cFree1'],
|
|
|
+ 'cFree2' => $item['cFree2'],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ $inspectData = [
|
|
|
+ [
|
|
|
+ "Inum" => "ArrInspect",
|
|
|
+ "Data" => [
|
|
|
+ "iHead" => [
|
|
|
+ "CSOURCEID" => $order['ID'],
|
|
|
+ "CDEPCODE" => $order['cDepCode'],
|
|
|
+ "DDATE" => date("Y-m-d"),
|
|
|
+ "CCHECKTYPECODE" => 'ARR',
|
|
|
+ ],
|
|
|
+ "iBody" => $inspectBody
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+
|
|
|
+ $url = $host . "/api/QmArr/ArrInspectAdd";
|
|
|
+ list($status, $result) = $this->post_helper1($url, json_encode($inspectData), $header, 30);
|
|
|
+ if(! $status) return [false, '报检单接口请求失败: ' . json_encode($result)];
|
|
|
+ if(! isset($result['code']) || $result['code'] != 0) {
|
|
|
+ return [false, '报检单生成失败: ' . ($result['msg'] ?? '未知错误')];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, '报检单生成成功'];
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // -------------- 全单走:采购入库单 --------------
|
|
|
+ $purchaseInBody = [];
|
|
|
+ $rn = 1;
|
|
|
+ $warehouse_code = "";
|
|
|
+ foreach ($order['details'] as $item) {
|
|
|
+ $qty = (float)($item['iQuantity'] ?? 0);
|
|
|
+ if ($qty <= 0) continue;
|
|
|
+ if(empty($warehouse_code)) $warehouse_code = $item['cWhCode'];
|
|
|
+
|
|
|
+// $purchaseInBody[] = [
|
|
|
+// "iRowNo" => $rn++,
|
|
|
+// "cInvCode" => $item['cInvCode'],
|
|
|
+// "cPosition" => "",
|
|
|
+// "cBatch" => $item['cBatch'],
|
|
|
+// "iinvexchrate" => (float)($item['iInvExchRate'] ?? 0),
|
|
|
+// "iQuantity" => $qty,
|
|
|
+// "iSum" => (float)($item['iSum'] ?? 0),
|
|
|
+// "iNum" => 0,
|
|
|
+// "iNQuantity" => $qty,
|
|
|
+// "iNNum" => 0,
|
|
|
+// "chVencode" => $order['cVenCode'],
|
|
|
+// "iPOsID" => $item['iPOsID'],
|
|
|
+// "iArrsId" => $item['Autoid']
|
|
|
+// ];
|
|
|
+
|
|
|
+ // --- 核心金额计算逻辑 ---
|
|
|
+ $taxRate = (float)($item['iTaxRate'] ?? 13.0); // 税率
|
|
|
+ $taxUnitPrice = (float)($item['iOriTaxCost'] ?? 0); // 原币含税单价
|
|
|
+
|
|
|
+ // 1. 价税合计 (iSum)
|
|
|
+ $iSum = round($qty * $taxUnitPrice, 2);
|
|
|
+ // 2. 原币无税金额 (imoney) = 价税合计 / (1 + 税率/100)
|
|
|
+ $iMoney = round($iSum / (1 + ($taxRate / 100)), 2);
|
|
|
+ // 3. 税额 (itax)
|
|
|
+ $iTax = round($iSum - $iMoney, 2);
|
|
|
+ // 4. 原币无税单价 (iunitprice)
|
|
|
+ $iUnitPrice = round($taxUnitPrice / (1 + ($taxRate / 100)), 6);
|
|
|
+ $purchaseInBody[] = [
|
|
|
+ "iRowNo" => $rn++,
|
|
|
+ "cInvCode" => $item['cInvCode'],
|
|
|
+ "cPosition" => "",
|
|
|
+ "cBatch" => $item['cBatch'],
|
|
|
+ "iinvexchrate" => (float)($item['iInvExchRate'] ?? 0),
|
|
|
+ "iQuantity" => $qty,
|
|
|
+ "iSum" => (float)($item['iSum'] ?? 0),
|
|
|
+ "iNum" => 0,
|
|
|
+ "iNQuantity" => $qty,
|
|
|
+ "iNNum" => 0,
|
|
|
+ "chVencode" => $order['cVenCode'],
|
|
|
+ "iPOsID" => $item['iPOsID'],
|
|
|
+ "iArrsId" => $item['Autoid'],
|
|
|
+
|
|
|
+ // --- 新增价格字段 ---
|
|
|
+ "iOriTaxCost" => (float)$taxUnitPrice, // 原币含税单价
|
|
|
+ "iOriCost" => (float)$iUnitPrice, // 原币无税单价
|
|
|
+ "iOriMoney" => (float)$iMoney, // 原币无税金额
|
|
|
+ "iOriTaxPrice" => (float)$iTax, // 原币税额
|
|
|
+ "iOriSum" => (float)$iSum, // 原币价税合计
|
|
|
+ "iTaxRate" => (float)$taxRate, // 税率
|
|
|
+ // 本币字段 (inat...) 建议也加上,防止 U8 换算误差
|
|
|
+ "fNatMoney" => (float)$iMoney, // 本币无税金额
|
|
|
+ "fNatTax" => (float)$iTax, // 本币税额
|
|
|
+ "fNatSum" => (float)$iSum, // 本币价税合计
|
|
|
+ "dMadeDate" => $item['DPRODATE'] ?? null,
|
|
|
+ "dVDate" => $item['DVDATE'] ?? null,
|
|
|
+ 'cFree1' => $item['CFREE1'] ?? null,
|
|
|
+ 'cFree2' => $item['CFREE2'] ?? null,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ $purchaseInData = [
|
|
|
+ [
|
|
|
+ "Inum" => "PurchaseIn",
|
|
|
+ "Data" => [
|
|
|
+ "iHead" => [
|
|
|
+ "IsVerify" => true,
|
|
|
+ "bCalPrice" => true, // 开启自动计算
|
|
|
+ "PriceCalKey" => "iOriTaxCost", // 以含税单价为准
|
|
|
+// "IsVerify" => true,
|
|
|
+// "bCalPrice" => false,
|
|
|
+// "PriceCalKey" => "iSum",
|
|
|
+ "cWhCode" => $warehouse_code,
|
|
|
+ "cRdCode" => "0101",
|
|
|
+ "cDepCode" => $order['cDepCode'],
|
|
|
+ "cVenCode" => $order['cVenCode'],
|
|
|
+ "cARVCode" => $order['cCode'],
|
|
|
+ "cSource" => "采购到货单",
|
|
|
+ "cBusType" => "普通采购",
|
|
|
+ "cMemo" => "接口生成",
|
|
|
+ "cexch_name" => "人民币",
|
|
|
+ "iExchRate" => $order['iExchRate'],
|
|
|
+ "iTaxRate" => $order['iTaxRate'],
|
|
|
+ "dDate" => date("Y-m-d")
|
|
|
+ ],
|
|
|
+ "iBody" => $purchaseInBody
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+
|
|
|
+ $url = $host . "/api/PurchaseIn/Add";
|
|
|
+ list($status, $result) = $this->post_helper1($url, json_encode($purchaseInData), $header, 30);
|
|
|
+ if(! $status) return [false, '采购入库单接口请求失败: ' . json_encode($result)];
|
|
|
+ if(! isset($result['code']) || $result['code'] != 0) {
|
|
|
+ return [false, '采购入库单生成失败: ' . ($result['msg'] ?? '未知错误')];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, '采购入库单生成成功'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public function materialOut($data)
|
|
|
{
|
|
|
if (empty($data['orderId'])) return [false, '领料申请单ID不能为空'];
|