Files
OMS/app/ome/lib/order/order.php
2025-12-28 23:13:25 +08:00

514 lines
21 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
/**
* Copyright © ShopeX http://www.shopex.cn. All rights reserved.
* See LICENSE file for license details.
*/
class ome_order_order{
/**
* 余单撤消
* @access public
* @param string $order_id 订单号
* @param int $reback_price 实际退款金额
* @param int $revock_price 余单撤消的商品总金额
* @return 处理成功或者失败
*/
public function order_revoke($order_id, $reback_price='', $revock_price='')
{
$flag = true;//[拆单]发货单打回成功标志
$oOrder = app::get('ome')->model("orders");
$oOrder_items = app::get('ome')->model("order_items");
$oShop = app::get('ome')->model('shop');
$oOperation_log = app::get('ome')->model('operation_log');
//[拆单]获取订单关联详情_保存快照
$order_detail = $oOrder->dump($order_id, "*", array("order_objects"=>array("*",array("order_items"=>array('*')))));
$order_detail['pmt_order'] = floatval($order_detail['pmt_order']);
$order_detail['payinfo']['cost_payment'] = floatval($order_detail['payinfo']['cost_payment']);
$order_update = array();
$order_update['process_status'] = 'remain_cancel';//确认状态:余单撤消
$order_update['ship_status'] = '1';//发货状态:已发货
//余单撤消的"商品总额"
$cancel_item_price = $this->get_cancel_item_price($order_detail);
//余单撤消的商品金额
if($order_detail['pmt_order']){
$revock_price = $this->get_cancel_diff_money($order_detail); //有订单优惠,计算商品实付金额
}else{
$revock_price = kernel::single('ome_order_func')->order_items_diff_money($order_id);
}
//余单撤消的"商品优惠金额"
$cancel_pmt_price = $this->get_cancel_pmt_price($order_detail);
//余单撤消的"订单优惠分摊"
$pmt_order_money = $this->get_cancel_pmt_order_price($order_detail);
//订单是否有组合商品部分发货
/* if (!$this->getPgkDeliveryStatus($order_detail)) {
return ['result'=>false,'msg'=>'该订单存在组合商品部分发货无法撤销余单'];
} */
//商品总额 = 原商品总额 - 余单撤消的商品价格
$order_update['cost_item'] = $order_detail['cost_item'] - $cancel_item_price;
//折扣 = 原折扣 + (撤消的实付金额 - 退款金额)
//$order_update['discount'] = $order_detail['discount'] + ($revock_price - $reback_price);
//商品促销优惠 = 商品促销优惠 - 余单撤消的商品优惠金额
$order_update['pmt_goods'] = $order_detail['pmt_goods'] - $cancel_pmt_price;
//需平摊删除商品对应订单优惠(订单促销优惠 = 订单促销优惠 - 余单撤消的商品优惠分摊)
$order_update['pmt_order'] = $order_detail['pmt_order'] - $pmt_order_money;
//配送费用 + 保价费用 + 税金 + 支付费用
$other_amount = $order_detail['shipping']['cost_shipping'] + $order_detail['shipping']['cost_protect'] + $order_detail['cost_tax'];
if($order_detail['payinfo']['cost_payment']){
$other_amount += $order_detail['payinfo']['cost_payment']; //支付费用
}
//重新计算订单总额
$order_update['total_amount'] = $order_update['cost_item'] + $order_update['discount'] + $other_amount - $order_update['pmt_order'] - $order_update['pmt_goods'];
//订单归档
$order_update['archive'] = 1;
$filter = array('order_id'=>$order_id);
//打回订单未发货的发货单
$flag = $oOrder->rebackDeliveryByOrderId($order_id, true, '');
#打回发货单失败
if($flag == false)
{
$msg = '余单撤销失败';
$oOperation_log->write_log('order_modify@ome', $order_id, $msg);//操作日志
return false;
}
//更新订单
$oOrder->update($order_update, $filter);
//店铺信息
$shop_detail = $oShop->dump(array('shop_id'=>$order_detail['shop_id']), 'node_type');
$node_type = $shop_detail['node_type'];
$basicMStockFreezeLib = kernel::single('material_basic_material_stock_freeze');
//获取撤消的商品明细
$cancelitems = array();
$cancel_sql = "SELECT product_id,bn,nums,sendnum,(nums-sendnum) as cancel_num,((nums-sendnum)*price) as c_total_money,obj_id FROM `sdb_ome_order_items` WHERE order_id='".$order_id."' AND `sendnum`<`nums` AND `delete`='false' ";
$cancel_items = kernel::database()->select($cancel_sql);
if ($cancel_items){
$objects = app::get('ome')->model('order_objects')->getList('obj_id,goods_id', ['obj_id'=>array_column($cancel_items, 'obj_id')]);
$objects = array_column($objects, null, 'obj_id');
uasort($cancel_items, [kernel::single('console_iostockorder'), 'cmp_productid']);
$branchBatchList = [];
foreach ($cancel_items as $c_key=>$c_items){
//减少冻结库存
$branchBatchList[] = [
'bm_id' => $c_items['product_id'],
'sm_id' => $objects[$c_items['obj_id']]['goods_id'],
'obj_type' => material_basic_material_stock_freeze::__ORDER,
'bill_type' => 0,
'obj_id' => $order_id,
'branch_id' => '',
'bmsq_id' => material_basic_material_stock_freeze::__SHARE_STORE,
'num' => $c_items['cancel_num'],
];
$cancelitems[] = '货号:'.$c_items['bn'].'(购买数:'.$c_items['nums'].',已发货:'.$c_items['sendnum'].',本次撤销:'.$c_items['cancel_num'].'个)';
}
// 减少冻结库存
$basicMStockFreezeLib->unfreezeBatch($branchBatchList, __CLASS__.'::'.__FUNCTION__, $err);
}
$cancelitems = implode(';',$cancelitems);
$msg = '余单撤销(撤销商品总金额为:'.$revock_price.';明细为:'.$cancelitems;
//余单撤消后,清除订单级预占店铺冻结流水
// unfreezeBatch已经清除
// $basicMStockFreezeLib->delOrderFreeze($order_id);
/* */
//更新订单明细
$order = app::get('ome')->model('orders')->dump($order_id,"order_id",array("order_objects"=>array("*",array("order_items"=>array("*")))));
if ($order['order_objects']){
foreach ($order['order_objects'] as $obj){
if ($obj) {
$delete = true;
foreach ($obj['order_items'] as $item){
if ($item['sendnum'] == 0){
$sql = "UPDATE `sdb_ome_order_items` SET `delete`='true' WHERE `item_id`='".$item['item_id']."'";
kernel::database()->exec($sql);
}else {
$delete = false;
}
}
if ($delete == true){
$sql = "UPDATE `sdb_ome_order_objects` SET `delete`='true' WHERE `obj_id`='".$obj['obj_id']."'";
kernel::database()->exec($sql);
}
}
}
}
//操作日志
$log_id = $oOperation_log->write_log('order_modify@ome', $order_id, $msg);
//[拆单]余单撤消_保存订单快照
$oOrder->write_log_detail($log_id, $order_detail);
$c2c_shop_list = ome_shop_type::shop_list();
if (!in_array($node_type, $c2c_shop_list)){
//订单编辑同步
if ($service_order = kernel::servicelist('service.order')){
foreach($service_order as $object=>$instance){
if(method_exists($instance, 'update_order')){
$instance->update_order($order_id);
}
}
}
}
//发货单同步
if (in_array($node_type, $c2c_shop_list)){
//C2C前端店铺回写发货单
$sql = "SELECT de.`delivery_id` FROM `sdb_ome_delivery` de
JOIN `sdb_ome_delivery_order` dor ON dor.`delivery_id`=de.`delivery_id` AND dor.`order_id`='".$order_id."'
WHERE de.`logi_no` IS NOT NULL ORDER BY de.`delivery_id` DESC";
$c2c_delivery = kernel::database()->selectrow($sql);
$delivery_id = $c2c_delivery['delivery_id'];
if ($delivery_id){
kernel::single('ome_event_trigger_shop_delivery')->delivery_add($delivery_id);
}
}
/*------------------------------------------------------ */
//-- [拆单]余单撤消后_生成销售单
/*------------------------------------------------------ */
#判断是否存在销售单
$sql = "SELECT COUNT(*) AS num FROM sdb_ome_sales WHERE order_id='".$order_id."'";
$sales_row = kernel::database()->selectrow($sql);
if(empty($sales_row['num']))
{
#获取"最后成功发货"的普通发货单ID
$sql = "SELECT dord.delivery_id FROM sdb_ome_delivery_order AS dord LEFT JOIN sdb_ome_delivery AS d
ON(dord.delivery_id=d.delivery_id) WHERE dord.order_id='".$order_id."' AND (d.parent_id=0 OR d.is_bind='true')
AND d.disabled='false' AND d.status='succ' AND d.type='normal' ORDER BY delivery_time DESC";
$delivery_row = kernel::database()->selectrow($sql);
$delivery_id = $delivery_row['delivery_id'];
if($delivery_id)
{
#生成销售单
$iostock_data = kernel::single('siso_receipt_iostock_sold')->get_io_data(array('delivery_id'=>$delivery_id,'process_status'=>'remain_cancel'));
kernel::single('siso_receipt_sales_sold')->create(array('delivery_id'=>$delivery_id,'iostock'=>$iostock_data), $msg);
}
}
//余单撤销后,需要发起多包裹状态回写,因为物流信息作为补充回写,一般是发货完成才会触发
if (in_array($order_detail['shop_type'], ome_shop_type::many_split_type())) {
kernel::single('ome_event_trigger_shop_delivery')->delivery_confirm_retry([$order_id]);
}
return true;
}
/**
* 判断订单中是否有捆绑商品部分发货
* @Author: xueding
* @Vsersion: 2022/9/13 下午6:07
* @param $orderDetail
* @return bool
*/
public function getPgkDeliveryStatus($orderDetail)
{
foreach($orderDetail['order_objects'] as $object => $objVal) {
if ($objVal['obj_type'] == 'pkg') {
$sendnum = array_sum(array_column($objVal['order_items'],'sendnum'));
$quantity = array_sum(array_column($objVal['order_items'],'quantity'));
if ($sendnum > 0 && $quantity != $sendnum) {
$msg = '该订单存在组合商品部分发货无法撤销余单';
$oOperation_log = app::get('ome')->model('operation_log');
$oOperation_log->write_log('order_modify@ome', $orderDetail['order_id'], $msg);//操作日志
return false;
}
}
}
return true;
}
/**
* 订单数据字段格式化过滤
* @access public
* @param $order_sdf 订单标准sdf结构数据
* @return 订单标准sdf结构数据
*/
public function modify_sdfdata($order_sdf){
if ($order_sdf['shop_type'] == 'taobao'){
foreach($order_sdf['order_objects'] as $key=>$object){
if ($object['obj_type'] != 'pkg' || !$object['amount']) continue;
$obj_amount = $object['amount'];
$count_items = count($object['order_items']);
if ( $obj_amount > $count_items ){
$average_item_price = floor($obj_amount / $count_items);
$remain_price = $obj_amount - $average_item_price * $count_items;
}else{
$average_item_price = round($obj_amount / $count_items, 3);
}
$i = 1;
foreach($object['order_items'] as $k=>$item){
$amount = $price = 0;
if ( $i == 1 ){
$amount = bcadd($average_item_price,$remain_price,3);
}else{
$amount = $average_item_price;
}
if ($item['quantity']){
$price = round($amount / $item['quantity'], 3);
}else{
$price = $amount;
}
$order_sdf['order_objects'][$key]['order_items'][$k]['price'] = $price;
$order_sdf['order_objects'][$key]['order_items'][$k]['amount'] = $amount;
$i++;
}
}
}
return $order_sdf;
}
/**
* 计算捆绑、礼包的差额
* @access public
* @param $order_objects objects_sdf 结构
* @return Number 差额
*/
public function obj_difference($order_objects){
$obj_amount = $items_amount = 0;
$db = kernel::database();
$obj_sendnum = 1;
if ($order_objects['order_items']){
$items_tmp = array();
// 捆绑商品明细总金额
foreach ($order_objects['order_items'] as $items){
if (empty($items_tmp)){
$items_tmp = $items;
}
$items_amount += $items['amount'];
}
// 计算当前捆绑的发送数量
$sql = " SELECT `nums` FROM `sdb_ome_order_items` WHERE `item_id`='".$items_tmp['item_id']."' ";
$old_order_items = $db->selectrow($sql);
if ($items_tmp['number']){
$obj_sendnum = $order_objects['nums'] / ($old_order_items['nums'] / $items_tmp['number']);
}
$obj_amount = $obj_sendnum * $order_objects['price'];
}
$difference = $obj_amount - $items_amount;
return $difference;
}
/**
* 处理本地或shopex体系的0元订单
*
* @return void
* @author
**/
function order_pay_confirm($shop_id,$order_id,$total_amount)
{
$ome_payment_confirm = app::get('ome')->getConf('ome.payment.confirm');
$orderObj = app::get('ome')->model('orders');
if($ome_payment_confirm == 'false'){//不需要经过财审,直接生成支付单
$op_info = kernel::single('ome_func')->getDesktopUser();
$pay_time = time();
$paymentObj = app::get('ome')->model('payments');
$sdf = array(
'payment_bn' => $paymentObj->gen_id(),
'shop_id' => $shop_id,
'order_id' => $order_id,
'currency' => 'CNY',
'money' => '0',
'paycost' => '0',
'cur_money' => '0',
'pay_type' => 'online',
't_begin' => $pay_time,
'download_time' => $pay_time,
't_end' => $pay_time,
'status' => 'succ',
'memo'=>'0元订单自动生成支付单',
'op_id'=> $op_info['op_id'],
);
$paymentObj->create_payments($sdf);
$pay_status = '1';
$sql ="UPDATE `sdb_ome_orders` SET pay_status='".$pay_status."', paytime='".$pay_time."' WHERE `order_id`='".$order_id."'";
}else{
$pay_status = '0';
$sql ="UPDATE `sdb_ome_orders` SET pay_status='".$pay_status."' WHERE `order_id`='".$order_id."'";
}
$orderObj->db->exec($sql);
return true;
}
/**
* 获取余单撤消的商品原价
*/
public function get_cancel_item_price($order){
$amount = 0;
if ($order['order_objects']){
foreach ($order['order_objects'] as $obj){
if($obj['obj_type'] == 'pkg'){
$tmp_amount = kernel::single('ome_order_remain_pkg')->get_order_total_price($obj);
$amount += $tmp_amount;
}elseif($obj['obj_type'] == 'gift'){
continue; //赠品为0元,跳过
}else{
$tmp_amount = kernel::single('ome_order_remain_goods')->get_order_total_price($obj);
$amount += $tmp_amount;
}
}
}
return $amount;
}
/**
* 有订单优惠时,获取余单撤消的商品实付金额(实付金额 = 销售价 - 优惠分摊)
*/
public function get_cancel_diff_money($order){
$amount = 0;
if ($order['order_objects']){
foreach ($order['order_objects'] as $obj){
if($obj['obj_type'] == 'pkg'){
$tmp_amount = kernel::single('ome_order_remain_pkg')->get_order_diff_money($obj);
$amount += $tmp_amount;
}elseif($obj['obj_type'] == 'gift'){
continue; //赠品为0元,跳过
}else{
$tmp_amount = kernel::single('ome_order_remain_goods')->get_order_diff_money($obj);
$amount += $tmp_amount;
}
}
}
return $amount;
}
/**
* 获取余单撤消的商品优惠金额
*/
public function get_cancel_pmt_price($order){
$amount = 0;
if ($order['order_objects']){
foreach ($order['order_objects'] as $obj){
if($obj['obj_type'] == 'pkg'){
$tmp_amount = kernel::single('ome_order_remain_pkg')->get_order_pmt_price($obj);
$amount += $tmp_amount;
}elseif($obj['obj_type'] == 'gift'){
continue; //赠品为0元,跳过
}else{
$tmp_amount = kernel::single('ome_order_remain_goods')->get_order_pmt_price($obj);
$amount += $tmp_amount;
}
}
}
return $amount;
}
/**
* 获取余单撤消商品的的订单优惠分摊
*/
public function get_cancel_pmt_order_price($order){
$amount = 0;
if ($order['order_objects']){
foreach ($order['order_objects'] as $obj){
if($obj['obj_type'] == 'pkg'){
$tmp_amount = kernel::single('ome_order_remain_pkg')->get_order_pmt_order_price($obj);
$amount += $tmp_amount;
}elseif($obj['obj_type'] == 'gift'){
continue; //赠品为0元,跳过
}else{
$tmp_amount = kernel::single('ome_order_remain_goods')->get_order_pmt_order_price($obj);
$amount += $tmp_amount;
}
}
}
return $amount;
}
/**
* 订单全额退款成功后,系统自动余单撤消 并删除未发货的商品
* todo满足以下条件
* 1、订单是部分发货
* 2、订单已经全额退款
* 3、还有货品没有发货
*/
public function fullRefund_order_revoke($order_id){
if(empty($order_id)){
return false;
}
$oOrder = app::get('ome')->model('orders');
$orderInfo = $oOrder->dump($order_id, 'order_id, pay_status, ship_status, pmt_order', array("order_objects"=>array("*",array("order_items"=>array("*")))));
if($orderInfo['pay_status'] != '5' || $orderInfo['ship_status'] != '2'){
return false; //不是(部分发货、全额退款)
}
if($orderInfo['archive'] == 1 || $orderInfo['abnormal'] == 'true'){
return false; //订单已归档 OR 异常订单
}
if(!in_array($orderInfo['process_status'], array('splitting', 'splited'))){
return false; //订单不是部分拆分、已拆分完
}
//判断是否还有货品没有发货
$is_unshipped = false;
foreach ($orderInfo['order_objects'] as $objKey => $objVal){
foreach ($objVal['order_items'] as $itemKey => $itemVal){
if($itemVal['delete']=='false' && $itemVal['sendnum']<$itemVal['quantity']){
$is_unshipped = true;
}
}
}
if(!$is_unshipped){
return false; //货品已经全部发货
}
//计算未发货商品的金额
$orderInfo['pmt_order'] = floatval($orderInfo['pmt_order']);
if($orderInfo['pmt_order']){
//订单优惠时
$reback_price = kernel::single('ome_order_order')->get_cancel_diff_money($orderInfo);
}else{
$reback_price = kernel::single('ome_order_func')->order_items_diff_money($order_id);
}
$revock_price = 0; //撤销商品总额(默认0元后面会重新计算)
$result = $this->order_revoke($order_id, $reback_price, $revock_price);
return $result;
}
}