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

八、生成订单

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) {// 创建OrderEntityOrderEntity 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@Overridepublic 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.mzph.cn/news/70570.shtml

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

相关文章

[HNCTF 2022] web 刷题记录

文章目录 [HNCTF 2022 Week1]easy_html[HNCTF 2022 Week1]easy_upload[HNCTF 2022 Week1]Interesting_http[HNCTF 2022 WEEK2]ez_SSTI[HNCTF 2022 WEEK2]ez_ssrf[HNCTF 2022 WEEK2]Canyource [HNCTF 2022 Week1]easy_html 打开题目提示cookie有线索 访问一下url 发现要求我们…

mybatisplus多租户原理略解

概述 当前mybatisPlus版本 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version> </dependency>jdk版本&#xff1a;17 springboot版本&#xff1a;…

深入探讨Kubernetes(K8s)在云原生架构中的关键作用和应用

文章目录 1. 容器化的应用程序管理2. 自动化扩展和负载均衡3. 容器编排和调度4. 存储管理5. 自动化滚动更新6. 多云和混合云部署7. 监控和日志8. 安全9. 社区支持和生态系统10. 未来展望案例 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1…

2023年高教社杯全国大学生数学建模竞赛参赛事项注意

MathClub数模资源&#xff0c;含专属思路 资源链接&#xff1a;点击这里获取众多数模资料、思路精讲、论文模板latex和word、学习书籍等 2023高教社杯数学建模国赛–赛前准备 一年一度的数学建模国赛要来啦&#xff01;&#xff01;&#xff01;小编仔细阅读了比赛官方网站上…

【请求报错:javax.net.ssl.SSLHandshakeException: No appropriate protocol】

1、问题描述 在请求服务时报错说SSL握手异常协议禁用啥的&#xff0c;而且我的连接数据库的url也加了useSSLfalse javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)2、解决方法 在网上查找了方法…

LeetCode 1004.最大连续1的个数

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 硬往题目介绍上边去想的话其实非常困难&#xff0c;如果换种方式思考就会简单许多。 若我们将思想转化为&#xff0c;找出最长的子串(里面含有的0的数量最大为k)&#xff0c;然后返…

QT实现任意阶贝塞尔曲线绘制

bezier曲线在编程中的难点在于求取曲线的系数&#xff0c;如果系数确定了那么就可以用微小的直线段画出曲线。bezier曲线的系数也就是bernstein系数&#xff0c;此系数的性质可以自行百度&#xff0c;我们在这里是利用bernstein系数的递推性质求取&#xff1a; 简单举例 两个…

运维Shell脚本小试牛刀(七):在函数文脚本件中调用另外一个脚本文件中函数|函数递归调用|函数后台执行

运维Shell脚本小试牛刀(一) 运维Shell脚本小试牛刀(二) 运维Shell脚本小试牛刀(三)::$(cd $(dirname $0)&#xff1b; pwd)命令详解 运维Shell脚本小试牛刀(四): 多层嵌套if...elif...elif....else fi_蜗牛杨哥的博客-CSDN博客 Cenos7安装小火车程序动画 运维Shell脚本小试…

【扩散模型 李宏毅B站教学以及基础代码运用】

李宏毅教学视频&#xff1a; Link1 B站DDPM公式推导以及代码实现&#xff1a; Link2 这个视频里面有论文里面的公式推导&#xff0c;并且1小时10分开始讲解实例代码。 文章目录 扩散模型概念&#xff1a;Diffusion Model工作原理&#xff1a;影像生成模型本质上的共同目标B站…

算法——组合程序算法解析

组合就是从m个元素的数组中求n个元素的所有组合&#xff0c;代码如下&#xff1a; #include <iostream> #include <vector> using namespace std; // 递归求解组合 void combinations(vector<int>& nums, vector<int>& combination, int star…

Linux 安装 JDK

要在Linux上安装JDK 1&#xff0c;按照以下步骤进行操作&#xff1a; 1. 下载JDK安装文件&#xff1a;首先&#xff0c;你需要找到适用于你操作系统的JDK安装文件&#xff08;tar.gz或tar.bz2格式&#xff09;。你可以从Oracle官方网站或其他可信的来源下载该文件。 2. 解压…

Ansible自动化运维

目录 前言 一、概述 常见的开源自动化运维工具比较 二、ansible环境搭建 三、ansible模块 &#xff08;一&#xff09;、hostname模块 &#xff08;二&#xff09;、file模块 &#xff08;三&#xff09;、copy模块 &#xff08;四&#xff09;、fetch模块 &#xff…

借助各大模型的优点生成原创视频(真人人声)Plus

【技术背景】 众所周知&#xff0c;组成视频的3大元素&#xff0c;即文本语音图片。接着小编逐一介绍生成原创视频的过程。 【文本生成】 天工AI搜索&#xff08;thttp://iangong.cn&#xff09; 直接手机短信验证就可以使用&#xff0c;该大模型已经接入互联网&#xff0c…

什么是IIFE(Immediately Invoked Function Expression)?它有什么作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐IIFE 的基本语法⭐IIFE 的主要作用⭐如何使用 IIFE 来创建私有变量和模块封装⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅…

GOOGLE SRE 运维模式解读

一、SRE核心是什么 我总结下来是&#xff1a;通过软件工程的方式开发&#xff08;GOOGLE规定SRE团队必须将50%的精力花在真实的开发工作上&#xff09;一些自动化的工具系统来解放传统运维工程师大量重复和手工操作&#xff0c;从而让新生代的SRE工程师有更多的时间&#xff1…

五种定时任务方案(Timer+ScheduleExecutorService+spring task+多线程执行+quartz)

方案一&#xff1a;Timer (1)Timer.schedule(TimerTask task,Date time)安排在制定的时间执行指定的任务。 (2)Timer.schedule(TimerTask task,Date firstTime ,long period)安排指定的任务在指定的时间开始进行重复的固定延迟执行&#xff0e; (3)Timer.schedule(TimerTask…

YashanDB:潜心实干,数据库核心技术突破没有捷径可走

都说数据库是三大基础软件中的一块硬骨头&#xff0c;技术门槛高、研发周期长、工程要求高&#xff0c;市场长期被几大巨头所把持。 因此&#xff0c;实现突破一直是中国数据库产业的夙愿。自上个世纪80年代起&#xff0c;中国数据库产业走过艰辛坎坷的四十余载&#xff0c;终…

【数据结构】二叉搜索树——二叉搜索树的概念和介绍、二叉搜索树的简单实现、二叉搜索树的增删查改

文章目录 二叉搜索树1. 二叉搜索树的概念和介绍2. 二叉搜索树的简单实现2.1二叉搜索树的插入2.2二叉搜索树的查找2.3二叉搜索树的遍历2.4二叉搜索树的删除2.5完整代码和测试 二叉搜索树 1. 二叉搜索树的概念和介绍 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&…

【Spring 事务和事务传播机制】

目录 1 事务概述 1.1 为什么需要事务 1.2 事务的特性 1.3 Spring 中事务的实现 2 Spring 声明式事务 2.1 Transactional 2.2 Transactional 的作用范围 2.3 Transactional 的各种参数 2.3.1 ioslation 2.4 事务发生了异常&#xff0c;也不回滚的情况 异常被捕获时 3 事务的传…

通过 Blob 对二进制流文件下载实现文件保存下载

原理&#xff1a;前端将二进制文件做转换实现下载: 请求后端接口->接收后端返回的二进制流(通过二进制流&#xff08;Blob&#xff09;下载,把后端返回的二进制文件放在 Blob 里面)->再通过file-saver插件保存 页面上使用&#xff1a; <span click"downloadFil…