| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092 | 
							- <?php
 
- namespace app\common\Service;
 
- use app\common\Enum\GoodsEnum;
 
- use app\common\model\Order;
 
- use app\common\model\OrderGoods;
 
- 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 think\Db;
 
- use think\Exception;
 
- use app\common\model\OrderAddress;
 
- use app\common\Enum\OrderEnum;
 
- use app\common\exception\BusinessException;
 
- use app\common\Service\Order\OrderActionService;
 
- use app\common\Enum\OrderActionEnum;
 
- use app\common\Service\SkuSpec;
 
- use app\common\Service\ParentOrderService;
 
- /**
 
-  * 订单服务类
 
-  * 封装订单创建相关逻辑
 
-  * 
 
-  * 新增功能:
 
-  * - createSingleGoodsOrders(): 创建单商品订单,一个商品一个订单
 
-  * 
 
-  * 使用示例:
 
-  * 
 
-  * // 创建单商品订单(一个商品一个订单)
 
-  * $goodsList = [
 
-  *     ['goods_id' => 1, 'goods_sku_id' => 10, 'nums' => 2],
 
-  *     ['goods_id' => 2, 'goods_sku_id' => 20, 'nums' => 1],
 
-  *     ['goods_id' => 3, 'goods_sku_id' => 30, 'nums' => 3]
 
-  * ];
 
-  * $orders = OrderService::createSingleGoodsOrders($addressId, $userId, $goodsList, $userCouponId, $remark);
 
-  * // 返回3个订单对象的数组,每个商品对应一个订单
 
-  * 
 
-  * // 创建传统订单(多商品合并为一个订单)
 
-  * $order = OrderService::createOrder($addressId, $userId, $goodsList, $userCouponId, $remark);
 
-  * // 返回1个包含所有商品的订单对象
 
-  */
 
- 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      
 
-      */
 
-     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)) {
 
-             $goodsModel = new Goods();
 
-             $goodsCollection = $goodsModel->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)) {
 
-             $skuModel = new Sku();
 
-             $skuCollection = $skuModel->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 = 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 BusinessException("商品数量必须大于0");
 
-             }
 
-             // 检查商品是否存在
 
-             if (!isset($goodsData[$goods_id])) {
 
-                 throw new BusinessException("商品已下架");
 
-             }
 
-             $goods = $goodsData[$goods_id];
 
-             // 所有商品都必须有SKU(包括单规格商品的默认SKU)
 
-             if (empty($skuData) || !isset($skuData[$goods_sku_id])) {
 
-                 throw new BusinessException("商品规格不存在");
 
-             }
 
-             $sku = $skuData[$goods_sku_id];
 
-             
 
-             // 验证SKU是否属于该商品
 
-             if ($sku->goods_id != $goods_id) {
 
-                 throw new BusinessException("商品规格不匹配");
 
-             }
 
-             
 
-             // 获取规格属性字符串(单规格商品的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 BusinessException("商品已下架");
 
-             }
 
-             
 
-             // 库存验证(统一使用SKU库存)
 
-             if ($item->sku->stocks < $item->nums) {
 
-                 throw new BusinessException("商品库存不足,请重新修改数量");
 
-             }
 
-             
 
-             // 统一使用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_attr'       => $item->sku->sku_attr,
 
-                 'goods_spec_value_ids' => $item->sku->spec_value_ids,
 
-                 '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, // 状态
 
-                 'supplier_id'          => $item->goods->supplier_id,
 
-                 'inspection_type_id'   => $item->goods->inspection_type_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 BusinessException
 
-      */
 
-     public static function createOrder($addressId, $userId, $goodsList, $userCouponId = 0, $remark = '',$supplierId = 0)
 
-     {
 
-         $address = Address::get($addressId);
 
-         if (!$address || $address['user_id'] != $userId) {
 
-             throw new BusinessException("地址未找到");
 
-         }
 
-         if (empty($goodsList)) {
 
-             throw new BusinessException("商品列表不能为空");
 
-         }
 
-         $orderTimeout = ShopConfigService::getConfigs('shop.order.order_timeout',false) ?? 3600;
 
-         $orderSn = date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999);
 
-         // 订单主表信息 (基于新表结构)
 
