更新了优惠券模块

This commit is contained in:
chen-xin-zhi 2025-02-10 21:59:59 +08:00
parent 84c004d40c
commit b162ce4b26
24 changed files with 902 additions and 66 deletions

View File

@ -16,9 +16,13 @@ import com.cultural.heritage.model.dto.timeperiod.TimePeriodAddRequest;
import com.cultural.heritage.model.dto.timeperiod.single.TimePeriodSingleAddRequest;
import com.cultural.heritage.model.dto.timeperiod.single.TimePeriodSingleUpdateRequest;
import com.cultural.heritage.model.entity.AppointmentDate;
import com.cultural.heritage.model.entity.Good;
import com.cultural.heritage.model.entity.PendingServiceGood;
import com.cultural.heritage.model.entity.TimePeriod;
import com.cultural.heritage.service.good.AppointmentDateService;
import com.cultural.heritage.service.good.GoodService;
import com.cultural.heritage.service.good.TimePeriodService;
import com.cultural.heritage.service.order.PendingServiceGoodService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
@ -30,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@ -48,6 +53,15 @@ public class AppointmentDateController {
private TimePeriodService timePeriodService;
@Resource
private PendingServiceGoodService pendingServiceGoodService;
@Resource
private GoodService goodService;
/**
* Web端管理员根据id删除预约日期
* @param commonRequest 预约日期id
@ -71,7 +85,16 @@ public class AppointmentDateController {
// 删除这个预约日期
boolean success = appointmentDateService.removeById(id);
ThrowUtils.throwIf(!success, ErrorCode.OPERATION_ERROR, "预约日期删除失败");
// 删除服务类商品待处理记录
QueryWrapper<PendingServiceGood> goodQueryWrapper = new QueryWrapper<>();
goodQueryWrapper.eq("appointmentDateId", id);
boolean result = pendingServiceGoodService.remove(goodQueryWrapper);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录删除失败");
return ResultUtils.success(true);
}
@ -92,6 +115,13 @@ public class AppointmentDateController {
Long id = commonRequest.getId();
boolean remove = timePeriodService.removeById(id);
ThrowUtils.throwIf(!remove, ErrorCode.OPERATION_ERROR, "预约时间段删除失败");
// 删除服务类商品待处理记录
QueryWrapper<PendingServiceGood> goodQueryWrapper = new QueryWrapper<>();
goodQueryWrapper.eq("timePeriodId", id);
boolean result = pendingServiceGoodService.remove(goodQueryWrapper);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录删除失败");
return ResultUtils.success(true);
}
@ -147,6 +177,15 @@ public class AppointmentDateController {
boolean update = timePeriodService.updateById(timePeriod);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "预约时间段人数修改失败");
// 删除服务类商品待处理记录
UpdateWrapper<PendingServiceGood> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("timePeriodId", id);
updateWrapper.set("minNumber", timePeriodSingleUpdateRequest.getMinNumber());
updateWrapper.set("maxNumber", timePeriodSingleUpdateRequest.getMaxNumber());
boolean result = pendingServiceGoodService.update(updateWrapper);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录更新失败");
return ResultUtils.success(true);
}
@ -168,6 +207,28 @@ public class AppointmentDateController {
BeanUtils.copyProperties(timePeriodSingleAddRequest, timePeriod);
boolean save = timePeriodService.save(timePeriod);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "预约时间段添加失败");
// 添加服务类商品待处理记录
PendingServiceGood pendingServiceGood = new PendingServiceGood();
BeanUtils.copyProperties(timePeriodSingleAddRequest, pendingServiceGood);
Long appointmentDateId = timePeriodSingleAddRequest.getAppointmentDateId();
AppointmentDate appointmentDate = appointmentDateService.getById(appointmentDateId);
ThrowUtils.throwIf(appointmentDate == null, ErrorCode.OPERATION_ERROR, "当前预约日期不存在");
Long goodId = appointmentDate.getGoodId();
Good good = goodService.getById(goodId);
ThrowUtils.throwIf(good == null, ErrorCode.OPERATION_ERROR, "当前服务类商品不存在");
pendingServiceGood.setGoodId(goodId);
pendingServiceGood.setGoodImg(good.getGoodImg());
pendingServiceGood.setPrice(good.getPrice());
pendingServiceGood.setTimePeriodId(timePeriod.getId());
pendingServiceGood.setReservationDate(appointmentDate.getSpecificDate());
boolean result = pendingServiceGoodService.save(pendingServiceGood);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录添加失败");
return ResultUtils.success(timePeriod.getId());
}
@ -204,6 +265,30 @@ public class AppointmentDateController {
boolean result = timePeriodService.saveBatch(timePeriodList);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "批量添加预约时间段失败");
// 批量添加服务类商品待处理记录
Long goodId = appointmentDate.getGoodId();
Good good = goodService.getById(goodId);
ThrowUtils.throwIf(good == null, ErrorCode.OPERATION_ERROR, "当前商品不存在");
List<PendingServiceGood> pendingServiceGoodList = new ArrayList<>();
for (TimePeriod timePeriod : timePeriodList) {
PendingServiceGood pendingServiceGood = new PendingServiceGood();
pendingServiceGood.setGoodId(goodId);
pendingServiceGood.setGoodImg(good.getGoodImg());
pendingServiceGood.setPrice(good.getPrice());
pendingServiceGood.setAppointmentDateId(appointmentDate.getId());
pendingServiceGood.setReservationDate(appointmentDate.getSpecificDate());
pendingServiceGood.setTimePeriodId(timePeriod.getId());
pendingServiceGood.setTimeSlot(timePeriod.getTimeSlot());
pendingServiceGood.setMinNumber(timePeriod.getMinNumber());
pendingServiceGood.setMaxNumber(timePeriod.getMaxNumber());
pendingServiceGoodList.add(pendingServiceGood);
}
boolean saveBatch = pendingServiceGoodService.saveBatch(pendingServiceGoodList);
ThrowUtils.throwIf(!saveBatch, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录批量添加失败");
return ResultUtils.success(true);
}

View File

@ -33,6 +33,7 @@ import com.cultural.heritage.model.vo.good.ServiceGoodCardVO;
import com.cultural.heritage.model.vo.good.ServiceGoodVO;
import com.cultural.heritage.model.vo.timeperiod.TimePeriodVO;
import com.cultural.heritage.service.good.*;
import com.cultural.heritage.service.order.PendingServiceGoodService;
import com.cultural.heritage.service.user.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -81,6 +82,10 @@ public class GoodController {
private CartExperienceService cartExperienceService;
@Resource
private PendingServiceGoodService pendingServiceGoodService;
/**
@ -164,6 +169,23 @@ public class GoodController {
}
boolean result = timePeriodService.saveBatch(timePeriods);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
// 批量插入服务类商品待处理记录
List<AppointmentDateTimePeriodVO> appointmentDateTimePeriodVOList = appointmentDateService.queryAppointmentDateDetailById(good.getId());
List<PendingServiceGood> pendingServiceGoodList = new ArrayList<>();
for (AppointmentDateTimePeriodVO appointmentDateTimePeriodVO : appointmentDateTimePeriodVOList) {
PendingServiceGood pendingServiceGood = new PendingServiceGood();
BeanUtils.copyProperties(appointmentDateTimePeriodVO, pendingServiceGood);
pendingServiceGood.setId(null);
pendingServiceGood.setGoodImg(good.getGoodImg());
pendingServiceGood.setPrice(good.getPrice());
pendingServiceGood.setReservationDate(appointmentDateTimePeriodVO.getSpecificDate());
pendingServiceGood.setAppointmentDateId(appointmentDateTimePeriodVO.getId());
pendingServiceGoodList.add(pendingServiceGood);
}
boolean batch = pendingServiceGoodService.saveBatch(pendingServiceGoodList);
ThrowUtils.throwIf(!batch, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录批量插入失败");
return ResultUtils.success(true);
}
@ -221,7 +243,16 @@ public class GoodController {
// 删除商品表中的服务类商品
boolean result = goodService.removeById(id);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类商品删除失败");
// 删除服务类商品待处理记录
QueryWrapper<PendingServiceGood> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("goodId", id);
boolean removeBatch = pendingServiceGoodService.remove(queryWrapper);
ThrowUtils.throwIf(!removeBatch, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录删除失败");
return ResultUtils.success(true);
}
@ -230,17 +261,18 @@ public class GoodController {
/**
* Web端用户批量删除服务类商品
* @param ids 服务类商品id列表
* @param commonBatchRequest 服务类商品id列表
* @return 是否删除成功
*/
@PostMapping("/delBatch/service")
@Operation(summary = "Web端用户批量删除服务类商品", description = "服务类商品id列表权限管理员(admin, boss)方法名delBatchServiceGoods")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
@Transactional(rollbackFor = Exception.class)
public BaseResponse<Boolean> delBatchServiceGoods(@RequestBody List<Long> ids) {
if (CollectionUtils.isEmpty(ids)) {
public BaseResponse<Boolean> delBatchServiceGoods(@RequestBody CommonBatchRequest commonBatchRequest) {
if (commonBatchRequest == null || CollectionUtils.isEmpty(commonBatchRequest.getIdList())) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
List<Long> ids = commonBatchRequest.getIdList();
//删除预约时间段表中与该商品关联的记录
QueryWrapper<AppointmentDate> queryWrapper = new QueryWrapper<>();
queryWrapper.in("goodId", ids);
@ -259,6 +291,13 @@ public class GoodController {
boolean result = goodService.removeBatchByIds(ids);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类商品删除失败");
// 批量删除服务类商品待处理记录
QueryWrapper<PendingServiceGood> goodQueryWrapper = new QueryWrapper<>();
goodQueryWrapper.in("goodId", ids);
boolean removeBatch = pendingServiceGoodService.remove(goodQueryWrapper);
ThrowUtils.throwIf(!removeBatch, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录批量删除失败");
return ResultUtils.success(true);
}
@ -612,7 +651,6 @@ public class GoodController {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Long id = commonRequest.getId();
//删除预约时间段表中与该商品关联的记录
QueryWrapper<AppointmentDate> dateQueryWrapper = new QueryWrapper<>();
dateQueryWrapper.eq("goodId", id);
@ -626,9 +664,16 @@ public class GoodController {
// 删除预约日期表中与该商品关联的记录
boolean isSuccess = appointmentDateService.remove(dateQueryWrapper);
ThrowUtils.throwIf(!isSuccess, ErrorCode.OPERATION_ERROR, "服务类商品预约日期删除失败");
// 删除服务类商品待处理记录
QueryWrapper<PendingServiceGood> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("goodId", id);
boolean removeBatch = pendingServiceGoodService.remove(queryWrapper);
ThrowUtils.throwIf(!removeBatch, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录删除失败");
}
private void dealServiceGoodAppointmentDate(ServiceGoodAddRequest serviceGoodAddRequest, Good good) {
// 添加当前商品的预约日期
List<AppointmentDateAddRequest> appointmentDateAddRequestList = serviceGoodAddRequest.getAppointmentDateAddRequestList();
@ -662,6 +707,22 @@ public class GoodController {
}
boolean result = timePeriodService.saveBatch(timePeriods);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
// 批量插入服务类商品待处理记录
List<AppointmentDateTimePeriodVO> appointmentDateTimePeriodVOList = appointmentDateService.queryAppointmentDateDetailById(good.getId());
List<PendingServiceGood> pendingServiceGoodList = new ArrayList<>();
for (AppointmentDateTimePeriodVO appointmentDateTimePeriodVO : appointmentDateTimePeriodVOList) {
PendingServiceGood pendingServiceGood = new PendingServiceGood();
BeanUtils.copyProperties(appointmentDateTimePeriodVO, pendingServiceGood);
pendingServiceGood.setId(null);
pendingServiceGood.setGoodImg(good.getGoodImg());
pendingServiceGood.setPrice(good.getPrice());
pendingServiceGood.setReservationDate(appointmentDateTimePeriodVO.getSpecificDate());
pendingServiceGood.setAppointmentDateId(appointmentDateTimePeriodVO.getId());
pendingServiceGoodList.add(pendingServiceGood);
}
boolean batch = pendingServiceGoodService.saveBatch(pendingServiceGoodList);
ThrowUtils.throwIf(!batch, ErrorCode.OPERATION_ERROR, "服务类商品待处理记录批量插入失败");
}

View File

@ -258,6 +258,10 @@ public class OrderController {
/**
* 小程序端用户查询订单
* @return 用户订单列表

View File

@ -0,0 +1,101 @@
package com.cultural.heritage.controller.order;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cultural.heritage.annotation.AuthCheck;
import com.cultural.heritage.common.BaseResponse;
import com.cultural.heritage.common.ErrorCode;
import com.cultural.heritage.common.ResultUtils;
import com.cultural.heritage.constant.UserConstant;
import com.cultural.heritage.exception.BusinessException;
import com.cultural.heritage.model.dto.order.BookingOrderQueryRequest;
import com.cultural.heritage.model.entity.PendingServiceGood;
import com.cultural.heritage.model.entity.PendingServiceOrder;
import com.cultural.heritage.model.vo.order.PendingServiceGoodVO;
import com.cultural.heritage.model.vo.order.PendingServiceOrderVO;
import com.cultural.heritage.service.order.PendingServiceGoodService;
import com.cultural.heritage.service.order.PendingServiceOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/pending")
@Slf4j
@Tag(name = "待处理商品管理模块")
@Transactional(rollbackFor = Exception.class)
public class PendingServiceGoodController {
@Resource
private PendingServiceGoodService pendingServiceGoodService;
@Resource
private PendingServiceOrderService pendingServiceOrderService;
/**
* Web端管理员查询预约情况
* @param bookingOrderQueryRequest 服务类商品预约情况查询请求体
* @return 服务类商品预约情况列表
*/
@PostMapping("/list/advance/detail")
@Operation(summary = "Web端管理员查询预约情况", description = "参数:订单查询请求体,权限:管理员(admin, boss)方法名listOrder")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<List<PendingServiceGoodVO>> listBookingOrderDetail(@RequestBody BookingOrderQueryRequest bookingOrderQueryRequest) {
if (bookingOrderQueryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
QueryWrapper<PendingServiceGood> queryWrapper = pendingServiceGoodService.getQueryWrapper(bookingOrderQueryRequest);
List<PendingServiceGood> pendingServiceGoodList = pendingServiceGoodService.list(queryWrapper);
List<Long> pendingGoodIds = pendingServiceGoodList.stream().map(PendingServiceGood::getId).toList();
QueryWrapper<PendingServiceOrder> orderQueryWrapper = new QueryWrapper<>();
orderQueryWrapper.in("pendingId", pendingGoodIds);
List<PendingServiceOrder> pendingServiceOrderList = pendingServiceOrderService.list(orderQueryWrapper);
List<PendingServiceOrderVO> pendingServiceOrderVOS = pendingServiceOrderList.stream().map(pendingServiceOrder -> {
PendingServiceOrderVO pendingServiceOrderVO = new PendingServiceOrderVO();
BeanUtils.copyProperties(pendingServiceOrder, pendingServiceOrderVO);
return pendingServiceOrderVO;
}).toList();
// 封装map集合服务类商品待处理id待处理服务类订单列表
Map<Long, List<PendingServiceOrderVO>> map = new HashMap<>();
for (PendingServiceOrderVO pendingServiceOrderVO : pendingServiceOrderVOS) {
Long pendingId = pendingServiceOrderVO.getPendingId();
List<PendingServiceOrderVO> pendingServiceOrderVOList = map.get(pendingId);
if (pendingServiceOrderVOList == null) {
pendingServiceOrderVOList = new ArrayList<>();
}
pendingServiceOrderVOList.add(pendingServiceOrderVO);
map.put(pendingId, pendingServiceOrderVOList);
}
List<PendingServiceGoodVO> pendingServiceGoodVOList = pendingServiceGoodList.stream().map(pendingServiceGood -> {
PendingServiceGoodVO pendingServiceGoodVO = new PendingServiceGoodVO();
BeanUtils.copyProperties(pendingServiceGood, pendingServiceGoodVO);
Long goodId = pendingServiceGood.getId();
List<PendingServiceOrderVO> pendingServiceOrderVOList = map.get(goodId);
pendingServiceGoodVO.setPendingServiceOrderVOList(pendingServiceOrderVOList);
return pendingServiceGoodVO;
}).toList();
return ResultUtils.success(pendingServiceGoodVOList);
}
}

View File

@ -72,6 +72,7 @@ public class WeChatPayController {
return ResultUtils.success(response);
}
/**
* JSAPI 下单回调
*/
@ -87,8 +88,10 @@ public class WeChatPayController {
return ResultUtils.success(true);
}
/**
* 退款仅管理员
* Web端管理员全额退款
* @param commonRequest 订单id
*/
@PostMapping("/refund/create")
@ -106,7 +109,7 @@ public class WeChatPayController {
/**
* Web管理员退款订单明细
* Web管理员部分退款
* @param commonRequest 订单明细id
*/
@PostMapping("/refund/part/create")
@ -125,7 +128,7 @@ public class WeChatPayController {
/**
* 退款回调
* 全额退款回调
*/
@PostMapping("/refund/callback")
public BaseResponse<Boolean> callbackRefund(HttpServletRequest request) {
@ -137,15 +140,30 @@ public class WeChatPayController {
return ResultUtils.success(true);
}
/**
* 发送订阅消息
* 部分退款回调
*/
@GetMapping("/refund/callback")
public BaseResponse<Boolean> testSendMessage() {
String miniOpenId = "oydCP7TGAWUqN_d0g3y6bbQkbe2I";
String templateId = "AJqdU29ETU1kzBGzXaxA-OVs5AvGY1s4xaSJY1JNaiE";
boolean subscribeMessage = weChatService.sendSubscribeMessage(miniOpenId, templateId);
return ResultUtils.success(subscribeMessage);
@PostMapping("/refund/part/callback")
public BaseResponse<Boolean> callbackRefundPart(HttpServletRequest request) {
// 获取退款信息
RefundNotification refundNotification = weChatService.getRefundInfo(request);
// 退款回调
boolean result = weChatService.refundPartCallback(refundNotification);
ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR, "退款回调失败");
return ResultUtils.success(true);
}
// /**
// * 发送订阅消息
// */
// @GetMapping("/refund/callback")
// public BaseResponse<Boolean> testSendMessage() {
// String miniOpenId = "oydCP7TGAWUqN_d0g3y6bbQkbe2I";
// String templateId = "AJqdU29ETU1kzBGzXaxA-OVs5AvGY1s4xaSJY1JNaiE";
// boolean subscribeMessage = weChatService.sendSubscribeMessage(miniOpenId, templateId);
// return ResultUtils.success(subscribeMessage);
// }
}

View File

@ -0,0 +1,7 @@
package com.cultural.heritage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cultural.heritage.model.entity.PendingServiceGood;
public interface PendingServiceGoodMapper extends BaseMapper<PendingServiceGood> {
}

View File

@ -0,0 +1,7 @@
package com.cultural.heritage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cultural.heritage.model.entity.PendingServiceOrder;
public interface PendingServiceOrderMapper extends BaseMapper<PendingServiceOrder> {
}

View File

@ -0,0 +1,37 @@
package com.cultural.heritage.model.dto.order;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "服务类商品预约情况查询请求体", requiredProperties = {"goodId", "quantity"})
public class BookingOrderQueryRequest implements Serializable {
/**
* 商品id
*/
private Long goodId;
/**
* 预约日期
*/
private String reservationDate;
/**
* 预约时间段
*/
private String timeSlot;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,93 @@
package com.cultural.heritage.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 待处理服务类商品表
* @TableName pending_service_good
*/
@Data
@TableName(value = "pending_service_good")
public class PendingServiceGood implements Serializable {
/**
* 服务类商品待处理id
*/
private Long id;
/**
* 商品id
*/
private Long goodId;
/**
* 商品图片
*/
private String goodImg;
/**
* 商品价格
*/
private BigDecimal price;
/**
* 预约日期id
*/
private Long appointmentDateId;
/**
* 预约时间段id
*/
private Long timePeriodId;
/**
* 预约日期
*/
private String reservationDate;
/**
* 预约时间段
*/
private String timeSlot;
/**
* 最小预约人数
*/
private Integer minNumber;
/**
* 最大预约人数
*/
private Integer maxNumber;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,98 @@
package com.cultural.heritage.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 待处理服务类订单表
* @TableName pending_service_order
*/
@Data
@TableName(value = "pending_service_order")
public class PendingServiceOrder implements Serializable {
/**
* 服务类订单待处理id
*/
private Long id;
/**
* 订单明细id
*/
private Long orderItemId;
/**
* 订单号
*/
private String orderNumber;
/**
* 用户id
*/
private Long userId;
/**
* 用户姓名
*/
private String name;
/**
* 手机号
*/
private String phone;
/**
* 购买数量
*/
private Integer quantity;
/**
* 预估支付金额
*/
private BigDecimal itemTotalAmount;
/**
* 订单明细状态
*/
private String orderItemStatus;
/**
* 服务类商品待处理id
*/
private Long pendingId;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 是否删除
*/
private Integer isDelete;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -39,6 +39,7 @@ public class RefundRecord implements Serializable {
private String outRefundNo;
/**
* 退款金额
*/

View File

@ -0,0 +1,69 @@
package com.cultural.heritage.model.vo.order;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
public class PendingServiceGoodVO implements Serializable {
/**
* 服务类商品待处理id
*/
private Long id;
/**
* 商品id
*/
private Long goodId;
/**
* 商品图片
*/
private String goodImg;
/**
* 商品价格
*/
private BigDecimal price;
/**
* 预约日期
*/
private String reservationDate;
/**
* 预约时间段
*/
private String timeSlot;
/**
* 最小预约人数
*/
private Integer minNumber;
/**
* 最大预约人数
*/
private Integer maxNumber;
/**
* 订单预约情况
*/
private List<PendingServiceOrderVO> pendingServiceOrderVOList;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,77 @@
package com.cultural.heritage.model.vo.order;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class PendingServiceOrderVO implements Serializable {
/**
* 服务类订单待处理id
*/
private Long id;
/**
* 订单明细id
*/
private Long orderItemId;
/**
* 订单号
*/
private String orderNumber;
/**
* 用户id
*/
private Long userId;
/**
* 用户姓名
*/
private String name;
/**
* 手机号
*/
private String phone;
/**
* 购买数量
*/
private Integer quantity;
/**
* 预估支付金额
*/
private BigDecimal itemTotalAmount;
/**
* 订单明细状态
*/
private String orderItemStatus;
/**
* 服务类商品待处理id
*/
private Long pendingId;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -24,4 +24,5 @@ public interface AppointmentDateService extends IService<AppointmentDate> {
* (多表联查)根据id查询商品的预约情况
*/
List<AppointmentDateTimePeriodVO> queryAppointmentDateDetailById(Long goodId);
}

View File

@ -42,4 +42,5 @@ public interface GoodService extends IService<Good> {
List<CartExperience> updateCartExperienceGoodPrice(Long goodId, BigDecimal targetPrice);
}

View File

@ -9,6 +9,7 @@ import com.cultural.heritage.mapper.CartExperienceMapper;
import com.cultural.heritage.mapper.CartRecordMapper;
import com.cultural.heritage.mapper.GoodMapper;
import com.cultural.heritage.model.dto.good.GoodQueryRequest;
import com.cultural.heritage.model.dto.order.BookingOrderQueryRequest;
import com.cultural.heritage.model.entity.CartExperience;
import com.cultural.heritage.model.entity.CartRecord;
import com.cultural.heritage.model.entity.Good;
@ -156,4 +157,6 @@ public class GoodServiceImpl extends ServiceImpl<GoodMapper, Good> implements Go
}
}

View File

@ -0,0 +1,15 @@
package com.cultural.heritage.service.order;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cultural.heritage.model.dto.order.BookingOrderQueryRequest;
import com.cultural.heritage.model.entity.PendingServiceGood;
public interface PendingServiceGoodService extends IService<PendingServiceGood> {
/**
* 获取待处理商品查询条件
*/
QueryWrapper<PendingServiceGood> getQueryWrapper(BookingOrderQueryRequest bookingOrderQueryRequest);
}

View File

@ -0,0 +1,7 @@
package com.cultural.heritage.service.order;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cultural.heritage.model.entity.PendingServiceOrder;
public interface PendingServiceOrderService extends IService<PendingServiceOrder> {
}

View File

@ -0,0 +1,33 @@
package com.cultural.heritage.service.order.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cultural.heritage.mapper.PendingServiceGoodMapper;
import com.cultural.heritage.model.dto.order.BookingOrderQueryRequest;
import com.cultural.heritage.model.entity.PendingServiceGood;
import com.cultural.heritage.service.order.PendingServiceGoodService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@Service
public class PendingServiceGoodServiceImpl extends ServiceImpl<PendingServiceGoodMapper, PendingServiceGood> implements PendingServiceGoodService {
/**
* 获取待处理商品查询条件
*/
@Override
public QueryWrapper<PendingServiceGood> getQueryWrapper(BookingOrderQueryRequest bookingOrderQueryRequest) {
Long goodId = bookingOrderQueryRequest.getGoodId();
String reservationDate = bookingOrderQueryRequest.getReservationDate();
String timeSlot = bookingOrderQueryRequest.getTimeSlot();
QueryWrapper<PendingServiceGood> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(ObjectUtils.isNotEmpty(goodId), "goodId", goodId);
queryWrapper.eq(StringUtils.isNotBlank(reservationDate), "reservationDate", reservationDate);
queryWrapper.eq(StringUtils.isNotBlank(timeSlot), "timeSlot", timeSlot);
return queryWrapper;
}
}

View File

@ -0,0 +1,11 @@
package com.cultural.heritage.service.order.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cultural.heritage.mapper.PendingServiceOrderMapper;
import com.cultural.heritage.model.entity.PendingServiceOrder;
import com.cultural.heritage.service.order.PendingServiceOrderService;
import org.springframework.stereotype.Service;
@Service
public class PendingServiceOrderServiceImpl extends ServiceImpl<PendingServiceOrderMapper, PendingServiceOrder> implements PendingServiceOrderService {
}

View File

@ -31,12 +31,12 @@ public interface WeChatService {
boolean paymentCallback(Transaction transaction) throws IOException;
/**
* 退款申请
* 全额退款申请
*/
Refund refundPayment(String orderId, BigDecimal amount);
/**
* 退款申请
* 部分退款申请
*/
Refund refundPartPayment(String orderItemsId, BigDecimal amount);
@ -51,8 +51,13 @@ public interface WeChatService {
boolean refundCallback(RefundNotification refundNotification);
/**
* 发送订阅模板消息
* 部分退款回调
*/
boolean sendSubscribeMessage(String openid, String templateId);
boolean refundPartCallback(RefundNotification refundNotification);
// /**
// * 发送订阅模板消息
// */
// boolean sendSubscribeMessage(String openid, String templateId);
}

View File

@ -1,9 +1,6 @@
package com.cultural.heritage.service.wx.impl;
import cn.binarywang.wx.miniapp.api.WxMaMsgService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cultural.heritage.common.ErrorCode;
@ -12,15 +9,14 @@ import com.cultural.heritage.config.WxPayConfig;
import com.cultural.heritage.constant.OrderStatusConstant;
import com.cultural.heritage.exception.BusinessException;
import com.cultural.heritage.exception.ThrowUtils;
import com.cultural.heritage.model.dto.order.BookingOrderQueryRequest;
import com.cultural.heritage.model.dto.snapshot.CouponSnapshot;
import com.cultural.heritage.model.dto.snapshot.GoodSnapshot;
import com.cultural.heritage.model.entity.Good;
import com.cultural.heritage.model.entity.Order;
import com.cultural.heritage.model.entity.OrderItems;
import com.cultural.heritage.model.entity.*;
import com.cultural.heritage.model.enums.GoodTypeEnum;
import com.cultural.heritage.service.good.AppointmentDateService;
import com.cultural.heritage.service.good.GoodService;
import com.cultural.heritage.service.order.OrderItemService;
import com.cultural.heritage.service.order.OrderService;
import com.cultural.heritage.service.order.RefundRecordService;
import com.cultural.heritage.service.order.*;
import com.cultural.heritage.service.wx.WeChatService;
import com.cultural.heritage.utils.RefundUtils;
import com.wechat.pay.java.core.notification.NotificationParser;
@ -38,6 +34,7 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -74,12 +71,25 @@ public class WeChatServiceImpl implements WeChatService {
@Resource
private RefundRecordService refundRecordService;
@Resource
private AppointmentDateService appointmentDateService;
@Resource
private PendingServiceGoodService pendingServiceGoodService;
@Resource
private PendingServiceOrderService pendingServiceOrderService;
/**
* 请求参数
*/
public static RequestParam requestParam = null;
/**
* 微信支付
*/
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized PrepayWithRequestPaymentResponse createPayment(String orderId, String miniOpenId, BigDecimal amount) {
@ -111,12 +121,21 @@ public class WeChatServiceImpl implements WeChatService {
return wxPayConfig.getJsapiServiceExtension().prepayWithRequestPayment(request);
}
/**
* 获取支付回调信息
*/
@Override
public Transaction getTransactionInfo(HttpServletRequest request) {
NotificationParser notificationParser = getNotificationParser(request);
return notificationParser.parse(requestParam, Transaction.class);
}
/**
* 支付回调
*/
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized boolean paymentCallback(Transaction transaction) {
@ -136,10 +155,54 @@ public class WeChatServiceImpl implements WeChatService {
boolean update = orderService.updateById(order);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "订单状态修改失败");
// 生成服务类订单待处理记录
GoodTypeEnum goodTypeEnum = GoodTypeEnum.getEnumByValue(order.getOrderType());
if (GoodTypeEnum.SERVICE.equals(goodTypeEnum)) {
// 封装map集合服务类商品待处理id, 服务类商品待处理记录
Map<String, PendingServiceGood> pendingGoodMap = new HashMap<>();
List<PendingServiceGood> pendingServiceGoodList = pendingServiceGoodService.list();
for (PendingServiceGood pendingServiceGood : pendingServiceGoodList) {
BookingOrderQueryRequest bookingOrderQueryRequest = new BookingOrderQueryRequest();
BeanUtils.copyProperties(pendingServiceGood, bookingOrderQueryRequest);
pendingGoodMap.put(bookingOrderQueryRequest.toString(), pendingServiceGood);
}
QueryWrapper<OrderItems> orderItemsQueryWrapper = new QueryWrapper<>();
orderItemsQueryWrapper.eq("orderId", order.getId());
List<OrderItems> orderItemsList = orderItemService.list(orderItemsQueryWrapper);
List<PendingServiceOrder> pendingServiceOrderList = new ArrayList<>();
for (OrderItems orderItems : orderItemsList) {
PendingServiceOrder pendingServiceOrder = new PendingServiceOrder();
pendingServiceOrder.setOrderItemId(orderItems.getId());
pendingServiceOrder.setOrderNumber(order.getOrderNumber());
pendingServiceOrder.setUserId(order.getUserId());
pendingServiceOrder.setName(order.getContactsSnapshot().getName());
pendingServiceOrder.setPhone(order.getContactsSnapshot().getPhone());
pendingServiceOrder.setQuantity(orderItems.getQuantity());
pendingServiceOrder.setItemTotalAmount(orderItems.getItemTotalAmount());
pendingServiceOrder.setOrderItemStatus(order.getOrderStatus());
BookingOrderQueryRequest bookingOrderQueryRequest = new BookingOrderQueryRequest(orderItems.getGoodSnapshot().getId(), orderItems.getReservationDate(), orderItems.getTimeSlot());
PendingServiceGood pendingServiceGood = pendingGoodMap.get(bookingOrderQueryRequest.toString());
pendingServiceOrder.setPendingId(pendingServiceGood.getId());
pendingServiceOrderList.add(pendingServiceOrder);
}
boolean saveBatch = pendingServiceOrderService.saveBatch(pendingServiceOrderList);
ThrowUtils.throwIf(!saveBatch, ErrorCode.OPERATION_ERROR, "服务类订单待处理记录批量生成失败");
}
System.out.println("---------------------------微信支付回调(结束)-------------------------------");
return true;
}
/**
* 全额退款
*/
@Override
public Refund refundPayment(String orderId, BigDecimal amount) {
// 获取订单号
@ -171,6 +234,9 @@ public class WeChatServiceImpl implements WeChatService {
}
/**
* 部分退款
*/
@Override
public Refund refundPartPayment(String orderItemsId, BigDecimal amount) {
// 获取订单明细
@ -212,10 +278,14 @@ public class WeChatServiceImpl implements WeChatService {
System.out.println("退款请求:" + createRequest);
Refund refund = wxPayConfig.getRefundService().create(createRequest);
System.out.println("退款申请结果:" + refund);
return refund;
}
/**
* 获取退款回调信息
*/
@Override
public RefundNotification getRefundInfo(HttpServletRequest request) {
NotificationParser notificationParser = getNotificationParser(request);
@ -223,7 +293,9 @@ public class WeChatServiceImpl implements WeChatService {
}
/**
* 全额退款回调
*/
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized boolean refundCallback(RefundNotification refundNotification) {
@ -244,6 +316,8 @@ public class WeChatServiceImpl implements WeChatService {
boolean update = orderService.updateById(order);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "订单状态修改失败");
// 生成退款记录
// 恢复商品库存
QueryWrapper<OrderItems> orderItemsQueryWrapper = new QueryWrapper<>();
orderItemsQueryWrapper.eq("orderId", order.getId());
@ -283,49 +357,63 @@ public class WeChatServiceImpl implements WeChatService {
return true;
}
@Override
public boolean sendSubscribeMessage(String openid, String templateId) {
try {
// 获取小程序对象
WxMaService wxMaService = wxOpenConfig.getWxMaService();
// 获取消息接口
WxMaMsgService msgService = wxMaService.getMsgService();
// 构建订阅消息体
WxMaSubscribeMessage wxMaSubscribeMessage = new WxMaSubscribeMessage();
wxMaSubscribeMessage.setToUser(openid);
wxMaSubscribeMessage.setTemplateId(templateId);
List<WxMaSubscribeMessage.MsgData> msgDataList = getMsgData();
wxMaSubscribeMessage.setData(msgDataList);
// 发送消息
msgService.sendSubscribeMsg(wxMaSubscribeMessage);
return true;
} catch (Exception e) {
log.error("发送订阅消息失败:", e);
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "发送订阅消息失败");
}
}
/**
* 提取消息数据
* 部分退款回调
*/
private static List<WxMaSubscribeMessage.MsgData> getMsgData() {
List<WxMaSubscribeMessage.MsgData> msgDataList = new ArrayList<>();
String[][] dataItems = {
{"character_string1", "2022060215050983711"},
{"time2", "2022-06-22 15:48:05"},
{"thing3", "测试店"},
{"amount4", "99999元"},
{"thing5", "收款到账,请查看"}
};
for (String[] item : dataItems) {
WxMaSubscribeMessage.MsgData msgData = new WxMaSubscribeMessage.MsgData();
msgData.setName(item[0]);
msgData.setValue(item[1]);
msgDataList.add(msgData);
}
return msgDataList;
@Override
public boolean refundPartCallback(RefundNotification refundNotification) {
return false;
}
//
// @Override
// public boolean sendSubscribeMessage(String openid, String templateId) {
// try {
// // 获取小程序对象
// WxMaService wxMaService = wxOpenConfig.getWxMaService();
// // 获取消息接口
// WxMaMsgService msgService = wxMaService.getMsgService();
// // 构建订阅消息体
// WxMaSubscribeMessage wxMaSubscribeMessage = new WxMaSubscribeMessage();
// wxMaSubscribeMessage.setToUser(openid);
// wxMaSubscribeMessage.setTemplateId(templateId);
// List<WxMaSubscribeMessage.MsgData> msgDataList = getMsgData();
// wxMaSubscribeMessage.setData(msgDataList);
// // 发送消息
// msgService.sendSubscribeMsg(wxMaSubscribeMessage);
// return true;
// } catch (Exception e) {
// log.error("发送订阅消息失败:", e);
// throw new BusinessException(ErrorCode.SYSTEM_ERROR, "发送订阅消息失败");
// }
// }
// /**
// * 提取消息数据
// */
// private static List<WxMaSubscribeMessage.MsgData> getMsgData() {
// List<WxMaSubscribeMessage.MsgData> msgDataList = new ArrayList<>();
// String[][] dataItems = {
// {"character_string1", "2022060215050983711"},
// {"time2", "2022-06-22 15:48:05"},
// {"thing3", "测试店"},
// {"amount4", "99999元"},
// {"thing5", "收款到账,请查看"}
// };
// for (String[] item : dataItems) {
// WxMaSubscribeMessage.MsgData msgData = new WxMaSubscribeMessage.MsgData();
// msgData.setName(item[0]);
// msgData.setValue(item[1]);
// msgDataList.add(msgData);
// }
// return msgDataList;
// }
/**
* 根据微信官方发送的请求获取信息
*/

View File

@ -0,0 +1,7 @@
<?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.cultural.heritage.mapper.PendingServiceGoodMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?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.cultural.heritage.mapper.PendingServiceOrderMapper">
</mapper>