Files
OMS/app/wms/lib/logistics.php
chenping 61783b7d01 1. 【新增】售后单售后原因类型支持搜索
2. 【新增】手工创建订单折扣可输入正数

3. 【优化】盘点申请单确认

4. 【修复】采购退货单模拟出库失败问题

5. 【新增】订单金额客户实付与结算金额

6. 【优化】仓库发货统计报表物料名称显示

7. 【优化】自有仓储虚拟发货逻辑

8. 【修复】基础物料分类管理问题
2026-04-01 11:59:17 +08:00

205 lines
8.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* WMS 物流相关封装
* 统一通过 erpapi shop request 调用各平台物流接口
*/
class wms_logistics
{
/**
* 官方提货(提货物流)
* 入参为 wms delivery_id通过 outer_delivery_bn 对应 ome_delivery.delivery_bn 取 ome 发货单,
* 用 ome_event_trigger_shop_data_delivery_alibaba->get_sdf 取 sdf再调 erpapi 对应平台 officialPickup
* @param int|array $delivery_id wms 发货单主键;或数组且含 key delivery_id
* @return array 统一返回 ['rsp' => 'succ'|'fail', 'msg' => '', 'data' => ...],便于后续根据成功/失败处理
*/
public function officialPickup($delivery_id)
{
$fail = function ($msg, $data = null) {
return ['rsp' => 'fail', 'msg' => $msg, 'data' => $data];
};
$ok = function ($result) {
if (is_array($result) && isset($result['rsp'])) {
return $result;
}
return ['rsp' => 'succ', 'msg' => '', 'data' => $result];
};
$wms_delivery_id = is_array($delivery_id) ? (isset($delivery_id['delivery_id']) ? (int)$delivery_id['delivery_id'] : 0) : (int)$delivery_id;
if ($wms_delivery_id <= 0) {
return $fail('无效的发货单ID');
}
$wmsDeliveryMdl = app::get('wms')->model('delivery');
$wmsDelivery = $wmsDeliveryMdl->dump($wms_delivery_id, 'delivery_id,outer_delivery_bn,shop_id');
if (empty($wmsDelivery) || empty($wmsDelivery['outer_delivery_bn']) || empty($wmsDelivery['shop_id'])) {
return $fail('未找到WMS发货单或缺少 outer_delivery_bn/shop_id');
}
$omeDeliveryMdl = app::get('ome')->model('delivery');
$omeDelivery = $omeDeliveryMdl->dump(['delivery_bn' => $wmsDelivery['outer_delivery_bn']]);
if (empty($omeDelivery) || empty($omeDelivery['delivery_id'])) {
return $fail('未找到对应的OMS发货单');
}
$ome_delivery_id = $omeDelivery['delivery_id'];
$deliveryList = $omeDeliveryMdl->getList('*', ['delivery_id' => $ome_delivery_id]);
if (empty($deliveryList)) {
return $fail('OMS发货单列表为空');
}
$deliveryOrderMdl = app::get('ome')->model('delivery_order');
$deliveryOrderList = $deliveryOrderMdl->getList('delivery_id,order_id', ['delivery_id' => $ome_delivery_id]);
$order_ids = [];
$delivery_orders = [];
$orderList = [];
foreach ($deliveryOrderList as $row) {
$order_ids[] = $row['order_id'];
$delivery_orders[$row['delivery_id']] = &$orderList[$row['order_id']];
}
$orderModel = app::get('ome')->model('orders');
$orders = $orderModel->getList('*', ['order_id' => $order_ids]);
foreach ($orders as $o) {
$orderList[$o['order_id']] = $o;
}
$delivery = $deliveryList[0];
$order = isset($delivery_orders[$ome_delivery_id]) ? $delivery_orders[$ome_delivery_id] : null;
$sdf = $this->_buildOfficialPickupSdf($ome_delivery_id, $delivery, $order);
if (empty($sdf)) {
return $fail('获取平台发货数据(sdf)为空');
}
$result = kernel::single('erpapi_router_request')->set('shop', $wmsDelivery['shop_id'])->logistics_officialPickup($sdf);
$ret = $ok($result);
// 仅成功时:从平台返回结果中提取运单号,回写 OMS / WMS原 erpapi_shop_matrix_alibaba_request_delivery confirm_callback 逻辑)
if ($ret['rsp'] === 'succ' || $ret['rsp'] === 'success') {
$this->_officialPickupSyncLogiNo($ret, $sdf['delivery_bn'], $wmsDelivery['delivery_id']);
}
return $ret;
}
/**
* 在本类内直接组装 officialPickup 所需 sdf与 erpapi alibaba request logistics 入参一致,避免 router 取数不全
* 结构orderinfo.order_bn、delivery_items(oid/nums/number/weight)、memo、delivery_time、delivery_bn
* @param int $ome_delivery_id OMS 发货单 id
* @param array $delivery OMS 发货单行(含 delivery_bn, delivery_time, memo 等)
* @param array|null $order OMS 订单行(含 order_bn/platform_order_bn
* @return array 空表示组装失败,否则为 alibaba officialPickup 所需 sdf
*/
protected function _buildOfficialPickupSdf($ome_delivery_id, $delivery, $order)
{
if (empty($delivery) || empty($order)) {
return [];
}
$order_bn = isset($order['platform_order_bn']) && $order['platform_order_bn'] !== ''
? $order['platform_order_bn']
: (isset($order['order_bn']) ? $order['order_bn'] : '');
if ($order_bn === '') {
return [];
}
$detailMdl = app::get('ome')->model('delivery_items_detail');
$details = $detailMdl->getList('*', ['delivery_id' => $ome_delivery_id]);
if (empty($details)) {
return [];
}
$objIds = array_unique(array_column($details, 'order_obj_id'));
$objMdl = app::get('ome')->model('order_objects');
$objRows = $objMdl->getList('obj_id,oid', ['obj_id' => $objIds]);
$objId2Oid = [];
foreach ($objRows as $r) {
$objId2Oid[$r['obj_id']] = isset($r['oid']) ? trim((string)$r['oid']) : '';
}
$delivery_items = [];
foreach ($details as $d) {
$oid = isset($objId2Oid[$d['order_obj_id']]) ? $objId2Oid[$d['order_obj_id']] : '';
if ($oid === '') {
continue;
}
$num = isset($d['number']) ? (int)$d['number'] : 0;
if ($num < 1) {
continue;
}
$delivery_items[] = [
'oid' => $oid,
'nums' => $num,
'number' => $num,
'weight' => isset($d['weight']) ? (float)$d['weight'] : 0,
];
}
if (empty($delivery_items)) {
return [];
}
return [
'orderinfo' => ['order_bn' => $order_bn],
'delivery_items'=> $delivery_items,
'memo' => isset($delivery['memo']) ? $delivery['memo'] : '',
'delivery_time' => isset($delivery['delivery_time']) ? $delivery['delivery_time'] : time(),
'delivery_bn' => isset($delivery['delivery_bn']) ? $delivery['delivery_bn'] : '',
];
}
/**
* 从 officialPickup 返回的 result 中解析出 result.pickUpInfo与 yunqi saveOfficialPickupResult 一致data 可能为 JSON 字符串,且含 msg 内嵌 JSON
* @param array $result ['rsp'=>'succ','data'=>'...'] 其中 data 可能为 '{"msg":"{\"result\":{\"pickUpInfo\":{...}}}","success":true}'
* @return array|null pickUpInfo 或 null
*/
protected function _parseOfficialPickupResult($result)
{
$data = isset($result['data']) ? $result['data'] : $result;
if (is_string($data)) {
$data = json_decode($data, true);
if (is_array($data) && isset($data['msg']) && is_string($data['msg'])) {
$inner = json_decode($data['msg'], true);
if (is_array($inner)) {
$data = array_merge($data, $inner);
}
}
}
if (!is_array($data)) {
$data = array();
}
if (!empty($data['result']['pickUpInfo'])) {
return $data['result']['pickUpInfo'];
}
if (!empty($result['result']['pickUpInfo'])) {
return $result['result']['pickUpInfo'];
}
return null;
}
/**
* 官方提货成功:从接口返回中解析 pickUpInfo.mailNo回写 OMS 与 WMS 运单号
* @param array $result officialPickup 返回的 ['rsp'=>'succ','data'=>...]
* @param string $delivery_bn OMS 发货单号delivery_bn
* @param int $wms_delivery_id WMS 发货单主键
*/
protected function _officialPickupSyncLogiNo($result, $delivery_bn, $wms_delivery_id)
{
$pickUpInfo = $this->_parseOfficialPickupResult($result);
if (empty($pickUpInfo) || empty($pickUpInfo['mailNo'])) {
return;
}
$mailNo = trim($pickUpInfo['mailNo']);
// OMS: 通过 addLogiNo 统一链路更新 ome_delivery.logi_no
kernel::single('ome_event_receive_delivery')->update([
'delivery_bn' => $delivery_bn,
'logi_no' => $mailNo,
'action' => 'addLogiNo',
'status' => 'update',
]);
// WMS: 同步更新 wms_delivery_bill.logi_notype=1 主单)
app::get('wms')->model('delivery_bill')->update(
['logi_no' => $mailNo],
['delivery_id' => $wms_delivery_id, 'type' => 1]
);
}
}