-         $orderInfo = [
 
-             'type'                 => 1, // 1:普通订单
 
-             '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, // 订单金额 + 运费
 
-             'express_fee'          => 0, // 配送费用
 
-             'expire_time'          => time() + $orderTimeout, // 过期时间
 
-             'order_status'         => OrderEnum::STATUS_CREATE, // 待付款
 
-             'invoice_status'       => 0, // 发票开具状态
 
-             'remark'               => $remark, // 用户备注
 
-             'user_coupon_id'       => $userCouponId ?: null,
 
-             'ip'                   => request()->ip(), // IP地址
 
-             'status'               => 'normal', 
 
-         ];
 
-         $orderInfo['platform']  = request()->header('platform', 'H5');
 
-         // 通过商品列表计算订单明细
 
-         list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $address->area_id, $userCouponId);
 
-          $orderInfo['pay_amount']          =  bcsub($orderInfo['order_amount'], $orderInfo['discount_fee'], 2);
 
-          $orderInfo['pay_original_amount'] =   $orderInfo['pay_amount'];
 
-          $orderInfo['pay_remain_amount']   =  $orderInfo['pay_amount']; 
 
-          
 
-         // 创建订单
 
-         $order = self::createOrderWithTransaction($orderInfo, $orderItem, $calculatedGoodsList, $userCoupon, $address);
 
-         
 
-         return $order;
 
-     }
 
-     /**
 
-      * 创建单商品订单 - 一个商品一个订单
 
-      * @param int $addressId 地址ID
 
-      * @param int $userId 用户ID
 
-      * @param array $goodsList 商品列表(支持多商品但会拆分为多个订单)
 
-      * @param int $userCouponId 优惠券ID(仅用于第一个订单)
 
-      * @param string $remark 备注
 
-      * @return array 返回创建的订单数组
 
-      * @throws BusinessException
 
-      */
 
-     public static function createSingleGoodsOrders($addressId, $userId, $goodsList, $userCouponId = 0, $remark = '')
 
-     {
 
-         // 验证地址
 
-         $address = Address::get($addressId);
 
-         if (!$address || $address['user_id'] != $userId) {
 
-             throw new BusinessException("地址未找到");
 
-         }
 
-         if (empty($goodsList)) {
 
-             throw new BusinessException("商品列表不能为空");
 
-         }
 
-         // 验证商品列表格式
 
-         self::validateGoodsList($goodsList);
 
-         $orderTimeout = ShopConfigService::getConfigs('shop.order.order_timeout', false) ?? 3600;
 
-         $platform = request()->header('platform', 'H5');
 
-         $ip = request()->ip();
 
-         $orders = [];
 
-         $firstOrder = true;
 
-         // 为每个商品创建单独的订单
 
-         foreach ($goodsList as $goodsItem) {
 
-             // 构建单商品列表
 
-             $singleGoodsList = [$goodsItem];
 
-             
 
-             // 生成订单号
 
-             $orderSn = date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999);
 
-             // 订单主表信息
 
-             $orderInfo = [
 
-                 'type'                 => 1, // 1:普通订单
 
-                 '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, // 订单金额 + 运费
 
-                 'express_fee'          => 0, // 配送费用
 
-                 'expire_time'          => time() + $orderTimeout, // 过期时间
 
-                 'order_status'         => OrderEnum::STATUS_CREATE, // 待付款
 
-                 'invoice_status'       => 0, // 发票开具状态
 
-                 'remark'               => $remark, // 用户备注
 
-                 'user_coupon_id'       => $firstOrder && $userCouponId > 0 ? $userCouponId : null, // 优惠券仅用于第一个订单
 
-                 'ip'                   => $ip,
 
-                 'status'               => 'normal',
 
-                 'platform'             => $platform,
 
-             ];
 
-             try {
 
-                 // 通过单商品列表计算订单明细
 
-                 list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods(
 
-                     $orderInfo, 
 
-                     $singleGoodsList, 
 
-                     $userId, 
 
-                     $address->area_id, 
 
-                     $firstOrder && $userCouponId > 0 ? $userCouponId : 0
 
-                 );
 
-                 $orderInfo['pay_amount'] = bcsub($orderInfo['order_amount'], $orderInfo['discount_fee'], 2);
 
-                 $orderInfo['pay_original_amount'] = $orderInfo['pay_amount'];
 
-                 $orderInfo['pay_remain_amount'] = $orderInfo['pay_amount'];
 
-                 // 创建订单
 
-                 $order = self::createOrderWithTransaction($orderInfo, $orderItem, $calculatedGoodsList, $userCoupon, $address);
 
-                 $orders[] = $order;
 
-                 // 第一个订单创建完成后,后续订单不再使用优惠券
 
-                 $firstOrder = false;
 
-             } catch (Exception $e) {
 
-                 // 如果某个订单创建失败,记录错误并继续创建其他订单
 
-                 \think\Log::error("创建单商品订单失败: " . $e->getMessage() . ", 商品ID: " . $goodsItem['goods_id']);
 
-                 throw new BusinessException("创建订单失败: " . $e->getMessage());
 
-             }
 
-         }
 
