| 
					
				 | 
			
			
				@@ -0,0 +1,521 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<?php 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+namespace app\common\Service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use app\common\Enum\GoodsEnum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use app\common\model\Order; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use app\common\model\OrderGoods; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use app\common\model\OrderAction; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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 array $orderInfo 订单基础信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param array $goods_list 商品列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param int $user_id 用户ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param int $area_id 地区ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param int $user_coupon_id 优惠券ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return array 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @throws Exception 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected static function computeGoods(&$orderInfo, $goodsList, $userId, $areaId, $userCouponId = 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $config = get_addon_config('shop'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $orderInfo['amount'] = 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $processedGoodsList = []; // 处理后的商品列表,避免与参数$goodsList冲突 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 校验优惠券 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ($userCouponId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $userCouponModel = new UserCoupon(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $userCoupon = $userCouponModel->checkUserOrUse($userCouponId, $userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $orderInfo['user_coupon_id'] = $userCouponId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 提取所有商品ID和SKU ID,进行批量查询 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $goodsIds = array_column($goodsList, 'goods_id'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $skuIds = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach ($goodsList as $index => $item) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isset($item['goods_sku_id']) && $item['goods_sku_id'] > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $skuIds[] = $item['goods_sku_id']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 批量查询商品信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $goodsData = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!empty($goodsIds)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $goodsCollection = Goods::with(['brand']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ->where('id', 'in', $goodsIds) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ->where('status', GoodsEnum::STATUS_ON_SALE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ->select(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach ($goodsCollection as $goods) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $goodsData[$goods->id] = $goods; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 批量查询SKU信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $skuData = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $multiSpecSkuIds = []; // 用于存储多规格商品的SKU ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!empty($skuIds)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $skuCollection = Sku::where('id', 'in', $skuIds)->select(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach ($skuCollection as $sku) {                
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $skuData[$sku->id] = $sku; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 过滤出有规格值的SKU ID(spec_value_ids不为空) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!empty($sku->spec_value_ids)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $multiSpecSkuIds[] = $sku->id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 批量查询规格属性字符串(只查询多规格商品的SKU) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $skuAttrData = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!empty($multiSpecSkuIds)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $skuAttrData = \app\common\Service\SkuSpec::getSkuAttrs($multiSpecSkuIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 验证并构建商品数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach ($goodsList as $item) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $goods_id = $item['goods_id']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $goods_sku_id = $item['goods_sku_id']; // 现在所有商品都应该有SKU ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $nums = $item['nums']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ($nums <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品数量必须大于0"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 检查商品是否存在 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!isset($goodsData[$goods_id])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品已下架"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $goods = $goodsData[$goods_id]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 所有商品都必须有SKU(包括单规格商品的默认SKU) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (empty($skuData) || !isset($skuData[$goods_sku_id])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品规格不存在"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $sku = $skuData[$goods_sku_id]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 验证SKU是否属于该商品 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ($sku->goods_id != $goods_id) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品规格不匹配"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 获取规格属性字符串(单规格商品的sku_attr为空) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $sku_attr = $skuAttrData[$goods_sku_id] ?? ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 构建商品对象,模拟购物车数据结构 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $goodsItem = (object)[ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'goods_id' => $goods_id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'goods_sku_id' => $goods_sku_id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'nums' => $nums, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'goods' => $goods, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'sku' => $sku, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'sku_attr' => $sku_attr 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $processedGoodsList[] = $goodsItem; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 计算商品价格和运费(统一使用SKU进行计算) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach ($processedGoodsList as $item) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $goodsItemData = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (empty($item->goods) || empty($item->sku)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品已下架"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 库存验证(统一使用SKU库存) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ($item->sku->stocks < $item->nums) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品库存不足,请重新修改数量"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 统一使用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['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['goods_price'] = bcadd($orderInfo['goods_price'], $amount, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 商品数量累计 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $orderInfo['goods_num'] += $item->nums; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $freight_id = $item->goods->express_template_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 计算邮费【合并运费模板】 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!isset($shippingTemp[$freight_id])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $shippingTemp[$freight_id] = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'nums'   => $item->nums, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'weight' => $item->sku->weight, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'amount' => $amount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $shippingTemp[$freight_id] = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'nums'   => bcadd($shippingTemp[$freight_id]['nums'], $item->nums, 2), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'weight' => bcadd($shippingTemp[$freight_id]['weight'], $item->sku->weight, 2), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'amount' => bcadd($shippingTemp[$freight_id]['amount'], $amount, 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 创建订单商品数据 (基于正确的表结构) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $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_ids, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'brand_id'             => $item->goods->brand_id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $orderItem[] = $orderItemData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 按运费模板计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach ($shippingTemp as $key => $item) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $shippingfee = Freight::calculate($key, $areaId, $item['nums'], $item['weight'], $item['amount']); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $orderInfo['express_fee'] = bcadd($orderInfo['express_fee'], $shippingfee, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 订单金额(商品价格+运费) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $orderInfo['order_amount'] = bcadd($orderInfo['goods_price'], $orderInfo['express_fee'], 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 订单应付金额(暂时等于订单金额,后续会减去优惠) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $orderInfo['amount'] = $orderInfo['order_amount']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // if (!empty($userCoupon)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     // 校验优惠券 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $goods_ids = array_column($orderItem, 'goods_id'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $category_ids = array_column($orderItem, 'category_id'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $brand_ids = array_column($orderItem, 'brand_id'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $couponModel = new Coupon(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $coupon = $couponModel->getCoupon($userCoupon['coupon_id']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //         ->checkCoupon() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //         ->checkOpen() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //         ->checkUseTime($userCoupon['createtime']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //         ->checkConditionGoods($goods_ids, $userId, $category_ids, $brand_ids); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     // 计算折扣金额,判断是使用不含运费,还是含运费的金额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goods_price'] : $orderInfo['order_amount']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     list($new_money, $coupon_money) = $coupon->doBuy($amount); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     // 判断优惠金额是否超出总价,超出则直接设定优惠金额为总价 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $orderInfo['coupon_discount_fee'] = $coupon_money > $amount ? $amount : $coupon_money; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //     $orderInfo['discount_fee'] = $orderInfo['coupon_discount_fee']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 计算最终应付金额【订单金额减去折扣】 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $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, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 在事务中创建订单 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param array $orderInfo 订单信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param array $orderItem 订单商品列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param array $goodsList 商品列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param object $userCoupon 优惠券 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param object $address 地址信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return Order 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @throws Exception 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected static function createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon, $address) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $order = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Db::startTrans(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 创建订单 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $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) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $item->sku->setDec('stocks', $item->nums); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $item->goods->setDec("stocks", $item->nums); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 计算单个商品折扣后的价格 (基于新字段名) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $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_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['goods_price'] = $saleprice; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            unset($item); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 批量创建订单商品数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!empty($orderItem)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (new OrderGoods())->saveAll($orderItem); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 修改地址使用次数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ($address) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $address->setInc('usednums'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 优惠券已使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!empty($userCoupon)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $userCoupon->save(['is_used' => 2]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 提交事务 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Db::commit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception $e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Db::rollback(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new Exception($e->getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 记录操作 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        OrderAction::push($orderInfo['order_sn'], '系统', '订单创建成功'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 订单应付金额为0时直接结算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ($order['amount'] == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Order::settle($order->order_sn, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $order = Order::get($order->id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return $order; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 验证商品规格参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param array $goods_list 商品列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @throws Exception 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static function validateGoodsList($goods_list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (empty($goods_list) || !is_array($goods_list)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new Exception("商品列表不能为空"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach ($goods_list as $item) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!isset($item['goods_id']) || !is_numeric($item['goods_id']) || $item['goods_id'] <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品ID无效"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!isset($item['nums']) || !is_numeric($item['nums']) || $item['nums'] <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品数量必须大于0"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isset($item['goods_sku_id']) && !is_numeric($item['goods_sku_id'])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new Exception("商品规格ID无效"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 统一的订单计算方法(用于预览订单) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @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 calculateOrder($goodsList, $userId, $areaId = 0, $userCouponId = 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (empty($goodsList)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new Exception("商品列表不能为空"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 验证商品列表格式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self::validateGoodsList($goodsList); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 订单基础信息(用于计算,不包含订单号) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $orderInfo = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            '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, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $areaId, $userCouponId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'orderItem' => $orderItem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'goodsList' => $calculatedGoodsList, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'orderInfo' => $orderInfo, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'userCoupon' => $userCoupon 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 订单列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param $param 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return \think\Paginator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static function getOrderList($userId = 0, $param,$status = []) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $pageSize = 15; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!empty($param['pageSize'])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $pageSize = $param['pageSize']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return Order::with(['orderGoods']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ->where(function ($query) use ($param) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!empty($userId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $query->where('user_id', $userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!empty($status)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $query->whereIn('order_status', $status ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (isset($param['keywords']) && $param['keywords'] != '') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $query->where('order_sn', 'in', function ($query) use ($param) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return $query->name('shop_order_goods')->where('order_sn|goods_title', 'like', '%' . $param['q'] . '%')->field('order_sn'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ->order('createtime desc') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ->paginate($pageSize, false, ['query' => request()->get()]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}  
			 |