记得上下班打卡 | git大法好,push需谨慎

Commit ee504be7 authored by wangyifan's avatar wangyifan

商品退款功能改造

parent 65b4df16
package com.liquidnet.service.goblin.param;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class GoblinStoreOrderRefundParam {
@ApiModelProperty(value = "订单id")
@NotNull(message = "订单id不能为空")
private String orderId;
@ApiModelProperty(value = "退款orderSkuId列表[发货后可选;不传为整单退款;发货前强制整单退款]")
private List<String> orderSkuIds;
@ApiModelProperty(value = "退款原因")
private String reason;
@ApiModelProperty(value = "详细描述")
private String describes;
}
......@@ -3,10 +3,8 @@ package com.liquidnet.service.goblin.service.manage;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderDetailsVo;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreBackOrderListVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderListVo;
import com.liquidnet.service.goblin.param.RefundCallbackParam;
import com.liquidnet.service.goblin.param.GoblinStoreOrderRefundParam;
import java.math.BigDecimal;
......@@ -28,5 +26,7 @@ public interface IGoblinStoreBackOrderService {
ResponseDto<Boolean> refusedRefund(String backOrderId);
ResponseDto<Boolean> refundOrder(GoblinStoreOrderRefundParam param);
ResponseDto<Boolean> changeSkuRefund(String backOrderId, BigDecimal refundPrice, String orderSkuId);
}
......@@ -4,12 +4,9 @@ import com.github.pagehelper.PageInfo;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderDetailsVo;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreBackOrderListVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderListVo;
import com.liquidnet.service.goblin.param.RefundCallbackParam;
import com.liquidnet.service.goblin.param.GoblinStoreOrderRefundParam;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreBackOrderService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
......@@ -83,6 +80,12 @@ public class GoblinStoreBackOrderController {
return goblinStoreBackOrderService.refusedRefund(backOrderId);
}
@ApiOperation(value = "发起退款")
@PostMapping(value = "refund")
public ResponseDto<Boolean> refundOrder(@RequestBody @Valid GoblinStoreOrderRefundParam param) {
return goblinStoreBackOrderService.refundOrder(param);
}
@ApiOperation(value = "修改金额")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "backOrderId", value = "订单id"),
......
package com.liquidnet.service.goblin.service.impl.helper;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinOrderSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderVo;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import java.math.BigDecimal;
import java.util.HashMap;
@Component
@Slf4j
public class GoblinRefundHelper {
@Autowired
private GoblinRedisUtils redisUtils;
@Value("${liquidnet.service.order.url-pay.goblinRefundUrl}")
private String synUrl;
@Value("${liquidnet.service.dragon.urls.refundApply}")
private String refundApply;
@Value("${liquidnet.service.order.url-pay.goblinRefundUrl}")
private String goblinRefundUrl;
@Value("${liquidnet.service.dragon.urls.refundResult}")
private String refundApplyCallBack;
public static BigDecimal remainRefundPrice(GoblinOrderSkuVo orderSkuVo, BigDecimal applyingRefundPrice) {
BigDecimal priceActual = nullToZero(orderSkuVo.getSkuPriceActual());
BigDecimal priceRefund = nullToZero(orderSkuVo.getPriceRefund());
BigDecimal applying = nullToZero(applyingRefundPrice);
BigDecimal remain = priceActual.subtract(priceRefund).subtract(applying);
return remain.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : remain;
}
public static BigDecimal beforeShipRefundPrice(BigDecimal skuRefundPrice, BigDecimal priceExpress) {
return nullToZero(skuRefundPrice).add(nullToZero(priceExpress));
}
public static GoblinBackOrderSkuVo buildBackOrderSkuVo(GoblinOrderSkuVo orderSkuVo, BigDecimal refundPrice, String nowStr) {
GoblinBackOrderSkuVo backOrderSkuVo = GoblinBackOrderSkuVo.getNew();
backOrderSkuVo.setOrderSkuId(orderSkuVo.getOrderSkuId());
backOrderSkuVo.setSpuId(orderSkuVo.getSpuId());
backOrderSkuVo.setSpuName(orderSkuVo.getSpuName());
backOrderSkuVo.setSkuId(orderSkuVo.getSkuId());
backOrderSkuVo.setSkuName(orderSkuVo.getSkuName());
backOrderSkuVo.setRefundPrice(refundPrice);
backOrderSkuVo.setSkuSpecs(orderSkuVo.getSkuSpecs());
backOrderSkuVo.setCreatedAt(nowStr);
backOrderSkuVo.setSkuPic(orderSkuVo.getSkuImage());
backOrderSkuVo.setSkuType(orderSkuVo.getSkuType());
return backOrderSkuVo;
}
public static boolean isBackOrderFinished(Integer status) {
return status != null && (status == 2 || status == 3 || status == 5 || status == 8 || status == 9 || status == 10 || status == 11);
}
public static boolean isUnshippedSku(GoblinOrderSkuVo orderSkuVo) {
return orderSkuVo != null && orderSkuVo.getStatus() == 2;
}
public static boolean isShippedSku(GoblinOrderSkuVo orderSkuVo) {
if (orderSkuVo == null) {
return false;
}
return orderSkuVo.getStatus() == 3 || orderSkuVo.getStatus() == 4;
}
public String initRefund(GoblinStoreOrderVo orderVo, BigDecimal price, String refundCode) {
MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
params.add("code", orderVo.getPayCode());
params.add("notifyUrl", synUrl);
params.add("orderCode", orderVo.getMasterOrderCode());
params.add("orderRefundCode", refundCode);
params.add("paymentId", orderVo.getPaymentId());
params.add("paymentType", orderVo.getPaymentType());
params.add("price", String.valueOf(price));
params.add("priceTotal", String.valueOf(getMasterOrderActualPrice(orderVo)));
params.add("reason", "按需退款");
MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
headers.add("Accept", "application/json;charset=UTF-8");
String returnString = HttpUtil.post(refundApply, params, headers);
log.debug("REFUND DATA = " + returnString);
return returnString;
}
public String alipayCallBack(GoblinStoreOrderVo orderVo, String refundCode) {
MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
params.add("callBackUrl", goblinRefundUrl);
params.add("orderCode", orderVo.getMasterOrderCode());
params.add("orderRefundCode", refundCode);
params.add("paymentId", orderVo.getPaymentId());
MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
headers.add("Accept", "application/json;charset=UTF-8");
log.debug("REFUND CALLBACK params = " + params);
String returnString = HttpUtil.post(refundApplyCallBack, params, headers);
log.debug("REFUND CALLBACK DATA = " + returnString);
return returnString;
}
public boolean isRefundSuccess(String returnString) {
HashMap hashMapResult = JsonUtils.fromJson(returnString, HashMap.class);
Boolean success = (Boolean) hashMapResult.get("success");
return Boolean.TRUE.equals(success);
}
public String getRefundMessage(String returnString) {
HashMap hashMapResult = JsonUtils.fromJson(returnString, HashMap.class);
String message = (String) hashMapResult.get("message");
return message == null ? "" : message;
}
private BigDecimal getMasterOrderActualPrice(GoblinStoreOrderVo orderVo) {
BigDecimal totalPrice = BigDecimal.ZERO;
String[] orderIds = redisUtils.getMasterCode(orderVo.getMasterOrderCode());
if (orderIds == null || orderIds.length == 0) {
return nullToZero(orderVo.getPriceActual());
}
for (String orderId : orderIds) {
GoblinStoreOrderVo vo = redisUtils.getGoblinOrder(orderId);
if (vo != null) {
totalPrice = totalPrice.add(nullToZero(vo.getPriceActual()));
}
}
return totalPrice.compareTo(BigDecimal.ZERO) > 0 ? totalPrice : nullToZero(orderVo.getPriceActual());
}
private static BigDecimal nullToZero(BigDecimal value) {
return value == null ? BigDecimal.ZERO : value;
}
}
......@@ -1711,6 +1711,21 @@ public class GoblinMongoUtils {
return refundPrice;
}
// 获取指定子单已成功或进行中的退款金额;新退款链路需要精确到当前 orderSkuId,避免多子单退款单被重复累计。
public BigDecimal getRefundOrderSkuVoPriceBySkuId(String orderSkuId) {
BigDecimal refundPrice = BigDecimal.ZERO;
List<GoblinBackOrderVo> backOrderVos = mongoTemplate.find(Query.query(Criteria.where("backOrderSkuVos.orderSkuId").is(orderSkuId).and("status").nin(3, 5, 9, 10, 11)),
GoblinBackOrderVo.class, GoblinBackOrderVo.class.getSimpleName());
for (GoblinBackOrderVo vo : backOrderVos) {
for (GoblinBackOrderSkuVo orderSkuVo : vo.getBackOrderSkuVos()) {
if (orderSkuId.equals(orderSkuVo.getOrderSkuId())) {
refundPrice = refundPrice.add(orderSkuVo.getRefundPrice());
}
}
}
return refundPrice;
}
//根据spuId查询活动id
public List<String> getMarketIdListBySpuId(String spuId) {
Query query = Query.query(Criteria.where("marketId").ne(null).and("spuId").regex(spuId.concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue()).concat(".*")));
......
......@@ -129,6 +129,7 @@ goblin_order.store.log=INSERT INTO goblin_order_operation_log (`order_log_id`,`o
goblin_order.store.refundLog=INSERT INTO goblin_back_order_log (`back_order_log_id`,`back_order_id`,`operation_type`,`message`,`operation_name`,`status`,`created_at`) VALUES(?,?,?,?,?,?,?)
goblin_order.store.orderExpressPrice=UPDATE goblin_store_order SET price_total =? , price_modify = ? ,price_voucher = ? , price_actual = ? ,price_express = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.store.backOrder=INSERT INTO goblin_back_order (`back_order_id`,`back_code`,`order_id`,`order_code`,`store_id`,`user_id`,`sku_id_nums`,`type`,`reason`,`describes`,`real_back_price`,`status`,`created_at`,`audit_at`,`error_reason`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
goblin_order.store.backOrderWithExpress=INSERT INTO goblin_back_order (`back_order_id`,`back_code`,`order_id`,`order_code`,`store_id`,`user_id`,`sku_id_nums`,`type`,`reason`,`describes`,`real_back_price`,`back_price_express`,`status`,`pics`,`created_at`,`audit_at`,`error_reason`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
goblin_order.store.changeExpress=UPDATE goblin_back_order SET real_back_price = ? ,back_price_express = ? updated_at = ? WHERE back_order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.store.changeSku=UPDATE goblin_back_order SET real_back_price = ? , updated_at = ? WHERE back_order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.store.backOrderStatus=UPDATE goblin_back_order SET status = ? , refuse_at=?,refuse_size=?,updated_at = ? WHERE back_order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
......@@ -137,6 +138,7 @@ goblin_order.store.orderStatus.time=UPDATE goblin_store_order SET status = ? ,zh
goblin_order.store.applyRefund=UPDATE goblin_back_order SET status = ? ,reason=?,audit_at=?, updated_at = ? WHERE back_order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
#---- \u7528\u6237\u8BA2\u5355\u64CD\u4F5C
goblin_order.user.applyRefund=INSERT INTO goblin_back_order (`back_order_id`,`back_code`,`order_id`,`order_code`,`store_id`,`user_id`,`sku_id_nums`,`type`,`reason`,`describes`,`real_back_price`,`back_price_express`,`status`,`logis_company_name`,`mail_no`,`pics`,`created_at`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
goblin_order.user.applyRefundAuto=INSERT INTO goblin_back_order (`back_order_id`,`back_code`,`order_id`,`order_code`,`store_id`,`user_id`,`sku_id_nums`,`type`,`reason`,`describes`,`real_back_price`,`back_price_express`,`status`,`logis_company_name`,`mail_no`,`pics`,`created_at`,`audit_at`,`error_reason`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
goblin_order.user.againRefund=UPDATE goblin_back_order SET status = ? , describes = ? , pics = ? , reason = ? , type = ?, updated_at=? where back_order_id=?
#---- \u8D2D\u7269\u8F66\u64CD\u4F5C
goblin_shop.cart.delete=UPDATE goblin_shopping_cart set del_tag=? where user_id=? and sku_id=?
......
package com.liquidnet.service.goblin.test;
import com.liquidnet.service.goblin.dto.vo.GoblinOrderSkuVo;
import com.liquidnet.service.goblin.service.impl.helper.GoblinRefundHelper;
import org.junit.Assert;
import org.junit.Test;
import java.math.BigDecimal;
public class GoblinRefundHelperTest {
@Test
public void remainRefundPriceSubtractsRefundedAndApplyingAmount() {
GoblinOrderSkuVo skuVo = new GoblinOrderSkuVo();
skuVo.setSkuPriceActual(new BigDecimal("100.00"));
skuVo.setPriceRefund(new BigDecimal("30.00"));
BigDecimal remain = GoblinRefundHelper.remainRefundPrice(skuVo, new BigDecimal("20.00"));
Assert.assertEquals(0, new BigDecimal("50.00").compareTo(remain));
}
@Test
public void remainRefundPriceNeverReturnsNegativeAmount() {
GoblinOrderSkuVo skuVo = new GoblinOrderSkuVo();
skuVo.setSkuPriceActual(new BigDecimal("10.00"));
skuVo.setPriceRefund(new BigDecimal("8.00"));
BigDecimal remain = GoblinRefundHelper.remainRefundPrice(skuVo, new BigDecimal("5.00"));
Assert.assertEquals(0, BigDecimal.ZERO.compareTo(remain));
}
@Test
public void beforeShipRefundIncludesExpressFee() {
BigDecimal refundPrice = GoblinRefundHelper.beforeShipRefundPrice(new BigDecimal("80.00"), new BigDecimal("12.00"));
Assert.assertEquals(0, new BigDecimal("92.00").compareTo(refundPrice));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment