| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 | <?phpnamespace 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;use app\common\Enum\OrderEnum;use app\common\exception\BusinessException;use app\common\Service\Order\OrderActionService;use app\common\Enum\OrderActionEnum;/** * 订单服务类 * 封装订单创建相关逻辑 */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)) {            $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 BusinessException("商品数量必须大于0");            }            // 检查商品是否存在            if (!isset($goodsData[$goods_id])) {                throw new   ("商品已下架");            }            $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_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,            ];                        $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("商品列表不能为空");        }        $config = get_addon_config('shop');        $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() + $config['order_timeout'], // 过期时间            '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 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('used_nums');            }                        // 优惠券已使用            if (!empty($userCoupon)) {                $userCoupon->save(['is_used' => 2]);            }                        // 提交事务            Db::commit();        } catch (Exception $e) {            Db::rollback();            throw new Exception($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 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 = [],$supplierId = 0)    {        $pageSize = 10;        if (!empty($param['pageSize'])) {            $pageSize = $param['pageSize'];        }        return Order::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, $userId)    {        return Order::with(['orderGoods'])        ->where('id', $orderId)        ->where('user_id', $userId)        ->find();    }    public static function getDetailByOrderSn($orderSn)    {        return Order::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_PAY)->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();               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()]);    }    /**     * 获取供应商订单详情 - 只返回该供应商的商品     * @param string $orderSn 订单号     * @param int $supplierId 供应商ID     * @return array|null     */    public static function getSupplierOrderDetail($orderSn, $supplierId)    {        $order = Order::where('order_sn', $orderSn)->find();        if (!$order) {            return null;        }                // 获取该供应商在此订单中的商品        $orderGoods = OrderGoods::where('order_sn', $orderSn)            ->where('supplier_id', $supplierId)            ->select();                $order->orderGoods = $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;        }                $order = $orderData['order'];        $orderGoods = $orderData['order_goods'];                // 检查订单状态是否允许发货(验收通过状态)        if ($order['order_status'] != OrderEnum::STATUS_INSPECTION_PASS) {            return false;        }                // 检查该订单商品是否已经发货        if ($orderGoods['delivery_status'] == 1) {            return false;        }                return $orderData;    }} 
 |