mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
trade:完成交易订单的发货逻辑
This commit is contained in:
parent
07f1681b50
commit
66abe4a84b
@ -62,7 +62,7 @@ public class PayOrderUnifiedReqDTO {
|
||||
*/
|
||||
@NotNull(message = "支付金额不能为空")
|
||||
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
||||
private Long amount;
|
||||
private Integer amount;
|
||||
|
||||
/**
|
||||
* 支付过期时间
|
||||
|
@ -63,7 +63,7 @@ public class PayRefundUnifiedReqDTO {
|
||||
*/
|
||||
@NotNull(message = "退款金额不能为空")
|
||||
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
||||
private Long amount;
|
||||
private Integer amount;
|
||||
|
||||
/**
|
||||
* 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要
|
||||
|
@ -69,7 +69,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
this.init();
|
||||
}
|
||||
|
||||
protected Double calculateAmount(Long amount) {
|
||||
protected Double calculateAmount(Integer amount) {
|
||||
return amount / 100.0;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ public class PayClientFactoryImplIntegrationTest {
|
||||
|
||||
private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() {
|
||||
PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO();
|
||||
reqDTO.setAmount(123L);
|
||||
reqDTO.setAmount(123);
|
||||
reqDTO.setSubject("IPhone 13");
|
||||
reqDTO.setBody("biubiubiu");
|
||||
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
|
||||
|
@ -73,7 +73,7 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
|
||||
Long shopOrderId = System.currentTimeMillis();
|
||||
PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO();
|
||||
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
|
||||
reqDTO.setAmount(1L);
|
||||
reqDTO.setAmount(1);
|
||||
reqDTO.setBody("内容:" + shopOrderId);
|
||||
reqDTO.setSubject("标题:"+shopOrderId);
|
||||
String notify="http://niubi.natapp1.cc/api/pay/order/notify";
|
||||
|
@ -23,9 +23,10 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
|
||||
ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
|
||||
ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "交易订单更新支付状态失败,订单不是【未支付】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "交易订单更新支付状态失败,支付单编号不匹配");
|
||||
ErrorCode ORDER_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "交易订单更新支付状态失败,支付单编号不匹配");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态");
|
||||
|
||||
// ========== After Sale 模块 1-011-000-000 ==========
|
||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
|
||||
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.trade.enums.order;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 交易订单 - 发货状态
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum TradeOrderDeliveryStatusEnum {
|
||||
|
||||
UNDELIVERED(0, "未发货"),
|
||||
DELIVERED(1, "已发货"),
|
||||
RECEIVED(2, "已收货");
|
||||
|
||||
/**
|
||||
* 状态值
|
||||
*/
|
||||
private final Integer status;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
@ -52,9 +52,30 @@ public enum TradeOrderStatusEnum implements IntArrayValuable {
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isUnpaid(Integer status) {
|
||||
return ObjectUtil.equal(UNPAID.getStatus(), status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定状态,是否正处于【已支付】状态
|
||||
*
|
||||
* @param status 指定状态
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isPaid(Integer status) {
|
||||
return ObjectUtil.equal(PAID.getStatus(), status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定状态,是否正处于【待发货】状态
|
||||
*
|
||||
* @param status 指定状态
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isUndelivered(Integer status) {
|
||||
return ObjectUtil.equal(UNDELIVERED.getStatus(), status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断指定状态,是否正处于【已取消】状态
|
||||
*
|
||||
|
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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 javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Api(tags = "管理后台 - 交易订单")
|
||||
@RestController
|
||||
@RequestMapping("/trade/order")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class TradeOrderController {
|
||||
|
||||
@Resource
|
||||
private TradeOrderService tradeOrderService;
|
||||
|
||||
@PostMapping("/delivery")
|
||||
@ApiOperation("发货订单")
|
||||
@PreAuthorize("@ss.hasPermission('trade:order:delivery')")
|
||||
public CommonResult<Boolean> deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) {
|
||||
tradeOrderService.deliveryOrder(getLoginUserId(), deliveryReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 订单发货 Request VO")
|
||||
@Data
|
||||
public class TradeOrderDeliveryReqVO {
|
||||
|
||||
@ApiModelProperty(name = "订单编号", required = true, example = "1024")
|
||||
@NotNull(message = "订单编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(name = "发货物流公司编号", required = true, example = "1")
|
||||
@NotNull(message = "发货物流公司编号不能为空")
|
||||
private Long logisticsId;
|
||||
|
||||
@ApiModelProperty(name = "发货物流单号", required = true, example = "SF123456789")
|
||||
@NotEmpty(message = "发货物流单号不能为空")
|
||||
private String logisticsNo;
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ -24,7 +25,7 @@ public class AppTradeAfterSaleDeliveryReqVO {
|
||||
private String logisticsNo;
|
||||
|
||||
@ApiModelProperty(name = "退货时间", required = true)
|
||||
@NotNull(message = "退货时间不能为空")
|
||||
@NotEmpty(message = "退货时间不能为空")
|
||||
private LocalDateTime deliveryTime;
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO.OrderItem;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderAfterSaleStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderDeliveryStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
@ -178,20 +179,24 @@ public class TradeOrderDO extends BaseDO {
|
||||
*/
|
||||
private Long deliveryTemplateId;
|
||||
/**
|
||||
* 物流公司单号
|
||||
* 发货物流公司编号
|
||||
*/
|
||||
private String expressNo;
|
||||
private Long logisticsId;
|
||||
/**
|
||||
* 发货物流单号
|
||||
*/
|
||||
private String logisticsNo;
|
||||
/**
|
||||
* 发货状态
|
||||
*
|
||||
* true - 已发货
|
||||
* false - 未发货
|
||||
* 枚举 {@link TradeOrderDeliveryStatusEnum}
|
||||
*/
|
||||
private Boolean deliveryStatus;
|
||||
private Integer deliveryStatus;
|
||||
/**
|
||||
* 发货时间
|
||||
*/
|
||||
private LocalDateTime deliveryTime;
|
||||
|
||||
/**
|
||||
* 收货时间
|
||||
*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.trade.service.order;
|
||||
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
@ -15,7 +16,7 @@ public interface TradeOrderService {
|
||||
// =================== Order ===================
|
||||
|
||||
/**
|
||||
* 创建交易订单
|
||||
* 【会员】创建交易订单
|
||||
*
|
||||
* @param userId 登录用户
|
||||
* @param userIp 用户 IP 地址
|
||||
@ -24,6 +25,22 @@ public interface TradeOrderService {
|
||||
*/
|
||||
Long createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新交易订单已支付
|
||||
*
|
||||
* @param id 交易订单编号
|
||||
* @param payOrderId 支付订单编号
|
||||
*/
|
||||
void updateOrderPaid(Long id, Long payOrderId);
|
||||
|
||||
/**
|
||||
* 【管理员】发货交易订单
|
||||
*
|
||||
* @param userId 管理员编号
|
||||
* @param deliveryReqVO 发货请求
|
||||
*/
|
||||
void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO);
|
||||
|
||||
/**
|
||||
* 获得指定用户,指定的交易订单
|
||||
*
|
||||
@ -33,14 +50,6 @@ public interface TradeOrderService {
|
||||
*/
|
||||
TradeOrderDO getOrder(Long userId, Long orderId);
|
||||
|
||||
/**
|
||||
* 更新交易订单已支付
|
||||
*
|
||||
* @param id 交易订单编号
|
||||
* @param payOrderId 支付订单编号
|
||||
*/
|
||||
void updateOrderPaid(Long id, Long payOrderId);
|
||||
|
||||
// =================== Order Item ===================
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item;
|
||||
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
||||
@ -107,94 +108,6 @@ public class TradeOrderServiceImpl implements TradeOrderService {
|
||||
return tradeOrderDO.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeOrderDO getOrder(Long userId, Long orderId) {
|
||||
TradeOrderDO order = tradeOrderMapper.selectById(orderId);
|
||||
if (order != null
|
||||
&& ObjectUtil.notEqual(order.getUserId(), userId)) {
|
||||
return null;
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOrderPaid(Long id, Long payOrderId) {
|
||||
// 校验并获得交易订单
|
||||
KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPaid(id, payOrderId);
|
||||
TradeOrderDO order = orderResult.getKey();
|
||||
PayOrderRespDTO payOrder = orderResult.getValue();
|
||||
|
||||
// 更新 TradeOrderDO 状态为已支付,等待发货
|
||||
int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(),
|
||||
new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayed(true)
|
||||
.setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode()));
|
||||
if (updateCount == 0) {
|
||||
throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
|
||||
}
|
||||
|
||||
// TODO 芋艿:发送订单变化的消息
|
||||
|
||||
// TODO 芋艿:发送站内信
|
||||
|
||||
// TODO 芋艿:OrderLog
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验交易订单满足被支付的条件
|
||||
*
|
||||
* 1. 交易订单未支付
|
||||
* 2. 支付单已支付
|
||||
*
|
||||
* @param id 交易订单编号
|
||||
* @param payOrderId 支付订单编号
|
||||
* @return 交易订单
|
||||
*/
|
||||
private KeyValue<TradeOrderDO, PayOrderRespDTO> validateOrderPaid(Long id, Long payOrderId) {
|
||||
// 校验订单是否存在
|
||||
TradeOrderDO order = tradeOrderMapper.selectById(id);
|
||||
if (order == null) {
|
||||
throw exception(ORDER_NOT_FOUND);
|
||||
}
|
||||
// 校验订单未支付
|
||||
if (TradeOrderStatusEnum.isUnpaid(order.getStatus())) { // 状态
|
||||
log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]",
|
||||
id, JsonUtils.toJsonString(order));
|
||||
throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
|
||||
}
|
||||
// 校验支付订单匹配
|
||||
if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
|
||||
log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(order));
|
||||
throw exception(ORDER_UPDATE_PAID_PAY_ORDER_ID_ERROR);
|
||||
}
|
||||
|
||||
// 校验支付单是否存在
|
||||
PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
|
||||
if (payOrder == null) {
|
||||
log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
|
||||
throw exception(PAY_ORDER_NOT_FOUND);
|
||||
}
|
||||
// 校验支付单已支付
|
||||
if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
|
||||
log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(payOrder));
|
||||
throw exception(ORDER_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS);
|
||||
}
|
||||
// 校验支付金额一致
|
||||
if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPayPrice())) {
|
||||
log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
|
||||
throw exception(ORDER_UPDATE_PAID_PAY_PRICE_NOT_MATCH);
|
||||
}
|
||||
// 校验支付订单匹配(二次)
|
||||
if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) {
|
||||
log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(payOrder));
|
||||
throw exception(ORDER_UPDATE_PAID_PAY_ORDER_ID_ERROR);
|
||||
}
|
||||
return new KeyValue<>(order, payOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验商品 SKU 是否可出售
|
||||
*
|
||||
@ -269,7 +182,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
|
||||
tradeOrderDO.setProductCount(getSumValue(order.getItems(), PriceCalculateRespDTO.OrderItem::getCount, Integer::sum));
|
||||
tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源?
|
||||
tradeOrderDO.setAdjustPrice(0).setPayed(false); // 支付信息
|
||||
tradeOrderDO.setDeliveryStatus(false); // 物流信息
|
||||
tradeOrderDO.setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); // 物流信息
|
||||
tradeOrderDO.setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.NONE.getStatus()).setRefundPrice(0); // 退款信息
|
||||
tradeOrderMapper.insert(tradeOrderDO);
|
||||
return tradeOrderDO;
|
||||
@ -324,7 +237,142 @@ public class TradeOrderServiceImpl implements TradeOrderService {
|
||||
tradeOrderMapper.updateById(new TradeOrderDO().setId(tradeOrderDO.getId()).setPayOrderId(payOrderId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOrderPaid(Long id, Long payOrderId) {
|
||||
// 校验并获得交易订单(可支付)
|
||||
KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPayable(id, payOrderId);
|
||||
TradeOrderDO order = orderResult.getKey();
|
||||
PayOrderRespDTO payOrder = orderResult.getValue();
|
||||
|
||||
// 更新 TradeOrderDO 状态为已支付,等待发货
|
||||
int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(),
|
||||
new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayed(true)
|
||||
.setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode()));
|
||||
if (updateCount == 0) {
|
||||
throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
|
||||
}
|
||||
|
||||
// TODO 芋艿:发送订单变化的消息
|
||||
|
||||
// TODO 芋艿:发送站内信
|
||||
|
||||
// TODO 芋艿:OrderLog
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验交易订单满足被支付的条件
|
||||
*
|
||||
* 1. 交易订单未支付
|
||||
* 2. 支付单已支付
|
||||
*
|
||||
* @param id 交易订单编号
|
||||
* @param payOrderId 支付订单编号
|
||||
* @return 交易订单
|
||||
*/
|
||||
private KeyValue<TradeOrderDO, PayOrderRespDTO> validateOrderPayable(Long id, Long payOrderId) {
|
||||
// 校验订单是否存在
|
||||
TradeOrderDO order = tradeOrderMapper.selectById(id);
|
||||
if (order == null) {
|
||||
throw exception(ORDER_NOT_FOUND);
|
||||
}
|
||||
// 校验订单未支付
|
||||
if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayed()) {
|
||||
log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]",
|
||||
id, JsonUtils.toJsonString(order));
|
||||
throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
|
||||
}
|
||||
// 校验支付订单匹配
|
||||
if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
|
||||
log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(order));
|
||||
throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
|
||||
}
|
||||
|
||||
// 校验支付单是否存在
|
||||
PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
|
||||
if (payOrder == null) {
|
||||
log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
|
||||
throw exception(PAY_ORDER_NOT_FOUND);
|
||||
}
|
||||
// 校验支付单已支付
|
||||
if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
|
||||
log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(payOrder));
|
||||
throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS);
|
||||
}
|
||||
// 校验支付金额一致
|
||||
if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPayPrice())) {
|
||||
log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
|
||||
throw exception(ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH);
|
||||
}
|
||||
// 校验支付订单匹配(二次)
|
||||
if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) {
|
||||
log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
|
||||
id, payOrderId, JsonUtils.toJsonString(payOrder));
|
||||
throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
|
||||
}
|
||||
return new KeyValue<>(order, payOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) {
|
||||
// 校验并获得交易订单(可发货)
|
||||
TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
|
||||
|
||||
// TODO 芋艿:logisticsId 校验存在
|
||||
|
||||
// 更新 TradeOrderDO 状态为已发货,等待收货
|
||||
int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
|
||||
new TradeOrderDO().setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
|
||||
.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo())
|
||||
.setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()));
|
||||
if (updateCount == 0) {
|
||||
throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
|
||||
}
|
||||
|
||||
// TODO 芋艿:发送订单变化的消息
|
||||
|
||||
// TODO 芋艿:发送站内信
|
||||
|
||||
// TODO 芋艿:OrderLog
|
||||
|
||||
// TODO 设计:like:是否要单独一个 delivery 发货单表???
|
||||
// TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞
|
||||
// TODO 设计:lili:是不是发货后,才支持售后?
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验交易订单满足被发货的条件
|
||||
*
|
||||
* 1. 交易订单未发货
|
||||
*
|
||||
* @param id 交易订单编号
|
||||
* @return 交易订单
|
||||
*/
|
||||
private TradeOrderDO validateOrderDeliverable(Long id) {
|
||||
// 校验订单是否存在
|
||||
TradeOrderDO order = tradeOrderMapper.selectById(id);
|
||||
if (order == null) {
|
||||
throw exception(ORDER_NOT_FOUND);
|
||||
}
|
||||
// 校验订单是否是待发货状态
|
||||
if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())
|
||||
|| ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus())) {
|
||||
throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeOrderDO getOrder(Long userId, Long orderId) {
|
||||
TradeOrderDO order = tradeOrderMapper.selectById(orderId);
|
||||
if (order != null
|
||||
&& ObjectUtil.notEqual(order.getUserId(), userId)) {
|
||||
return null;
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
// =================== Order Item ===================
|
||||
|
||||
|
@ -16,15 +16,13 @@ import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderAfterSaleStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.*;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -38,6 +36,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
@ -173,8 +173,8 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
|
||||
assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
|
||||
assertNull(tradeOrderDO.getPayChannelCode());
|
||||
assertNull(tradeOrderDO.getDeliveryTemplateId());
|
||||
assertNull(tradeOrderDO.getExpressNo());
|
||||
assertFalse(tradeOrderDO.getDeliveryStatus());
|
||||
assertNull(tradeOrderDO.getLogisticsId());
|
||||
assertEquals(tradeOrderDO.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus());
|
||||
assertNull(tradeOrderDO.getDeliveryTime());
|
||||
assertNull(tradeOrderDO.getReceiveTime());
|
||||
assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
|
||||
@ -246,11 +246,11 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateOrderPaid() {
|
||||
public void testUpdateOrderPaid() {
|
||||
// mock 数据(TradeOrder)
|
||||
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
|
||||
o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
|
||||
o.setPayOrderId(10L).setPayPrice(100).setPayTime(null);
|
||||
o.setPayOrderId(10L).setPayed(false).setPayPrice(100).setPayTime(null);
|
||||
});
|
||||
tradeOrderMapper.insert(order);
|
||||
// 准备参数
|
||||
@ -260,13 +260,39 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
|
||||
when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub")
|
||||
.setMerchantOrderId("1")).setAmount(100));
|
||||
|
||||
// 调用
|
||||
tradeOrderService.updateOrderPaid(id, payOrderId);
|
||||
// 断言
|
||||
TradeOrderDO dbOrder = tradeOrderMapper.selectById(id);
|
||||
assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.PAID.getStatus());
|
||||
assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
|
||||
assertTrue(dbOrder.getPayed());
|
||||
assertNotNull(dbOrder.getPayTime());
|
||||
assertEquals(dbOrder.getPayChannelCode(), "wx_pub");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeliveryOrder() {
|
||||
// mock 数据(TradeOrder)
|
||||
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
|
||||
o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
|
||||
o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null)
|
||||
.setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus());
|
||||
});
|
||||
tradeOrderMapper.insert(order);
|
||||
// 准备参数
|
||||
TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L)
|
||||
.setLogisticsId(10L).setLogisticsNo("100");
|
||||
// mock 方法(支付单)
|
||||
|
||||
// 调用
|
||||
tradeOrderService.deliveryOrder(randomLongId(), deliveryReqVO);
|
||||
// 断言
|
||||
TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L);
|
||||
assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus());
|
||||
assertEquals(dbOrder.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.DELIVERED.getStatus());
|
||||
assertPojoEquals(dbOrder, deliveryReqVO);
|
||||
assertNotNull(dbOrder.getDeliveryTime());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,10 +20,11 @@ CREATE TABLE IF NOT EXISTS "trade_order" (
|
||||
"delivery_price" int NOT NULL,
|
||||
"adjust_price" int NOT NULL,
|
||||
"pay_price" int NOT NULL,
|
||||
"pay_order_id" int,
|
||||
"pay_order_id" bigint,
|
||||
"pay_channel_code" varchar,
|
||||
"delivery_template_id" bigint,
|
||||
"express_no" varchar,
|
||||
"logistics_id" bigint,
|
||||
"logistics_no" varchar,
|
||||
"delivery_status" bit NOT NULL,
|
||||
"delivery_time" datetime,
|
||||
"receive_time" datetime,
|
||||
|
@ -132,11 +132,11 @@ public class PayRefundDO extends BaseDO {
|
||||
/**
|
||||
* 支付金额,单位:分
|
||||
*/
|
||||
private Long payAmount;
|
||||
private Integer payAmount;
|
||||
/**
|
||||
* 退款金额,单位:分
|
||||
*/
|
||||
private Long refundAmount;
|
||||
private Integer refundAmount;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
|
@ -31,7 +31,7 @@ public class PayRefundReqDTO {
|
||||
*/
|
||||
@NotNull(message = "退款金额不能为空")
|
||||
@DecimalMin(value = "0", inclusive = false, message = "退款金额必须大于零")
|
||||
private Long amount;
|
||||
private Integer amount;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
|
Loading…
Reference in New Issue
Block a user