-         if (empty($orders)) {
 
-             throw new BusinessException("所有订单创建失败");
 
-         }
 
-         return $orders;
 
-     }
 
-     /**
 
-      * 在事务中创建订单
 
-      * @param array $orderInfo 订单信息
 
-      * @param array $orderItem 订单商品列表
 
-      * @param array $goodsList 商品列表
 
-      * @param object $userCoupon 优惠券
 
-      * @param object $address 地址信息
 
-      * @return Order
 
-      * @throws BusinessException
 
-      */
 
-     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('used_nums');
 
-             }
 
-             
 
-             // 优惠券已使用
 
-             if (!empty($userCoupon)) {
 
-                 $userCoupon->save(['is_used' => 2]);
 
-             }
 
-             
 
-             // 提交事务
 
-             Db::commit();
 
-         } catch (Exception $e) {
 
-             Db::rollback();
 
-             throw new BusinessException($e->getMessage());
 
-         }
 
-         
 
-         // 记录操作
 
-         OrderActionService::recordUserAction(
 
-             $orderInfo['order_sn'],
 
-             OrderActionEnum::ACTION_CREATE,
 
-             $orderInfo['user_id'],
 
-             '创建订单',
 
-             $orderInfo['user_id']
 
-         );
 
-         
 
-         // 订单应付金额为0时直接结算
 
-         if ($order['amount'] == 0) {
 
-             // Order::settle($order->order_sn, 0);
 
-             // $order = Order::get($order->id);
 
-             return $order;
 
-         }
 
-         
 
-         return $order;
 
-     }
 
-     /**
 
-      * 验证商品规格参数
 
-      * @param array $goods_list 商品列表
 
-      * @throws BusinessException
 
-      */
 
-     public static function validateGoodsList($goods_list)
 
-     {
 
-         if (empty($goods_list) || !is_array($goods_list)) {
 
-             throw new BusinessException("商品列表不能为空");
 
-         }
 
-         foreach ($goods_list as $item) {
 
-             if (!isset($item['goods_id']) || !is_numeric($item['goods_id']) || $item['goods_id'] <= 0) {
 
-                 throw new BusinessException("商品ID无效");
 
-             }
 
-             
 
-             if (!isset($item['nums']) || !is_numeric($item['nums']) || $item['nums'] <= 0) {
 
-                 throw new BusinessException("商品数量必须大于0");
 
-             }
 
-             
 
-             if (isset($item['goods_sku_id']) && !is_numeric($item['goods_sku_id'])) {
 
-                 throw new BusinessException("商品规格ID无效");
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * 创建父子订单 - 每个商品一个子订单,统一支付父订单
 
-      * @param int $addressId 地址ID
 
-      * @param int $userId 用户ID
 
-      * @param array $goodsList 商品列表
 
-      * @param int $userCouponId 优惠券ID
 
-      * @param string $remark 备注
 
-      * @return array 返回父订单和子订单信息
 
-      * @throws BusinessException
 
-      */
 
-     public static function createParentChildOrders($addressId, $userId, $goodsList, $userCouponId = 0, $remark = '')
 
-     {
 
-         return ParentOrderService::createParentChildOrders($addressId, $userId, $goodsList, $userCouponId, $remark);
 
-     }
 
-     /**
 
-      * 统一的订单计算方法(用于预览订单)
 
-      * @param array $goods_list 标准化的商品列表
 
-      * @param int $user_id 用户ID
 
-      * @param int $area_id 地区ID
 
-      * @param int $user_coupon_id 优惠券ID
 
-      * @return array
 
-      * @throws BusinessException
 
-      */
 
-     public static function calculateOrder($goodsList, $userId, $areaId = 0, $userCouponId = 0)
 
-     {
 
-         if (empty($goodsList)) {
 
-             throw new BusinessException("商品列表不能为空");
 
-         }
 
-       
 
-         // 验证商品列表格式
 
-         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 = [],$supplierId = 0)
 
-     {
 
-         $pageSize = 10;
 
-         if (!empty($param['pageSize'])) {
 
-             $pageSize = $param['pageSize'];
 
-         }
 
-         $orderModel = new Order();
 
-         return $orderModel->with(['orderGoods'])
 
-             ->where(function ($query) use ($param,$userId,$status) {
 
-                 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');
 
-                     });
 
-                 }
 
-                 if (!empty($supplierId)) {
 
-                     $query->where('order_sn', 'in', function ($query) use ($supplierId) {
 
-                         return $query->name('shop_order_goods')->where('supplier_id', $supplierId)->field('order_sn');
 
-                     }); 
 
-                 }
 
-             })
 
-             ->order('createtime desc')
 
-             ->paginate($pageSize, false, ['query' => request()->get()]);
 
-     }
 
