今天继续来一个简单清晰的业务逻辑开发!
业务:取消订单(管理端)
业务规则:
-
取消订单其实就是将订单状态修改为“已取消”
-
商家取消订单时需要指定取消原因
-
商家取消订单时,如果用户已经完成了支付,需要为用户退款
接口设计:
基本信息:Path:/admin/order/cancel
Method:PUT
请求参数:无
代码实现:
DTO类,可以简单当做一个实体类,这个只是准确地根据数据库进行比较严格的封装。
OrdersCancelDTO
@Data public class OrdersCancelDTO implements Serializable { private Long id; //订单取消原因 private String cancelReason; }
@Data注解就不用多说了,省略了get,set...等方法的啰嗦写法。纯属正常实体类的书写。
Controller类:
OrderController
/** * 取消订单 * * @return */ @PutMapping("/cancel") @ApiOperation("取消订单") public Result cancel(@RequestBody OrdersCancelDTO ordersCancelDTO) throws Exception { orderService.cancel(ordersCancelDTO); return Result.success(); }
到了日常开始的控制层,这里cancel内部用来接收取消订单的整个实体对象,然后对其进行取消处理。上面也提到,取消订单就是修改其状态罢了,先对其进行封装接收,再对其进行修改。
service接口层:
OrderService
/** * 商家取消订单 * * @param ordersCancelDTO */ void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception;
接着就是服务层,这个就不说了,很常规的创建方法。
实现类:
OrderServiceImpl
/** * 取消订单 * * @param ordersCancelDTO */ public void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception { // 根据id查询订单 Orders ordersDB = orderMapper.getById(ordersCancelDTO.getId()); //支付状态 Integer payStatus = ordersDB.getPayStatus(); if (payStatus == 1) { //用户已支付,需要退款 String refund = weChatPayUtil.refund( ordersDB.getNumber(), ordersDB.getNumber(), new BigDecimal(0.01), new BigDecimal(0.01)); log.info("申请退款:{}", refund); } // 管理端取消订单需要退款,根据订单id更新订单状态、取消原因、取消时间 Orders orders = new Orders(); orders.setId(ordersCancelDTO.getId()); orders.setStatus(Orders.CANCELLED); orders.setCancelReason(ordersCancelDTO.getCancelReason()); orders.setCancelTime(LocalDateTime.now()); orderMapper.update(orders); }
这里来实现接口层创建的方法,里面的操作自己可以去理解理解,其中用到了两个逻辑方法,getById()和update(),都在持久层mapper中进行扩展。
持久层mapper:
OrderMapper
/** * 根据id查询订单 * @param id * @return */ @Select("select * from orders where id = #{id};") Orders getById(Long id); /** * 修改订单信息 * @param orders */ void update(Orders orders);
这里就是对上面两个方法进行实现,可以看到,之前发的文章中提到的简单的sql语句和复杂的动态sql语句,在这里都体现出来了,getById()简单的编写出来,二update()则在下面的XML映射文件中进行编写。
XML映射文件:
OrderMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.sky.mapper.OrderMapper"> <update id="update" parameterType="com.sky.entity.Orders"> update orders <set> <if test="cancelReason != null and cancelReason!='' "> cancel_reason=#{cancelReason}, </if> <if test="rejectionReason != null and rejectionReason!='' "> rejection_reason=#{rejectionReason}, </if> <if test="cancelTime != null"> cancel_time=#{cancelTime}, </if> <if test="payStatus != null"> pay_status=#{payStatus}, </if> <if test="payMethod != null"> pay_method=#{payMethod}, </if> <if test="checkoutTime != null"> checkout_time=#{checkoutTime}, </if> <if test="status != null"> status = #{status}, </if> <if test="deliveryTime != null"> delivery_time = #{deliveryTime} </if> </set> where id = #{id} </update> </mapper>
到这里,可以理解为什么要在xml单独写sql了吧,因为有写动态sql确实很复杂,总不能都写在mapper层里面或service层里面吧!
今天,就到这里了!
👍