package com.tcm.training.admin.app.points.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.tcm.training.admin.app.auth.service.AppAuthSessionService;
|
import com.tcm.training.admin.app.points.vo.AppPointsExchangeOrderDetailVO;
|
import com.tcm.training.admin.app.points.vo.AppPointsExchangeOrderItemVO;
|
import com.tcm.training.admin.common.PageResponse;
|
import com.tcm.training.admin.live.entity.Clinic;
|
import com.tcm.training.admin.live.mapper.ClinicMapper;
|
import com.tcm.training.admin.member.entity.AppUser;
|
import com.tcm.training.admin.member.mapper.UserMapper;
|
import com.tcm.training.admin.points.entity.PointsExchangeOrder;
|
import com.tcm.training.admin.points.entity.PointsExchangeOrderItem;
|
import com.tcm.training.admin.points.mapper.PointsExchangeOrderItemMapper;
|
import com.tcm.training.admin.points.mapper.PointsExchangeOrderMapper;
|
import com.tcm.training.admin.points.row.PointsExchangeItemRow;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDateTime;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* APP 兑换订单服务。
|
*/
|
@Service
|
public class AppPointsExchangeOrderService {
|
|
private static final int STATUS_PENDING = 0;
|
private static final int STATUS_RECEIVING = 1;
|
private static final int STATUS_COMPLETED = 2;
|
|
private final AppAuthSessionService appAuthSessionService;
|
private final PointsExchangeOrderItemMapper pointsExchangeOrderItemMapper;
|
private final PointsExchangeOrderMapper pointsExchangeOrderMapper;
|
private final UserMapper userMapper;
|
private final ClinicMapper clinicMapper;
|
|
/**
|
* 注入 APP 兑换订单所需依赖。
|
*/
|
public AppPointsExchangeOrderService(AppAuthSessionService appAuthSessionService,
|
PointsExchangeOrderItemMapper pointsExchangeOrderItemMapper,
|
PointsExchangeOrderMapper pointsExchangeOrderMapper,
|
UserMapper userMapper,
|
ClinicMapper clinicMapper) {
|
this.appAuthSessionService = appAuthSessionService;
|
this.pointsExchangeOrderItemMapper = pointsExchangeOrderItemMapper;
|
this.pointsExchangeOrderMapper = pointsExchangeOrderMapper;
|
this.userMapper = userMapper;
|
this.clinicMapper = clinicMapper;
|
}
|
|
/**
|
* 分页查询当前登录用户的兑换订单列表。
|
*/
|
public PageResponse<AppPointsExchangeOrderItemVO> page(int page, int pageSize, Integer status) {
|
Long appUserId = appAuthSessionService.requireLoginUserId();
|
int normalizedPage = page <= 0 ? 1 : page;
|
int normalizedPageSize = pageSize <= 0 ? 10 : pageSize;
|
IPage<PointsExchangeItemRow> result = pointsExchangeOrderItemMapper.selectAppItemPage(
|
new Page<PointsExchangeItemRow>(normalizedPage, normalizedPageSize),
|
appUserId,
|
normalizeStatus(status)
|
);
|
return PageResponse.of(toItemList(result.getRecords()), result.getTotal(), result.getCurrent(), result.getSize());
|
}
|
|
/**
|
* 获取当前登录用户的兑换订单详情。
|
*/
|
public AppPointsExchangeOrderDetailVO detail(Long id) {
|
Long appUserId = appAuthSessionService.requireLoginUserId();
|
PointsExchangeItemRow row = requireOwnedItemRow(id, appUserId);
|
AppUser user = userMapper.selectById(appUserId);
|
Clinic clinic = resolveClinic(user == null ? null : user.getClinicId());
|
|
AppPointsExchangeOrderDetailVO detail = new AppPointsExchangeOrderDetailVO();
|
detail.setId(row.getId());
|
detail.setOrderNo(trimToEmpty(row.getOrderNo()));
|
detail.setStatus(row.getStatus());
|
detail.setStatusText(resolveStatusText(row.getStatus()));
|
detail.setTrackingNo(trimToEmpty(row.getTrackingNo()));
|
detail.setCreatedAt(row.getCreatedAt());
|
detail.setShippedAt(row.getShippedAt());
|
detail.setCompletedAt(row.getCompletedAt());
|
detail.setCanConfirmReceived(Boolean.valueOf(isReceivable(row.getStatus())));
|
detail.setCanDelete(Boolean.valueOf(isDeletable(row.getStatus())));
|
|
AppPointsExchangeOrderDetailVO.GiftVO gift = new AppPointsExchangeOrderDetailVO.GiftVO();
|
gift.setCover(trimToEmpty(row.getGiftCover()));
|
gift.setName(trimToEmpty(row.getGiftName()));
|
gift.setRequiredPoints(defaultNumber(row.getRequiredPoints()));
|
gift.setItemCount(Integer.valueOf(1));
|
gift.setTotalPoints(defaultNumber(row.getSettledPoints()));
|
detail.setGift(gift);
|
|
AppPointsExchangeOrderDetailVO.ClinicVO clinicVO = new AppPointsExchangeOrderDetailVO.ClinicVO();
|
clinicVO.setName(trimToEmpty(clinic == null ? null : clinic.getName()));
|
clinicVO.setAddress(trimToEmpty(clinic == null ? null : clinic.getAddress()));
|
detail.setClinic(clinicVO);
|
return detail;
|
}
|
|
/**
|
* 确认当前登录用户的兑换订单已取货。
|
*/
|
@Transactional
|
public void confirmReceived(Long id) {
|
Long appUserId = appAuthSessionService.requireLoginUserId();
|
PointsExchangeOrderItem item = requireOwnedItem(id, appUserId);
|
if (!isReceivable(item.getStatus())) {
|
throw new IllegalArgumentException("当前订单不允许确认取货");
|
}
|
LocalDateTime now = LocalDateTime.now();
|
item.setStatus(STATUS_COMPLETED);
|
item.setCompletedAt(now);
|
pointsExchangeOrderItemMapper.updateById(item);
|
refreshSummaryOrderStatus(item.getOrderId(), now);
|
}
|
|
/**
|
* 删除当前登录用户已完成的兑换订单。
|
*/
|
@Transactional
|
public void delete(Long id) {
|
Long appUserId = appAuthSessionService.requireLoginUserId();
|
PointsExchangeOrderItem item = requireOwnedItem(id, appUserId);
|
if (!isDeletable(item.getStatus())) {
|
throw new IllegalArgumentException("当前订单不允许删除");
|
}
|
Long orderId = item.getOrderId();
|
pointsExchangeOrderItemMapper.deleteById(item.getId());
|
refreshSummaryOrderAfterDelete(orderId);
|
}
|
|
/**
|
* 将数据库行转换为 APP 列表展示结构。
|
*/
|
private List<AppPointsExchangeOrderItemVO> toItemList(List<PointsExchangeItemRow> rows) {
|
List<AppPointsExchangeOrderItemVO> list = new ArrayList<AppPointsExchangeOrderItemVO>();
|
if (rows == null) {
|
return list;
|
}
|
for (PointsExchangeItemRow row : rows) {
|
AppPointsExchangeOrderItemVO item = new AppPointsExchangeOrderItemVO();
|
item.setId(row.getId());
|
item.setOrderNo(trimToEmpty(row.getOrderNo()));
|
item.setGiftCover(trimToEmpty(row.getGiftCover()));
|
item.setGiftName(trimToEmpty(row.getGiftName()));
|
item.setRequiredPoints(defaultNumber(row.getRequiredPoints()));
|
item.setItemCount(Integer.valueOf(1));
|
item.setTotalPoints(defaultNumber(row.getSettledPoints()));
|
item.setStatus(row.getStatus());
|
item.setStatusText(resolveStatusText(row.getStatus()));
|
list.add(item);
|
}
|
return list;
|
}
|
|
/**
|
* 校验并返回当前登录用户名下的兑换订单行。
|
*/
|
private PointsExchangeItemRow requireOwnedItemRow(Long id, Long appUserId) {
|
PointsExchangeItemRow row = pointsExchangeOrderItemMapper.selectAppItemDetail(id, appUserId);
|
if (row == null) {
|
throw new IllegalArgumentException("兑换订单不存在");
|
}
|
return row;
|
}
|
|
/**
|
* 校验并返回当前登录用户名下的兑换订单实体。
|
*/
|
private PointsExchangeOrderItem requireOwnedItem(Long id, Long appUserId) {
|
PointsExchangeOrderItem item = pointsExchangeOrderItemMapper.selectOne(new LambdaQueryWrapper<PointsExchangeOrderItem>()
|
.eq(PointsExchangeOrderItem::getId, id)
|
.eq(PointsExchangeOrderItem::getAppUserId, appUserId)
|
.eq(PointsExchangeOrderItem::getDeleted, 0)
|
.last("limit 1"));
|
if (item == null) {
|
throw new IllegalArgumentException("兑换订单不存在");
|
}
|
return item;
|
}
|
|
/**
|
* 读取用户绑定诊所,不存在时返回空。
|
*/
|
private Clinic resolveClinic(Long clinicId) {
|
if (clinicId == null) {
|
return null;
|
}
|
Clinic clinic = clinicMapper.selectById(clinicId);
|
if (clinic == null || clinic.getDeleted() == null || clinic.getDeleted().intValue() != 0) {
|
return null;
|
}
|
return clinic;
|
}
|
|
/**
|
* 刷新汇总订单状态,保证确认取货后与明细一致。
|
*/
|
private void refreshSummaryOrderStatus(Long orderId, LocalDateTime completedAt) {
|
if (orderId == null) {
|
return;
|
}
|
PointsExchangeOrder order = pointsExchangeOrderMapper.selectById(orderId);
|
if (order == null || order.getDeleted() == null || order.getDeleted().intValue() != 0) {
|
return;
|
}
|
List<PointsExchangeOrderItem> items = pointsExchangeOrderItemMapper.selectList(new LambdaQueryWrapper<PointsExchangeOrderItem>()
|
.eq(PointsExchangeOrderItem::getDeleted, 0)
|
.eq(PointsExchangeOrderItem::getOrderId, orderId));
|
boolean allCompleted = !items.isEmpty();
|
for (PointsExchangeOrderItem item : items) {
|
if (!isCompleted(item.getStatus())) {
|
allCompleted = false;
|
break;
|
}
|
}
|
if (allCompleted) {
|
order.setStatus(STATUS_COMPLETED);
|
order.setCompletedAt(completedAt);
|
pointsExchangeOrderMapper.updateById(order);
|
}
|
}
|
|
/**
|
* 删除订单项后刷新汇总订单数量与状态;无明细时同步删除汇总单。
|
*/
|
private void refreshSummaryOrderAfterDelete(Long orderId) {
|
if (orderId == null) {
|
return;
|
}
|
PointsExchangeOrder order = pointsExchangeOrderMapper.selectById(orderId);
|
if (order == null || order.getDeleted() == null || order.getDeleted().intValue() != 0) {
|
return;
|
}
|
List<PointsExchangeOrderItem> items = pointsExchangeOrderItemMapper.selectList(new LambdaQueryWrapper<PointsExchangeOrderItem>()
|
.eq(PointsExchangeOrderItem::getDeleted, 0)
|
.eq(PointsExchangeOrderItem::getOrderId, orderId));
|
if (items == null || items.isEmpty()) {
|
pointsExchangeOrderMapper.deleteById(orderId);
|
return;
|
}
|
int totalPoints = 0;
|
boolean allCompleted = true;
|
for (PointsExchangeOrderItem item : items) {
|
totalPoints += defaultNumber(item.getSettledPoints()).intValue();
|
if (!isCompleted(item.getStatus())) {
|
allCompleted = false;
|
}
|
}
|
order.setItemCount(Integer.valueOf(items.size()));
|
order.setTotalPoints(Integer.valueOf(totalPoints));
|
if (allCompleted) {
|
order.setStatus(STATUS_COMPLETED);
|
}
|
pointsExchangeOrderMapper.updateById(order);
|
}
|
|
/**
|
* 归一化列表筛选状态,仅允许已定义状态值进入 SQL 条件。
|
*/
|
private Integer normalizeStatus(Integer status) {
|
if (status == null) {
|
return null;
|
}
|
if (status.intValue() == STATUS_PENDING || status.intValue() == STATUS_RECEIVING || status.intValue() == STATUS_COMPLETED) {
|
return status;
|
}
|
return null;
|
}
|
|
/**
|
* 判断当前状态是否允许确认取货。
|
*/
|
private boolean isReceivable(Integer status) {
|
return status != null && status.intValue() == STATUS_RECEIVING;
|
}
|
|
/**
|
* 判断当前状态是否允许删除。
|
*/
|
private boolean isDeletable(Integer status) {
|
return status != null && status.intValue() == STATUS_COMPLETED;
|
}
|
|
/**
|
* 判断当前状态是否为已完成。
|
*/
|
private boolean isCompleted(Integer status) {
|
return status != null && status.intValue() == STATUS_COMPLETED;
|
}
|
|
/**
|
* 将订单状态转换为页面展示文案。
|
*/
|
private String resolveStatusText(Integer status) {
|
if (status == null) {
|
return "";
|
}
|
if (status.intValue() == STATUS_PENDING) {
|
return "待发货";
|
}
|
if (status.intValue() == STATUS_RECEIVING) {
|
return "待取货";
|
}
|
if (status.intValue() == STATUS_COMPLETED) {
|
return "兑换完成";
|
}
|
return "";
|
}
|
|
/**
|
* 将可空文本归一化为空字符串。
|
*/
|
private String trimToEmpty(String value) {
|
if (value == null) {
|
return "";
|
}
|
return value.trim();
|
}
|
|
/**
|
* 将可空积分归一化为非空数字。
|
*/
|
private Integer defaultNumber(Integer value) {
|
return Integer.valueOf(value == null ? 0 : value.intValue());
|
}
|
}
|