【业务功能篇99】微服务-springcloud-springboot-电商订单模块-生成订单服务-锁定库存

news2024/12/29 9:42:07

八、生成订单

image.png

一个是需要生成订单信息一个是需要生成订单项信息。具体的核心代码为

/**
     * 创建订单的方法
     * @param vo
     * @return
     */
    private OrderCreateTO createOrder(OrderSubmitVO vo) {
        OrderCreateTO createTO = new OrderCreateTO();
        // 创建订单
        OrderEntity orderEntity = buildOrder(vo);
        createTO.setOrderEntity(orderEntity);
        // 创建OrderItemEntity 订单项
        List<OrderItemEntity> orderItemEntitys = buildOrderItems(orderEntity.getOrderSn());
        createTO.setOrderItemEntitys(orderItemEntitys);
        return createTO;
    }

    /**
     * 通过购物车中选中的商品来创建对应的购物项信息
     * @return
     */
    private List<OrderItemEntity> buildOrderItems(String orderSN) {
        List<OrderItemEntity> orderItemEntitys = new ArrayList<>();
        // 获取购物车中的商品信息 选中的
        List<OrderItemVo> userCartItems = cartFeginService.getUserCartItems();
        if(userCartItems != null && userCartItems.size() > 0){
            // 统一根据SKUID查询出对应的SPU的信息
            List<Long> spuIds = new ArrayList<>();
            for (OrderItemEntity orderItemEntity : orderItemEntitys) {
                if(!spuIds.contains(orderItemEntity.getSpuId())){
                    spuIds.add(orderItemEntity.getOrderId());
                }
            }
            // 远程调用商品服务获取到对应的SPU信息
            List<OrderItemSpuInfoVO> spuInfos = productService.getOrderItemSpuInfoBySpuId((Long[]) spuIds.toArray());
            Map<Long, OrderItemSpuInfoVO> map = spuInfos.stream().collect(Collectors.toMap(OrderItemSpuInfoVO::getId, item -> item));
            for (OrderItemVo userCartItem : userCartItems) {
                // 获取到商品信息对应的 SPU信息
                OrderItemSpuInfoVO spuInfo  = map.get(userCartItem.getSpuId());
                OrderItemEntity orderItemEntity = buildOrderItem(userCartItem,spuInfo);
                // 绑定对应的订单编号
                orderItemEntity.setOrderSn(orderSN);
                orderItemEntitys.add(orderItemEntity);
            }
        }

        return orderItemEntitys;
    }

    /**
     * 根据一个购物车中的商品创建对应的 订单项
     * @param userCartItem
     * @return
     */
    private OrderItemEntity buildOrderItem(OrderItemVo userCartItem,OrderItemSpuInfoVO spuInfo) {
        OrderItemEntity entity = new OrderItemEntity();
        // SKU信息
        entity.setSkuId(userCartItem.getSkuId());
        entity.setSkuName(userCartItem.getTitle());
        entity.setSkuPic(userCartItem.getImage());
        entity.setSkuQuantity(userCartItem.getCount());
        List<String> skuAttr = userCartItem.getSkuAttr();
        String skuAttrStr = StringUtils.collectionToDelimitedString(skuAttr, ";");
        entity.setSkuAttrsVals(skuAttrStr);
        // SPU信息
        entity.setSpuId(spuInfo.getId());
        entity.setSpuBrand(spuInfo.getBrandName());
        entity.setCategoryId(spuInfo.getCatalogId());
        entity.setSpuPic(spuInfo.getImg());
        // 优惠信息 忽略
        // 积分信息
        entity.setGiftGrowth(userCartItem.getPrice().intValue());
        entity.setGiftIntegration(userCartItem.getPrice().intValue());
        return entity;
    }

    private OrderEntity buildOrder(OrderSubmitVO vo) {
        // 创建OrderEntity
        OrderEntity orderEntity = new OrderEntity();
        // 创建订单编号
        String orderSn = IdWorker.getTimeId();
        orderEntity.setOrderSn(orderSn);
        MemberVO memberVO = (MemberVO) AuthInterceptor.threadLocal.get();
        // 设置会员相关的信息
        orderEntity.setMemberId(memberVO.getId());
        orderEntity.setMemberUsername(memberVO.getUsername());
        // 根据收获地址ID获取收获地址的详细信息
        MemberAddressVo memberAddressVo = memberFeginService.getAddressById(vo.getAddrId());
        orderEntity.setReceiverCity(memberAddressVo.getCity());
        orderEntity.setReceiverDetailAddress(memberAddressVo.getDetailAddress());
        orderEntity.setReceiverName(memberAddressVo.getName());
        orderEntity.setReceiverPhone(memberAddressVo.getPhone());
        orderEntity.setReceiverPostCode(memberAddressVo.getPostCode());
        orderEntity.setReceiverRegion(memberAddressVo.getRegion());
        orderEntity.setReceiverProvince(memberAddressVo.getProvince());
        // 设置订单的状态
        orderEntity.setStatus(OrderConstant.OrderStateEnum.FOR_THE_PAYMENT.getCode());
        return orderEntity;
    }

锁定库存的操作,需要操作ware仓储服务。

   /**
     * 锁定库存的操作
     * @param vo
     * @return
     */
    @Transactional
    @Override
    public Boolean orderLockStock(WareSkuLockVO vo) {
        List<OrderItemVo> items = vo.getItems();
        // 首先找到具有库存的仓库
        List<SkuWareHasStock> collect = items.stream().map(item -> {
            SkuWareHasStock skuWareHasStock = new SkuWareHasStock();
            skuWareHasStock.setSkuId(item.getSkuId());
            List<WareSkuEntity> wareSkuEntities = this.baseMapper.listHashStock(item.getSkuId());
            skuWareHasStock.setWareSkuEntities(wareSkuEntities);
            skuWareHasStock.setNum(item.getCount());
            return skuWareHasStock;
        }).collect(Collectors.toList());
        // 尝试锁定库存
        for (SkuWareHasStock skuWareHasStock : collect) {
            Long skuId = skuWareHasStock.getSkuId();
            List<WareSkuEntity> wareSkuEntities = skuWareHasStock.wareSkuEntities;
            if(wareSkuEntities == null && wareSkuEntities.size() == 0){
                // 当前商品没有库存了
                throw new NoStockExecption(skuId);
            }
            // 当前需要锁定的商品的梳理
            Integer count = skuWareHasStock.getNum();
            Boolean skuStocked = false; // 表示当前SkuId的库存没有锁定完成
            for (WareSkuEntity wareSkuEntity : wareSkuEntities) {
                // 循环获取到对应的 仓库,然后需要锁定库存
                // 获取当前仓库能够锁定的库存数
                Integer canStock = wareSkuEntity.getStock() - wareSkuEntity.getStockLocked();
                if(count <= canStock){
                    // 表示当前的skuId的商品的数量小于等于需要锁定的数量
                    Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),count);
                    count = 0;
                    skuStocked = true;
                }else{
                    // 需要锁定的库存大于 可以锁定的库存 就按照已有的库存来锁定
                    Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),canStock);
                    count = count - canStock;
                }
                if(count <= 0 ){
                    // 表示所有的商品都锁定了
                    break;
                }
            }
            if(count > 0){
                // 说明库存没有锁定完
                throw new NoStockExecption(skuId);
            }
            if(skuStocked == false){
                // 表示上一个商品的没有锁定库存成功
                throw new NoStockExecption(skuId);
            }
        }
        return true;
    }

没有库存或者锁定库存失败我们通过自定义的异常抛出

/**
 * 自定义异常:锁定库存失败的情况下产生的异常信
 */
public class NoStockExecption extends RuntimeException{

    private Long skuId;

    public NoStockExecption(Long skuId){
        super("当前商品["+skuId+"]没有库存了");
        this.skuId = skuId;

    }

    public Long getSkuId() {
        return skuId;
    }

    public void setSkuId(Long skuId) {
        this.skuId = skuId;
    }
}

如果下订单操作成功(订单数据和订单项数据)我们就会操作锁库存的行为

image.png