-      /**
 
-      * 
 
-      * @ 订单信息
 
-      * @param $orderId
 
-      * @param $userId
 
-      * @return array|false|\PDOStatement|string|Model
 
-      */
 
-     public static function getDetail($orderId = 0, $userId = 0)
 
-     {
 
-         $orderModel = new Order();
 
-         return $orderModel->with(['orderGoods'])
 
-         ->where('id', $orderId)
 
-         ->where(function($query) use ($userId){
 
-             if($userId > 0){
 
-                 $query->where('user_id', $userId);
 
-             }
 
-         })
 
-         ->find();
 
-     }
 
-     public static function getDetailByOrderSn($orderSn)
 
-     {
 
-         $orderModel = new Order();
 
-         return $orderModel->with(['orderGoods'])
 
-         ->where('order_sn', $orderSn)
 
-         ->find();
 
-     }
 
-     // 查询地址信息
 
-     public static function getAddressInfo($orderId)
 
-     {
 
-         return OrderAddress::where('order_id', $orderId)->find();
 
-     }
 
-       
 
-     /**
 
-      * 判断订单是否失效
 
-      * @param $order_sn
 
-      * @return bool
 
-      */
 
-     public static function isExpired($orderSn)
 
-     {
 
-         $orderInfo = self::getByOrderSn($orderSn);
 
-         //订单过期
 
-         if (!$orderInfo['orderstate'] && !$orderInfo['paystate'] && time() > $orderInfo['expiretime']) {
 
-             // 启动事务
 
-             Db::startTrans();
 
-             try {
 
-                 $orderInfo->save(['orderstate' => 2]);
 
-                 //库存恢复
 
-                 OrderGoods::setGoodsStocksInc($orderInfo->order_sn);
 
-                 // //恢复优惠券
 
-                 // UserCoupon::resetUserCoupon($orderInfo->user_coupon_id, $orderInfo->order_sn);
 
-                 // 提交事务
 
-                 Db::commit();
 
-             } catch (\Exception $e) {
 
-                 // 回滚事务
 
-                 Db::rollback();
 
-             }
 
-             return true;
 
-         }
 
-         return false;
 
-     }
 
-     public static function getByOrderSn($orderSn)
 
-     {
 
-         return Order::where('order_sn', $orderSn)->find();
 
-     }
 
-     public static function getByOrderId($orderId)
 
-     {
 
-         return Order::where('id', $orderId)->find();
 
-     }
 
-     // 获取状态订单统计
 
-     public static function getOrderStatusCount($userId = 0)
 
-     {
 
-         $info = [];
 
-         $info['unpay'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_CREATE)->count();
 
-         $info['unsend'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_INSPECTION_PASS)->count();
 
-         $info['unrec'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_SHIP)->count();
 
-         $info['uneva'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_CONFIRM)->count();
 
-         $info['inspect'] = Order::where('user_id', $userId)
 
-         ->whereIn('order_status',[
 
-             OrderEnum::STATUS_PAY,
 
-             OrderEnum::STATUS_INSPECTION,
 
-             OrderEnum::STATUS_INSPECTION_FAIL])
 
-             ->count();
 
-        
 
-         return $info;
 
-     }
 
-     // 更新订单状态
 
-     public static function updateOrderStatus($orderId = 0, $userId = 0, $status = 0)
 
