PHP订单模块梳理(乐观锁)

购物车功能点
1.0   购物车列表
2.0  添加到购物车
3.0   更新、删除购物车商品
4.0  选择或取消购物车商品
1.0下单
2.0订单支付、超时取消
3.0 确认收货
4.0订单评价
5.0订单列表、详情

er图设计
在这里插入图片描述

添加购物车的思路:
如果已经存在购物车货品,则增加数量;
否则添加新的购物车货品项.
逻辑思路
1.0  校验参数
$goodsId = $this->verifyId('goodsId', 0);
        $productId = $this->verifyId('productId', 0);
        $number = $this->verifyPositiveInteger('number', 0);

//2.0判断商品是否存在(主要判断商品是否可以购买)
if($number <= 0){
	return $this->badArgument();
}
$goods = GoodsService::getInstance()->getGoods($goodsId);
     if (is_null($goods) || !$goods->is_on_sale) {
            return $this->fail(CodeResponse::GOODS_UNSHELVE);
        }
        //判断购物车中是否存在此规格商品
        $product = GoodsServices::getInstance()->getGoodsProductById($productId);
             if (is_null($product) || $product->number < $number) {
            return $this->fail(CodeResponse::GOODS_NO_STOCK);
        }
        //获取购物车商品
         CartServices::getInstance()->add($this->userId(), $goodsId, $productId, $number);
         //如果没有添加购物车就添加一个新的,如果有就添加数量

在这里插入图片描述
在这里插入图片描述

更新:逻辑梳理
//1.0接收参数
$id = $this->verifyId('id', 0);
        $goodsId = $this->verifyId('goodsId', 0);
        $productId = $this->verifyId('productId', 0);
        $number = $this->verifyPositiveInteger('number', 0);
        //2.0获取当前购物车
         $cart = CartServices::getInstance()->getCartById($this->userId(), $id);
         //3.0如果购物车是null返回错误
          if (is_null($cart)) {
            return $this->badArgumentValue();
        }
        //4.0//判断当前购物车是否等于当前购物车以及其他参数
         if ($cart->goods_id != $goodsId || $cart->product_id != $productId) {
            return $this->badArgumentValue();
        }
        //5.0判断当前货品是否下架
          $goods = GoodsServices::getInstance()->getGoods($goodsId);
        if (is_null($goods) || !$goods->is_on_sale) {
            return $this->fail(CodeResponse::GOODS_UNSHELVE);
        }
        //6.0判断商品的库存是否足够
        $product = GoodsServices::getInstance()->getGoodsProductById($productId);
        if (is_null($product) || $product->number < $number) {
            return $this->fail(CodeResponse::GOODS_NO_STOCK);
        }
        //7.0修改购物车
        
        $cart->number = $number;
        $ret = $cart->save();
        return $this->failOrSuccess($ret);

购物车:删除

逻辑:删除id
//验证是否数组是否为空
 $productIds = $this->verifyArrayNotEmpty('productIds', []);
 
        CartServices::getInstance()->delete($this->userId(), $productIds);
        return $this->index();

立即购买

逻辑梳理:立即购买与加入购物车的逻辑很相识
区别
1.如果购物车内已经存在购物车货品,前者的逻辑是添加,这里的逻辑是数量覆盖。
2.0添加成功以后,前者的逻辑是返回当前购物车数量,这里的逻辑是返回对应购物车像的ID
    /**
     * 立即购买
     * @return JsonResponse
     * @throws BusinessException
     */
    public function fastadd()
    {
        $goodsId = $this->verifyId('goodsId', 0);
        $productId = $this->verifyId('productId', 0);
        $number = $this->verifyPositiveInteger('number', 0);
        $cart = CartServices::getInstance()->fastadd($this->userId(), $goodsId, $productId, $number);
        return $this->success($cart->id);
    }
  public function fastadd($userId, $goodsId, $productId, $number)
    {
    	//获取商品信息
        list($goods, $product) = $this->getGoodsInfo($goodsId, $productId);
        
        $cartProduct = $this->getCartProduct($userId, $goodsId, $productId);
        if (is_null($cartProduct)) {
            return $this->newCart($userId, $goods, $product, $number);
        } else {
            return $this->editCart($cartProduct, $product, $number);
        }
    }
    public function getGoodsInfo($goodsId, $productId)
    {
        $goods = GoodsServices::getInstance()->getGoods($goodsId);
        if (is_null($goods) || !$goods->is_on_sale) {
            $this->throwBusinessException(CodeResponse::GOODS_UNSHELVE);
        }

        $product = GoodsServices::getInstance()->getGoodsProductById($productId);
        if (is_null($product)) {
            $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
        }
        return [$goods, $product];
    }
    public function getCartProduct($userId, $goodsId, $productId)
    {
        return Cart::query()->where('user_id', $userId)->where('goods_id', $goodsId)
            ->where('product_id', $productId)->first();
    }

    public function newCart($userId, Goods $goods, GoodsProduct $product, $number)
    {
        if ($number > $product->number) {
            $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
        }
        $cart = Cart::new();
        $cart->goods_sn = $goods->goods_sn;
        $cart->goods_name = $goods->name;
        $cart->pic_url = $product->url ?: $goods->pic_url;
        $cart->price = $product->price;
        $cart->specifications = $product->specifications;
        $cart->user_id = $userId;
        $cart->checked = true;
        $cart->number = $number;
        $cart->goods_id = $goods->id;
        $cart->product_id = $product->id;
        $cart->save();
        return $cart;
    }
    public function editCart($existCart, $product, $num)
    {
        if ($num > $product->number) {
            $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
        }
        $existCart->number = $num;
        $existCart->save();
        return $existCart;
    }

