|
@@ -6,122 +6,24 @@ use app\common\Enum\GoodsEnum;
|
|
|
use app\common\model\Order;
|
|
|
use app\common\model\OrderGoods;
|
|
|
use app\common\model\OrderAction;
|
|
|
-use app\common\model\Carts;
|
|
|
use app\common\model\Address;
|
|
|
use app\common\model\UserCoupon;
|
|
|
use app\common\model\Goods;
|
|
|
use app\common\model\Sku;
|
|
|
use app\common\model\Freight;
|
|
|
use app\common\model\Coupon;
|
|
|
+use app\common\model\Carts;
|
|
|
use think\Db;
|
|
|
use think\Exception;
|
|
|
-
|
|
|
+use app\common\model\OrderAddress;
|
|
|
/**
|
|
|
* 订单服务类
|
|
|
* 封装订单创建相关逻辑
|
|
|
*/
|
|
|
class OrderService
|
|
|
{
|
|
|
-
|
|
|
- /**
|
|
|
- * 统一的创建订单方法
|
|
|
- * @param int $address_id 地址ID
|
|
|
- * @param int $user_id 用户ID
|
|
|
- * @param array $goods_list 标准化的商品列表
|
|
|
- * @param int $user_coupon_id 优惠券ID
|
|
|
- * @param string $memo 备注
|
|
|
- * @param array $cart_ids 购物车ID数组(如果是购物车模式需要清空)
|
|
|
- * @return Order
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- public static function createOrder($address_id, $user_id, $goods_list, $user_coupon_id = 0, $memo = '', $cart_ids = [])
|
|
|
- {
|
|
|
- $address = Address::get($address_id);
|
|
|
- if (!$address || $address['user_id'] != $user_id) {
|
|
|
- throw new Exception("地址未找到");
|
|
|
- }
|
|
|
-
|
|
|
- if (empty($goods_list)) {
|
|
|
- throw new Exception("商品列表不能为空");
|
|
|
- }
|
|
|
-
|
|
|
- $config = get_addon_config('shop');
|
|
|
- $order_sn = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
|
|
|
-
|
|
|
- // 订单主表信息
|
|
|
- $orderInfo = [
|
|
|
- 'user_id' => $user_id,
|
|
|
- 'order_sn' => $order_sn,
|
|
|
- 'address_id' => $address->id,
|
|
|
- 'province_id' => $address->province_id,
|
|
|
- 'city_id' => $address->city_id,
|
|
|
- 'area_id' => $address->area_id,
|
|
|
- 'receiver' => $address->receiver,
|
|
|
- 'mobile' => $address->mobile,
|
|
|
- 'address' => $address->address,
|
|
|
- 'zipcode' => $address->zipcode,
|
|
|
- 'goodsprice' => 0, // 商品金额 (不含运费)
|
|
|
- 'amount' => 0, // 总金额 (含运费)
|
|
|
- 'shippingfee' => 0, // 运费
|
|
|
- 'discount' => 0, // 优惠金额
|
|
|
- 'saleamount' => 0,
|
|
|
- 'memo' => $memo,
|
|
|
- 'expiretime' => time() + $config['order_timeout'], // 订单失效
|
|
|
- 'status' => 'normal'
|
|
|
- ];
|
|
|
-
|
|
|
- // 通过商品列表计算订单明细
|
|
|
- list($orderItem, $goodsList, $userCoupon) = self::computeGoods($orderInfo, $goods_list, $user_id, $address->area_id, $user_coupon_id);
|
|
|
-
|
|
|
- // 创建订单
|
|
|
- $order = self::createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon);
|
|
|
-
|
|
|
- // 如果是购物车模式,需要清空购物车
|
|
|
- if (!empty($cart_ids)) {
|
|
|
- Carts::clear($cart_ids);
|
|
|
- }
|
|
|
-
|
|
|
- return $order;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 通过购物车创建订单
|
|
|
- * @param int $address_id 地址ID
|
|
|
- * @param int $user_id 用户ID
|
|
|
- * @param array $cart_ids 购物车ID数组
|
|
|
- * @param int $user_coupon_id 优惠券ID
|
|
|
- * @param string $memo 备注
|
|
|
- * @return Order
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- public static function createOrderByCart($address_id, $user_id, $cart_ids, $user_coupon_id = 0, $memo = '')
|
|
|
- {
|
|
|
- if (empty($cart_ids)) {
|
|
|
- throw new Exception("购物车列表不能为空");
|
|
|
- }
|
|
|
-
|
|
|
- // 将购物车数据转换为标准的商品列表格式
|
|
|
- $goods_list = self::convertCartToGoodsList($cart_ids, $user_id);
|
|
|
-
|
|
|
- return self::createOrder($address_id, $user_id, $goods_list, $user_coupon_id, $memo, $cart_ids);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 直接通过商品规格数量创建订单
|
|
|
- * @param int $address_id 地址ID
|
|
|
- * @param int $user_id 用户ID
|
|
|
- * @param array $goods_list 商品列表 [['goods_id'=>1, 'goods_sku_id'=>0, 'nums'=>1], ...]
|
|
|
- * @param int $user_coupon_id 优惠券ID
|
|
|
- * @param string $memo 备注
|
|
|
- * @return Order
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- public static function createOrderByGoods($address_id, $user_id, $goods_list, $user_coupon_id = 0, $memo = '')
|
|
|
- {
|
|
|
- return self::createOrder($address_id, $user_id, $goods_list, $user_coupon_id, $memo);
|
|
|
- }
|
|
|
|
|
|
- /**
|
|
|
+ /**
|
|
|
* 根据商品列表计算订单明细
|
|
|
* @param array $orderInfo 订单基础信息
|
|
|
* @param array $goods_list 商品列表
|
|
@@ -131,44 +33,41 @@ class OrderService
|
|
|
* @return array
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
- protected static function computeGoods(&$orderInfo, $goods_list, $user_id, $area_id, $user_coupon_id = 0)
|
|
|
+ protected static function computeGoods(&$orderInfo, $goodsList, $userId, $areaId, $userCouponId = 0)
|
|
|
{
|
|
|
$config = get_addon_config('shop');
|
|
|
$orderInfo['amount'] = 0;
|
|
|
- $orderInfo['goodsprice'] = 0;
|
|
|
- $orderInfo['shippingfee'] = 0;
|
|
|
- $orderInfo['discount'] = 0;
|
|
|
+ $orderInfo['goods_price'] = 0;
|
|
|
+ $orderInfo['goods_num'] = 0;
|
|
|
+ $orderInfo['express_fee'] = 0;
|
|
|
+ $orderInfo['discount_fee'] = 0;
|
|
|
+ $orderInfo['coupon_discount_fee'] = 0;
|
|
|
+ $orderInfo['order_amount'] = 0;
|
|
|
$orderItem = [];
|
|
|
$shippingTemp = [];
|
|
|
$userCoupon = null;
|
|
|
- $goodsList = [];
|
|
|
-
|
|
|
+ $processedGoodsList = []; // 处理后的商品列表,避免与参数$goodsList冲突
|
|
|
// 校验优惠券
|
|
|
- if ($user_coupon_id) {
|
|
|
+ if ($userCouponId) {
|
|
|
$userCouponModel = new UserCoupon();
|
|
|
- $userCoupon = $userCouponModel->checkUserOrUse($user_coupon_id, $user_id);
|
|
|
- $orderInfo['user_coupon_id'] = $user_coupon_id;
|
|
|
+ $userCoupon = $userCouponModel->checkUserOrUse($userCouponId, $userId);
|
|
|
+ $orderInfo['user_coupon_id'] = $userCouponId;
|
|
|
}
|
|
|
|
|
|
// 提取所有商品ID和SKU ID,进行批量查询
|
|
|
- $goods_ids = array_column($goods_list, 'goods_id');
|
|
|
- $sku_ids = [];
|
|
|
- $goods_without_sku = []; // 记录没有指定SKU ID的商品,需要查询默认SKU
|
|
|
-
|
|
|
- foreach ($goods_list as $index => $item) {
|
|
|
+ $goodsIds = array_column($goodsList, 'goods_id');
|
|
|
+ $skuIds = [];
|
|
|
+ foreach ($goodsList as $index => $item) {
|
|
|
if (isset($item['goods_sku_id']) && $item['goods_sku_id'] > 0) {
|
|
|
- $sku_ids[] = $item['goods_sku_id'];
|
|
|
- } else {
|
|
|
- // 没有指定SKU ID的商品,记录下来后续查询默认SKU
|
|
|
- $goods_without_sku[$index] = $item['goods_id'];
|
|
|
+ $skuIds[] = $item['goods_sku_id'];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 批量查询商品信息
|
|
|
$goodsData = [];
|
|
|
- if (!empty($goods_ids)) {
|
|
|
+ if (!empty($goodsIds)) {
|
|
|
$goodsCollection = Goods::with(['category', 'brand'])
|
|
|
- ->where('id', 'in', $goods_ids)
|
|
|
+ ->where('id', 'in', $goodsIds)
|
|
|
->where('status', GoodsEnum::STATUS_ON_SALE)
|
|
|
->select();
|
|
|
foreach ($goodsCollection as $goods) {
|
|
@@ -179,8 +78,8 @@ class OrderService
|
|
|
// 批量查询SKU信息
|
|
|
$skuData = [];
|
|
|
$multiSpecSkuIds = []; // 用于存储多规格商品的SKU ID
|
|
|
- if (!empty($sku_ids)) {
|
|
|
- $skuCollection = Sku::where('id', 'in', $sku_ids)->select();
|
|
|
+ if (!empty($skuIds)) {
|
|
|
+ $skuCollection = Sku::where('id', 'in', $skuIds)->select();
|
|
|
foreach ($skuCollection as $sku) {
|
|
|
$skuData[$sku->id] = $sku;
|
|
|
// 过滤出有规格值的SKU ID(spec_value_ids不为空)
|
|
@@ -189,30 +88,6 @@ class OrderService
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // 查询没有指定SKU ID的商品的默认SKU(单规格商品或多规格商品的默认SKU)
|
|
|
- if (!empty($goods_without_sku)) {
|
|
|
- $defaultSkuCollection = Sku::where('goods_id', 'in', array_values($goods_without_sku))
|
|
|
- ->where('is_default', 1)
|
|
|
- ->select();
|
|
|
- foreach ($defaultSkuCollection as $sku) {
|
|
|
- $skuData[$sku->id] = $sku;
|
|
|
- // 更新对应的goods_list项,补充SKU ID
|
|
|
- foreach ($goods_without_sku as $list_index => $goods_id) {
|
|
|
- if ($sku->goods_id == $goods_id) {
|
|
|
- $goods_list[$list_index]['goods_sku_id'] = $sku->id;
|
|
|
- $sku_ids[] = $sku->id; // 添加到sku_ids中用于后续查询规格属性
|
|
|
- // 如果默认SKU有规格值,也加入到多规格SKU列表
|
|
|
- if (!empty($sku->spec_value_ids)) {
|
|
|
- $multiSpecSkuIds[] = $sku->id;
|
|
|
- }
|
|
|
- unset($goods_without_sku[$list_index]);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
// 批量查询规格属性字符串(只查询多规格商品的SKU)
|
|
|
$skuAttrData = [];
|
|
|
if (!empty($multiSpecSkuIds)) {
|
|
@@ -220,7 +95,7 @@ class OrderService
|
|
|
}
|
|
|
|
|
|
// 验证并构建商品数据
|
|
|
- foreach ($goods_list as $item) {
|
|
|
+ foreach ($goodsList as $item) {
|
|
|
$goods_id = $item['goods_id'];
|
|
|
$goods_sku_id = $item['goods_sku_id']; // 现在所有商品都应该有SKU ID
|
|
|
$nums = $item['nums'];
|
|
@@ -259,11 +134,11 @@ class OrderService
|
|
|
'sku_attr' => $sku_attr
|
|
|
];
|
|
|
|
|
|
- $goodsList[] = $goodsItem;
|
|
|
+ $processedGoodsList[] = $goodsItem;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 计算商品价格和运费(统一使用SKU进行计算)
|
|
|
- foreach ($goodsList as $item) {
|
|
|
+ foreach ($processedGoodsList as $item) {
|
|
|
$goodsItemData = [];
|
|
|
|
|
|
if (empty($item->goods) || empty($item->sku)) {
|
|
@@ -278,15 +153,17 @@ class OrderService
|
|
|
// 统一使用SKU数据进行计算
|
|
|
$goodsItemData['image'] = !empty($item->sku->image) ? $item->sku->image : $item->goods->image;
|
|
|
$goodsItemData['price'] = $item->sku->price;
|
|
|
- $goodsItemData['lineation_price'] = $item->sku->lineation_price;
|
|
|
+ // $goodsItemData['lineation_price'] = $item->sku->lineation_price;
|
|
|
$goodsItemData['sku_sn'] = $item->sku->sku_sn;
|
|
|
$amount = bcmul($item->sku->price, $item->nums, 2);
|
|
|
|
|
|
$goodsItemData['amount'] = $amount;
|
|
|
- // 订单总价
|
|
|
+ // 订单应付金额
|
|
|
$orderInfo['amount'] = bcadd($orderInfo['amount'], $amount, 2);
|
|
|
// 商品总价
|
|
|
- $orderInfo['goodsprice'] = bcadd($orderInfo['goodsprice'], $amount, 2);
|
|
|
+ $orderInfo['goods_price'] = bcadd($orderInfo['goods_price'], $amount, 2);
|
|
|
+ // 商品数量累计
|
|
|
+ $orderInfo['goods_num'] += $item->nums;
|
|
|
|
|
|
$freight_id = $item->goods->express_template_id;
|
|
|
// 计算邮费【合并运费模板】
|
|
@@ -304,30 +181,43 @@ class OrderService
|
|
|
];
|
|
|
}
|
|
|
|
|
|
- // 创建订单商品数据
|
|
|
- $orderItem[] = array_merge($goodsItemData, [
|
|
|
- 'order_sn' => $orderInfo['order_sn'],
|
|
|
- 'goods_id' => $item->goods_id,
|
|
|
- 'title' => $item->goods->title,
|
|
|
- 'url' => $item->goods->url,
|
|
|
- 'nums' => $item->nums,
|
|
|
- 'goods_sku_id' => $item->goods_sku_id,
|
|
|
- 'attrdata' => $item->sku_attr,
|
|
|
- 'weight' => $item->sku->weight,
|
|
|
- 'category_id' => $item->goods->category_id,
|
|
|
- 'brand_id' => $item->goods->brand_id,
|
|
|
- ]);
|
|
|
+ // 创建订单商品数据 (基于正确的表结构)
|
|
|
+ $orderItemData = [
|
|
|
+ 'user_id' => $userId,
|
|
|
+ 'order_sn' => '', // 将在订单创建后补充
|
|
|
+ 'goods_sn' => $item->goods->goods_sn ?: '', // 商品货号
|
|
|
+ 'sku_sn' => $item->sku->sku_sn ?: '', // SKU编号
|
|
|
+ 'goods_type' => $item->goods->type ?: 0, // 商品类型
|
|
|
+ 'goods_id' => $item->goods->id,
|
|
|
+ 'goods_sku_id' => $item->sku->id,
|
|
|
+ 'goods_title' => $item->goods->title,
|
|
|
+ 'goods_market_price' => $item->sku->market_price ?: 0, // 市场价
|
|
|
+ 'goods_original_price' => $item->sku->price, // 商城售价
|
|
|
+ 'goods_price' => $amount, // 实付金额
|
|
|
+ 'goods_image' => $goodsItemData['image'],
|
|
|
+ 'goods_weight' => $item->sku->weight ?: 0,
|
|
|
+ 'nums' => $item->nums,
|
|
|
+ 'sale_status' => 0, // 销售状态:0=待申请
|
|
|
+ 'comment_status' => 0, // 评论状态:0=未评论
|
|
|
+ 'status' => 1, // 状态
|
|
|
+ // 添加分类和品牌信息用于优惠券计算 (临时字段,不会保存到数据库)
|
|
|
+ 'category_id' => $item->goods->category_id,
|
|
|
+ 'brand_id' => $item->goods->brand_id,
|
|
|
+ ];
|
|
|
+
|
|
|
+ $orderItem[] = $orderItemData;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 按运费模板计算
|
|
|
foreach ($shippingTemp as $key => $item) {
|
|
|
- $shippingfee = Freight::calculate($key, $area_id, $item['nums'], $item['weight'], $item['amount']);
|
|
|
- $orderInfo['shippingfee'] = bcadd($orderInfo['shippingfee'], $shippingfee, 2);
|
|
|
+ $shippingfee = Freight::calculate($key, $areaId, $item['nums'], $item['weight'], $item['amount']);
|
|
|
+ $orderInfo['express_fee'] = bcadd($orderInfo['express_fee'], $shippingfee, 2);
|
|
|
}
|
|
|
|
|
|
- // 订单总价(含邮费)
|
|
|
- $orderInfo['amount'] = bcadd($orderInfo['goodsprice'], $orderInfo['shippingfee'], 2);
|
|
|
+ // 订单金额(商品价格+运费)
|
|
|
+ $orderInfo['order_amount'] = bcadd($orderInfo['goods_price'], $orderInfo['express_fee'], 2);
|
|
|
+ // 订单应付金额(暂时等于订单金额,后续会减去优惠)
|
|
|
+ $orderInfo['amount'] = $orderInfo['order_amount'];
|
|
|
|
|
|
if (!empty($userCoupon)) {
|
|
|
// 校验优惠券
|
|
@@ -339,27 +229,93 @@ class OrderService
|
|
|
->checkCoupon()
|
|
|
->checkOpen()
|
|
|
->checkUseTime($userCoupon['createtime'])
|
|
|
- ->checkConditionGoods($goods_ids, $user_id, $category_ids, $brand_ids);
|
|
|
+ ->checkConditionGoods($goods_ids, $userId, $category_ids, $brand_ids);
|
|
|
|
|
|
// 计算折扣金额,判断是使用不含运费,还是含运费的金额
|
|
|
- $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goodsprice'] : $orderInfo['amount'];
|
|
|
+ $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goods_price'] : $orderInfo['order_amount'];
|
|
|
list($new_money, $coupon_money) = $coupon->doBuy($amount);
|
|
|
|
|
|
// 判断优惠金额是否超出总价,超出则直接设定优惠金额为总价
|
|
|
- $orderInfo['discount'] = $coupon_money > $amount ? $amount : $coupon_money;
|
|
|
+ $orderInfo['coupon_discount_fee'] = $coupon_money > $amount ? $amount : $coupon_money;
|
|
|
+ $orderInfo['discount_fee'] = $orderInfo['coupon_discount_fee'];
|
|
|
}
|
|
|
|
|
|
- // 计算订单的应付金额【减去折扣】
|
|
|
- $orderInfo['saleamount'] = max(0, bcsub($orderInfo['amount'], $orderInfo['discount'], 2));
|
|
|
- $orderInfo['discount'] = bcadd($orderInfo['discount'], 0, 2);
|
|
|
+ // 计算最终应付金额【订单金额减去折扣】
|
|
|
+ $orderInfo['amount'] = max(0, bcsub($orderInfo['order_amount'], $orderInfo['discount_fee'], 2));
|
|
|
+ $orderInfo['pay_amount'] = $orderInfo['amount']; // 实际付款金额等于应付金额
|
|
|
+ $orderInfo['discount_fee'] = bcadd($orderInfo['discount_fee'], 0, 2);
|
|
|
|
|
|
return [
|
|
|
$orderItem,
|
|
|
- $goodsList,
|
|
|
+ $processedGoodsList,
|
|
|
$userCoupon
|
|
|
];
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一的创建订单方法
|
|
|
+ * @param int $address_id 地址ID
|
|
|
+ * @param int $user_id 用户ID
|
|
|
+ * @param array $goods_list 标准化的商品列表
|
|
|
+ * @param int $user_coupon_id 优惠券ID
|
|
|
+ * @param string $memo 备注
|
|
|
+ * @param array $cart_ids 购物车ID数组(如果是购物车模式需要清空)
|
|
|
+ * @return Order
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public static function createOrder($addressId, $userId, $goodsList, $userCouponId = 0, $remark = '')
|
|
|
+ {
|
|
|
+ $address = Address::get($addressId);
|
|
|
+ if (!$address || $address['user_id'] != $userId) {
|
|
|
+ throw new Exception("地址未找到");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty($goodsList)) {
|
|
|
+ throw new Exception("商品列表不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ $config = get_addon_config('shop');
|
|
|
+ $orderSn = date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999);
|
|
|
+
|
|
|
+ // 订单主表信息 (基于新表结构)
|
|
|
+ $orderInfo = [
|
|
|
+ 'type' => 1, // 1:普通订单
|
|
|
+ 'source' => 'H5', // 订单来源 (暂定H5,可根据实际情况调整)
|
|
|
+ 'order_sn' => $orderSn,
|
|
|
+ 'user_id' => $userId,
|
|
|
+ 'amount' => 0, // 订单应付金额
|
|
|
+ 'goods_price' => 0, // 商品总费用
|
|
|
+ 'goods_num' => 0, // 商品数量
|
|
|
+ 'discount_fee' => 0, // 优惠金额
|
|
|
+ 'coupon_discount_fee' => 0, // 优惠券金额
|
|
|
+ 'promo_discount_fee' => 0, // 营销金额
|
|
|
+ 'order_amount' => 0, // 订单金额
|
|
|
+ 'pay_amount' => 0, // 实际付款金额
|
|
|
+ 'pay_type' => '', // 支付方式
|
|
|
+ 'pay_time' => null, // 支付时间
|
|
|
+ 'delivery_type' => 1, // 发货方式
|
|
|
+ 'express_name' => '', // 快递名称
|
|
|
+ 'express_no' => '', // 快递单号
|
|
|
+ 'express_fee' => 0, // 配送费用
|
|
|
+ 'expire_time' => time() + $config['order_timeout'], // 过期时间
|
|
|
+ 'order_status' => \app\common\Enum\OrderEnum::STATUS_CREATE, // 待付款
|
|
|
+ 'invoice_status' => 0, // 发票开具状态
|
|
|
+ 'remark' => $remark, // 用户备注
|
|
|
+ 'user_coupon_id' => $userCouponId ?: null,
|
|
|
+ 'ip' => request()->ip(), // IP地址
|
|
|
+ 'status' => 'normal'
|
|
|
+ ];
|
|
|
+
|
|
|
+
|
|
|
+ // 通过商品列表计算订单明细
|
|
|
+ list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $address->area_id, $userCouponId);
|
|
|
+ // 创建订单
|
|
|
+ $order = self::createOrderWithTransaction($orderInfo, $orderItem, $calculatedGoodsList, $userCoupon, $address);
|
|
|
+
|
|
|
+ return $order;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* 在事务中创建订单
|
|
@@ -367,10 +323,11 @@ class OrderService
|
|
|
* @param array $orderItem 订单商品列表
|
|
|
* @param array $goodsList 商品列表
|
|
|
* @param object $userCoupon 优惠券
|
|
|
+ * @param object $address 地址信息
|
|
|
* @return Order
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
- protected static function createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon)
|
|
|
+ protected static function createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon, $address)
|
|
|
{
|
|
|
$order = null;
|
|
|
Db::startTrans();
|
|
@@ -378,6 +335,30 @@ class OrderService
|
|
|
// 创建订单
|
|
|
$order = Order::create($orderInfo, true);
|
|
|
|
|
|
+ // 为每个订单商品添加订单ID和订单号
|
|
|
+ foreach ($orderItem as &$item) {
|
|
|
+ $item['order_id'] = $order->id;
|
|
|
+ $item['order_sn'] = $order->order_sn;
|
|
|
+ // 移除临时字段
|
|
|
+ unset($item['category_id'], $item['brand_id']);
|
|
|
+ }
|
|
|
+ unset($item);
|
|
|
+ // 创建订单地址信息
|
|
|
+ $orderAddressData = [
|
|
|
+ 'order_id' => $order->id,
|
|
|
+ 'user_id' => $orderInfo['user_id'],
|
|
|
+ 'consignee' => $address->receiver,
|
|
|
+ 'mobile' => $address->mobile,
|
|
|
+ 'province_name' => $address->province->name ?? '',
|
|
|
+ 'city_name' => $address->city->name ?? '',
|
|
|
+ 'district_name' => $address->area->name ?? '',
|
|
|
+ 'address' => $address->address,
|
|
|
+ 'province_id' => $address->province_id,
|
|
|
+ 'city_id' => $address->city_id,
|
|
|
+ 'district_id' => $address->area_id,
|
|
|
+ ];
|
|
|
+ OrderAddress::create($orderAddressData);
|
|
|
+
|
|
|
// 减库存
|
|
|
foreach ($goodsList as $index => $item) {
|
|
|
if ($item->sku) {
|
|
@@ -386,29 +367,28 @@ class OrderService
|
|
|
$item->goods->setDec("stocks", $item->nums);
|
|
|
}
|
|
|
|
|
|
- // 计算单个商品折扣后的价格
|
|
|
- $saleamount = bcsub($order['saleamount'], $order['shippingfee'], 2);
|
|
|
- $saleratio = $order['goodsprice'] > 0 ? bcdiv($saleamount, $order['goodsprice'], 10) : 1;
|
|
|
+ // 计算单个商品折扣后的价格 (基于新字段名)
|
|
|
+ $saleamount = bcsub($order['amount'], $order['express_fee'], 2);
|
|
|
+ $saleratio = $order['goods_price'] > 0 ? bcdiv($saleamount, $order['goods_price'], 10) : 1;
|
|
|
$saleremains = $saleamount;
|
|
|
|
|
|
foreach ($orderItem as $index => &$item) {
|
|
|
if (!isset($orderItem[$index + 1])) {
|
|
|
$saleprice = $saleremains;
|
|
|
} else {
|
|
|
- $saleprice = $order['discount'] == 0 ? bcmul($item['price'], $item['nums'], 2) : bcmul(bcmul($item['price'], $item['nums'], 2), $saleratio, 2);
|
|
|
+ $saleprice = $order['discount_fee'] == 0 ? bcmul($item['goods_original_price'], $item['nums'], 2) : bcmul(bcmul($item['goods_original_price'], $item['nums'], 2), $saleratio, 2);
|
|
|
}
|
|
|
$saleremains = bcsub($saleremains, $saleprice, 2);
|
|
|
- $item['realprice'] = $saleprice;
|
|
|
+ $item['goods_price'] = $saleprice;
|
|
|
}
|
|
|
unset($item);
|
|
|
|
|
|
- // 创建订单商品数据
|
|
|
- foreach ($orderItem as $index => $item) {
|
|
|
- OrderGoods::create($item, true);
|
|
|
+ // 批量创建订单商品数据
|
|
|
+ if (!empty($orderItem)) {
|
|
|
+ (new OrderGoods())->saveAll($orderItem);
|
|
|
}
|
|
|
|
|
|
// 修改地址使用次数
|
|
|
- $address = Address::get($orderInfo['address_id']);
|
|
|
if ($address) {
|
|
|
$address->setInc('usednums');
|
|
|
}
|
|
@@ -429,7 +409,7 @@ class OrderService
|
|
|
OrderAction::push($orderInfo['order_sn'], '系统', '订单创建成功');
|
|
|
|
|
|
// 订单应付金额为0时直接结算
|
|
|
- if ($order['saleamount'] == 0) {
|
|
|
+ if ($order['amount'] == 0) {
|
|
|
Order::settle($order->order_sn, 0);
|
|
|
$order = Order::get($order->id);
|
|
|
}
|
|
@@ -472,100 +452,36 @@ class OrderService
|
|
|
* @return array
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
- public static function calculateOrder($goods_list, $user_id, $area_id = 0, $user_coupon_id = 0)
|
|
|
+ public static function calculateOrder($goodsList, $userId, $areaId = 0, $userCouponId = 0)
|
|
|
{
|
|
|
- if (empty($goods_list)) {
|
|
|
+ if (empty($goodsList)) {
|
|
|
throw new Exception("商品列表不能为空");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 验证商品列表格式
|
|
|
- self::validateGoodsList($goods_list);
|
|
|
-
|
|
|
- $order_sn = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
|
|
|
+ self::validateGoodsList($goodsList);
|
|
|
|
|
|
- // 订单基础信息
|
|
|
+ // 订单基础信息(用于计算,不包含订单号)
|
|
|
$orderInfo = [
|
|
|
- 'order_sn' => $order_sn,
|
|
|
- 'goodsprice' => 0, // 商品金额 (不含运费)
|
|
|
- 'amount' => 0, // 总金额 (含运费)
|
|
|
- 'shippingfee' => 0, // 运费
|
|
|
- 'discount' => 0, // 优惠金额
|
|
|
- 'saleamount' => 0 // 应付金额
|
|
|
- ];
|
|
|
+ 'amount' => 0, // 应付金额
|
|
|
+ 'goods_price' => 0, // 商品金额 (不含运费)
|
|
|
+ 'goods_num' => 0, // 商品数量
|
|
|
+ 'discount_fee' => 0, // 总优惠金额
|
|
|
+ 'coupon_discount_fee' => 0, // 优惠券金额
|
|
|
+ 'promo_discount_fee' => 0, // 营销金额
|
|
|
+ 'order_amount' => 0, // 总金额 (含运费)
|
|
|
+ 'express_fee' => 0, // 运费
|
|
|
+ ];
|
|
|
|
|
|
// 计算商品明细
|
|
|
- list($orderItem, $goodsList, $userCoupon) = self::computeGoods($orderInfo, $goods_list, $user_id, $area_id, $user_coupon_id);
|
|
|
+ list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $areaId, $userCouponId);
|
|
|
|
|
|
return [
|
|
|
'orderItem' => $orderItem,
|
|
|
- 'goodsList' => $goodsList,
|
|
|
+ 'goodsList' => $calculatedGoodsList,
|
|
|
'orderInfo' => $orderInfo,
|
|
|
'userCoupon' => $userCoupon
|
|
|
];
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 通过商品规格计算订单明细(用于预览订单)
|
|
|
- * @param array $goods_list 商品列表
|
|
|
- * @param int $user_id 用户ID
|
|
|
- * @param int $area_id 地区ID
|
|
|
- * @param int $user_coupon_id 优惠券ID
|
|
|
- * @return array
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- public static function calculateOrderByGoods($goods_list, $user_id, $area_id = 0, $user_coupon_id = 0)
|
|
|
- {
|
|
|
- return self::calculateOrder($goods_list, $user_id, $area_id, $user_coupon_id);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 通过购物车计算订单明细(用于预览订单)
|
|
|
- * @param array $cart_ids 购物车ID列表
|
|
|
- * @param int $user_id 用户ID
|
|
|
- * @param int $area_id 地区ID
|
|
|
- * @param int $user_coupon_id 优惠券ID
|
|
|
- * @return array
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- public static function calculateOrderByCart($cart_ids, $user_id, $area_id = 0, $user_coupon_id = 0)
|
|
|
- {
|
|
|
- if (empty($cart_ids)) {
|
|
|
- throw new Exception("购物车列表不能为空");
|
|
|
- }
|
|
|
-
|
|
|
- // 将购物车数据转换为标准的商品列表格式
|
|
|
- $goods_list = self::convertCartToGoodsList($cart_ids, $user_id);
|
|
|
-
|
|
|
- return self::calculateOrder($goods_list, $user_id, $area_id, $user_coupon_id);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 将购物车数据转换为标准的商品列表格式
|
|
|
- * @param array $cart_ids 购物车ID列表
|
|
|
- * @param int $user_id 用户ID
|
|
|
- * @return array
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- public static function convertCartToGoodsList($cart_ids, $user_id)
|
|
|
- {
|
|
|
- // 查询购物车数据
|
|
|
- $cartItems = Carts::where('id', 'in', $cart_ids)
|
|
|
- ->where('user_id', $user_id)
|
|
|
- ->select();
|
|
|
-
|
|
|
- if (empty($cartItems)) {
|
|
|
- throw new Exception("购物车数据不存在");
|
|
|
- }
|
|
|
-
|
|
|
- $goods_list = [];
|
|
|
- foreach ($cartItems as $cart) {
|
|
|
- $goods_list[] = [
|
|
|
- 'goods_id' => $cart->goods_id,
|
|
|
- 'goods_sku_id' => $cart->goods_sku_id,
|
|
|
- 'nums' => $cart->nums
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- return $goods_list;
|
|
|
- }
|
|
|
}
|