锁定库存失败通过抛异常来使订单操作回滚

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/982206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

echarts饼图label自定义样式

生成的options {"tooltip": {"trigger": "item","axisPointer": {"type": "shadow"},"backgroundColor": "rgba(9, 24, 48, 0.5)","borderColor": "rgba(255,255,255,0.4)&q…

Python Qt学习(十)一个简易的POP3邮件客户端

公司把126这类的邮箱网站都封了&#xff0c;正好现在无事&#xff0c;加之&#xff0c;算是一个对这俩周学习Qt的一个总结吧。遂写了这么一个简易的通过POP3协议接收126邮件的客户端。 源代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from read…

OpenCV图像处理——矩形(Rect)类的常用操作

1.Rect类 创建类 Rect类成员变量x、y、width、height&#xff0c;分别为左上角点的坐标和矩形的宽和高。 创建一个Rect对象Rect,并在图像上画该矩形框。 cv::Rect rect(100, 50, 500, 500);cv::Mat cv_src cv::imread("11.JPG");cv::rectangle(cv_src, rect, cv:…

每一座屎山代码背后,都藏着一堆熟读代码规范的研发

&#x1f449;导读 韩寒在《他的国》中写道&#xff1a;“我们懂很多道理&#xff0c;却依然过不好这一生”&#xff0c;人们虽然知道很多道理&#xff0c;但并不一定能将这些道理应用到实际生活中。这种现象在生活中很常见&#xff0c;我们听了很多的成功学的道理&#xff0c;…

接入 NVIDIA A100、吞吐量提高 10 倍!Milvus GPU 版本使用指南

Milvus 2.3 正式支持 NVIDIA A100&#xff01; 作为为数不多的支持 GPU 的向量数据库产品&#xff0c;Milvus 2.3 在吞吐量和低延迟方面都带来了显著的变化&#xff0c;尤其是与此前的 CPU 版本相比&#xff0c;不仅吞吐量提高了 10 倍&#xff0c;还能将延迟控制在极低的水准。…

ChatGLM2-6B 部署

引言 这是ChatGLM2-6B 部署的阅读笔记&#xff0c;主要介绍了ChatGLM2-6B模型的部署和一些原理的简单解释。 ChatGLM-6B 它是单卡开源的对话模型。 充分的中英双语预训练 较低的部署门槛 FP16半精度下&#xff0c;需要至少13G的显存进行推理&#xff0c;甚至可以进一步降低…

罕见病 对称性脂肪瘤(MSL) 马德龙病

如果你体内脂肪瘤分布大致如下 而且个数不断增多 这篇文章适合你 症状 脂肪瘤个数一直增加 而且很对称 比如: 左手臂一个 右手臂一个 别名 多发性对称性脂肪增多症 Multiple symmetric lipomatosis (MSL) 多发性对称性脂肪瘤&#xff08;MSL&#xff09; 脂肪瘤 马德龙病(…

大场景的倾斜摄影三维模型OBJ格式轻量化处理处理关键处理技术分析

大场景的倾斜摄影三维模型OBJ格式轻量化处理处理关键处理技术分析 大场景的倾斜摄影三维模型是指通过航空或地面摄影获取的大范围、高分辨率的地理环境数据。为了在虚拟环境中加载和渲染这些模型&#xff0c;需要对其进行OBJ格式的轻量化处理。本文将分析大场景的倾斜摄影三维模…

SSRF漏洞实战

文章目录 SSRF概述SSRF原理SSRF 危害PHP复现SSRF漏洞检测端口扫描内网Web应用指纹识别攻击内网应用读取本地文件 Weblogic SSRF--Getshell复现SSRF攻击Redis原理漏洞检测端口扫描复现翻车&#xff0c;请看官方复现教程注入HTTP头&#xff0c;利用Redis反弹shell SSRF防御过滤输…

软路由的负载均衡设置:优化网络性能和带宽利用率

在现代网络环境中&#xff0c;提升网络性能和最大化带宽利用率至关重要。通过合理配置软路由IP的负载均衡设置&#xff0c;可以有效地实现这一目标&#xff0c;并提高整体稳定性与效果。本文将详细介绍如何进行软路由IP的负载均衡设置&#xff0c;从而优化网络表现、增加带宽利…

软件架构设计(六) 软件架构风格-MDA(模型驱动架构)

概念 模型驱动架构MDA, 全称叫做Model Driven Architecture。 Model:表示客观事物的抽象表示Architecture:表示构成系统的部件,连接件及其约束的规约Model Driven: 使用模型完成软件的分析,设计,构建,部署和维护等 开发活动MDA起源于分离系统规约和平台实现的思想。之前…

Python入门学习13(面向对象)

一、类的定义和使用 类的使用语法&#xff1a; 创建类对象的语法&#xff1a; ​​​​​​​ class Student:name None #学生的名字age None #学生的年龄def say_hi(self):print(f"Hi大家好&#xff0c;我是{self.name}")stu Student() stu.name &q…

软件系统平台验收测试报告

验收测试 一、验收测试 软件项目验收测试依据招投标文件以及相关行业标准、国家标准、法律法规等对软件的功能性、易用性、可靠性、兼容性、维护性、可移植性和用户文档等进行检测&#xff0c;对软件项目的质量进行科学的评价&#xff0c;为项目验收提供依据。 1、服务内容 …

成功解决OSError: [WinError 1455] 页面文件太小,无法完成操作

最近写了个训练文件&#xff0c;昨天在运行的时候都是好好的&#xff0c;今天一运行就报错了&#xff0c;不得不说&#xff0c;有点点奇怪。 OSError: [WinError 1455] 页面文件太小&#xff0c;无法完成操作。 Error loading "D:\AI\Anaconda\anaconda3\envs\torch1.8\li…

嵌入式学习笔记(16)反汇编工具objdump

2.4.1反汇编的原理&为什么要用反汇编 arm-linux-objdump -D led.elf > led_elf.dis objdump是gcc工具链中的反汇编工具&#xff0c;作用是由编译链接好的elf格式的可执行程序反过来得到汇编源代码 -D表示反汇编 > 左边的是elf可执行程序&#xff08;反汇编的源&am…

Linux RPM JDK升级

以JDK1.8升级JDK17为例 上传jdk17安装包到linux服务器 检查jdk版本 rpm -qa|grep jdk 删除查询到的jdk rpm -e --nodeps jdk1.8-1.8.0_201-fcs.x86_64 删除完毕后安装新的jdk rpm -ivh jdk-17_linux-x64_bin.rpm 检查jdk版本 java -version

Matlab信号处理3:fft(快速傅里叶变换)标准使用方式

Fs 1000; % 采样频率 T 1/Fs; % 采样周期&#xff1a;0.001s L 1500; % 信号长度 t (0:L-1)*T; % 时间向量. 时间向量从0开始递增&#xff0c;0s~1.499sS 0.7*sin(2*pi*50*t) sin(2*pi*120*t); % 模拟原信号 X S 2*randn(size(t)); …

jenkins快速跑通helloworld任务

jenkins新建helloworld示例 左上角“新建任务” 输入名称&#xff0c;选择第一个创建&#xff1a; 可以选择众多执行脚本&#xff0c;这里选择shell&#xff1a; 随后弹出一个窗口&#xff0c;将下面脚本填入&#xff1a; #!/bin/bashecho start... for i in {1..10}doecho $i…

什么是混合项目管理模式,以及价值

随着工作环境的不断变化&#xff0c;传统的项目管理方法&#xff08;如瀑布模型&#xff09;已经不能满足当前的需要&#xff0c;这也引发了对敏捷和瀑布式两种方法论之间优劣的新一轮讨论。瀑布模型是一种较为传统和结构化的项目管理方法&#xff0c;主要用于项目管理和软件开…

CH06_第一组重构(上)

提取函数&#xff08;Extract Function |106&#xff09; 曾用名&#xff1a;提炼函数&#xff08;Extract Function&#xff09; 反向重构&#xff1a;内联函数&#xff08;115&#xff09; 示例代码 function printOwing(invoice) {printBanner();let outstanding calcul…