购物车列表接口

//逻辑梳理
//1.0购物车列表是需要登录
//2.0根据用户获取相关的数据记录
//3.0循环一下购物车获取一下还没有失效的商品
//4.0统计购物车商品的总件数金额等
//5.0最后拼装返回
//获取购物车列表
    public function getCartList($userId)
    {
        return Cart::query()->where('user_id', $userId)->get();
    }
    public function getValidCartList($userId)
    {
    //获取有效的商品列表
        $list = $this->getCartList($userId);
        $goodsIds = $list->pluck('goods_id')->toArray();
        //获取商品信息
        $goodsList = GoodsServices::getInstance()
            ->getGoodsListByIds($goodsIds)->keyBy('id');
            //记录无效的商品id
        $invalidCartIds = [];
        //对数组进行过滤
        $list = $list->filter(function (Cart $cart) use ($goodsList, &$invalidCartIds) {
            /** @var Goods $goods */
            //拿到商品信息
            $goods = $goodsList->get($cart->goods_id);
            //过滤
            $isValid = !empty($goods) && $goods->is_on_sale;
            if (!$isValid) {
                $invalidCartIds[] = $cart->id;
            }
            return $isValid;
        });
        //删除无效的商品id
        $this->deleteCartList($invalidCartIds);
        return $list;
    }
    public function deleteCartList($ids)
    {
        if (empty($ids)) {
            return 0;
        }
        return Cart::query()->whereIn('id', $ids)->delete();
    }
    /**
     * 购物车列表信息
     * @return JsonResponse
     * @throws Exception
     */
    public function index()
    {
        $list = CartServices::getInstance()->getValidCartList($this->userId());
        //总数
        $goodsCount = 0;
        //总金额
        $goodsAmount = 0;
        //选中商品的总数
        $checkedGoodsCount = 0;
        //选中的总金额
        $checkedGoodsAmount = 0;
        foreach ($list as $item) {
            $goodsCount += $item->number;
            $amount = bcmul($item->price, $item->number, 2);
            $goodsAmount = bcadd($goodsAmount, $amount, 2);
            if ($item->checked) {
                $checkedGoodsCount += $item->number;
                $checkedGoodsAmount = bcadd($checkedGoodsAmount, $amount, 2);
            }
        }
        return $this->success(
            [
                'cartList' => $list->toArray(),
                'cartTotal' => [
                    'goodsCount' => $goodsCount,
                    'goodsAmount' => (double) $goodsAmount,
                    'checkedGoodsCount' => $checkedGoodsCount,
                    'checkedGoodsAmount' => (double) $checkedGoodsAmount,
                ]
            ]
        );
    }

下单前逻辑确认
在这里插入图片描述

 public function checkout()
    {
        //验证id
        $cartId = $this->verifyInteger('cartId');
        $addressId = $this->verifyInteger('addressId');
        $couponId = $this->verifyInteger('couponId');
        $grouponRulesId = $this->verifyInteger('grouponRulesId');

        // 获取地址
        $address = AddressServices::getInstance()->getAddressOrDefault($this->userId(), $addressId);
        $addressId = $address->id ?? 0;

        // 获取购物车的商品列表
        $checkedGoodsList = CartServices::getInstance()->getCheckedCartList($this->userId(), $cartId);

        // 计算商品总金额
        $grouponPrice = 0;
        $checkedGoodsPrice = CartServices::getInstance()->getCartPriceCutGroupon($checkedGoodsList, $grouponRulesId,
            $grouponPrice);

        // 获取优惠券信息
        $availableCouponLength = 0;
        $couponUser = CouponServices::getInstance()->getMostMeetPriceCoupon($this->userId(), $couponId,
            $checkedGoodsPrice, $availableCouponLength);
        // 兼容litemall的返回
        if ($couponId == -1 || is_null($couponId)) {
            // if (is_null($couponUser)) {
            $couponId = -1;
            $userCouponId = -1;
            $couponPrice = 0;
        } else {
            $couponId = $couponUser->coupon_id ?? 0;
            $userCouponId = $couponUser->id ?? 0;
            $couponPrice = CouponServices::getInstance()->getCoupon($couponId)->discount ?? 0;
        }

        // 运费
        $freightPrice = OrderServices::getInstance()->getFreight($checkedGoodsPrice);

        // 计算订单金额
        $orderPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderPrice = bcsub($orderPrice, $couponPrice, 2);
        $orderPrice = max(0, $orderPrice);

        return $this->success([
            "addressId" => $addressId,
            "couponId" => $couponId,
            "userCouponId" => $userCouponId,
            "cartId" => $cartId,
            "grouponRulesId" => $grouponRulesId,
            "grouponPrice" => $grouponPrice,
            "checkedAddress" => $address,
            "availableCouponLength" => $availableCouponLength,
            "goodsTotalPrice" => $checkedGoodsPrice,
            "freightPrice" => $freightPrice,
            "couponPrice" => $couponPrice,
            "orderTotalPrice" => $orderPrice,
            "actualPrice" => $orderPrice,
            "checkedGoodsList" => $checkedGoodsList->toArray(),
        ]);
    }
  /**
     * 获取地址或者返回默认地址
     * @param $userId
     * @param  null  $addressId
     * @return Address|Builder|Model|object|null
     * @throws BusinessException
     */
    public function getAddressOrDefault($userId, $addressId = null)
    {
        // 获取地址
        if (empty($addressId)) {
            $address = AddressServices::getInstance()->getDefaultAddress($userId);
        } else {
            $address = AddressServices::getInstance()->getAddress($userId, $addressId);
            if (empty($address)) {
                $this->throwBadArgumentValue();
            }
        }
        return $address;
    }
    public function getDefaultAddress($userId)
    {
            //返回默认地址
        return Address::query()->where('user_id', $userId)
            ->where('is_default', 1)->first();
    }
    /**
     * 获取用户地址
     * @param $userId
     * @param $addressId
     * @return Address|Model|null
     */
    public function getAddress($userId, $addressId)
    {
        return Address::query()->where('user_id', $userId)->where('id', $addressId)
            ->first();
    }