-     {
 
-     
 
-         $order = self::getDetail($orderId, $userId);
 
-         if (!$order) {
 
-             throw new BusinessException('订单不存在!');
 
-         }
 
-         // 验证状态
 
-         // if (!OrderEnum::isValidOrderStatus($status)) {
 
-         //     throw new BusinessException('状态不合法!');
 
-         // }
 
-         //  要处理每个状态对应的时间字段在枚举类中
 
-         $timeField = OrderEnum::STATUS_TIME_MAP[$status];
 
-         $updateData = [
 
-             'order_status' => $status,
 
-             $timeField => time()
 
-         ];
 
-         Order::where('id', $orderId)->update($updateData);
 
-         return $order;
 
-     }
 
-     /**
 
-      * 获取供应商订单列表 - 关联查询方式
 
-      * @param int $supplierId 供应商ID  
 
-      * @param int $userId 用户ID(可选)
 
-      * @param array $param 查询参数
 
-      * @param array $status 订单状态筛选
 
-      * @return \think\Paginator
 
-      */
 
-     public static function getSupplierOrderList($supplierId, $userId = 0, $param = [], $status = [])
 
-     {
 
-         $pageSize = $param['page_size'] ?? 10;
 
-         
 
-         return Order::alias('o')
 
-             ->join('shop_order_goods og', 'o.order_sn = og.order_sn', 'inner')
 
-             ->with(['orderGoods' => function($query) use ($supplierId) {
 
-                 $query->where('supplier_id', $supplierId);
 
-             }])
 
-             ->where('og.supplier_id', $supplierId)
 
-             ->where(function ($query) use ($param, $userId, $status) {
 
-                 if (!empty($userId)) {
 
-                     $query->where('o.user_id', $userId);
 
-                 }
 
-                 
 
-                 if (!empty($status)) {
 
-                     $query->whereIn('o.order_status', $status);
 
-                 }
 
-                 
 
-                 if (isset($param['keywords']) && $param['keywords'] != '') {
 
-                     $query->where(function($subQuery) use ($param) {
 
-                         $subQuery->where('o.order_sn', 'like', '%' . $param['keywords'] . '%')
 
-                                 ->whereOr('og.goods_title', 'like', '%' . $param['keywords'] . '%');
 
-                     });
 
-                 }
 
-             })
 
-             ->field('o.*')
 
-             ->group('o.id')
 
-             ->order('o.createtime desc')
 
-             ->paginate($pageSize, false, ['query' => request()->get()]);
 
-     }
 
-     /**
 
-      * 获取供应商订单详情 - 支持订单ID和订单号两种方式
 
-      * @param mixed $orderParam 订单ID或订单号
 
-      * @param int $supplierId 供应商ID
 
-      * @param int $userId 用户ID(可选,用于权限验证)
 
-      * @return array|null
 
-      */
 
-     public static function getSupplierOrderDetail($orderParam, $supplierId, $userId = 0)
 
-     {
 
-         // 根据参数类型判断是订单ID还是订单号
 
-         if (is_numeric($orderParam)) {
 
-             // 数字类型,当作订单ID处理
 
-             $query = Order::where('id', $orderParam);
 
-         } else {
 
-             // 字符串类型,当作订单号处理
 
-             $query = Order::where('order_sn', $orderParam);
 
-         }
 
-         
 
-         // 如果指定了用户ID,添加用户权限验证
 
-         if (!empty($userId)) {
 
-             $query->where('user_id', $userId);
 
-         }
 
-         
 
-         $order = $query->find();
 
-         if (!$order) {
 
-             return null;
 
-         }
 
-         
 
-         // 获取该供应商在此订单中的商品
 
-         $orderGoods = OrderGoods::where('order_sn', $order->order_sn)
 
-             ->where('supplier_id', $supplierId)
 
-             ->select();
 
-             
 
-         // 如果该供应商在此订单中没有商品,返回null
 
-         if (empty($orderGoods)) {
 
-             return null;
 
-         }
 
-         
 
-         $order->order_goods = $orderGoods;
 
-         return $order;
 
-     }
 
-     /**
 
-      * 获取供应商订单统计
 
-      * @param int $supplierId 供应商ID
 
-      * @param int $userId 用户ID(可选)
 
-      * @return array
 
-      */
 
-     public static function getSupplierOrderStatusCount($supplierId, $userId = 0)
 
