CRMEB_PRO_M/app/services/erp/OrderServices.php

840 lines
35 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
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\services\erp;
use app\jobs\order\OrderSyncJob;
use app\services\order\StoreOrderCartInfoServices;
use app\services\order\StoreOrderCreateServices;
use app\services\order\StoreOrderDeliveryServices;
use app\services\order\StoreOrderRefundServices;
use app\services\order\StoreOrderServices;
use crmeb\exceptions\AdminException;
use crmeb\services\erp\Erp as erpServices;
use think\facade\Log;
/**
* Class OrderServices
* @package app\services\erp
*/
class OrderServices
{
protected $services;
/**
* OrderServices constructor.
* @param erpServices $services
*/
public function __construct(erpServices $services)
{
$this->services = $services;
}
/**
* 订单上传
* @param int $oid
* @return bool
* @throws \Exception
*/
public function upload(int $oid): bool
{
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
$order = $orderServices->get($oid, ['*'], ['store']);
if ($order['id'] < 1) {
throw new AdminException('订单信息不能为空!');
}
// 过滤已退款订单和虚拟商品
if ($order['refund_status'] == 2 || $order['product_type'] > 0) {
return true;
}
$biz = [
'shop_id' => $this->getShopId($order->store->erp_shop_id ?? 0), // 店铺编号
'so_id' => $this->getErpOrderId($order['order_id'], $order['erp_order_id']), // 线上订单号, 长度 <= 50
'shop_status' => 'WAIT_SELLER_SEND_GOODS', // 订单状态 待发货
'buyer_message' => $order['mark'], // 买家留言
'shop_buyer_id' => (string)$order['uid'], // 买家帐号
'receiver_name' => $order['real_name'], // 收件人
'receiver_mobile' => $order['user_phone'], // 联系手机
'pay_amount' => (float)$order['pay_price'], // 应付金额,保留两位小数,单位元)
'freight' => (float)$order['freight_price'], // 运费
'order_date' => date('Y-m-d H:i:s', $order['add_time']), // 订单日期
'shop_modified' => date('Y-m-d H:i:s', $order['add_time']), // 订单修改日期
'items' => $this->getItems($oid, (int)$order['uid'], $order['unique']),
'pay' => [
'outer_pay_id' => 'xxx', // 外部支付单号最大50
'pay_date' => date('Y-m-d H:i:s', $order['pay_time']), // 支付日期
'payment' => $order['pay_type'], // 支付方式最大20
'seller_account' => 'seller', // 卖家支付账号,最大 50
'buyer_account' => 'buyer', // 买家支付账号,最大 200
'amount' => (float)$order['pay_price'] // 支付总额
]
];
$biz = array_merge($biz, $this->getAddress($order['user_address']));
$num = 3;
for ($i = $num; $i >= 0; $i--) {
if ($i <= 0) {
Log::error(['msg' => 'ERP订单上传失败,调用均为异常', 'oid' => $oid]);
return false;
}
try {
$result = $this->services->serviceDriver('order')->ordersUpload([$biz]);
if ($result['datas'][0]['issuccess'] && $order['erp_order_id'] != $biz['so_id']) {
$order->save(['erp_id' => $result['datas'][0]['o_id'], 'erp_order_id' => $biz['so_id']]);
}
break;
} catch (\Exception $e) {
usleep(1000 * 50);
Log::error('ERP订单上传失败,原因:' . $e->getMessage());
}
}
return true;
}
/**
* 收货地址
* @param string $userAddress
* @return array
*/
public function getAddress(string $userAddress): array
{
$receiver_state = $receiver_city = $receiver_district = $receiver_address = '';
if (!empty($userAddress)) {
$address = explode(' ', $userAddress);
$receiver_state = $address[0] ?? ''; // 收货省份
$receiver_city = $address[1] ?? ''; // 收货市
$receiver_district = $address[2] ?? ''; // 收货区
$receiver_address = $address[3] ?? ''; // 收货街道
$receiver_address .= $address[4] ?? ''; // 街道
}
return compact('receiver_state', 'receiver_city', 'receiver_district', 'receiver_address');
}
/**
* 获取erp指定订单商品详情
* @param int $oid
* @param int $uid
* @param string $unique
* @return array
*/
public function getItems(int $oid, int $uid, string $unique): array
{
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
$cartInfo = $storeOrderCartInfoServices->getOrderCartInfo($oid);
if (empty($cartInfo)) {
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
//同步查询订单商品为查询到 查询缓存信息
$orderInfo = $orderServices->getCacheOrderInfo($uid, $unique);
$cartInfo = $orderInfo['cartInfo'] ?? [];
}
$items = [];
foreach ($cartInfo as $cart) {
$cart = $cart['cart_info'] ?? $cart;
$attrInfo = $cart['productInfo']['attrInfo'];
$items[] = [
'sku_id' => $attrInfo['code'],
'shop_sku_id' => $attrInfo['code'],
'base_price' => (float)bcdiv((string)$cart['truePrice'], (string)$cart['cart_num'], 2),
'amount' => (float)$cart['truePrice'],
'qty' => $cart['cart_num'],
'pic' => $cart['productInfo']['image'],
'name' => $cart['productInfo']['store_name'],
'properties_value' => $attrInfo['suk'],
'outer_oi_id' => $cart['product_attr_unique'],
];
}
return $items;
}
/**
* 取消回调
* @param array $cancel
* @return bool
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function cancelCallback(array $cancel): bool
{
try {
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
$orders = explode('_', $cancel['so_id']);
$cancel['order_id'] = $orders[0] ?? '';
$order = $orderServices->getOne(['order_id' => $cancel['order_id']], '*');
if (!$order) {
throw new AdminException('订单信息不能为空!');
}
$order = is_object($order) ? $order->toArray() : $order;
$ids = [$order['erp_order_id']];
// 获取子订单号
$orders = $orderServices->getColumn(['pid' => $order['id']], 'erp_order_id', 'id');
if ($orders) {
$ids = array_values(array_unique(array_filter(array_merge($ids, $orders))));
}
$result = $this->services->serviceDriver('order')->ordersSingleQuery(['so_ids' => $ids]);
// 取消申请退货
$this->checkRefundApply((int)$order['id']);
// 部分退货
if (count($result['orders']) > 1) {
$this->applyPartRefund($cancel, $order, $result['orders'], $orderServices);
} else {
$this->applyRefund($cancel, $order, $orderServices);
}
} catch (\Exception $e) {
Log::error(['msg' => '订单取消失败,原因:' . $e->getMessage(), 'data' => $cancel]);
}
return true;
}
/**
* 订单申请退款
* @param array $cancel
* @param array $order
* @param StoreOrderServices $orderServices
* @return void
*/
protected function applyRefund(array $cancel, array $order, StoreOrderServices $orderServices)
{
try {
$data['refund_reason_wap_explain'] = $cancel['remark'];
$data['order_id'] = $cancel['order_id'];
/** @var StoreOrderRefundServices $storeOrderRefundServices */
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
if ($storeOrderRefundServices->count(['store_order_id' => $order['id'], 'refund_type' => [0, 1, 2, 4, 5], 'is_cancel' => 0, 'is_del' => 1])) {
throw new AdminException('请先处理售后申请!');
}
//0元退款
if ($order['pay_price'] == 0 && in_array($order['refund_status'], [0, 1])) {
$refund_price = 0;
} else {
if ($order['pay_price'] == $order['refund_price']) {
throw new AdminException('已退完支付金额!不能再退款了!');
}
$refund_price = bcsub((string)$order['pay_price'], $order['refund_price'], 2);
}
$data['refund_status'] = 2;
$data['refund_type'] = 6;
$refund_data['pay_price'] = $order['pay_price'];
$refund_data['refund_price'] = $refund_price;
if ($order['refund_price'] > 0) {
mt_srand();
$refund_data['refund_id'] = $order['order_id'] . rand(100, 999);
}
/** @var StoreOrderCreateServices $service */
$storeOrderCreateServices = app()->make(StoreOrderCreateServices::class);
//生成退款订单
$refundOrderData['uid'] = $order['uid'];
$refundOrderData['store_id'] = $order['store_id'];
$refundOrderData['store_order_id'] = $order['id'];
$refundOrderData['refund_num'] = $order['total_num'];
$refundOrderData['refund_type'] = $data['refund_type'];
$refundOrderData['refund_price'] = $order['pay_price'];
$refundOrderData['refunded_price'] = $refund_price;
$refundOrderData['refund_reason'] = $cancel['remark'];
$refundOrderData['order_id'] = $storeOrderCreateServices->getNewOrderId('');
$refundOrderData['refunded_time'] = time();
$refundOrderData['add_time'] = time();
/** @var StoreOrderCartInfoServices $orderInfoServices */
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
$cartInfos = $storeOrderCartInfoServices->getCartColunm(['oid' => $order['id']], 'id,cart_id,cart_num,cart_info');
foreach ($cartInfos as &$cartInfo) {
$cartInfo['cart_info'] = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
}
$refundOrderData['cart_info'] = json_encode(array_column($cartInfos, 'cart_info'));
$res = $storeOrderRefundServices->save($refundOrderData);
//修改订单退款状态
if ($storeOrderRefundServices->agreeRefund((int)$res->id, $refund_data)) {
//主动退款清楚原本退款单
$storeOrderRefundServices->delete(['store_order_id' => $order['id']]);
$orderServices->update($order['id'], $data);
} else {
$storeOrderRefundServices->storeProductOrderRefundYFasle((int)$order['id'], $refund_price);
}
} catch (\Exception $e) {
Log::error('订单申请退款失败,原因:' . $e->getMessage());
}
}
/**
* 部分退款申请
* @param array $cancel
* @param array $order
* @param array $orders
* @param StoreOrderServices $orderServices
* @return bool|void
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
protected function applyPartRefund(array $cancel, array $order, array $orders, StoreOrderServices $orderServices)
{
try {
$cartWhere = ['oid' => $order['id']];
// 获取拆单信息
if ($order['pid'] < 0) {
$oIds = $orderServices->Value([['pid', '=', $order['id']], ['refund_status', '<', 2], ['status', '=', 0]], 'GROUP_CONCAT(id)');
if (!empty($oIds)) {
$oIds = array_filter(explode(',', $oIds));
}
$cartWhere = ['oid' => $oIds, 'split_status' => [0, 1]];
}
/** @var StoreOrderCartInfoServices $orderInfoServices */
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
$cartInfos = $storeOrderCartInfoServices->getCartColunm($cartWhere, 'id,oid,cart_id,cart_num,split_surplus_num,cart_info');
foreach ($cartInfos as &$cartInfo) {
$cartInfo['cart_info'] = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
}
// 过滤已退商品
$cancelled = $this->filter($orders, $order['id']);
if (empty($cancelled)) {
return true;
}
$cartOid = 0;
$cartIds = [];
foreach ($cartInfos as $cart) {
$num = $cancelled[$cart['cart_info']['productInfo']['attrInfo']['code']] ?? 0;
if ($num > 0) {
$allow = $num <= $cart['split_surplus_num'] ? $num : $num - $cart['split_surplus_num'];
$cartId = (string)$cart['cart_id'];
if (isset($cartIds[$cartId])) {
$cartIds[$cartId]['cart_num'] += $allow;
} else {
$cartIds[$cartId] = ['cart_id' => $cartId, 'cart_num' => $allow, 'oid' => $cart['oid']];
$cartOid = $cart['oid'];
}
}
}
if ($order['pid'] < 0) {
$oid = $orderServices->Value([['pid', '=', $order['id']], ['refund_status', '<', 2], ['status', '=', 0]], 'id');
if ($oid < 1) {
return true;
}
$order = $orderServices->getOne(['id' => $oid], '*');
if (!$order) {
throw new AdminException('订单信息不能为空!');
}
}
/** @var StoreOrderRefundServices $storeOrderRefundServices */
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
$refundData = ['refund_reason' => $cancel['remark'], 'refund_explain' => 'ERP取消订单', 'refund_img' => json_encode([])];
$refundId = $storeOrderRefundServices->applyRefund($cartOid, $order['uid'], $order, array_values($cartIds), 1, 0.00, $refundData, 1, false);
if ($refundId) {
$refund = $storeOrderRefundServices->get($refundId);
// 立即退款
$this->receivedCallback(['outer_as_id' => $refund['order_id']], 1);
}
} catch (\Exception $e) {
Log::error('订单部分退款申请失败,原因:' . $e->getMessage());
}
}
/**
* 订单发货
* @param array $data
* @return bool
*/
public function deliverCallback(array $data): bool
{
try {
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
/** @var StoreOrderDeliveryServices $orderDeliveryServices */
$orderDeliveryServices = app()->make(StoreOrderDeliveryServices::class);
$order = $orderServices->getOne(['erp_id' => $data['o_id'], 'status' => 0], '*');
$deliver = [
"type" => 1, // 订单统一使用快递配送
"delivery_name" => $data['logistics_company'], // 快递公司名称
"delivery_id" => $data['l_id'], // 快递公司单号
"delivery_code" => $data['lc_id'], // 快递公司编码
"express_record_type" => "1", // 快递
'express_temp_id' => '',
'expressTemp' => [],
"to_name" => '',
"to_tel" => '',
"to_addr" => '',
"sh_delivery_name" => "",
"sh_delivery_id" => "",
"sh_delivery_uid" => "",
"fictitious_content" => "",
"export_open" => true,
'erp_id' => (int)$data['o_id'] // 内部订单编号
];
// 单个订单发货
if (!empty($order)) {
// 取消申请退货
$this->checkRefundApply($order['id']);
$other = ["to_name" => $order['real_name'], "to_tel" => $order['user_phone'], "to_addr" => $order['user_address']];
$orderDeliveryServices->delivery($order['id'], array_merge($deliver, $other));
return true;
}
// 根据订单ID查找为空则订单异常
$order = $orderServices->getOne(['erp_order_id' => $data['so_id']], '*');
if (!$order) {
throw new AdminException('订单信息获取异常,不能进行自动发货!');
}
// 拆单发货
/** @var StoreOrderCartInfoServices $cartInfoServices */
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
$list = $cartInfoServices->getSplitCartList($order['id']);
if ($order['pid'] < 0 && empty($list)) {
$oIds = $orderServices->Value([['pid', '=', $order['id']], ['status', '=', 0], ['refund_status', '<', 2]], 'GROUP_CONCAT(id)');
if ($oIds) {
$oIds = array_filter(explode(',', $oIds));
// 获取拆单信息进行匹配是否拆单
$cartWhere = ['oid' => $oIds, 'split_status' => [0, 1]];
$list = $cartInfoServices->getCartColunm($cartWhere, 'id,oid,cart_id,cart_num,split_surplus_num,cart_info');
foreach ($list as &$cartInfo) {
$cartInfo['cart_info'] = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
}
}
}
// 获取发货数据
[$deliver['cart_ids'], $oid] = $this->generateCart($data['items'], $list);
if (empty($deliver['cart_ids'])) {
return true;
}
// 取消申请退货
$this->checkRefundApply($oid);
$other = ["to_name" => $order['real_name'], "to_tel" => $order['user_phone'], "to_addr" => $order['user_address']];
$orderDeliveryServices->splitDelivery($oid, array_merge($deliver, $other));
} catch (\Exception $e) {
Log::error('发货回调失败, 原因:' . $e->getMessage());
}
return true;
}
/**
* 订单拆分后的数据
* @param array $items
* @param array $list
* @return array
* @throws Exception
*/
public function generateCart(array $items, array $list): array
{
$carts = [];
$oid = 0;
foreach ($items as $item) {
foreach ($list as $cart) {
if ($item['sku_id'] == $cart['cart_info']['productInfo']['attrInfo']['code']) {
$carts[] = ['cart_id' => $cart['cart_id'], 'cart_num' => (int)$item['qty']];
$oid = $cart['oid'];
}
}
}
return [$carts, $oid];
}
/**
* 售后单上传
* @param array $refundIds
* @return bool
*/
public function refundOrderUpload(array $refundIds, string $shopStatus = 'WAIT_SELLER_CONFIRM_GOODS')
{
try {
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
/** @var StoreOrderRefundServices $storeOrderRefundServices */
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
$list = [];
foreach ($refundIds as $refundId) {
$refund = $storeOrderRefundServices->getOne(['id' => $refundId], '*', ['order']);
if ($refund->order['pid'] > 0) {
$order = $orderServices->get($refund->order['pid']);
if (!$order) {
throw new AdminException('父级订单信息不能为空!');
}
$soId = $order->erp_order_id;
} else {
$soId = $refund->order->erp_order_id;
}
$refundData = [
'shop_id' => $this->getShopId($refund->order->store->erp_shop_id ?? 0), // 店铺编号
'outer_as_id' => $refund['order_id'], // 退货退款单号,平台唯一
'so_id' => $soId, // 平台订单号
'type' => '普通退货', // 售后类型
'shop_status' => $shopStatus, // WAIT_SELLER_CONFIRM_GOODS:等待卖家确认收货 CLOSED:退款关闭
'good_status' => 'BUYER_RETURNED_GOODS', // 买家已退货
'question_type' => null,
'remark' => $refund['refund_reason'], // 问题类型
'total_amount' => (float)$refund->order['pay_price'], // 原单据总金额
'refund' => (float)$refund['refund_price'], // 卖家应退金额
'payment' => 0.00 // 买家应补偿金额
];
$items = [];
foreach ($refund['cart_info'] as $cart) {
$items[] = [
'sku_id' => $cart['productInfo']['attrInfo']['code'], // 商家商品编码
'qty' => (int)$cart['cart_num'], // 退货数量
'amount' => bcadd(bcmul((string)($cart['truePrice'] ?? 0), (string)$cart['cart_num'], 4), (string)($cart['postage_price'] ?? 0), 2), // SKU退款金额
'type' => '退货',
'pic' => $cart['productInfo']['attrInfo']['image']
];
}
$refundData['items'] = $items;
$list[] = $refundData;
}
$result = $this->services->serviceDriver('order')->afterSaleUpload($list);
if ($result['datas'][0]['issuccess'] != true) {
Log::error('退货单:' . implode(',', $refundIds) . ' 发送失败,原因:' . $result['datas'][0]['msg']);
}
} catch (\Exception $e) {
Log::error(['msg' => '售后单上传失败,原因:' . $e->getMessage(), 'data' => ['refundIds' => $refundIds, 'shopStatus' => $shopStatus]]);
}
}
/**
* 获取店铺编号
* @param int $erpShopId
* @return int
*/
public function getShopId(int $erpShopId): int
{
if ($erpShopId < 1) {
$erpShopId = sys_config('jst_default_shopid');
}
return (int)$erpShopId;
}
/**
* ERP订单取消
* @param string $orderId
* @param array $erpOrderId
* @return void
*/
public function cancelOrder(string $orderId, array $erpOrderId = [])
{
$erpOrderId[] = $orderId;
$result = $this->services->serviceDriver('order')->ordersSingleQuery(['so_ids' => array_filter($erpOrderId), 'status' => 'WaitConfirm']);
if (!$erpIds = array_column($result['orders'], 'o_id')) {
Log::error(['msg' => 'ERP订单取消失败,原因:未找到待发货订单', 'data' => [$orderId, $erpOrderId]]);
return false;
}
$cancelData = ['o_ids' => $erpIds, 'cancel_type' => '用户申请退货, 重新生成订单'];
$num = 3;
for ($i = $num; $i >= 0; $i--) {
if ($i <= 0) {
Log::error(['msg' => 'ERP订单取消失败,调用均为异常', 'data' => [$orderId, $erpOrderId]]);
return false;
}
try {
$this->services->serviceDriver('order')->orderByOIdCancel($cancelData);
return true;
} catch (\Exception $e) {
usleep(1000 * 50);
Log::error('ERP订单取消失败,原因:' . $e->getMessage());
}
}
return false;
}
/**
* 售后收货回调
* @param array $refund
* @param int $type
* @param bool $isUpload
* @return void
*/
public function receivedCallback(array $refund, int $type = 1, bool $isUpload = false)
{
try {
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
/** @var StoreOrderRefundServices $orderRefundServices */
$orderRefundServices = app()->make(StoreOrderRefundServices::class);
$data = [
'refund_type' => 6, // 已退款
'refunded_time' => time()
];
if ($type == 1) {
$data['refund_status'] = 2;
$data['refund_type'] = 6;
} else if ($type == 2) {
$data['refund_status'] = 0;
$data['refund_type'] = 3;
}
$orderRefund = $orderRefundServices->getOne(['order_id' => $refund['outer_as_id']]);
if (!$orderRefund) {
throw new AdminException('Data does not exist!');
}
$id = (int)$orderRefund['id'];
if ($type == 2) {
$refundData = [
'refuse_reason' => 'ERP订单发货取消',
'refund_type' => 3,
'refunded_time' => time()
];
$orderRefundServices->refuseRefund($id, $refundData, $orderRefund);
} else {
if ($orderRefund['is_cancel'] == 1) {
throw new AdminException('用户已取消申请!');
}
$order = $orderServices->get((int)$orderRefund['store_order_id']);
if (!$order) {
throw new AdminException('Data does not exist!');
}
if (!in_array($orderRefund['refund_type'], [0, 1, 2, 5]) && !($orderRefund['refund_type'] == 4 && $orderRefund['apply_type'] == 3)) {
throw new AdminException('售后订单状态不支持该操作');
}
// 0元退款
if ($orderRefund['refund_price'] == 0) {
$refund_price = 0;
} else {
$refund_price = $orderRefund['refund_price'];
if ($orderRefund['refund_price'] == $orderRefund['refunded_price']) {
throw new AdminException('已退完支付金额!不能再退款了');
}
$data['refunded_price'] = bcadd($refund_price, $orderRefund['refunded_price'], 2);
$bj = bccomp((string)$orderRefund['refund_price'], $data['refunded_price'], 2);
if ($bj < 0) {
throw new AdminException('退款金额大于支付金额,请修改退款金额');
}
}
$refund_data['pay_price'] = $order['pay_price'];
$refund_data['refund_price'] = $refund_price;
if ($order['refund_price'] > 0) {
mt_srand();
$refund_data['refund_id'] = $order['order_id'] . rand(100, 999);
}
// 修改订单退款状态
unset($data['refund_price']);
if ($orderRefundServices->agreeRefund($id, $refund_data)) {
$orderRefundServices->update($id, $data);
} else {
$orderRefundServices->storeProductOrderRefundYFasle($id, $refund_price);
throw new AdminException('退货单退款失败');
}
// 重新上传订单
if ($type && $isUpload) {
$orders = explode('_', $refund['so_id']);
$order = $orderServices->getOne(['order_id' => $orders[0] ?? ''], 'id, pid, status, refund_status, erp_order_id');
if (!$order) {
throw new AdminException('订单不存在');
}
$erpOrderId = [];
$oid = (int)$order['id'];
$status = (int)$order['status'];
if ($order['pid'] < 0) {
$childOrder = $orderServices->getOne([['pid', '=', $order['id']], ['status', '=', 0], ['refund_status', '=', 0]], 'id, pid, status, refund_status, erp_order_id');
$refundChild = $orderServices->getColumn([['pid', '=', $order['id']], ['status', '=', 0], ['refund_status', '=', 2]], 'erp_order_id');
if (!empty($refundChild)) {
$erpOrderId = array_unique($refundChild);
}
if ($childOrder) {
$oid = (int)$childOrder['id'];
$erpOrderId[] = $childOrder['erp_order_id'];
$status = (int)$childOrder['status'];
}
}
if ($oid > 0) {
!in_array($status, [2, 4]) && OrderSyncJob::dispatchDo('reorderOrder', [$order['erp_order_id'], $erpOrderId, $oid]);
} else {
Log::error(['msg' => '售后收货回调没有需要取消的订单', 'data' => $refund]);
}
}
}
} catch (\Exception $e) {
Log::error(['msg' => '售后收货回调失败,原因:' . $e->getMessage(), 'data' => ['refund' => $refund, 'type' => $type, 'isUpload' => $isUpload]]);
}
}
/**
* 过滤ERP不可退订单
* @param array $orders
* @param int $oid
* @return array
*/
protected function filter(array $orders, int $oid): array
{
$cancelled = $waitConfirm = [];
foreach ($orders as $cartOrder) {
if (in_array($cartOrder['status'], ['WaitConfirm', 'Sent'])) {
foreach ($cartOrder['items'] as $item) {
if (!isset($waitConfirm[$item['sku_id']])) {
$waitConfirm[$item['sku_id']] = $item['qty'];
} else {
$waitConfirm[$item['sku_id']] += $item['qty'];
}
}
}
}
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
$cartInfo = $storeOrderCartInfoServices->getOrderCartInfo($oid);
foreach ($cartInfo as $cart) {
$attrInfo = $cart['cart_info']['productInfo']['attrInfo'];
$cancelled[$attrInfo['code']] = $cart['cart_info']['cart_num'];
if (isset($waitConfirm[$attrInfo['code']])) {
$cancelled[$attrInfo['code']] -= $waitConfirm[$attrInfo['code']];
if ($cancelled[$attrInfo['code']] < 1) {
unset($cancelled[$attrInfo['code']]);
}
}
}
$refundData = $this->getOrderRefund($oid);
foreach ($refundData as $key => $item) {
$num = $cancelled[$key] ?? 0;
if ($num > 0) {
$cancelled[$key] -= $item;
if ($cancelled[$key] < 1) {
unset($cancelled[$key]);
}
}
}
return $cancelled;
}
/**
* 累计订单已退数量
* @param int $oid
* @return array
*/
public function getOrderRefund(int $oid): array
{
$attrData = [];
$refunds = $this->orderRefundList($oid);
foreach ($refunds as $refund) {
foreach ($refund['cart_info'] as $item) {
if (!isset($attrData[$item['productInfo']['attrInfo']['code']])) {
$attrData[$item['productInfo']['attrInfo']['code']] = $item['cart_num'];
} else {
$attrData[$item['productInfo']['attrInfo']['code']] += $item['cart_num'];
}
}
}
return $attrData;
}
/**
* 存在申请退货单则关闭
* @param int $oid
* @return bool
*/
public function checkRefundApply(int $oid): bool
{
$refunds = $this->orderRefundList($oid, 1);
if (!empty($refunds)) {
$refundIds = [];
foreach ($refunds as $refund) {
$refundIds[] = $refund['id'];
$this->receivedCallback(['outer_as_id' => $refund['order_id']], 2);
}
// 关闭 ERP 退货单
$this->refundOrderUpload($refundIds, 'CLOSED');
}
return true;
}
/**
* 订单退货单相关信息
* @param int $id
* @param int $refundType
* @return array
*/
public function orderRefundList(int $id, int $refundType = 4): array
{
/** @var StoreOrderRefundServices $storeOrderRefundServices */
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
$refunds = $storeOrderRefundServices->getRefundList(['store_order_id' => $id, 'refundTypes' => $refundType], 'id, store_order_id, store_id, order_id, uid, cart_info');
/** @var StoreOrderServices $orderServices */
$orderServices = app()->make(StoreOrderServices::class);
$ids = $orderServices->Value(['pid' => $id], 'GROUP_CONCAT(id)');
if ($ids) {
$ids = array_filter(explode(',', $ids));
$list = $storeOrderRefundServices->getRefundList(['store_order_id' => $ids, 'refundTypes' => $refundType], 'id, store_order_id, store_id, order_id, uid, cart_info');
$refunds = array_merge($refunds, $list);
}
return $refunds;
}
/**
* ERP订单号
* @return string $orderId
* @return string $erpOrderId
*/
public function getErpOrderId(string $orderId, string $erpOrderId = ''): string
{
if (!empty($erpOrderId)) {
$arr = explode('_', $erpOrderId);
if (count($arr) == 1) {
return $erpOrderId . '_1';
}
$num = end($arr);
return $arr[0] . '_' . ++$num;
}
return $orderId;
}
}