在这里插入图片描述

  /**
     * 获取已选择购物车商品列表
     * @param $userId
     * @param $cartId
     * @return Cart[]|Collection
     * @throws BusinessException
     */
    public function getCheckedCartList($userId, $cartId = null)
    {
        if (empty($cartId)) {
            $checkedGoodsList = $this->getCheckedCarts($userId);
        } else {
            $cart = $this->getCartById($userId, $cartId);
            if (empty($cart)) {
                $this->throwBadArgumentValue();
            }
            $checkedGoodsList = collect([$cart]);
        }
        return $checkedGoodsList;
    }
    public function getCheckedCarts($userId)
    {
        return Cart::query()->where('user_id', $userId)
            ->where('checked', 1)->get();
    }
    public function getCartById($userId, $id)
    {
        return Cart::query()->where('user_id', $userId)->where('id', $id)->first();
    }

在这里插入图片描述

 public function getCartPriceCutGroupon($checkedGoodsList, $grouponRulesId, &$grouponPrice = 0)
    {
        //获取一下团购规则
        $grouponRules = GrouponServices::getInstance()->getGrouponRulesById($grouponRulesId);
        $checkedGoodsPrice = 0;
        //循环一下获取到购物车的列表
        foreach ($checkedGoodsList as $cart) {
            //(如果有团购商品就用团购规则来计算,如果没有就用原价)
            //所以需要判断goods_id == 购物车->goods_id
            if ($grouponRules && $grouponRules->goods_id == $cart->goods_id) {
                //计算团购优惠的总金额
                $grouponPrice = bcmul($grouponRules->discount, $cart->number, 2);
                //如果都满足减折扣
                $price = bcsub($cart->price, $grouponRules->discount, 2);
            } else {
                $price = $cart->price;
            }
            //计算单个商品的总金额
            $price = bcmul($price, $cart->number, 2);
            //计算所有商品的总金额
            $checkedGoodsPrice = bcadd($checkedGoodsPrice, $price, 2);
        }
        return $checkedGoodsPrice;
    }

在这里插入图片描述
先创建一个枚举用来区别不同的优惠卷

<?php

namespace App\Enums;

class CouponUserEnums
{
    const STATUS_USABLE = 0;
    const STATUS_USED = 1;
    const STATUS_EXPIRED = 2;
    const STATUS_OUT = 3;
}
    /**
     * 验证当前价格是否可以使用这张优惠券
     * @param  Coupon  $coupon
     * @param  CouponUser  $couponUser
     * @param  double  $price
     * @return bool
     * @throws Exception
     */
    public function checkCouponAndPrice($coupon, $couponUser, $price)
    {
        //如果优惠用户为空返回错误
        if (empty($couponUser)) {
            return false;
        }
        //如果优惠券为空返回错误
        if (empty($coupon)) {
            return false;
        }
        //如果用户与优惠卷  id不一样说明 数据不一致.
        if ($couponUser->coupon_id != $coupon->id) {
            return false;
        }
        //如果优惠券的状态不是0的话,那也是不能使用的
        if ($coupon->status != CouponEnums::STATUS_NORMAL) {
            return false;
        }
          //验证优惠卷支持的商品类型
        if ($coupon->goods_type != CouponEnums::GOODS_TYPE_ALL) {
            return false;
        }
            //需要满足最低消费金额
        if (bccomp($coupon->min, $price) == 1) {
            return false;
        }

        $now = now();
        switch ($coupon->time_type) {
            case CouponEnums::TIME_TYPE_TIME:
                $start = Carbon::parse($coupon->start_time);
                $end = Carbon::parse($coupon->end_time);
                //如果当前时间在开始时间或者结束时间之后
                if ($now->isBefore($start) || $now->isAfter($end)) {
                    return false;
                }
                break;
                //算相对时间:从优惠卷领娶的时间开始算
            case CouponEnums::TIME_TYPE_DAYS:
                //当前时间加上有效时间
                $expired = Carbon::parse($couponUser->add_time)->addDays($coupon->days);
                //如果超过了有效时间
                if ($now->isAfter($expired)) {
                    return false;
                }
                break;
            default:
                return false;
        }
        return true;
    }
  public function getMeetPriceCouponAndSort($userId, $price)

    {
        //获娶可以用的优惠券
        $couponUsers = CouponServices::getInstance()->getUsableCoupons($userId);
        //获取优惠卷的id列表
        $couponIds = $couponUsers->pluck('coupon_id')->toArray();
        //批量获取优惠券
        $coupons = CouponServices::getInstance()->getCoupons($couponIds)->keyBy('id');
        //过滤不需要的内容filter
        return $couponUsers->filter(function (CouponUser $couponUser) use ($coupons, $price) {
            /** @var Coupon $coupon */
            $coupon = $coupons->get($couponUser->coupon_id);
            return CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $price);
            //默认选取优惠力度最大的
        })->sortByDesc(function (CouponUser $couponUser) use ($coupons) {
            /** @var Coupon $coupon */
            $coupon = $coupons->get($couponUser->coupon_id);
            return $coupon->discount;//discount优惠金额
        });
    }

在这里插入图片描述
一下代码还会进行封装切勿复制粘贴

  public function getMeetPriceCouponAndSort($userId, $price)

    {
        //获娶可以用的优惠券
        $couponUsers = CouponServices::getInstance()->getUsableCoupons($userId);
        //获取优惠卷的id列表
        $couponIds = $couponUsers->pluck('coupon_id')->toArray();
        //批量获取优惠券
        $coupons = CouponServices::getInstance()->getCoupons($couponIds)->keyBy('id');
        //过滤不需要的内容filter
        return $couponUsers->filter(function (CouponUser $couponUser) use ($coupons, $price) {
            /** @var Coupon $coupon */
            $coupon = $coupons->get($couponUser->coupon_id);
            return CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $price);
            //默认选取优惠力度最大的
        })->sortByDesc(function (CouponUser $couponUser) use ($coupons) {
            /** @var Coupon $coupon */
            $coupon = $coupons->get($couponUser->coupon_id);
            return $coupon->discount;//discount优惠金额
        });


			//初始化优惠卷价格
			$couponFirst = 0;
		//如果couponId是null或者couponId == -1  不使用优惠卷
		if(is_null($couponId) || $couponId == -1;){
			$userCouponId = -1;
			}elseif ($couponId == 0){
			/** @var CouponUser $couponUser */
				$couponUser = $couponUsers->first();
				$couponId = $couponUser->coupon_id ?? 0;
				//获取优惠信息
			 $couponPrice = CouponServices::getInstance()->getCoupon($couponId)->discount ?? 0;
			 } else {
			//如果传了$couponId
			//获取$coupon对象信息
			$coupon = CouponServices::getInstance()->getCoupon($couponId);
			//获取$coupon 对象信息
			$couponUser = CouponServices::getInstance()->getCouponUser($userCouponId);
			//验证这个优惠卷是否可用
			$is = CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $price);
			 if ($is) {
                $couponPrice = $coupon->disscount ?? 0 ;
                //下面两句可以省略不写 因为 验证通过了肯定可以
                //$couponId = $couponUser -> coupon_id ?? 0;
               // $userCouponId = $couponUser -> id ?? 0;
            }
			
}
			 	
				
				
				}
    }

    public function getCouponUser($id, $columns = ['*'])
    {
        return CouponUser::query()->find($id, $columns);
    }

到此优惠卷相关内容已经完成 接下来 算运费

在这里插入代码片

在这里插入图片描述

在这里插入图片描述

<?php

namespace App\Services;

use App\Models\System;

class SystemServices extends BaseServices
{

    // 小程序相关配置
    const LITEMALL_WX_INDEX_NEW = "litemall_wx_index_new";
    const LITEMALL_WX_INDEX_HOT = "litemall_wx_index_hot";
    const LITEMALL_WX_INDEX_BRAND = "litemall_wx_index_brand";
    const LITEMALL_WX_INDEX_TOPIC = "litemall_wx_index_topic";
    const LITEMALL_WX_INDEX_CATLOG_LIST = "litemall_wx_catlog_list";
    const LITEMALL_WX_INDEX_CATLOG_GOODS = "litemall_wx_catlog_goods";
    const LITEMALL_WX_SHARE = "litemall_wx_share";
    // 运费相关配置
    const LITEMALL_EXPRESS_FREIGHT_VALUE = "litemall_express_freight_value";
    const LITEMALL_EXPRESS_FREIGHT_MIN = "litemall_express_freight_min";
    // 订单相关配置
    const LITEMALL_ORDER_UNPAID = "litemall_order_unpaid";
    const LITEMALL_ORDER_UNCONFIRM = "litemall_order_unconfirm";
    const LITEMALL_ORDER_COMMENT = "litemall_order_comment";
    // 商场相关配置
    const LITEMALL_MALL_NAME = "litemall_mall_name";
    const LITEMALL_MALL_ADDRESS = "litemall_mall_address";
    const LITEMALL_MALL_PHONE = "litemall_mall_phone";
    const LITEMALL_MALL_QQ = "litemall_mall_qq";
    const LITEMALL_MALL_LONGITUDE = "litemall_mall_longitude";
    const LITEMALL_MALL_Latitude = "litemall_mall_latitude";

    public function getOrderUnConfirmDays()
    {
        return (int) $this->get(self::LITEMALL_ORDER_UNCONFIRM);
    }

    public function getOrderUnpaidDelayMinutes()
    {
        return (int) $this->get(self::LITEMALL_ORDER_UNPAID);
    }

    public function getFreightValue()
    {
        return (double) $this->get(self::LITEMALL_EXPRESS_FREIGHT_VALUE);
    }

    public function getFreightMin()
    {
        return (double) $this->get(self::LITEMALL_EXPRESS_FREIGHT_MIN);
    }

    
    //获取 系统配置方法
    public function get($key)
    {
        $value = System::query()->where('key_name', $key)->first(['key_value']);
        $value = $value['key_value'] ?? null;
        if ($value == 'false' || $value == 'FALSE') {
            return false;
        }
        if ($value == 'true' || $value == 'TRUE') {
            return true;
        }
        return $value;
    }
}
  public function getMeetPriceCouponAndSort($userId, $price)

    {
        //获娶可以用的优惠券
        $couponUsers = CouponServices::getInstance()->getUsableCoupons($userId);
        //获取优惠卷的id列表
        $couponIds = $couponUsers->pluck('coupon_id')->toArray();
        //批量获取优惠券
        $coupons = CouponServices::getInstance()->getCoupons($couponIds)->keyBy('id');
        //过滤不需要的内容filter
        return $couponUsers->filter(function (CouponUser $couponUser) use ($coupons, $price) {
            /** @var Coupon $coupon */
            $coupon = $coupons->get($couponUser->coupon_id);
            return CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $price);
            //默认选取优惠力度最大的
        })->sortByDesc(function (CouponUser $couponUser) use ($coupons) {
            /** @var Coupon $coupon */
            $coupon = $coupons->get($couponUser->coupon_id);
            return $coupon->discount;//discount优惠金额
        });


			//初始化优惠卷价格
			$couponFirst = 0;
		//如果couponId是null或者couponId == -1  不使用优惠卷
		if(is_null($couponId) || $couponId == -1;){				
			$couponId = -1;
			$userCouponId = -1;
			}elseif ($couponId == 0){
			/** @var CouponUser $couponUser */
				$couponUser = $couponUsers->first();
				$couponId = $couponUser->coupon_id ?? 0;
				//获取优惠信息
			 $couponPrice = CouponServices::getInstance()->getCoupon($couponId)->discount ?? 0;
			 } else {
			//如果传了$couponId
			//获取$coupon对象信息
			$coupon = CouponServices::getInstance()->getCoupon($couponId);
			//获取$coupon 对象信息
			$couponUser = CouponServices::getInstance()->getCouponUser($userCouponId);
			//验证这个优惠卷是否可用
			$is = CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $price);
			 if ($is) {
                $couponPrice = $coupon->disscount ?? 0 ;
                //下面两句可以省略不写 因为 验证通过了肯定可以
                //$couponId = $couponUser -> coupon_id ?? 0;
               // $userCouponId = $couponUser -> id ?? 0;
            }
			
}

     //运费
     $freightPrice = 0;
     //获取最低运费
     $freightMin = SYstemServices::getInstance()->getFreightMin();
             if (bccomp($freightMin, $price) == 1) {
            $freightPrice = SystemServices::getInstance()->getFreightValue();
        }
        
			
			// 计算订单金额    +运费-优惠卷
        $orderPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderPrice = bcsub($orderPrice, $couponPrice, 2);
                return $this->success([
            "addressId" => $addressId,
            "couponId" => $couponId,
            "userCouponId" => $userCouponId,
            "cartId" => $cartId,
            "grouponRulesId" => $grouponRulesId,
            "grouponPrice" => $grouponPrice,
            "checkedAddress" => $address,
            "availableCouponLength" => $availableCouponLength,
            "goodsTotalPrice" => $checkedGoodsPrice,
            "freightPrice" => $freightPrice,
            "couponPrice" => $couponPrice,
            "orderTotalPrice" => $orderPrice,
            "actualPrice" => $orderPrice,
            "checkedGoodsList" => $checkedGoodsList->toArray(),
        ]);
			 	
				
				
				}
    }

    public function getFreightValue()
    {
        return (double) $this->get(self::LITEMALL_EXPRESS_FREIGHT_VALUE);
    }