-     {
 
-         $baseQuery = function($status) use ($supplierId, $userId) {
 
-             $query = Order::alias('o')
 
-                 ->join('shop_order_goods og', 'o.order_sn = og.order_sn', 'inner')
 
-                 ->where('og.supplier_id', $supplierId)
 
-                 ->where('o.order_status', $status);
 
-             
 
-             if (!empty($userId)) {
 
-                 $query->where('o.user_id', $userId);
 
-             }
 
-             
 
-             return $query->count('DISTINCT o.id');
 
-         };
 
-         
 
-         return [
 
-             'unpay'  => $baseQuery(OrderEnum::STATUS_CREATE),  // 待付款
 
-             'unsend' => $baseQuery(OrderEnum::STATUS_PAY),     // 待发货
 
-             'unrec'  => $baseQuery(OrderEnum::STATUS_SHIP),    // 待收货
 
-             'uneva'  => $baseQuery(OrderEnum::STATUS_CONFIRM), // 待评价
 
-         ];
 
-     }
 
-     /**
 
-      * 验证订单和订单商品是否存在
 
-      * @param int $orderId 订单ID
 
-      * @param int $orderGoodsId 订单商品ID
 
-      * @return array|false 返回订单和订单商品信息,不存在返回false
 
-      */
 
-     public static function validateOrderAndOrderGoods($orderId, $orderGoodsId)
 
-     {
 
-         // 查询订单
 
-         $order = Order::where('id', $orderId)->find();
 
-         if (!$order) {
 
-             return false;
 
-         }
 
-         
 
-         // 查询订单商品
 
-         $orderGoods = OrderGoods::where('id', $orderGoodsId)
 
-             ->where('order_id', $orderId)
 
-             ->find();
 
-         if (!$orderGoods) {
 
-             return false;
 
-         }
 
-         
 
-         return [
 
-             'order' => $order,
 
-             'order_goods' => $orderGoods
 
-         ];
 
-     }
 
-     /**
 
-      * 更新订单商品的验收状态
 
-      * @param int $orderGoodsId 订单商品ID
 
-      * @param int $inspectStatus 验收状态 0:待验收 1:验收通过 2:验收不通过
 
-      * @return bool
 
-      */
 
-     public static function updateOrderGoodsInspectStatus($orderGoodsId, $inspectStatus)
 
-     {
 
-         return OrderGoods::where('id', $orderGoodsId)->update([
 
-             'inspect_status' => $inspectStatus,
 
-             'inspect_time' => time()
 
-         ]);
 
-     }
 
-     /**
 
-      * 检查订单中所有商品的验收状态
 
-      * @param int $orderId 订单ID
 
-      * @return array 返回验收状态统计
 
-      */
 
-     public static function checkOrderInspectStatus($orderId)
 
-     {
 
-         $orderGoods = OrderGoods::where('order_id', $orderId)->select();
 
-         
 
-         $statusCount = [
 
-             'total' => count($orderGoods), // 总商品数
 
-             'pending' => 0,    // 待验收
 
-             'passed' => 0,     // 验收通过
 
-             'failed' => 0      // 验收不通过
 
-         ];
 
-         
 
-         foreach ($orderGoods as $goods) {
 
-             switch ($goods['inspect_status']) {
 
-                 case 0:
 
-                     $statusCount['pending']++;
 
-                     break;
 
-                 case 1:
 
-                     $statusCount['passed']++;
 
-                     break;
 
-                 case 2:
 
-                     $statusCount['failed']++;
 
-                     break;
 
-             }
 
-         }
 
-         
 
-         return $statusCount;
 
-     }
 
-     /**
 
-      * 根据验收状态决定是否更新订单状态
 
-      * @param int $orderId 订单ID
 
-      * @param int $userId 用户ID
 
-      * @return bool
 
-      */
 
-     public static function updateOrderStatusByInspectResult($orderId, $userId = 0)
 
