You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prestashop 1.7 Order类:如何更新商品列表、重算运费及增值税?

如何在PrestaShop 1.7中修改现有订单的商品并重新计算运费与增值税

一、核心思路说明

PrestaShop的订单数据分散在order、order_detail、order_tax、order_shipping等表中,所以修改订单商品需要操作OrderDetail实体,之后再同步更新订单的总金额、税费和运费。Order和Product类本身确实没有提供一站式的修改方法,得结合多个关联类来手动处理。


二、具体操作步骤

1. 初始化订单对象

首先要确保你能正确获取到目标订单的实例:

$orderId = 123; // 替换成你的订单ID
$order = new Order((int)$orderId);
if (!$order->id) {
    throw new Exception('指定的订单不存在');
}

2. 添加商品到订单

要新增订单商品,需要创建OrderDetail实例,并填充必要的商品信息(注意要和订单的语言、货币、客户组匹配):

$productId = 456; // 要添加的商品ID
$product = new Product((int)$productId);
if (!$product->id) {
    throw new Exception('指定的商品不存在');
}

// 根据订单上下文获取商品的含税/不含税价格
$priceExclTax = $product->getPrice(
    true, // true表示获取不含税价格
    null,
    6,
    null,
    false,
    false,
    false,
    1,
    false,
    null,
    null,
    null,
    $order->id_customer // 传入订单客户ID,确保价格匹配客户组
);
$priceInclTax = $product->getPrice(
    false, // false表示获取含税价格
    null,
    6,
    null,
    false,
    false,
    false,
    1,
    false,
    null,
    null,
    null,
    $order->id_customer
);

// 创建订单明细
$orderDetail = new OrderDetail();
$orderDetail->id_order = $order->id;
$orderDetail->id_product = $product->id;
$orderDetail->id_product_attribute = 0; // 如果是组合商品,替换为对应的属性ID
$orderDetail->product_quantity = 1; // 要添加的数量
$orderDetail->product_price = $priceExclTax;
$orderDetail->product_price_wt = $priceInclTax;
$orderDetail->product_name = $product->name[$order->id_lang]; // 匹配订单语言
$orderDetail->product_reference = $product->reference;
$orderDetail->save();

3. 修改订单商品数量

找到目标订单对应的OrderDetail记录,直接修改数量并保存:

$targetProductId = 456; // 要修改的商品ID
$newQuantity = 3; // 新的数量

// 查询对应的订单明细
$orderDetailData = OrderDetail::getList(
    ['id_order_detail'],
    ['id_order' => $order->id, 'id_product' => $targetProductId]
);

if (!empty($orderDetailData)) {
    $orderDetail = new OrderDetail((int)$orderDetailData[0]['id_order_detail']);
    $orderDetail->product_quantity = (int)$newQuantity;
    // 如果商品价格有变动,同步更新product_price和product_price_wt
    // $orderDetail->product_price = $newPriceExclTax;
    // $orderDetail->product_price_wt = $newPriceInclTax;
    $orderDetail->save();
} else {
    throw new Exception('订单中未找到该商品');
}

4. 删除订单中的商品

找到对应的OrderDetail记录并删除即可:

$targetProductId = 456; // 要删除的商品ID

$orderDetailIds = OrderDetail::getList(
    ['id_order_detail'],
    ['id_order' => $order->id, 'id_product' => $targetProductId]
);

foreach ($orderDetailIds as $odData) {
    $orderDetail = new OrderDetail((int)$odData['id_order_detail']);
    $orderDetail->delete();
}

三、重新计算运费与增值税

完成商品修改后,需要同步更新订单的运费、税费和总金额:

1. 重新计算运费

你已经找到的Order::refreshShippingCost()方法可以直接用,第二个参数传true会同时重新计算运费的税费:

// 重新计算运费,true表示同步更新运费税费
$order->refreshShippingCost(true);

2. 重新计算订单总金额与增值税

需要先清理旧的税费记录,再重新计算各项总额并更新订单:

// 启动数据库事务,避免中途出错导致数据不一致
Db::getInstance()->beginTransaction();

try {
    // 1. 删除旧的订单税费记录
    OrderTax::cleanOrdersTaxes($order->id);

    // 2. 计算商品总金额(含税/不含税)
    $totalProductsExclTax = 0;
    $totalProductsInclTax = 0;
    $orderDetails = OrderDetail::getList(
        ['product_price', 'product_price_wt', 'product_quantity'],
        ['id_order' => $order->id]
    );

    foreach ($orderDetails as $od) {
        $totalProductsExclTax += (float)$od['product_price'] * (int)$od['product_quantity'];
        $totalProductsInclTax += (float)$od['product_price_wt'] * (int)$od['product_quantity'];
    }

    // 3. 获取运费的含税/不含税金额
    $shippingExclTax = (float)$order->total_shipping;
    $shippingInclTax = (float)$order->total_shipping_tax_incl;

    // 4. 计算订单总金额
    $totalExclTax = $totalProductsExclTax + $shippingExclTax;
    $totalInclTax = $totalProductsInclTax + $shippingInclTax;

    // 5. 更新订单核心字段
    $order->total_products = $totalProductsExclTax;
    $order->total_products_wt = $totalProductsInclTax;
    $order->total_paid_tax_excl = $totalExclTax;
    $order->total_paid_tax_incl = $totalInclTax;
    $order->total_paid = $totalInclTax; // 注意:如果订单使用非默认货币,需要额外处理汇率转换
    $order->save();

    // 6. 重新生成订单税费记录
    $order->getTaxes();

    // 提交事务
    Db::getInstance()->commit();
} catch (Exception $e) {
    // 出错回滚事务
    Db::getInstance()->rollback();
    throw new Exception('更新订单失败:' . $e->getMessage());
}

四、注意事项

  • 事务处理:一定要用数据库事务包裹所有修改操作,防止部分操作失败导致数据混乱。
  • 货币与客户组:商品价格要匹配订单的货币和客户组,避免价格计算错误。
  • 组合商品:如果操作的是组合商品,要正确传入id_product_attribute,否则会导致商品信息错误。
  • 订单状态通知:修改订单后,建议根据实际情况更新订单状态并通知客户(比如通过邮件)。

内容的提问来源于stack exchange,提问作者JarsOfJam-Scheduler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:07:45