优化下单前信息确认

    /**
     * 下单前信息确认
     * @return JsonResponse
     * @throws BusinessException
     * @throws Exception
     */
    public function checkout()
    {
        //验证id
        $cartId = $this->verifyInteger('cartId');
        $addressId = $this->verifyInteger('addressId');
        $couponId = $this->verifyInteger('couponId');
        $grouponRulesId = $this->verifyInteger('grouponRulesId');

        // 获取地址
        $address = AddressServices::getInstance()->getAddressOrDefault($this->userId(), $addressId);
        $addressId = $address->id ?? 0;

        // 获取购物车的商品列表
        $checkedGoodsList = CartServices::getInstance()->getCheckedCartList($this->userId(), $cartId);

        // 计算商品总金额
        $grouponPrice = 0;
        $checkedGoodsPrice = CartServices::getInstance()->getCartPriceCutGroupon($checkedGoodsList, $grouponRulesId,
            $grouponPrice);

        // 获取优惠券信息
        $availableCouponLength = 0;
        $couponUser = CouponServices::getInstance()->getMostMeetPriceCoupon($this->userId(), $couponId,
            $checkedGoodsPrice, $availableCouponLength);
        // 兼容litemall的返回
        if ($couponId == -1 || is_null($couponId)) {
            // if (is_null($couponUser)) {
            $couponId = -1;
            $userCouponId = -1;
            $couponPrice = 0;
        } else {
            $couponId = $couponUser->coupon_id ?? 0;
            $userCouponId = $couponUser->id ?? 0;
            $couponPrice = CouponServices::getInstance()->getCoupon($couponId)->discount ?? 0;
        }

        // 运费
        $freightPrice = OrderServices::getInstance()->getFreight($checkedGoodsPrice);

        // 计算订单金额
        $orderPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderPrice = bcsub($orderPrice, $couponPrice, 2);
        $orderPrice = max(0, $orderPrice);

        return $this->success([
            "addressId" => $addressId,
            "couponId" => $couponId,
            "userCouponId" => $userCouponId,
            "cartId" => $cartId,
            "grouponRulesId" => $grouponRulesId,
            "grouponPrice" => $grouponPrice,
            "checkedAddress" => $address,
            "availableCouponLength" => $availableCouponLength,
            "goodsTotalPrice" => $checkedGoodsPrice,
            "freightPrice" => $freightPrice,
            "couponPrice" => $couponPrice,
            "orderTotalPrice" => $orderPrice,
            "actualPrice" => $orderPrice,
            "checkedGoodsList" => $checkedGoodsList->toArray(),
        ]);
    }
}
    /**
     * 获取地址或者返回默认地址
     * @param $userId
     * @param  null  $addressId
     * @return Address|Builder|Model|object|null
     * @throws BusinessException
     */
    public function getAddressOrDefault($userId, $addressId = null)
    {
        // 获取地址
        if (empty($addressId)) {
            $address = AddressServices::getInstance()->getDefaultAddress($userId);
        } else {
            $address = AddressServices::getInstance()->getAddress($userId, $addressId);
            if (empty($address)) {
                $this->throwBadArgumentValue();
            }
        }
        return $address;
    }
    public function getDefaultAddress($userId)
    {
        return Address::query()->where('user_id', $userId)
            ->where('is_default', 1)->first();
    }

    /**
     * 获取用户地址
     * @param $userId
     * @param $addressId
     * @return Address|Model|null
     */
    public function getAddress($userId, $addressId)
    {
        return Address::query()->where('user_id', $userId)->where('id', $addressId)
            ->first();
    }
    /**
     * @throws BusinessException
     */
    public function throwBadArgumentValue()
    {
        $this->throwBusinessException(CodeResponse::PARAM_VALUE_ILLEGAL);
    }

