diff --git a/src/main/java/com/cultural/heritage/constant/OrderStatusConstant.java b/src/main/java/com/cultural/heritage/constant/OrderStatusConstant.java index eeb9258..59a2819 100644 --- a/src/main/java/com/cultural/heritage/constant/OrderStatusConstant.java +++ b/src/main/java/com/cultural/heritage/constant/OrderStatusConstant.java @@ -21,4 +21,6 @@ public interface OrderStatusConstant { String PAYMENT_REFUNDED = "已退款"; + + } diff --git a/src/main/java/com/cultural/heritage/controller/good/CartExperienceController.java b/src/main/java/com/cultural/heritage/controller/good/CartExperienceController.java index 90114f4..f260157 100644 --- a/src/main/java/com/cultural/heritage/controller/good/CartExperienceController.java +++ b/src/main/java/com/cultural/heritage/controller/good/CartExperienceController.java @@ -1,7 +1,6 @@ package com.cultural.heritage.controller.good; -import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.cultural.heritage.common.BaseResponse; import com.cultural.heritage.common.ErrorCode; @@ -12,14 +11,14 @@ import com.cultural.heritage.model.dto.CommonBatchRequest; import com.cultural.heritage.model.dto.cartService.CartExperienceAddRequest; import com.cultural.heritage.model.dto.cartService.CartExperienceUpdateRequest; import com.cultural.heritage.model.dto.order.BuySingleServiceGoodVerifyRequest; -import com.cultural.heritage.model.entity.CartExperience; -import com.cultural.heritage.model.entity.Good; -import com.cultural.heritage.model.entity.User; +import com.cultural.heritage.model.entity.*; import com.cultural.heritage.model.vo.cartService.CartExperienceGoodVO; import com.cultural.heritage.model.vo.cartService.CartExperienceOrderVO; import com.cultural.heritage.model.vo.cartService.CartExperienceVO; +import com.cultural.heritage.service.common.CommonService; import com.cultural.heritage.service.good.CartExperienceService; import com.cultural.heritage.service.good.GoodService; +import com.cultural.heritage.service.order.PendingServiceOrderService; import com.cultural.heritage.service.user.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -55,6 +54,15 @@ public class CartExperienceController { private UserService userService; + @Resource + private CommonService commonService; + + + @Resource + private PendingServiceOrderService pendingServiceOrderService; + + + /** * 小程序端用户添加服务类商品至购物车 @@ -86,11 +94,8 @@ public class CartExperienceController { } userService.getLoginUser(request); - // 获取购物车id列表 - List cartIds = cartExperienceUpdateRequestList.stream().map(CartExperienceUpdateRequest::getId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", cartIds); - List cartExperienceList = cartExperienceService.list(queryWrapper); + // 获取服务类购物车商品列表 + List cartExperienceList = commonService.getItemsByIds(cartExperienceUpdateRequestList, cartExperienceService, CartExperienceUpdateRequest::getId); // 封装map集合(键:购物车id, 值:商品数量) Map QuantityMap = new HashMap<>(); @@ -108,11 +113,8 @@ public class CartExperienceController { timeSlotMap.put(id, timeSlot); } - // 获取商品id列表 - List goodIds = cartExperienceList.stream().map(CartExperience::getGoodId).toList(); - QueryWrapper goodQueryWrapper = new QueryWrapper<>(); - goodQueryWrapper.in("id", goodIds); - List goodList = goodService.list(goodQueryWrapper); + // 获取商品列表 + List goodList = commonService.getItemsByIds(cartExperienceList, goodService, CartExperience::getGoodId); // 封装map集合(键:商品id, 值:商品价格) Map priceMap = new HashMap<>(); @@ -219,18 +221,11 @@ public class CartExperienceController { } userService.getLoginUser(request); List cartExperienceIds = commonBatchRequest.getIdList(); - List cartExperienceList = cartExperienceService.list(); - // 获取购物车列表信息 - List cartExperiences = cartExperienceList.stream().filter(cartExperience -> { - Long id = cartExperience.getId(); - return cartExperienceIds.contains(id); - }).toList(); + // 获取购物车信息列表 + List cartExperiences = commonService.getListByIds(cartExperienceIds, cartExperienceService); - // 提取出购物车中的商品id列表 - List goodIds = cartExperiences.stream().map(CartExperience::getGoodId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", goodIds); - List goodList = goodService.list(queryWrapper); + // 获取购物车中的商品列表 + List goodList = commonService.getItemsByIds(cartExperiences, goodService, CartExperience::getGoodId); // 封装goodMap(根据商品id查询商品) Map goodMap = new HashMap<>(); @@ -238,6 +233,22 @@ public class CartExperienceController { goodMap.put(good.getId(), good); } + // 校验购物车商品 + Map pendingServiceGoodMap = goodService.getPendingServiceGoodMap(); + List pendingServiceOrderList = pendingServiceOrderService.list(); + for (CartExperience cartExperience : cartExperiences) { + Long goodId = cartExperience.getGoodId(); + String reservationDate = cartExperience.getReservationDate(); + String timeSlot = cartExperience.getTimeSlot(); + Integer quantity = cartExperience.getQuantity(); + Good good = goodMap.get(goodId); + // 判断商品是否存在或者下架 + goodService.checkGoodIsExist(good); + // 校验购买的服务类购物车中的商品预约情况是否合理 + goodService.checkServiceGoodCartBookingDetailIsProperly(goodId, reservationDate, timeSlot, quantity, pendingServiceGoodMap, pendingServiceOrderList); + } + + // 封装提交订单页的商品信息列表 List cartOrderVOList = new ArrayList<>(); for (CartExperience cartExperience : cartExperiences) { @@ -276,22 +287,16 @@ public class CartExperienceController { } userService.getLoginUser(request); Long goodId = buySingleServiceGoodVerifyRequest.getGoodId(); + // 校验商品是否存在或者下架 Good good = goodService.getById(goodId); - ThrowUtils.throwIf(good == null || good.getIsShelves() == 0, ErrorCode.SYSTEM_ERROR, "商品已下架或不存在"); + goodService.checkGoodIsExist(good); String reservationDate = buySingleServiceGoodVerifyRequest.getReservationDate(); String timeSlot = buySingleServiceGoodVerifyRequest.getTimeSlot(); + Integer quantity = buySingleServiceGoodVerifyRequest.getQuantity(); - String startTime = timeSlot.split("-")[0]; - String advanceDateTimeStr = reservationDate + " " + startTime + ":00"; - String currentDateTimeStr = DateUtil.now(); - - Date advanceDateTime = DateUtil.parse(advanceDateTimeStr, "yyyy-MM-dd HH:mm:ss"); - Date currentDateTime = DateUtil.parse(currentDateTimeStr, "yyyy-MM-dd HH:mm:ss"); - - int result = DateUtil.compare(advanceDateTime, currentDateTime); - ThrowUtils.throwIf(result <= 0, ErrorCode.OPERATION_ERROR, "当前时间段已过期"); - + // 校验购买的服务类商品预约情况是否合理 + goodService.checkServiceGoodBookingDetailIsProperly(goodId, reservationDate, timeSlot, quantity); return ResultUtils.success(true); } diff --git a/src/main/java/com/cultural/heritage/controller/good/CartRecordController.java b/src/main/java/com/cultural/heritage/controller/good/CartRecordController.java index 467d922..6dccd72 100644 --- a/src/main/java/com/cultural/heritage/controller/good/CartRecordController.java +++ b/src/main/java/com/cultural/heritage/controller/good/CartRecordController.java @@ -16,6 +16,7 @@ import com.cultural.heritage.model.entity.User; import com.cultural.heritage.model.vo.cart.CartGoodVO; import com.cultural.heritage.model.vo.cart.CartOrderVO; import com.cultural.heritage.model.vo.cart.CartRecordVO; +import com.cultural.heritage.service.common.CommonService; import com.cultural.heritage.service.good.CartRecordService; import com.cultural.heritage.service.good.GoodService; import com.cultural.heritage.service.user.UserService; @@ -41,6 +42,10 @@ import java.util.*; public class CartRecordController { + @Resource + private CommonService commonService; + + @Resource private CartRecordService cartRecordService; @@ -82,25 +87,17 @@ public class CartRecordController { } userService.getLoginUser(request); - // 获取购物车id列表 - List cartIds = cartRecordUpdateRequestList.stream().map(CartRecordUpdateRequest::getId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", cartIds); - List cartRecordList = cartRecordService.list(queryWrapper); + // 获取购物车列表 + List cartRecordList = commonService.getItemsByIds(cartRecordUpdateRequestList, cartRecordService, CartRecordUpdateRequest::getId); // 封装map集合(键:购物车id, 值:商品数量) Map QuantityMap = new HashMap<>(); for (CartRecordUpdateRequest cartRecordUpdateRequest : cartRecordUpdateRequestList) { - Long id = cartRecordUpdateRequest.getId(); - Integer quantity = cartRecordUpdateRequest.getQuantity(); - QuantityMap.put(id, quantity); + QuantityMap.put(cartRecordUpdateRequest.getId(), cartRecordUpdateRequest.getQuantity()); } - // 获取商品id列表 - List goodIds = cartRecordList.stream().map(CartRecord::getGoodId).toList(); - QueryWrapper goodQueryWrapper = new QueryWrapper<>(); - goodQueryWrapper.in("id", goodIds); - List goodList = goodService.list(goodQueryWrapper); + // 获取商品列表 + List goodList = commonService.getItemsByIds(cartRecordList, goodService, CartRecord::getGoodId); // 封装map集合(键:商品id, 值:商品价格) Map priceMap = new HashMap<>(); @@ -134,7 +131,7 @@ public class CartRecordController { @PostMapping("/delete") @Operation(summary = "小程序端用户删除常规类购物车中的物品", description = "参数:购物车记录删除请求体(商品id列表,如[2,3,4]),权限:所有人,方法名:deleteCart") public BaseResponse deleteCart(@RequestBody CommonBatchRequest commonBatchRequest, HttpServletRequest request) { - if (commonBatchRequest == null || commonBatchRequest.getIdList().isEmpty()) { + if (commonBatchRequest == null || CollectionUtils.isEmpty(commonBatchRequest.getIdList())) { throw new BusinessException(ErrorCode.PARAMS_ERROR); } userService.getLoginUser(request); @@ -197,29 +194,29 @@ public class CartRecordController { @PostMapping("/submit/list") @Operation(summary = "小程序端显示常规类购物车提交订单页的商品信息", description = "参数:购物车id列表,权限:所有人,方法名:listCartRecord") public BaseResponse> listCartRecord(@RequestBody CommonBatchRequest commonBatchRequest, HttpServletRequest request) { - if (commonBatchRequest == null || commonBatchRequest.getIdList().isEmpty()) { + if (commonBatchRequest == null || CollectionUtils.isEmpty(commonBatchRequest.getIdList())) { throw new BusinessException(ErrorCode.PARAMS_ERROR); } userService.getLoginUser(request); List cartRecordIds = commonBatchRequest.getIdList(); - List cartRecordList = cartRecordService.list(); - // 获取购物车列表信息 - List cartRecords = cartRecordList.stream().filter(cartRecord -> { - Long id = cartRecord.getId(); - return cartRecordIds.contains(id); - }).toList(); + // 根据id列表获取购物车信息列表 + List cartRecords = commonService.getListByIds(cartRecordIds, cartRecordService); - // 提取出购物车中的商品id列表 - List goodIds = cartRecords.stream().map(CartRecord::getGoodId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", goodIds); - List goodList = goodService.list(queryWrapper); + // 提取出购物车中的商品列表 + List goodList = commonService.getItemsByIds(cartRecords, goodService, CartRecord::getGoodId); // 封装goodMap(根据商品id查询商品) Map goodMap = new HashMap<>(); for (Good good : goodList) { goodMap.put(good.getId(), good); } + // 校验购物车商品 + for (CartRecord cartRecord : cartRecords) { + Good good = goodMap.get(cartRecord.getGoodId()); + Integer quantity = cartRecord.getQuantity(); + goodService.checkGoodIsExist(good); + goodService.checkInventoryIsEnough(quantity, good.getInventory()); + } // 封装提交订单页的商品信息列表 List cartOrderVOList = new ArrayList<>(); @@ -259,8 +256,8 @@ public class CartRecordController { Long goodId = buySingleGoodVerifyRequest.getGoodId(); Integer quantity = buySingleGoodVerifyRequest.getQuantity(); Good good = goodService.getById(goodId); - ThrowUtils.throwIf(good == null || good.getIsShelves() == 0, ErrorCode.SYSTEM_ERROR, "商品已下架或不存在"); - ThrowUtils.throwIf(quantity > good.getInventory(), ErrorCode.SYSTEM_ERROR, "商品库存不足"); + goodService.checkGoodIsExist(good); + goodService.checkInventoryIsEnough(quantity, good.getInventory()); return ResultUtils.success(true); } diff --git a/src/main/java/com/cultural/heritage/controller/order/OrderController.java b/src/main/java/com/cultural/heritage/controller/order/OrderController.java index 17b800b..5aeeaf8 100644 --- a/src/main/java/com/cultural/heritage/controller/order/OrderController.java +++ b/src/main/java/com/cultural/heritage/controller/order/OrderController.java @@ -91,7 +91,7 @@ public class OrderController { /** - * 小程序端用户创建常规类(服务类)商品订单 + * 小程序端用户创建常规类(服务类)商品订单 * @param generalGoodSingleBuyAddRequest 常规类商品单独购买创建请求体 * @return 是否创建成功 */ diff --git a/src/main/java/com/cultural/heritage/model/entity/PendingServiceGood.java b/src/main/java/com/cultural/heritage/model/entity/PendingServiceGood.java index 8d7934d..3a898a4 100644 --- a/src/main/java/com/cultural/heritage/model/entity/PendingServiceGood.java +++ b/src/main/java/com/cultural/heritage/model/entity/PendingServiceGood.java @@ -65,6 +65,12 @@ public class PendingServiceGood implements Serializable { private String timeSlot; + /** + * 是否可预约 + */ + private Integer isAvailable; + + /** * 最小预约人数 */ diff --git a/src/main/java/com/cultural/heritage/model/vo/order/PendingServiceGoodVO.java b/src/main/java/com/cultural/heritage/model/vo/order/PendingServiceGoodVO.java index 11ea5b5..7dcbf92 100644 --- a/src/main/java/com/cultural/heritage/model/vo/order/PendingServiceGoodVO.java +++ b/src/main/java/com/cultural/heritage/model/vo/order/PendingServiceGoodVO.java @@ -46,6 +46,12 @@ public class PendingServiceGoodVO implements Serializable { private String timeSlot; + /** + * 是否可预约 + */ + private Integer isAvailable; + + /** * 最小预约人数 */ diff --git a/src/main/java/com/cultural/heritage/service/common/CommonService.java b/src/main/java/com/cultural/heritage/service/common/CommonService.java new file mode 100644 index 0000000..3ddaf26 --- /dev/null +++ b/src/main/java/com/cultural/heritage/service/common/CommonService.java @@ -0,0 +1,22 @@ +package com.cultural.heritage.service.common; + +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; +import java.util.function.Function; + +public interface CommonService { + + + /** + * 取出一个集合的某个id列表, 去另外一个集合中筛选出属于这个id列表的集合 + */ + List getItemsByIds(List records, IService genericService, Function getId); + + + + /** + * 根据 ID 列表获取对应的实体列表 + */ + List getListByIds(List ids, IService genericService); +} diff --git a/src/main/java/com/cultural/heritage/service/common/impl/CommonServiceImpl.java b/src/main/java/com/cultural/heritage/service/common/impl/CommonServiceImpl.java new file mode 100644 index 0000000..4eaef1e --- /dev/null +++ b/src/main/java/com/cultural/heritage/service/common/impl/CommonServiceImpl.java @@ -0,0 +1,47 @@ +package com.cultural.heritage.service.common.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.cultural.heritage.service.common.CommonService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service +public class CommonServiceImpl implements CommonService { + + + /** + * 取出一个集合的某个id列表, 去另外一个集合中筛选出属于这个id列表的集合 + */ + @Override + public List getItemsByIds(List records, IService genericService, Function getId) { + // 提取ID + List ids = records.stream() + .map(getId) // 提取每个元素的ID + .collect(Collectors.toList()); + + // 构造查询条件 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("id", ids); + + // 返回查询结果 + return genericService.list(queryWrapper); + } + + + /** + * 根据 ID 列表获取对应的实体列表 + */ + @Override + public List getListByIds(List ids, IService genericService) { + // 构造查询条件 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("id", ids); // 使用 IN 条件 + + // 调用具体的服务执行查询 + return genericService.list(queryWrapper); + } +} diff --git a/src/main/java/com/cultural/heritage/service/good/CartExperienceService.java b/src/main/java/com/cultural/heritage/service/good/CartExperienceService.java index 7a4dc7c..1636462 100644 --- a/src/main/java/com/cultural/heritage/service/good/CartExperienceService.java +++ b/src/main/java/com/cultural/heritage/service/good/CartExperienceService.java @@ -15,7 +15,7 @@ public interface CartExperienceService extends IService { /** * 更新购物车的商品属性 */ - boolean updateCartGoodAttribute(CartExperienceAddRequest cartExperienceAddRequest, HttpServletRequest request); + void updateCartGoodAttribute(CartExperienceAddRequest cartExperienceAddRequest, HttpServletRequest request); /** diff --git a/src/main/java/com/cultural/heritage/service/good/CartRecordService.java b/src/main/java/com/cultural/heritage/service/good/CartRecordService.java index 71696b6..d78b096 100644 --- a/src/main/java/com/cultural/heritage/service/good/CartRecordService.java +++ b/src/main/java/com/cultural/heritage/service/good/CartRecordService.java @@ -14,7 +14,7 @@ public interface CartRecordService extends IService { /** * 更新购物车的商品属性 */ - boolean updateCartGoodAttribute(CartRecordAddRequest cartRecordAddRequest, HttpServletRequest request); + void updateCartGoodAttribute(CartRecordAddRequest cartRecordAddRequest, HttpServletRequest request); /** diff --git a/src/main/java/com/cultural/heritage/service/good/GoodService.java b/src/main/java/com/cultural/heritage/service/good/GoodService.java index 0fab809..7cffb62 100644 --- a/src/main/java/com/cultural/heritage/service/good/GoodService.java +++ b/src/main/java/com/cultural/heritage/service/good/GoodService.java @@ -3,12 +3,11 @@ package com.cultural.heritage.service.good; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.IService; import com.cultural.heritage.model.dto.good.GoodQueryRequest; -import com.cultural.heritage.model.entity.CartExperience; -import com.cultural.heritage.model.entity.CartRecord; -import com.cultural.heritage.model.entity.Good; +import com.cultural.heritage.model.entity.*; import java.math.BigDecimal; import java.util.List; +import java.util.Map; public interface GoodService extends IService { @@ -18,12 +17,6 @@ public interface GoodService extends IService { QueryWrapper getGoodQueryWrapper(GoodQueryRequest goodQueryRequest, boolean isServiceGood); - /** - * 根据商品类名查询商品列表 - */ - List getGoodListByTypeName(String typeName); - - /** * 校验 */ @@ -43,4 +36,37 @@ public interface GoodService extends IService { + /** + * 判断商品是否存在或者下架 + */ + void checkGoodIsExist(Good good); + + + /** + * 判断常规类商品库存是否充足 + */ + void checkInventoryIsEnough(Integer neededQuantity, Integer actualQuantity); + + + + /** + * 封装一个Map集合(键:BookingOrderQueryRequest.toString(),值:服务类商品待处理商品记录) + */ + Map getPendingServiceGoodMap(); + + + + /** + * 校验购买的服务类商品预约情况是否合理 + */ + void checkServiceGoodBookingDetailIsProperly(Long goodId, String reservationDate, String timeSlot, Integer quantity); + + + + /** + * 校验购买的服务类购物车中的商品预约情况是否合理 + */ + boolean checkServiceGoodCartBookingDetailIsProperly(Long goodId, String reservationDate, String timeSlot, Integer quantity, Map pendingServiceGoodMap, List pendingServiceOrderList); + + } diff --git a/src/main/java/com/cultural/heritage/service/good/impl/CartExperienceServiceImpl.java b/src/main/java/com/cultural/heritage/service/good/impl/CartExperienceServiceImpl.java index e08bed4..0b81746 100644 --- a/src/main/java/com/cultural/heritage/service/good/impl/CartExperienceServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/good/impl/CartExperienceServiceImpl.java @@ -9,13 +9,13 @@ import com.cultural.heritage.exception.ThrowUtils; import com.cultural.heritage.mapper.CartExperienceMapper; import com.cultural.heritage.model.dto.cartService.CartExperienceAddRequest; import com.cultural.heritage.model.dto.cartService.CartExperienceOrderItemAddRequest; -import com.cultural.heritage.model.entity.CartExperience; -import com.cultural.heritage.model.entity.Good; -import com.cultural.heritage.model.entity.User; +import com.cultural.heritage.model.entity.*; import com.cultural.heritage.model.vo.cartService.CartExperienceGoodVO; import com.cultural.heritage.model.vo.cartService.CartExperienceVO; +import com.cultural.heritage.service.common.CommonService; import com.cultural.heritage.service.good.CartExperienceService; import com.cultural.heritage.service.good.GoodService; +import com.cultural.heritage.service.order.PendingServiceOrderService; import com.cultural.heritage.service.user.UserService; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; @@ -46,48 +46,57 @@ public class CartExperienceServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("userId", userId); queryWrapper.eq("goodId", goodId); - CartExperience cartExperience = this.baseMapper.selectOne(queryWrapper); + queryWrapper.eq("reservationDate", reservationDate); + queryWrapper.eq("timeSlot", timeSlot); + CartExperience cartExperience = this.getOne(queryWrapper); if (cartExperience != null) { - // 判断数量是否超出库存 - int currentQuantity = cartExperience.getQuantity() + cartExperienceAddRequest.getQuantity(); - if (currentQuantity > good.getInventory()) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "商品库存不足, 无法添加"); - } + // 校验当前服务类商品的预约情况 + Integer originQuantity = cartExperience.getQuantity(); + goodService.checkServiceGoodBookingDetailIsProperly(goodId, reservationDate, timeSlot, originQuantity + addQuantity); // 如果购物车中已存在该商品, 就叠加数量 - cartExperience.setQuantity(currentQuantity); - cartExperience.setSubtotal(good.getPrice().multiply(BigDecimal.valueOf(currentQuantity))); + cartExperience.setQuantity(originQuantity + addQuantity); + cartExperience.setSubtotal(good.getPrice().multiply(BigDecimal.valueOf(cartExperience.getQuantity()))); boolean result = this.updateById(cartExperience); ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "更新购物车商品数量失败"); } else { - // 判断数量是否超出库存 - Integer currentQuantity = cartExperienceAddRequest.getQuantity(); - if (currentQuantity > good.getInventory()) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "商品库存不足, 无法添加"); - } + // 校验当前服务类商品的预约情况 + goodService.checkServiceGoodBookingDetailIsProperly(goodId, reservationDate, timeSlot, addQuantity); // 如果购物车不存在该商品,就向购物车中添加一项 CartExperience cartExperienceRecord = new CartExperience(); BeanUtils.copyProperties(cartExperienceAddRequest, cartExperienceRecord); cartExperienceRecord.setUserId(userId); + cartExperienceRecord.setQuantity(addQuantity); cartExperienceRecord.setSubtotal(good.getPrice().multiply(BigDecimal.valueOf(cartExperienceRecord.getQuantity()))); // 校验 this.validCart(cartExperienceRecord, false); boolean result = this.save(cartExperienceRecord); ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); } - return true; } @@ -174,23 +183,17 @@ public class CartExperienceServiceImpl extends ServiceImpl pendingServiceGoodMap, List pendingServiceOrderList) { // 校验购物车中的商品是否存在 if (good == null || good.getIsShelves() == 0) { - log.info("商品不存在或者已下架, 购物车id为" + cartExperience.getId()); return false; } // 判断当前时间是否晚于预约时间 String reservationDate = cartExperience.getReservationDate(); - String startTime = cartExperience.getTimeSlot().split("-")[0]; - String advanceDateTimeStr = reservationDate + " " + startTime + ":00"; - String currentDateTimeStr = DateUtil.now(); - - Date advanceDateTime = DateUtil.parse(advanceDateTimeStr, "yyyy-MM-dd HH:mm:ss"); - Date currentDateTime = DateUtil.parse(currentDateTimeStr, "yyyy-MM-dd HH:mm:ss"); - - int result = DateUtil.compare(advanceDateTime, currentDateTime); - return result > 0; + String timeSlot = cartExperience.getTimeSlot(); + Integer quantity = cartExperience.getQuantity(); + // 校验购买的服务类购物车中的商品预约情况是否合理 + return goodService.checkServiceGoodCartBookingDetailIsProperly(good.getId(), reservationDate, timeSlot, quantity, pendingServiceGoodMap, pendingServiceOrderList); } @@ -230,19 +233,18 @@ public class CartExperienceServiceImpl extends ServiceImpl getInvalidCartIds(List cartExperienceList) { // 获取购物车的商品id列表 - List goodIds = cartExperienceList.stream().map(CartExperience::getGoodId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", goodIds); - List goodList = goodService.list(queryWrapper); + List goodList = commonService.getItemsByIds(cartExperienceList, goodService, CartExperience::getGoodId); // 封装map集合(键:商品id, 值:商品详情信息) Map map = new HashMap<>(); for (Good good : goodList) { map.put(good.getId(), good); } + Map pendingServiceGoodMap = goodService.getPendingServiceGoodMap(); + List pendingServiceOrderList = pendingServiceOrderService.list(); List cartExperiences = cartExperienceList.stream().filter(cartExperience -> { Long goodId = cartExperience.getGoodId(); Good good = map.get(goodId); - return !validIsConsistent(cartExperience, good); + return !validIsConsistent(cartExperience, good, pendingServiceGoodMap, pendingServiceOrderList); }).toList(); return cartExperiences.stream().map(CartExperience::getId).toList(); } diff --git a/src/main/java/com/cultural/heritage/service/good/impl/CartRecordServiceImpl.java b/src/main/java/com/cultural/heritage/service/good/impl/CartRecordServiceImpl.java index ff5e528..4a62f78 100644 --- a/src/main/java/com/cultural/heritage/service/good/impl/CartRecordServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/good/impl/CartRecordServiceImpl.java @@ -13,6 +13,7 @@ import com.cultural.heritage.model.entity.Good; import com.cultural.heritage.model.entity.User; import com.cultural.heritage.model.vo.cart.CartGoodVO; import com.cultural.heritage.model.vo.cart.CartRecordVO; +import com.cultural.heritage.service.common.CommonService; import com.cultural.heritage.service.good.CartRecordService; import com.cultural.heritage.service.good.GoodService; import com.cultural.heritage.service.user.UserService; @@ -41,16 +42,20 @@ public class CartRecordServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("userId", userId); queryWrapper.eq("goodId", goodId); @@ -58,9 +63,7 @@ public class CartRecordServiceImpl extends ServiceImpl good.getInventory()) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "商品库存不足, 无法添加"); - } + goodService.checkInventoryIsEnough(currentQuantity, good.getInventory()); // 如果购物车中已存在该商品, 就叠加数量 cartRecord.setQuantity(currentQuantity); cartRecord.setSubtotal(good.getPrice().multiply(BigDecimal.valueOf(currentQuantity))); @@ -69,9 +72,7 @@ public class CartRecordServiceImpl extends ServiceImpl good.getInventory()) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "商品库存不足, 无法添加"); - } + goodService.checkInventoryIsEnough(currentQuantity, good.getInventory()); // 如果购物车不存在该商品,就向购物车中添加一项 CartRecord cartGood = new CartRecord(); BeanUtils.copyProperties(cartRecordAddRequest, cartGood); @@ -82,7 +83,6 @@ public class CartRecordServiceImpl extends ServiceImpl inventory) { - log.info("商品库存量不足, 购物车id为" + cartRecord.getId()); - return false; - } - return true; + return quantity <= inventory; } @@ -181,18 +176,12 @@ public class CartRecordServiceImpl extends ServiceImpl map = new HashMap<>(); for (CartOrderItemAddRequest cartOrderItemAddRequest : cartOrderItemAddRequestList) { - Long cartRecordId = cartOrderItemAddRequest.getCartRecordId(); - Integer quantity = cartOrderItemAddRequest.getQuantity(); - map.put(cartRecordId, quantity); + map.put(cartOrderItemAddRequest.getCartRecordId(), cartOrderItemAddRequest.getQuantity()); } // 修改购物车商品项的购买数量 - List cartRecordIds = cartOrderItemAddRequestList.stream().map(CartOrderItemAddRequest::getCartRecordId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", cartRecordIds); - List cartRecordList = this.list(queryWrapper); + List cartRecordList = commonService.getItemsByIds(cartOrderItemAddRequestList, this, CartOrderItemAddRequest::getCartRecordId); for (CartRecord cartRecord : cartRecordList) { - Long id = cartRecord.getId(); - Integer quantity = map.get(id); + Integer quantity = map.get(cartRecord.getId()); cartRecord.setQuantity(quantity); } List cartIds = getInvalidCartIds(cartRecordList); @@ -205,11 +194,8 @@ public class CartRecordServiceImpl extends ServiceImpl getInvalidCartIds(List cartRecords) { - // 获取购物车的商品id列表 - List goodIds = cartRecords.stream().map(CartRecord::getGoodId).toList(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", goodIds); - List goodList = goodService.list(queryWrapper); + // 获取购物车的商品列表 + List goodList = commonService.getItemsByIds(cartRecords, goodService, CartRecord::getGoodId); // 封装map集合(键:商品id, 值:商品详情信息) Map map = new HashMap<>(); for (Good good : goodList) { diff --git a/src/main/java/com/cultural/heritage/service/good/impl/GoodServiceImpl.java b/src/main/java/com/cultural/heritage/service/good/impl/GoodServiceImpl.java index bde8abe..7839e42 100644 --- a/src/main/java/com/cultural/heritage/service/good/impl/GoodServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/good/impl/GoodServiceImpl.java @@ -1,29 +1,33 @@ package com.cultural.heritage.service.good.impl; +import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.cultural.heritage.common.ErrorCode; import com.cultural.heritage.constant.CommonConstant; +import com.cultural.heritage.constant.OrderStatusConstant; import com.cultural.heritage.exception.BusinessException; +import com.cultural.heritage.exception.ThrowUtils; 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; +import com.cultural.heritage.model.entity.*; import com.cultural.heritage.service.good.GoodService; +import com.cultural.heritage.service.order.PendingServiceGoodService; +import com.cultural.heritage.service.order.PendingServiceOrderService; import com.cultural.heritage.utils.SqlUtils; import jakarta.annotation.Resource; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; import java.math.BigDecimal; -import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Service public class GoodServiceImpl extends ServiceImpl implements GoodService { @@ -37,6 +41,14 @@ public class GoodServiceImpl extends ServiceImpl implements Go private CartExperienceMapper cartExperienceMapper; + @Resource + private PendingServiceGoodService pendingServiceGoodService; + + + @Resource + private PendingServiceOrderService pendingServiceOrderService; + + /** * 商品查询条件 */ @@ -70,20 +82,7 @@ public class GoodServiceImpl extends ServiceImpl implements Go } - /** - * 根据商品类名查询商品列表 - */ - @Override - public List getGoodListByTypeName(String typeName) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("type", typeName); - queryWrapper.eq("isShelves", 1); - List list = this.list(queryWrapper); - if (CollectionUtils.isEmpty(list)) { - return new ArrayList<>(); - } - return list; - } + /** @@ -158,5 +157,118 @@ public class GoodServiceImpl extends ServiceImpl implements Go + /** + * 判断商品是否存在或者下架 + */ + @Override + public void checkGoodIsExist(Good good) { + ThrowUtils.throwIf(good == null || good.getIsShelves() == 0, ErrorCode.OPERATION_ERROR, "商品不存在或者已下架"); + } + + + /** + * 判断常规类商品库存是否充足 + */ + @Override + public void checkInventoryIsEnough(Integer neededQuantity, Integer actualQuantity) { + ThrowUtils.throwIf(neededQuantity > actualQuantity, ErrorCode.OPERATION_ERROR, "商品库存不足"); + } + + + + + /** + * 封装一个Map集合(键:BookingOrderQueryRequest.toString(),值:服务类商品待处理商品记录) + */ + @Override + public Map getPendingServiceGoodMap() { + Map map = new HashMap<>(); + List pendingServiceGoodList = pendingServiceGoodService.list(); + for (PendingServiceGood pendingServiceGood : pendingServiceGoodList) { + Long goodId = pendingServiceGood.getGoodId(); + String reservationDate = pendingServiceGood.getReservationDate(); + String timeSlot = pendingServiceGood.getTimeSlot(); + BookingOrderQueryRequest bookingOrderQueryRequest = new BookingOrderQueryRequest(goodId, reservationDate, timeSlot); + map.put(bookingOrderQueryRequest.toString(), pendingServiceGood); + } + return map; + } + + + + /** + * 校验购买的服务类商品预约情况是否合理 + */ + @Override + public void checkServiceGoodBookingDetailIsProperly(Long goodId, String reservationDate, String timeSlot, Integer quantity) { + BookingOrderQueryRequest bookingOrderQueryRequest = new BookingOrderQueryRequest(goodId, reservationDate, timeSlot); + Map pendingServiceGoodMap = this.getPendingServiceGoodMap(); + PendingServiceGood pendingServiceGood = pendingServiceGoodMap.get(bookingOrderQueryRequest.toString()); + + Integer isAvailable = pendingServiceGood.getIsAvailable(); + ThrowUtils.throwIf(isAvailable == 0, ErrorCode.OPERATION_ERROR, "当前时间段不可预约"); + + String startTime = timeSlot.split("-")[0]; + String advanceDateTimeStr = reservationDate + " " + startTime + ":00"; + String currentDateTimeStr = DateUtil.now(); + + Date advanceDateTime = DateUtil.parse(advanceDateTimeStr, "yyyy-MM-dd HH:mm:ss"); + Date currentDateTime = DateUtil.parse(currentDateTimeStr, "yyyy-MM-dd HH:mm:ss"); + + int result = DateUtil.compare(advanceDateTime, currentDateTime); + ThrowUtils.throwIf(result <= 0, ErrorCode.OPERATION_ERROR, "当前时间段已过期"); + + Long pendingId = pendingServiceGood.getId(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("pendingId", pendingId); + queryWrapper.eq("orderItemStatus", OrderStatusConstant.PENDING_SHIPMENT); + List pendingServiceOrderList = pendingServiceOrderService.list(queryWrapper); + Integer totalNumber = 0; + for (PendingServiceOrder pendingServiceOrder : pendingServiceOrderList) { + totalNumber += pendingServiceOrder.getQuantity(); + } + Integer maxNumber = pendingServiceGood.getMaxNumber(); + ThrowUtils.throwIf(totalNumber + quantity > maxNumber, ErrorCode.OPERATION_ERROR, "当前预约数量已超过上限"); + } + + + + + /** + * 校验购买的服务类购物车中的商品预约情况是否合理 + */ + @Override + public boolean checkServiceGoodCartBookingDetailIsProperly(Long goodId, String reservationDate, String timeSlot, Integer quantity, Map pendingServiceGoodMap, List pendingServiceOrderList) { + BookingOrderQueryRequest bookingOrderQueryRequest = new BookingOrderQueryRequest(goodId, reservationDate, timeSlot); + PendingServiceGood pendingServiceGood = pendingServiceGoodMap.get(bookingOrderQueryRequest.toString()); + + Integer isAvailable = pendingServiceGood.getIsAvailable(); + if (isAvailable == 0) return false; + + String startTime = timeSlot.split("-")[0]; + String advanceDateTimeStr = reservationDate + " " + startTime + ":00"; + String currentDateTimeStr = DateUtil.now(); + + Date advanceDateTime = DateUtil.parse(advanceDateTimeStr, "yyyy-MM-dd HH:mm:ss"); + Date currentDateTime = DateUtil.parse(currentDateTimeStr, "yyyy-MM-dd HH:mm:ss"); + + int result = DateUtil.compare(advanceDateTime, currentDateTime); + if (result <= 0) return false; + + Long pendingId = pendingServiceGood.getId(); + pendingServiceOrderList = pendingServiceOrderList.stream().filter(pendingServiceOrder -> { + String orderItemStatus = pendingServiceOrder.getOrderItemStatus(); + Long serviceOrderPendingId = pendingServiceOrder.getPendingId(); + return orderItemStatus.equals(OrderStatusConstant.PENDING_SHIPMENT) && serviceOrderPendingId.equals(pendingId); + }).toList(); + + Integer totalNumber = 0; + for (PendingServiceOrder pendingServiceOrder : pendingServiceOrderList) { + totalNumber += pendingServiceOrder.getQuantity(); + } + Integer maxNumber = pendingServiceGood.getMaxNumber(); + return totalNumber + quantity <= maxNumber; + } + } diff --git a/src/main/java/com/cultural/heritage/service/order/OrderService.java b/src/main/java/com/cultural/heritage/service/order/OrderService.java index 2424ae0..d30c7c6 100644 --- a/src/main/java/com/cultural/heritage/service/order/OrderService.java +++ b/src/main/java/com/cultural/heritage/service/order/OrderService.java @@ -47,7 +47,6 @@ public interface OrderService extends IService { void validSingleGoodOrder(GeneralGoodSingleBuyAddRequest generalGoodSingleBuyAddRequest, boolean isGeneral); - /** * 计算单个商品购买的总金额 */ diff --git a/src/main/java/com/cultural/heritage/service/order/PendingServiceOrderService.java b/src/main/java/com/cultural/heritage/service/order/PendingServiceOrderService.java index 9631a25..88e8b82 100644 --- a/src/main/java/com/cultural/heritage/service/order/PendingServiceOrderService.java +++ b/src/main/java/com/cultural/heritage/service/order/PendingServiceOrderService.java @@ -4,4 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.cultural.heritage.model.entity.PendingServiceOrder; public interface PendingServiceOrderService extends IService { + + + } diff --git a/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java b/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java index 6cc2020..88ac31b 100644 --- a/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java @@ -1,6 +1,5 @@ package com.cultural.heritage.service.order.impl; -import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -31,6 +30,8 @@ import com.cultural.heritage.model.vo.coupon.CouponVO; import com.cultural.heritage.service.good.*; import com.cultural.heritage.service.order.OrderItemService; import com.cultural.heritage.service.order.OrderService; +import com.cultural.heritage.service.order.PendingServiceGoodService; +import com.cultural.heritage.service.order.PendingServiceOrderService; import com.cultural.heritage.utils.MultiDelayMessage; import com.cultural.heritage.utils.OrderNumberUtils; import com.cultural.heritage.utils.SqlUtils; @@ -92,6 +93,14 @@ public class OrderServiceImpl extends ServiceImpl implements private UserCouponService userCouponService; + @Resource + private PendingServiceGoodService pendingServiceGoodService; + + + @Resource + private PendingServiceOrderService pendingServiceOrderService; + + /** * 获取查询条件 */ @@ -314,22 +323,16 @@ public class OrderServiceImpl extends ServiceImpl implements OrderItemMainInfoAddRequest orderItemMainInfoAddRequest = orderItemMainInfoAddRequestList.get(0); Long goodId = orderItemMainInfoAddRequest.getGoodId(); Good good = goodService.getById(goodId); - ThrowUtils.throwIf(good == null || good.getIsShelves() == 0, ErrorCode.OPERATION_ERROR, "商品已下架或者不存在"); + // 判断商品是否存在或者下架 + goodService.checkGoodIsExist(good); if (isGeneral) { - Integer quantity = orderItemMainInfoAddRequest.getQuantity(); - ThrowUtils.throwIf(quantity > good.getInventory(), ErrorCode.OPERATION_ERROR, "商品库存不足"); + goodService.checkInventoryIsEnough(orderItemMainInfoAddRequest.getQuantity(), good.getInventory()); } else { String reservationDate = orderItemMainInfoAddRequest.getReservationDate(); - String startTime = orderItemMainInfoAddRequest.getTimeSlot().split("-")[0]; - String advanceDateTimeStr = reservationDate + " " + startTime + ":00"; - String currentDateTimeStr = DateUtil.now(); - - Date advanceDateTime = DateUtil.parse(advanceDateTimeStr, "yyyy-MM-dd HH:mm:ss"); - Date currentDateTime = DateUtil.parse(currentDateTimeStr, "yyyy-MM-dd HH:mm:ss"); - - int result = DateUtil.compare(advanceDateTime, currentDateTime); - ThrowUtils.throwIf(result <= 0, ErrorCode.OPERATION_ERROR, "当前时间段已过期"); + String timeSlot = orderItemMainInfoAddRequest.getTimeSlot(); + Integer quantity = orderItemMainInfoAddRequest.getQuantity(); + goodService.checkServiceGoodBookingDetailIsProperly(goodId, reservationDate, timeSlot, quantity); } } diff --git a/src/main/java/com/cultural/heritage/service/order/impl/PendingServiceOrderServiceImpl.java b/src/main/java/com/cultural/heritage/service/order/impl/PendingServiceOrderServiceImpl.java index 8c19116..e29f0e5 100644 --- a/src/main/java/com/cultural/heritage/service/order/impl/PendingServiceOrderServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/order/impl/PendingServiceOrderServiceImpl.java @@ -8,4 +8,6 @@ import org.springframework.stereotype.Service; @Service public class PendingServiceOrderServiceImpl extends ServiceImpl implements PendingServiceOrderService { + + } diff --git a/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java b/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java index 670e8a7..3699018 100644 --- a/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java @@ -3,6 +3,7 @@ package com.cultural.heritage.service.wx.impl; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.cultural.heritage.common.ErrorCode; import com.cultural.heritage.config.WxOpenConfig; import com.cultural.heritage.config.WxPayConfig; @@ -245,30 +246,58 @@ public class WeChatServiceImpl implements WeChatService { // 获取订单明细所属的订单 Order order = orderService.getById(orderItems.getOrderId()); ThrowUtils.throwIf(order == null, ErrorCode.OPERATION_ERROR, "订单不存在"); + // 判断该订单明细是否已经退款 + QueryWrapper pendingServiceOrderQueryWrapper = new QueryWrapper<>(); + pendingServiceOrderQueryWrapper.eq("orderItemId", orderItemsId); + PendingServiceOrder pendingServiceOrder = pendingServiceOrderService.getOne(pendingServiceOrderQueryWrapper); + ThrowUtils.throwIf(pendingServiceOrder == null || !pendingServiceOrder.getOrderItemStatus().equals(OrderStatusConstant.PENDING_SHIPMENT), ErrorCode.OPERATION_ERROR, "服务类订单待处理记录不存在或者当前订单明细状态错误"); + String orderNumber = order.getOrderNumber(); // 退款请求 CreateRequest createRequest = new CreateRequest(); // 商户订单号 createRequest.setOutTradeNo(orderNumber); // 商户退款单号 - String outRefundNo = RefundUtils.generateRefundNo(); + String outRefundNo = RefundUtils.generateRefundPartNo(orderItemsId); createRequest.setOutRefundNo(outRefundNo); // 退款结果回调 - createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/refund/callback"); + createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/refund/part/callback"); // 退款金额 AmountReq amountReq = new AmountReq(); + + BigDecimal refundAmount; CouponSnapshot couponSnapshot = order.getCouponSnapshot(); if (couponSnapshot == null) { refundAmount = amount; } else { - BigDecimal couponAmount = couponSnapshot.getConditionAmount(); - BigDecimal totalAmount = order.getTotalAmount().add(couponAmount); - BigDecimal itemShare = amount.divide(totalAmount, 10, RoundingMode.HALF_UP); - BigDecimal itemCouponRefund = itemShare.multiply(couponAmount); - refundAmount = amount.subtract(itemCouponRefund); + // 判断是否为最后一个商品,如果是,则将剩余金额全部退款 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("orderId", order.getId()); + long itemCount = orderItemService.count(queryWrapper); + + QueryWrapper recordQueryWrapper = new QueryWrapper<>(); + recordQueryWrapper.eq("outTradeNo", order.getOrderNumber()); + long refundCount = refundRecordService.count(recordQueryWrapper); + + if (itemCount - refundCount == 1) { + List refundRecords = refundRecordService.list(recordQueryWrapper); + BigDecimal refundTotalAmount = new BigDecimal("0.00"); + for (RefundRecord refundRecord : refundRecords) { + BigDecimal recordRefundAmount = refundRecord.getRefundAmount(); + refundTotalAmount = refundTotalAmount.add(recordRefundAmount); + } + refundAmount = order.getTotalAmount().subtract(refundTotalAmount); + } else { + BigDecimal couponAmount = couponSnapshot.getConditionAmount(); + BigDecimal totalAmount = order.getTotalAmount().add(couponAmount); + BigDecimal itemShare = amount.divide(totalAmount, 10, RoundingMode.HALF_UP); + BigDecimal itemCouponRefund = itemShare.multiply(couponAmount); + refundAmount = amount.subtract(itemCouponRefund); + } } + refundAmount = refundAmount.movePointRight(2).setScale(0, RoundingMode.HALF_UP); amountReq.setRefund(refundAmount.longValue()); amountReq.setTotal(order.getTotalAmount().movePointRight(2).longValue()); @@ -325,42 +354,59 @@ public class WeChatServiceImpl implements WeChatService { boolean save = refundRecordService.save(refundRecord); ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "退款记录生成失败"); - // 恢复商品库存 - QueryWrapper orderItemsQueryWrapper = new QueryWrapper<>(); - orderItemsQueryWrapper.eq("orderId", order.getId()); - List orderItemsList = orderItemService.list(orderItemsQueryWrapper); - // 获取商品id列表 - List goodIds = orderItemsList.stream().map(orderItems -> { - GoodSnapshot goodSnapshot = orderItems.getGoodSnapshot(); - return goodSnapshot.getId(); - }).toList(); - QueryWrapper goodQueryWrapper = new QueryWrapper<>(); - goodQueryWrapper.in("id", goodIds); - // 获取商品列表 - List goodList = goodService.list(goodQueryWrapper); - // 封装为map集合(键:商品id, 值:库存量),用来存储购买的商品id对应的购买数量 - Map map = new HashMap<>(); - for (OrderItems orderItems : orderItemsList) { - GoodSnapshot goodSnapshot = orderItems.getGoodSnapshot(); - Long goodId = goodSnapshot.getId(); - Integer quantity = orderItems.getQuantity(); - map.put(goodId, quantity); + + GoodTypeEnum orderTypeEnum = GoodTypeEnum.getEnumByValue(order.getOrderType()); + if (GoodTypeEnum.SERVICE.equals(orderTypeEnum)) { + // 更新服务类订单待处理记录 + QueryWrapper orderQueryWrapper = new QueryWrapper<>(); + orderQueryWrapper.eq("orderNumber", order.getOrderNumber()); + List pendingServiceOrderList = pendingServiceOrderService.list(orderQueryWrapper); + for (PendingServiceOrder pendingServiceOrder : pendingServiceOrderList) { + pendingServiceOrder.setOrderItemStatus(OrderStatusConstant.PAYMENT_REFUNDED); + } + boolean result = pendingServiceOrderService.updateBatchById(pendingServiceOrderList); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "服务类订单待处理记录批量更新失败"); + } else { + + // 恢复商品库存 + QueryWrapper orderItemsQueryWrapper = new QueryWrapper<>(); + orderItemsQueryWrapper.eq("orderId", order.getId()); + List orderItemsList = orderItemService.list(orderItemsQueryWrapper); + // 获取商品id列表 + List goodIds = orderItemsList.stream().map(orderItems -> { + GoodSnapshot goodSnapshot = orderItems.getGoodSnapshot(); + return goodSnapshot.getId(); + }).toList(); + QueryWrapper goodQueryWrapper = new QueryWrapper<>(); + goodQueryWrapper.in("id", goodIds); + // 获取商品列表 + List goodList = goodService.list(goodQueryWrapper); + // 封装为map集合(键:商品id, 值:库存量),用来存储购买的商品id对应的购买数量 + Map map = new HashMap<>(); + for (OrderItems orderItems : orderItemsList) { + GoodSnapshot goodSnapshot = orderItems.getGoodSnapshot(); + Long goodId = goodSnapshot.getId(); + Integer quantity = orderItems.getQuantity(); + map.put(goodId, quantity); + } + + // 批量更新商品库存 + for (Good good : goodList) { + Long goodId = good.getId(); + // 已经下单购买的数量 + Integer quantity = map.get(goodId); + // 原有的库存 + Integer inventory = good.getInventory(); + good.setInventory(quantity + inventory); + good.setUpdateTime(DateUtil.date()); + } + boolean updateBatch = goodService.updateBatchById(goodList); + ThrowUtils.throwIf(!updateBatch, ErrorCode.SYSTEM_ERROR, "商品库存恢复失败"); + + System.out.println("---------------------------微信退款回调(结束)-------------------------------"); } - // 批量更新商品库存 - for (Good good : goodList) { - Long goodId = good.getId(); - // 已经下单购买的数量 - Integer quantity = map.get(goodId); - // 原有的库存 - Integer inventory = good.getInventory(); - good.setInventory(quantity + inventory); - good.setUpdateTime(DateUtil.date()); - } - boolean updateBatch = goodService.updateBatchById(goodList); - ThrowUtils.throwIf(!updateBatch, ErrorCode.SYSTEM_ERROR, "商品库存恢复失败"); - System.out.println("---------------------------微信退款回调(结束)-------------------------------"); return true; } @@ -372,9 +418,49 @@ public class WeChatServiceImpl implements WeChatService { */ @Override public boolean refundPartCallback(RefundNotification refundNotification) { - return false; - } + System.out.println("---------------------------微信退款回调(开始)-------------------------------"); + // 获取订单信息 + String orderIdByString = refundNotification.getOutTradeNo(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("orderNumber", orderIdByString); + Order order = orderService.getOne(queryWrapper); + if (order == null) { + log.error("订单不存在"); + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在,订单号:" + orderIdByString); + } + // 生成退款记录 + RefundRecord refundRecord = new RefundRecord(); + refundRecord.setOutTradeNo(refundNotification.getOutTradeNo()); + refundRecord.setOutRefundNo(refundNotification.getOutRefundNo()); + refundRecord.setRefundAmount(order.getTotalAmount()); + + boolean save = refundRecordService.save(refundRecord); + ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "退款记录生成失败"); + + + String outRefundNo = refundNotification.getOutRefundNo(); + String orderItemId = RefundUtils.parseRefundNoToItemId(outRefundNo); + + GoodTypeEnum orderTypeEnum = GoodTypeEnum.getEnumByValue(order.getOrderType()); + if (GoodTypeEnum.SERVICE.equals(orderTypeEnum)) { + // 更新服务类订单待处理记录 + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("orderItemId", orderItemId).set("orderItemStatus", OrderStatusConstant.PAYMENT_REFUNDED); + boolean update = pendingServiceOrderService.update(updateWrapper); + ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "服务类订单待处理记录状态更新失败"); + } else { + // 恢复商品库存 + OrderItems orderItems = orderItemService.getById(orderItemId); + Long id = orderItems.getGoodSnapshot().getId(); + Good good = goodService.getById(id); + ThrowUtils.throwIf(good == null, ErrorCode.OPERATION_ERROR, "当前商品不存在"); + good.setInventory(good.getInventory() + orderItems.getQuantity()); + boolean update = goodService.updateById(good); + ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "商品库存恢复失败"); + } + return true; + } // diff --git a/src/main/java/com/cultural/heritage/utils/RefundUtils.java b/src/main/java/com/cultural/heritage/utils/RefundUtils.java index f90a9ef..7c8d0ed 100644 --- a/src/main/java/com/cultural/heritage/utils/RefundUtils.java +++ b/src/main/java/com/cultural/heritage/utils/RefundUtils.java @@ -6,7 +6,7 @@ import java.util.Random; public class RefundUtils { - // 生成唯一的退款单号,格式为 yyyyMMddHHmmssSSS + 随机数 + // 生成唯一的全额退款单号,格式为 yyyyMMddHHmmssSSS + 随机数 public static String generateRefundNo() { // 获取当前时间的时间戳 String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()); @@ -18,4 +18,36 @@ public class RefundUtils { return timestamp + randomNum; } + + // 生成唯一的部分退款单号,格式为 yyyyMMddHHmmssSSS + 订单明细 + public static String generateRefundPartNo(String orderItemId) { + // 获取当前时间的时间戳 + String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()); + + String orderItemString = padString(orderItemId); + + // 拼接退款单号 + return timestamp + orderItemString; + } + + // 将退款单号解析为订单明细id + public static String parseRefundNoToItemId(String outRefundNo) { + + // 提取剩下的原始数字部分 + String original = outRefundNo.substring(17); // 获取从第18位开始的部分 + + // 去掉前导0 + original = original.replaceAll("^0+", ""); // 正则表达式去除开头的0 + + return original; // 返回提取的原始字符串 + } + + + public static String padString(String input) { + if (input.length() < 4) { + input = String.format("%04d", Integer.parseInt(input)); // 补齐前导0 + } + return input; + } + }