-     {
 
-         $inspectStatus = self::checkOrderInspectStatus($orderId);
 
-         
 
-         // 如果所有商品都验收完成(没有待验收的商品)
 
-         if ($inspectStatus['pending'] == 0) {
 
-             // 如果所有商品都验收通过
 
-             if ($inspectStatus['failed'] == 0 && $inspectStatus['passed'] > 0) {
 
-                 // 更新订单状态为验收通过
 
-                 return self::updateOrderStatus($orderId, $userId, OrderEnum::STATUS_INSPECTION_PASS);
 
-             }
 
-             // 如果所有商品都验收不通过
 
-             elseif ($inspectStatus['failed'] > 0 && $inspectStatus['passed'] == 0) {
 
-                 // 更新订单状态为验收失败
 
-                 return self::updateOrderStatus($orderId, $userId, OrderEnum::STATUS_INSPECTION_FAIL);
 
-             }
 
-             // 如果部分商品验收通过,部分不通过
 
-             elseif ($inspectStatus['failed'] > 0 && $inspectStatus['passed'] > 0) {
 
-                 // 混合状态,由业务人员手动处理,不自动更新订单状态
 
-                 return true;
 
-             }
 
-         }
 
-         
 
-         return true;
 
-     }
 
-     /**
 
-      * 更新订单商品的发货状态
 
-      * @param int $orderGoodsId 订单商品ID
 
-      * @param string $expressName 快递公司
 
-      * @param string $expressNo 快递单号
 
-      * @param array $expressImage 快递图片
 
-      * @return bool
 
-      */
 
-     public static function updateOrderGoodsDeliveryStatus($orderGoodsId, $expressName, $expressNo, $expressImage = [])
 
-     {
 
-         $updateData = [
 
-             'express_name' => $expressName,
 
-             'express_no' => $expressNo,
 
-             'express_image' => is_array($expressImage) ? json_encode($expressImage) : $expressImage,
 
-             'delivery_status' => 1, // 已发货
 
-             'updatetime' => time()
 
-         ];
 
-         
 
-         return OrderGoods::where('id', $orderGoodsId)->update($updateData);
 
-     }
 
-     /**
 
-      * 检查订单中所有商品的发货状态
 
-      * @param int $orderId 订单ID
 
-      * @return array 返回发货状态统计
 
-      */
 
-     public static function checkOrderDeliveryStatus($orderId)
 
-     {
 
-         $orderGoods = OrderGoods::where('order_id', $orderId)->select();
 
-         
 
-         $statusCount = [
 
-             'total' => count($orderGoods), // 总商品数
 
-             'pending' => 0,    // 待发货
 
-             'delivered' => 0,  // 已发货
 
-         ];
 
-         
 
-         foreach ($orderGoods as $goods) {
 
-             if ($goods['delivery_status'] == 1) {
 
-                 $statusCount['delivered']++;
 
-             } else {
 
-                 $statusCount['pending']++;
 
-             }
 
-         }
 
-         
 
-         return $statusCount;
 
-     }
 
-     /**
 
-      * 根据发货状态决定是否更新订单状态
 
-      * @param int $orderId 订单ID
 
-      * @param int $userId 用户ID
 
-      * @return bool
 
-      */
 
-     public static function updateOrderStatusByDeliveryResult($orderId, $userId = 0)
 
-     {
 
-         $deliveryStatus = self::checkOrderDeliveryStatus($orderId);
 
-         
 
-         // 如果所有商品都已发货(没有待发货的商品)
 
-         if ($deliveryStatus['pending'] == 0 && $deliveryStatus['delivered'] > 0) {
 
-             // 更新订单状态为已发货
 
-             return self::updateOrderStatus($orderId, $userId, OrderEnum::STATUS_SHIP);
 
-         }
 
-         
 
-         return true;
 
-     }
 
-     /**
 
-      * 验证订单商品是否可以发货
 
-      * @param int $orderId 订单ID
 
-      * @param int $orderGoodsId 订单商品ID
 
-      * @return array|false 返回订单和订单商品信息,验证失败返回false
 
-      */
 
-     public static function validateOrderGoodsForDelivery($orderId, $orderGoodsId)
 
-     {
 
-         // 验证订单和订单商品是否存在
 
-         $orderData = self::validateOrderAndOrderGoods($orderId, $orderGoodsId);
 
-         if (!$orderData) {
 
-             return false;
 
-         }
 
-     
 
-         $orderGoods = $orderData['order_goods'];
 
-         // 检查订单商品的状态是都验货通过才可以发货
 
-         if ($orderGoods['inspect_status'] !== 1) {
 
-             return false;
 
-         }
 
-         // 检查该订单商品是否已经发货
 
-         if ($orderGoods['delivery_status'] == 1) {
 
-             return false;
 
-         }
 
-         
 
-         return $orderData;
 
-     }
 
- } 
 
 
  |