// 获取购物车的商品列表
c h e c k e d G o o d s L i s t = C a r t S e r v i c e s : : g e t I n s t a n c e ( ) − > g e t C h e c k e d C a r t L i s t ( checkedGoodsList = CartServices::getInstance()->getCheckedCartList( checkedGoodsList=CartServices::getInstance()>getCheckedCartList(this->userId(), $cartId);

    /**
     * 获取已选择购物车商品列表
     * @param $userId
     * @param $cartId
     * @return Cart[]|Collection
     * @throws BusinessException
     */
    public function getCheckedCartList($userId, $cartId = null)
    {
        if (empty($cartId)) {
            $checkedGoodsList = $this->getCheckedCarts($userId);
        } else {
            $cart = $this->getCartById($userId, $cartId);
            if (empty($cart)) {
                $this->throwBadArgumentValue();
            }
            $checkedGoodsList = collect([$cart]);
        }
        return $checkedGoodsList;
    }
    public function getCheckedCarts($userId)
    {
        return Cart::query()->where('user_id', $userId)
            ->where('checked', 1)->get();
    }

    public function getCartById($userId, $id)
    {
        return Cart::query()->where('user_id', $userId)->where('id', $id)->first();
    }
    /**
     * @throws BusinessException
     */
    public function throwBadArgumentValue()
    {
        $this->throwBusinessException(CodeResponse::PARAM_VALUE_ILLEGAL);
    }

这里以引用的方式传进来会getCartPriceCutGroupon方法执行后重新赋值

  // 计算商品总金额
        $grouponPrice = 0;
        $checkedGoodsPrice = CartServices::getInstance()->getCartPriceCutGroupon($checkedGoodsList, $grouponRulesId,
            $grouponPrice);
    public function getCartPriceCutGroupon($checkedGoodsList, $grouponRulesId, &$grouponPrice = 0)
    {
        //获取一下团购规则
        $grouponRules = GrouponServices::getInstance()->getGrouponRulesById($grouponRulesId);
        $checkedGoodsPrice = 0;
        //循环一下获取到购物车的列表
        foreach ($checkedGoodsList as $cart) {
            //(如果有团购商品就用团购规则来计算,如果没有就用原价)
            //所以需要判断goods_id == 购物车->goods_id
            if ($grouponRules && $grouponRules->goods_id == $cart->goods_id) {
                //计算团购优惠的总金额
                $grouponPrice = bcmul($grouponRules->discount, $cart->number, 2);
                //如果都满足减折扣
                $price = bcsub($cart->price, $grouponRules->discount, 2);
            } else {
                $price = $cart->price;
            }
            //计算单个商品的总金额
            $price = bcmul($price, $cart->number, 2);
            //计算所有商品的总金额
            $checkedGoodsPrice = bcadd($checkedGoodsPrice, $price, 2);
        }
        return $checkedGoodsPrice;
    }


 // 获取优惠券信息
        $availableCouponLength = 0;
        $couponUser = CouponServices::getInstance()->getMostMeetPriceCoupon($this->userId(), $couponId,
            $checkedGoodsPrice, $availableCouponLength);
        // 兼容litemall的返回   如果是空就返回 -1  如果不是非空就返回正常信息
        if ($couponId == -1 || is_null($couponId)) {
            // if (is_null($couponUser)) {
            $couponId = -1;
            $userCouponId = -1;
            $couponPrice = 0;
        } else {
            $couponId = $couponUser->coupon_id ?? 0;
            $userCouponId = $couponUser->id ?? 0;
            $couponPrice = CouponServices::getInstance()->getCoupon($couponId)->discount ?? 0;
        }

    /**
     * 获取适合当前价格的优惠券
     * @param $userId
     * @param $couponId
     * @param $price
     * @param  int  $availableCouponLength
     * @return CouponUser|null
     * @throws Exception
     */
    public function getMostMeetPriceCoupon($userId, $couponId, $price, &$availableCouponLength = 0)
    {
        $couponUsers = $this->getMeetPriceCouponAndSort($userId, $price);
        $availableCouponLength = $couponUsers->count();

        if (is_null($couponId) || $couponId == -1) {
            return null;
        }

        if (!empty($couponId)) {
            $coupon = $this->getCoupon($couponId);
            $couponUser = $this->getCouponUserByCouponId($userId, $couponId);
            $is = $this->checkCouponAndPrice($coupon, $couponUser, $price);
            if ($is) {
                return $couponUser;
            }
        }
        return $couponUsers->first();
    }

最后重构


        // 运费
        $freightPrice = OrderServices::getInstance()->getFreight($checkedGoodsPrice);

        // 计算订单金额
        $orderPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderPrice = bcsub($orderPrice, $couponPrice, 2);
        $orderPrice = max(0, $orderPrice);

        return $this->success([
            "addressId" => $addressId,
            "couponId" => $couponId,
            "userCouponId" => $userCouponId,
            "cartId" => $cartId,
            "grouponRulesId" => $grouponRulesId,
            "grouponPrice" => $grouponPrice,
            "checkedAddress" => $address,
            "availableCouponLength" => $availableCouponLength,
            "goodsTotalPrice" => $checkedGoodsPrice,
            "freightPrice" => $freightPrice,
            "couponPrice" => $couponPrice,
            "orderTotalPrice" => $orderPrice,
            "actualPrice" => $orderPrice,
            "checkedGoodsList" => $checkedGoodsList->toArray(),
        ]);
    /**
     * 获取运费
     * @param $price
     * @return float|int
     */
    public function getFreight($price)
    {
        $freightPrice = 0;
        $freightMin = SystemServices::getInstance()->getFreightMin();
        if (bccomp($freightMin, $price) == 1) {
            $freightPrice = SystemServices::getInstance()->getFreightValue();
        }
        return $freightPrice;
    }

    public function getOrderByUserIdAndId($userId, $orderId)
    {
        return Order::query()->where('user_id', $userId)->find($orderId);
    }

下单逻辑实在是有点恶心.后期还会整理  有些地方还可以整理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由于参数过长这里我们可以封装一下

在这里插入图片描述

  /**
     * 提交订单
     * @return JsonResponse
     * @throws BusinessException
     * @throws Throwable
     */
    public function submit()
    {
        //入参
        $input = OrderSubmitInput::new();


         //调用提交订单方法    transaction是开启事务
        $order = DB::transaction(function () use ($input) {
            return OrderServices::getInstance()->submit($this->userId(), $input);
        });
        return $this->success([
            'orderId' => $order->id,
            'grouponLikeId' => $input->grouponLinkId ?? 0
        ]);
    }
 /**
     * 提交订单
     * @param $userId
     * @param  OrderSubmitInput  $input
     * @return Order|void
     * @throws BusinessException
     */
    public function submit($userId, OrderSubmitInput $input)
    {
        // 验证团购规则的有效性
        if (!empty($input->grouponRulesId)) {
            GrouponServices::getInstance()->checkGrouponValid($userId, $input->grouponRulesId);
        }
        $address = AddressServices::getInstance()->getAddress($userId, $input->addressId);
        if (empty($address)) {
            return $this->throwBadArgumentValue();
        }

        // 获取购物车的商品列表
        $checkedGoodsList = CartServices::getInstance()->getCheckedCartList($userId, $input->cartId);

        // 计算商品总金额
        $grouponPrice = 0;
        $checkedGoodsPrice = CartServices::getInstance()->getCartPriceCutGroupon($checkedGoodsList,
            $input->grouponRulesId,
            $grouponPrice);

        // 获取优惠券面额
        $couponPrice = 0;
        if ($input->couponId > 0) {
            $coupon = CouponServices::getInstance()->getCoupon($input->couponId);
            $couponUser = CouponServices::getInstance()->getCouponUser($input->userCouponId);
            $is = CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $checkedGoodsPrice);
            if ($is) {
                $couponPrice = $coupon->discount;
            }
        }

        // 运费
        $freightPrice = $this->getFreight($checkedGoodsPrice);

        // 计算订单金额
        $orderTotalPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderTotalPrice = bcsub($orderTotalPrice, $couponPrice, 2);
        $orderTotalPrice = max(0, $orderTotalPrice);

        $order = Order::new();
        $order->user_id = $userId;
        $order->order_sn = $this->generateOrderSn();
        $order->order_status = OrderEnums::STATUS_CREATE;
        $order->consignee = $address->name;
        $order->mobile = $address->tel;
        $order->address = $address->province.$address->city.$address->county." ".$address->address_detail;
        $order->message = $input->message;
        $order->goods_price = $checkedGoodsPrice;
        $order->freight_price = $freightPrice;
        $order->integral_price = 0;
        $order->coupon_price = $couponPrice;
        $order->order_price = $orderTotalPrice;
        $order->actual_price = $orderTotalPrice;
        $order->groupon_price = $grouponPrice;
        $order->save();

        // 写入订单商品记录
        $this->saveOrderGoods($checkedGoodsList, $order->id);

        // 清理购物车记录
        CartServices::getInstance()->clearCartGoods($userId, $input->cartId);

        // 减库存
        $this->reduceProductsStock($checkedGoodsList);

        // 添加团购记录
        GrouponServices::getInstance()->openOrJoinGroupon($userId, $order->id, $input->grouponRulesId,
            $input->grouponLinkId);

        // 设置超时任务
        dispatch(new OrderUnpaidTimeEndJob($userId, $order->id));

        return $order;
    }

//此时暂时控制器的代码
在这里插入图片描述

在这里插入图片描述


        // 计算商品总金额
        $grouponPrice = 0;
        $checkedGoodsPrice = CartServices::getInstance()->getCartPriceCutGroupon($checkedGoodsList,
            $input->grouponRulesId,
            $grouponPrice);

        // 获取优惠券面额
        $couponPrice = 0;
        if ($input->couponId > 0) {
            $coupon = CouponServices::getInstance()->getCoupon($input->couponId);
            $couponUser = CouponServices::getInstance()->getCouponUser($input->userCouponId);
            $is = CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $checkedGoodsPrice);
            if ($is) {
                $couponPrice = $coupon->discount;
            }
        }

        // 运费
        $freightPrice = $this->getFreight($checkedGoodsPrice);

        // 计算订单金额
        $orderTotalPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderTotalPrice = bcsub($orderTotalPrice, $couponPrice, 2);
        $orderTotalPrice = max(0, $orderTotalPrice);

