新峰商城之订单(二):订单生成

        在订单确认页面处理完毕后,此时用户单击“提交订单”按钮,商城系统就对应生成一笔订单数据并保存在数据库中,此即订单生成功能。

        在单击“提交订单”按钮后,后端会进行一系列操作,包括数据查询、数据判断、数据整合等,订单生成流程图如下所示:

一、发起订单生成请求

        在订单确认页面order-settle.html中,编写“提交订单”按钮单击事件,代码如下所示:

$('#saveOrder').click(function () {var userAddress = $(".user_address_label").html();if (userAddress == '' || userAddress == '无') {Swal.fire({text: "请填写收货信息",icon: "error",iconColor:"#f05b72",});return;}if (userAddress.trim().length < 10) {Swal.fire({text: "请输入正确的收货信息",icon: "error",iconColor:"#f05b72",});return;}window.location.href = '../saveOrder';});

        前端主要验证用户输入的信息是否正确,如果验证通过,则向saveOrder请求地址发起订单生成请求。

二、订单生成请求处理

        首先在controller包中新建OrderController类用于处理订单模块的相关请求,然后新增saveOrder()方法用于订单生成的请求,代码如下所示:

@GetMapping("/saveOrder")
public String saveOrder(HttpSession httpSession) {NewBeeMallUserVO user = (NewBeeMallUserVO) httpSession.getAttribute(Constants.MALL_USER_SESSION_KEY);List<NewBeeMallShoppingCartItemVO> myShoppingCartItems = newBeeMallShoppingCartService.getMyShoppingCartItems(user.getUserId());if (!StringUtils.hasText(user.getAddress().trim())) {//无收货地址NewBeeMallException.fail(ServiceResultEnum.NULL_ADDRESS_ERROR.getResult());}if (CollectionUtils.isEmpty(myShoppingCartItems)) {//购物车中无数据则跳转至错误页NewBeeMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());}//保存订单并返回订单号String saveOrderResult = newBeeMallOrderService.saveOrder(user, myShoppingCartItems);//跳转到订单详情页return "redirect:/orders/" + saveOrderResult;}

        此方法处理的映射地址为/saveOrder,请求方法为GET,过程如下所示:

(1)验证收货地址信息

(2)验证购物车中是否有数据

(3)将购物项数据和用户信息作为参数传递给saveOrder()方法

(4)如果订单生成成功,则返回订单号,跳转至订单详情页

    

三、订单生成逻辑的实现

        在service包中新建订单模块的业务实现类,并实现订单生成的业务逻辑,代码如下所示:

@Override
@Transactional
public String saveOrder(NewBeeMallUserVO user, List<NewBeeMallShoppingCartItemVO> myShoppingCartItems) {List<Long> itemIdList = myShoppingCartItems.stream().map(NewBeeMallShoppingCartItemVO::getCartItemId).collect(Collectors.toList());List<Long> goodsIds = myShoppingCartItems.stream().map(NewBeeMallShoppingCartItemVO::getGoodsId).collect(Collectors.toList());List<NewBeeMallGoods> newBeeMallGoods = newBeeMallGoodsMapper.selectByPrimaryKeys(goodsIds);//检查是否包含已下架商品List<NewBeeMallGoods> goodsListNotSelling = newBeeMallGoods.stream().filter(newBeeMallGoodsTemp -> newBeeMallGoodsTemp.getGoodsSellStatus() != Constants.SELL_STATUS_UP).collect(Collectors.toList());if (!CollectionUtils.isEmpty(goodsListNotSelling)) {//goodsListNotSelling 对象非空则表示有下架商品NewBeeMallException.fail(goodsListNotSelling.get(0).getGoodsName() + "已下架,无法生成订单");}Map<Long, NewBeeMallGoods> newBeeMallGoodsMap = newBeeMallGoods.stream().collect(Collectors.toMap(NewBeeMallGoods::getGoodsId, Function.identity(), (entity1, entity2) -> entity1));//判断商品库存for (NewBeeMallShoppingCartItemVO shoppingCartItemVO : myShoppingCartItems) {//查出的商品中不存在购物车中的这条关联商品数据,直接返回错误提醒if (!newBeeMallGoodsMap.containsKey(shoppingCartItemVO.getGoodsId())) {NewBeeMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());}//存在数量大于库存的情况,直接返回错误提醒if (shoppingCartItemVO.getGoodsCount() > newBeeMallGoodsMap.get(shoppingCartItemVO.getGoodsId()).getStockNum()) {NewBeeMallException.fail(ServiceResultEnum.SHOPPING_ITEM_COUNT_ERROR.getResult());}}//删除购物项if (!CollectionUtils.isEmpty(itemIdList) && !CollectionUtils.isEmpty(goodsIds) && !CollectionUtils.isEmpty(newBeeMallGoods)) {if (newBeeMallShoppingCartItemMapper.deleteBatch(itemIdList) > 0) {List<StockNumDTO> stockNumDTOS = BeanUtil.copyList(myShoppingCartItems, StockNumDTO.class);int updateStockNumResult = newBeeMallGoodsMapper.updateStockNum(stockNumDTOS);if (updateStockNumResult < 1) {NewBeeMallException.fail(ServiceResultEnum.SHOPPING_ITEM_COUNT_ERROR.getResult());}//生成订单号String orderNo = NumberUtil.genOrderNo();int priceTotal = 0;//保存订单NewBeeMallOrder newBeeMallOrder = new NewBeeMallOrder();newBeeMallOrder.setOrderNo(orderNo);newBeeMallOrder.setUserId(user.getUserId());newBeeMallOrder.setUserAddress(user.getAddress());//总价for (NewBeeMallShoppingCartItemVO newBeeMallShoppingCartItemVO : myShoppingCartItems) {priceTotal += newBeeMallShoppingCartItemVO.getGoodsCount() * newBeeMallShoppingCartItemVO.getSellingPrice();}if (priceTotal < 1) {NewBeeMallException.fail(ServiceResultEnum.ORDER_PRICE_ERROR.getResult());}newBeeMallOrder.setTotalPrice(priceTotal);//订单body字段,用来作为生成支付单描述信息,暂时未接入第三方支付接口,故该字段暂时设为空字符串String extraInfo = "";newBeeMallOrder.setExtraInfo(extraInfo);//生成订单项并保存订单项纪录if (newBeeMallOrderMapper.insertSelective(newBeeMallOrder) > 0) {//生成所有的订单项快照,并保存至数据库List<NewBeeMallOrderItem> newBeeMallOrderItems = new ArrayList<>();for (NewBeeMallShoppingCartItemVO newBeeMallShoppingCartItemVO : myShoppingCartItems) {NewBeeMallOrderItem newBeeMallOrderItem = new NewBeeMallOrderItem();//使用BeanUtil工具类将newBeeMallShoppingCartItemVO中的属性复制到newBeeMallOrderItem对象中BeanUtil.copyProperties(newBeeMallShoppingCartItemVO, newBeeMallOrderItem);//NewBeeMallOrderMapper文件insert()方法中使用了useGeneratedKeys因此orderId可以获取到newBeeMallOrderItem.setOrderId(newBeeMallOrder.getOrderId());newBeeMallOrderItems.add(newBeeMallOrderItem);}//保存至数据库if (newBeeMallOrderItemMapper.insertBatch(newBeeMallOrderItems) > 0) {//所有操作成功后,将订单号返回,以供Controller方法跳转到订单详情return orderNo;}NewBeeMallException.fail(ServiceResultEnum.ORDER_PRICE_ERROR.getResult());}NewBeeMallException.fail(ServiceResultEnum.DB_ERROR.getResult());}NewBeeMallException.fail(ServiceResultEnum.DB_ERROR.getResult());}NewBeeMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());return ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult();}

        订单生成方法先验证,再进行订单数据封装,最后将订单数据和订单项数据保存到数据库中,其     详细过程如下所示:

        (1)检查结算商品中是否包含已下架商品

        (2)判断商品数据和商品库存

        (3)对象的非空判断

        (4)生成订单后,删除相应的购物项数据

        (5)更新商品库存记录

        (6)判断订单价格

        (7)生成订单号并封装成对象,保存订单记录至数据库

        (8)封装订单项并保存至数据库

        (9)返回新订单的订单号

        在此方法中添加@Transactional注解,若执行过程中出现异常,则回滚事务。

     

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

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

相关文章

构建与优化自定义进程池

1. 什么是进程池&#xff1f; 简单来说&#xff0c;进程池就是预先创建固定数量的工作进程&#xff0c;通过设计任务队列或调度算法来分配任务给空闲的进程 —— 实现“负载均衡”。 2. 进程池框架设计 枚举错误返回值&#xff1a; enum {UsageError 1,ArgError,PipeError };…

人工智能时代的学与教

疫情逐渐散去之后&#xff0c;最最吸引全球目光的应该就是ChatGPT-3了。美国政治家亨利基辛格领衔出版的新书《AI世代与我们人类的未来》(The Age of AI and Our Human Future)中举了一个例子来说明ChatGPT-3的能力。首先让ChatGPT-3阅读关于它自身能力的哲学评论之后&#xff…

【吊打面试官系列-MySQL面试题】MyISAM 表格将在哪里存储,并且还提供其存储格式?

大家好&#xff0c;我是锋哥。今天分享关于【MyISAM 表格将在哪里存储&#xff0c;并且还提供其存储格式&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; MyISAM 表格将在哪里存储&#xff0c;并且还提供其存储格式&#xff1f; 每个 MyISAM 表格以三种格式存储…

240912-设置WSL中的Ollama可在局域网访问

A. 最终效果 B. 设置Ollama&#xff08;前提&#xff09; sudo vim /etc/systemd/system/ollama.service[Unit] DescriptionOllama Service Afternetwork-online.target[Service] ExecStart/usr/bin/ollama serve Userollama Groupollama Restartalways RestartSec3 Environme…

读取t x t文件生成exce

读取t x t文件生成excel package com.moka.api.custom.core.controller; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermode…

LangChain基础知识大全

LangChain基础知识大全 一、部署ChatGLM-6B1.拉取源码2.安装环境3.下载模型4.修改api.py配置5.运行api.py 二、Models组件1.LLM&#xff08;大语言模型&#xff09;2.Chat Model&#xff08;聊天模型&#xff09;3.Embedding Model&#xff08;嵌入模型&#xff09;3.1 下载中文…

基于Python的自然语言处理系列(16):TorchText + CNN + Teacher Forcing

在本篇文章中&#xff0c;我们将实现 卷积序列到序列学习模型&#xff08;Convolutional Sequence to Sequence Learning&#xff09;。与之前介绍的基于循环神经网络&#xff08;RNN&#xff09;的模型不同&#xff0c;卷积模型不依赖递归成分&#xff0c;而是通过卷积层&…

增强现实系列—Map-Relative Pose Regression for Visual Re-Localization

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

基于JAVA+SpringBoot+Vue的社区智慧养老监护管理平台

基于JAVASpringBootVue的社区智慧养老监护管理平台 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1…

科研绘图系列:R语言多个AUC曲线图(multiple AUC curves)

文章目录 介绍加载R包导入数据数据预处理画图输出结果组图系统信息介绍 多个ROC曲线在同一张图上可以直观地展示和比较不同模型或方法的性能。这种图通常被称为ROC曲线图,它通过比较不同模型的ROC曲线下的面积(AUC)大小来比较模型的优劣。AUC值越大,模型的诊断或预测效果越…

前后端跨域问题及其在ThinkPHP中的解决方案

在现代Web开发中&#xff0c;前后端分离的架构越来越普遍&#xff0c;但这也带来了跨域问题。跨域指的是在一个域下的网页试图请求另一个域的资源&#xff0c;浏览器出于安全考虑会限制这种行为。本文将探讨如何在ThinkPHP中解决跨域问题。 #### 1. 什么是跨域&#xff1f; 跨…

一个皮肤科医生长痘的的自救

内服 复方锌铁钙口服液 丹参瞳胶囊 盐酸米诺环素胶囊 (每天一次) 内服 外用: 克林霉素甲硝搽剂 (泛红的痘痘) 人表皮生长因子(痘印)氢醌软膏 (点阵激光留下的色沉 早晚一次) 至少用两个月【痤疮|痘痘用药 一个皮肤科医生的自救】https://www.bilibili.com/video/BV1zu41…

算法题之每日温度

每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: 输入…

java计算机毕设课设—企业车辆管理系统(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; 资源获取方式在最下方 java计算机毕设课设—企业车辆管理系统(附源码、文章、相关截图、部署视频) 企业车辆管理系统通过计算机&#xff0c;能够直接“透视”车辆使用情况&#xff0c;数据计算自动完成&#xff0c;尽量减少人工干预&#xff0c;可…

Java项目实战II基于Java+Spring Boot+MySQL的植物健康系统(开发文档+源码+数据库)

目录 目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着…

实战指南:深度剖析Servlet+JSP+JDBC技术栈下的用户CRUD操作

本博客总结基于MVC(JSPServletJDBC)操作用户信息的CRUD&#xff08;增删改查功能&#xff09;的完整小项目。包括图片上传和回显&#xff0c;模糊查询&#xff0c;过滤器的登录校验和设置全局字符集以及监听器统计在线用户人数等额外功能&#xff0c;因为代码较多&#xff0c;我…

UnLua实现继承

一、在蓝图中实现继承 1、创建父类&#xff0c;并绑定Lua脚本 2、创建子类蓝图&#xff0c;如果先创建的子类&#xff0c;可以修改父类继承 注意&#xff0c;提示选择继承父类的接口&#xff01; 二、在Lua中实现继承 1、在父类Lua脚本中实现函数 BP_CharacterBase.lua func…

构建数字化生态系统:打造数字化转型中开放协作平台的最佳实践和关键实施技巧

在数字化转型浪潮中&#xff0c;企业如何确保成功实施至关重要。除了技术上的革新&#xff0c;企业还必须在战略执行、架构优化以及合规性管理等方面掌握最佳实践。随着云计算、大数据、人工智能等新兴技术的迅速发展&#xff0c;企业通过正确的实施技巧不仅能提升业务效率&…

Qemu开发ARM篇-3、qemu运行uboot演示

文章目录 1、运行uboot2、qemu常用命令 在上一篇Qemu开发ARM篇-2、uboot交叉编译文章中&#xff0c;我们搭建了交叉编译工具链&#xff0c;并成功进行了uboot的交叉编译&#xff0c;在该篇中&#xff0c;我们将演示如何利用qemu运行上一篇中交叉编译的uboot程序。 1、运行uboo…

计算机毕业设计之:基于微信小程序的学生考勤系统的设计与实现(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…