优化后

    /**
     * 提交订单
     * @param $userId
     * @param  OrderSubmitInput  $input
     * @return Order|void
     * @throws BusinessException
     */
    public function submit($userId, OrderSubmitInput $input)
    {
        // 验证团购规则的有效性
        if (!empty($input->grouponRulesId)) {
            //校验用户是否可以开启或参与某个团购活动
            GrouponServices::getInstance()->checkGrouponValid($userId, $input->grouponRulesId);
        }
        //获取收获地址
        $address = AddressServices::getInstance()->getAddress($userId, $input->addressId);
          //如果获取不到的话抛出异常
        if (empty($address)) {
            return $this->throwBadArgumentValue();
        }

        // 获取购物车的商品列表   计算总金额需要先获取商品列表
        $checkedGoodsList = CartServices::getInstance()->getCheckedCartList($userId, $input->cartId);

        // 计算商品总金额
        $grouponPrice = 0;
        $checkedGoodsPrice = CartServices::getInstance()->getCartPriceCutGroupon($checkedGoodsList,
            $input->grouponRulesId,
            $grouponPrice);

        // 获取优惠券面额   逻辑:这里只要用户选中了就代表是最终的选择
        $couponPrice = 0;
        if ($input->couponId > 0) {
            //获取优惠卷信息
            $coupon = CouponServices::getInstance()->getCoupon($input->couponId);
            //获取优惠用户
            $couponUser = CouponServices::getInstance()->getCouponUser($input->userCouponId);
            $is = CouponServices::getInstance()->checkCouponAndPrice($coupon, $couponUser, $checkedGoodsPrice);
            if ($is) {
                $couponPrice = $coupon->discount;
            }
        }

        // 运费
        $freightPrice = $this->getFreight($checkedGoodsPrice);

        // 计算订单金额
        $orderTotalPrice = bcadd($checkedGoodsPrice, $freightPrice, 2);
        $orderTotalPrice = bcsub($orderTotalPrice, $couponPrice, 2);
        $orderTotalPrice = max(0, $orderTotalPrice);

        //保存订单
        $order = Order::new();
        $order->user_id = $userId;
        $order->order_sn = $this->generateOrderSn();
        $order->order_status = OrderEnums::STATUS_CREATE;
        $order->consignee = $address->name;
        $order->mobile = $address->tel;
        $order->address = $address->province.$address->city.$address->county." ".$address->address_detail;
        $order->message = $input->message;
        $order->goods_price = $checkedGoodsPrice;
        $order->freight_price = $freightPrice;
        $order->integral_price = 0;
        $order->coupon_price = $couponPrice;
        $order->order_price = $orderTotalPrice;
        $order->actual_price = $orderTotalPrice;
        $order->groupon_price = $grouponPrice;
        $order->save();

        // 写入订单商品记录
        $this->saveOrderGoods($checkedGoodsList, $order->id);

        // 清理购物车记录
        CartServices::getInstance()->clearCartGoods($userId, $input->cartId);

        // 减库存   这里的减库存的逻辑可以先跳过
        $this->reduceProductsStock($checkedGoodsList);

        // 添加团购记录
        GrouponServices::getInstance()->openOrJoinGroupon($userId, $order->id, $input->grouponRulesId,
            $input->grouponLinkId);

        // 设置超时任务
        dispatch(new OrderUnpaidTimeEndJob($userId, $order->id));

        return $order;
    }
    public function reduceProductsStock($goodsList)
    {
        foreach ($goodsList as $cart) {
        //获取商品的信息
        $products = GoodsServices::getInstance()->getGoodsProductsByIds($productIds)->keyBy('id');
          //判断货品信息是否获取到了
            if (empty($product)) {
                $this->throwBadArgumentValue();
            }
            //判断库存是否充足
            if ($product->number < $cart->number) {
                $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
            }
            //减库存   decrement方法可以自动减库存
            GoodsProduct::query()->where('id',$product->id)->where('number','>',$cart->number)
            ->decrement('number',$cart->number);
        }
    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值