From 1b5fd04c5518d1c9e27cef669845a4b6fd9b05e6 Mon Sep 17 00:00:00 2001 From: Stormeye Wu Date: Thu, 15 Aug 2019 11:20:58 +0800 Subject: [PATCH] =?UTF-8?q?[POS][=E4=BF=AE=E6=94=B9]:=E5=8D=A1=E6=B6=88?= =?UTF-8?q?=E8=B4=B9=E6=94=AF=E6=8C=81pos,=20=E9=A2=84=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=8F=8A=E9=A2=84=E6=94=AF=E4=BB=98=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration/V201908150940__POS_CHANGED.sql | 2 + .../V201908151120__POS_CAR_SPEND.sql | 6 + .../iformall/controller/PosController.java | 74 ++++++++ .../java/com/iformall/service/PosService.java | 16 ++ .../iformall/service/impl/PosServiceImpl.java | 132 +++++++++++++ .../java/com/iformall/common/ErrorCode.java | 3 + .../com/iformall/domain/po/WxCardSpend.java | 10 +- .../com/iformall/enums/EnumCardSpendFrom.java | 39 ++++ .../iformall/enums/EnumCardSpendStatus.java | 5 +- .../iformall/mapper/WxCardSpendMapper.java | 5 +- .../java/com/iformall/pay/WxPayConstant.java | 4 + .../iformall/service/WxCardSpendService.java | 7 +- .../service/impl/WxCardSpendServiceImpl.java | 175 +++++++++++++++++- .../resources/mapper/WxCardSpendMapper.xml | 22 ++- 14 files changed, 489 insertions(+), 11 deletions(-) create mode 100644 mallinkAdmin/src/main/resources/db/migration/V201908150940__POS_CHANGED.sql create mode 100644 mallinkAdmin/src/main/resources/db/migration/V201908151120__POS_CAR_SPEND.sql create mode 100644 mallinkService/src/main/java/com/iformall/enums/EnumCardSpendFrom.java diff --git a/mallinkAdmin/src/main/resources/db/migration/V201908150940__POS_CHANGED.sql b/mallinkAdmin/src/main/resources/db/migration/V201908150940__POS_CHANGED.sql new file mode 100644 index 000000000..1108a87bf --- /dev/null +++ b/mallinkAdmin/src/main/resources/db/migration/V201908150940__POS_CHANGED.sql @@ -0,0 +1,2 @@ +alter table pos_mall_config +add column `card` tinyint(6) NOT NULL DEFAULT '0' COMMENT '会员优惠券状态,0-使用中,1-禁用'; \ No newline at end of file diff --git a/mallinkAdmin/src/main/resources/db/migration/V201908151120__POS_CAR_SPEND.sql b/mallinkAdmin/src/main/resources/db/migration/V201908151120__POS_CAR_SPEND.sql new file mode 100644 index 000000000..478f9c2e7 --- /dev/null +++ b/mallinkAdmin/src/main/resources/db/migration/V201908151120__POS_CAR_SPEND.sql @@ -0,0 +1,6 @@ +ALTER TABLE `wx_card_spend` +ADD `from` tinyint(6) NOT NULL DEFAULT '0' COMMENT '来源(0:C端小程序扫一扫, 1:B端POS, 2:东软POS)', +ADD `pos_refund_status` tinyint(6) NULL COMMENT 'pos状态(1:POS线下退款开始, 2:POS线下退款成功)', +ADD COLUMN `pos_order_id` bigint(20) NULL COMMENT 'POS订单账号', +CHANGE COLUMN `ip` `ip` varchar(20) COMMENT 'ip地址', +CHANGE COLUMN `pay_status` `pay_status` smallint(2) NOT NULL DEFAULT 0 COMMENT '支付状态(0:未分帐, 1:已分账, 2:已人工分账, 10:预支付(POS))'; \ No newline at end of file diff --git a/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java b/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java index 264165e65..3fec8b572 100644 --- a/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java +++ b/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java @@ -388,6 +388,80 @@ public class PosController extends BaseController { } } + @ApiOperation(value = "消费卡支付接口", notes = "{" + + "\"dev_id\":\"string(必填)\"," + + "\"tenant_id\":\"string(必填)\"," + + "\"merchant_id\":\"string(必填)\"," + + "\"bu_user_id\":\"string(必填)\"," + + "\"nonce_str\":\"string(必填)\"," + + "\"pos_order_id\":\"string(必填)\"," + + "\"pos_amount\":\"string(必填)\"," + + "\"card_id\":\"string(必填)\" }") + @PostMapping("/cardPay") + public Map cardPay(@RequestBody Map params) { + JSONObject payContent = new JSONObject(); + + // 1. check sign + Map retMap = checkSign(params, payContent); + if (retMap != null) { + // 签名相关异常返回 + return retMap; + } + String resKey = payContent.getString("resKey"); + logger.info("resKey: " + resKey); + + try { + retMap = posService.cardPay(params); + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_SUCCESS, null); + } catch (MallinkException e) { + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_FAIL, + e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_FAIL, + 500, e.getMessage()); + } + } + + @ApiOperation(value = "卡支付取消", notes = "{" + + "\"dev_id\":\"string(必填)\"," + + "\"tenant_id\":\"string(必填)\"," + + "\"merchant_id\":\"string(必填)\"," + + "\"bu_user_id\":\"string(必填)\"," + + "\"pos_order_id\":\"string(必填)\"," + + "\"coupon_order_id\":\"string(必填)\"" + + "\"nonce_str\":\"string(必填)\"," + + "\"force\":\"string(选填true/false)\" }") + @PostMapping("/cardPayCancel") + public Map cardPayCancel(@RequestBody Map params) { + JSONObject payContent = new JSONObject(); + + // 1. check sign + Map retMap = checkSign(params, payContent); + if (retMap != null) { + // 签名相关异常返回 + return retMap; + } + String resKey = payContent.getString("resKey"); + logger.info("resKey: " + resKey); + + try { + retMap = posService.cardPayCancel(params); + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_SUCCESS, null); + } catch (MallinkException e) { + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_FAIL, + e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_FAIL, + 500, e.getMessage()); + } + } + /** * 构造返回map,无签名, 有错误 diff --git a/mallinkPosApi/src/main/java/com/iformall/service/PosService.java b/mallinkPosApi/src/main/java/com/iformall/service/PosService.java index 155c2a0a7..9c9d777d6 100644 --- a/mallinkPosApi/src/main/java/com/iformall/service/PosService.java +++ b/mallinkPosApi/src/main/java/com/iformall/service/PosService.java @@ -55,4 +55,20 @@ public interface PosService { * @throws MallinkException */ Map couponOrderVerifyListDo(@RequestBody Map params, EnumVerifyActionType actionType) throws MallinkException; + + /** + * 消费卡POS支付 + * @param params + * @return + * @throws MallinkException + */ + Map cardPay(@RequestBody Map params) throws MallinkException; + + /** + * 消费卡POS支付取消 + * @param params + * @return + * @throws MallinkException + */ + Map cardPayCancel(@RequestBody Map params) throws MallinkException; } diff --git a/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java b/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java index 35dab742b..58cf5e0d7 100644 --- a/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java +++ b/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java @@ -44,6 +44,8 @@ public class PosServiceImpl implements PosService { private final PosCouponOrderVerifyService posCouponOrderVerifyService; private final WxScoreRulesService scoreRulesService; private final WxCreditHistoryService creditHistoryService; + private final WxCardInfoService cardInfoService; + private final WxCardSpendService cardSpendService; private final WxOrderMapper orderMapper; private final WxCouponOrderMapper couponOrderMapper; @@ -1148,4 +1150,134 @@ public class PosServiceImpl implements PosService { } logger.info("核销已取消: " + couponOrderCVo.getId()); } + + @Override + @Transactional(rollbackFor = Exception.class) + public Map cardPay(@RequestBody Map params) throws MallinkException { + Map retMap = new HashMap<>(); + + String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID + String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID + String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID + String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID + String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单总额(单位:分) + String cardIdStr = params.get(WxPayConstant.CARD_ID); // 消费卡ID + + if (StringUtils.isBlank(tenantId)) { + String errMessage = "request params[tenant_id] error."; + logger.error(errMessage); + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + PosMallConfig config = posMallConfigService.getByTenantId(tenantId); + if (config == null) { + logger.error(ErrorCode.POS_CONFIG_NOT_FOUND.getMessage()); + throw new MallinkException(ErrorCode.POS_CONFIG_NOT_FOUND); + } + if (!config.getCoupon().equals(EnumEnableType.Enable.getCode())) { + logger.error(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE.getMessage()); + throw new MallinkException(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE); + } + if (StringUtils.isBlank(merchantIdStr)) { + String errMessage = "request params[merchant_id] error."; + logger.error(errMessage); + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + if (StringUtils.isBlank(buUserIdStr)) { + String errMessage = "request params[bu_user_id] error."; + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + if (StringUtils.isBlank(posOrderIdStr)) { + String errMessage = "request params[pos_order_id] error."; + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + if (StringUtils.isBlank(posAmountStr)) { + String errMessage = "request params[pos_amount] error."; + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + if (StringUtils.isBlank(cardIdStr)) { + String errMessage = "request params[coupon_order_id] error."; + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + + Long merchantId, buUserId, posOrderId, cardId; + Integer posAmount = 0; + try { + merchantId = Long.valueOf(merchantIdStr); + buUserId = Long.valueOf(buUserIdStr); + posOrderId = Long.valueOf(posOrderIdStr); + posAmount = Integer.valueOf(posAmountStr); + cardId = Long.valueOf(cardIdStr); + } catch (NumberFormatException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); + } + WxCardInfo cardInfo = cardInfoService.getById(cardId); + if(cardInfo == null) { + String errMessage = "卡不存在: " + cardIdStr; + logger.error(errMessage); + throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND.getCode(), errMessage); + } + WxCouponMerchant couponMerchant = cardSpendService.checkMerchantInCoupon(cardInfo, merchantId); + if(couponMerchant == null) { + String errMessage = "商户不支持此卡 " + cardIdStr; + logger.error(errMessage); + throw new MallinkException(ErrorCode.COUPON_ORDER_MERANT_IS_NULL.getCode(), errMessage); + } + // 2. check merchant + WxMerchant merchant = merchantService.getById(merchantId); + if (merchant == null) { + logger.error(ErrorCode.MERCHANT_INFO_NOT_FOUND.getMessage() + ": " + merchantIdStr); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); + } + if (merchant.getIsDel().equals(EnumDelStatus.DEL.getCode()) || merchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())) { + logger.error(ErrorCode.MERCHANT_INFO_NOT_VALID.getMessage() + ": " + merchantIdStr); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_VALID); + } + // 3. check buUser + WxMerchantBUser buUser = merchantBUserService.getById(buUserId); + if (buUser == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage() + ": " + buUserIdStr); + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + if (!buUser.getMerchantId().equals(merchantId)) { + logger.error(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG.getMessage() + ": " + buUserIdStr); + throw new MallinkException(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG); + } + + WxCouponOrder couponOrder = couponOrderService.getById(cardId); + if(couponOrder == null) { + logger.error("卡不存在: " + cardIdStr); + throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND); + } + + if(posAmount > cardInfo.getRemainingAmount()) { + logger.error("卡余额不足: " + cardIdStr); + throw new MallinkException(ErrorCode.CARD_REMAIN_AMOUNT_IS_NOT_ENOUGH); + } + WxCardSpend record = new WxCardSpend(); + record.setTenantId(merchant.getTenantId()); + record.setCardId(cardId); + record.setOwnerId(couponOrder.getOwnerId()); + record.setMerchantId(merchantId); + record.setOrderId(posOrderId); + record.setDeductionAmount(posAmount); + + try { + //return cardSpendService.createCardSpend(record, order, couponMerchant); + } catch (MallinkException e) { + logger.error("card spend error, req 2: " + record.toString() + ", e:" + e.getMessage()); + throw new MallinkException(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("card spend error, req 3: " + record.toString() + ", e:" + e.getMessage()); + throw new MallinkException(500, e.getMessage()); + } + retMap.put(WxPayConstant.RET, ""); + return retMap; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Map cardPayCancel(@RequestBody Map params) throws MallinkException { + return null; + } } diff --git a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java index cf80ffc69..05cdd3fe7 100644 --- a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java @@ -27,6 +27,7 @@ public enum ErrorCode{ SYS_EXTEND_JSON_ERROR(1012, "JSON格式异常"), SYS_REPEAT_SUBMIT_EXCEPTION(1013, "请勿重复操作"), REPORT_TYPE_UNKNOWN(1014, "不支持的报表类型"), + SYS_MCH_NOT_FOUND(1015, "微信商户号未找到"), /** * 菜单 @@ -198,11 +199,13 @@ public enum ErrorCode{ CARD_IS_NOT_COST(9003, "优惠卡未消费,退款请用卡券退款,钱直接退回购买人手里"), CARD_TRANSFERED(9004, "卡已被领取"), CARD_TRANSFER_INVALID(9005, "卡转赠已失效"), + CARD_SUBSIDY_NOT_SET(9006, "卡补贴未设置"), /** * 卡消费 */ CARD_SPEND_IS_PAID(9050, "卡消费已支付"), + CARD_SPEND_IS_NOT_PREV(9051, "卡消费不是预消费订单"), /** * 砍价 diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java b/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java index 47a592547..0f4d6628f 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java @@ -35,6 +35,8 @@ public class WxCardSpend extends BaseEntity { @Excel(name = "订单号", width = 20, orderNum = "5") @io.swagger.annotations.ApiModelProperty(value="订单账号",name="orderId") private Long orderId; + @io.swagger.annotations.ApiModelProperty(value="POS订单账号",name="posOrderId") + private Long posOrderId; @io.swagger.annotations.ApiModelProperty(value="ip地址",name="ip") private String ip; @io.swagger.annotations.ApiModelProperty(value="抵扣金额",name="deductionAmount") @@ -60,9 +62,15 @@ public class WxCardSpend extends BaseEntity { private Date updateDate; @Excel(name = "支付状态", width = 20, orderNum = "11", replace = {"未支付_0", "已分账_1", "已人工分账_2"}) - @io.swagger.annotations.ApiModelProperty(value="支付状态(0:未分帐, 1:已分账, 2:已人工分账)",name="payStatus") + @io.swagger.annotations.ApiModelProperty(value="支付状态(0:未分帐, 1:已分账, 2:已人工分账, 10:预支付(POS))",name="payStatus") private Integer payStatus; + @io.swagger.annotations.ApiModelProperty(value="来源(0:C端小程序扫一扫, 1:B端POS, 2:东软POS)",name="from") + private Integer from; + + @io.swagger.annotations.ApiModelProperty(value="pos状态(1:POS线下退款开始, 2:POS线下退款成功)",name="posRefundStatus") + private Integer posRefundStatus; + @Transient @Excel(name = "消费金额(元)", width = 20, orderNum = "7") private String deductionAmountStr; diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendFrom.java b/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendFrom.java new file mode 100644 index 000000000..8953f5380 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendFrom.java @@ -0,0 +1,39 @@ +package com.iformall.enums; + +/** + * Created by Stormeye on 2018/08/09. + */ +public enum EnumCardSpendFrom { + + // 0:C端小程序扫一扫, 1:B端POS, 2:东软POS + + C(0, "支付"), + POS_B(1, "B端POS"), + POS_NEUSOFT(2, "东软POS"), + ; + + public static EnumCardSpendFrom getEnum(Integer code) { + for (EnumCardSpendFrom value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumCardSpendFrom(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendStatus.java b/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendStatus.java index 8b112b9f6..8d0b5b4a6 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendStatus.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumCardSpendStatus.java @@ -7,9 +7,10 @@ public enum EnumCardSpendStatus { // 0-未支付;1-已分账;2:已人工分账; - NOT_PAY(0, "未支付"), + NOT_PAY(0, "未支付,开始记录"), PS_SHARED(1, "已分账"), - MANUAL_PAY(2, "已人工分账") + MANUAL_PAY(2, "已人工分账"), + PREV_PAY(10, "预支付(POS短期内占用)"), ; public static EnumCardSpendStatus getEnum(Integer code) { diff --git a/mallinkService/src/main/java/com/iformall/mapper/WxCardSpendMapper.java b/mallinkService/src/main/java/com/iformall/mapper/WxCardSpendMapper.java index 846417c90..eb9dca973 100644 --- a/mallinkService/src/main/java/com/iformall/mapper/WxCardSpendMapper.java +++ b/mallinkService/src/main/java/com/iformall/mapper/WxCardSpendMapper.java @@ -22,7 +22,10 @@ public interface WxCardSpendMapper extends CommonMapper { List> sumCardSpendVoForOwner(WxCardSpendVo wxCardSpend); - + /** + * POS + */ + int deleteForPrevCancel(WxCardSpend record); } diff --git a/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java b/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java index d73ed7831..01ea446f7 100644 --- a/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java +++ b/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java @@ -31,6 +31,8 @@ public class WxPayConstant { public final static String VERIFY_INDEPENT = "independent"; public final static String VERIFY_PAY = "pay"; + public final static String CARD_ID = "card_id"; + public final static String REG_QRCODE_URL = "qrcode_url"; public final static String POS_QRCODE_RULE = "pos_qrcode_rule"; @@ -49,4 +51,6 @@ public class WxPayConstant { public final static String ORG_AMOUNT = "org_amount"; + public final static String RET = "ret"; + } diff --git a/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java b/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java index 2b27343f9..2ae6f58eb 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java @@ -4,6 +4,7 @@ import com.github.pagehelper.PageInfo; import com.iformall.common.ResultData; import com.iformall.domain.po.*; import com.iformall.domain.vo.WxCardSpendVo; +import com.iformall.exception.MallinkException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -102,5 +103,9 @@ public interface WxCardSpendService { */ void exportData(WxCardSpendVo wxCardSpendVo, HttpServletRequest request, HttpServletResponse response); - + /** + * POS 卡支付相关接口 + */ + void cardSpendForPosPrePay(WxCardSpend record) throws MallinkException; + void cardSpendForPosPrePayCancel(WxCardSpend record) throws MallinkException; } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java index e7f1584cc..a451a68af 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java @@ -127,7 +127,6 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { int iChargeFee = PayUtils.getPayRate(payment, payAccount.getRate()); Integer real_payment = payment - iChargeFee; Integer remain_real_pament = cardInfo.getRemainingShareFeeAmount() - real_payment; - Integer remaingAmount = cardInfo.getRemainingAmount()-record.getDeductionAmount(); if(remaingAmount.equals(0)) { // 最后一次支付时 @@ -137,6 +136,8 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { // 5 insert card_spend record.setId(idWorker.nextId()); + record.setTenantId(cardInfo.getTenantId()); + record.setFrom(EnumCardSpendFrom.C.getCode()); record.setPayment(payment); record.setRealPayment(real_payment); record.setCardBeforeAmount(cardInfo.getRemainingAmount()); @@ -180,7 +181,7 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { } // 7.1 update coupon card status if(cardInfo.getRemainingAmount().equals(0)) { - if (cardFinished(order, curDate, cardInfo)) { + if (cardFinished(curDate, cardInfo)) { return new ResultData(ErrorCode.DB_FAIL.getCode(), "couponOrder status 更新出错!"); } } @@ -279,11 +280,16 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { return new ResultData(record); } - private boolean cardFinished(WxOrder order, Date curDate, WxCardInfo cardInfo) { + /** + * 卡已用完 + * @param curDate + * @param cardInfo + * @return + */ + private boolean cardFinished(Date curDate, WxCardInfo cardInfo) { WxCouponOrder couponOrder = new WxCouponOrder(); couponOrder.setId(cardInfo.getId()); couponOrder.setCouponId(cardInfo.getCouponId()); - couponOrder.setOrderId(order.getId()); couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.CARD_COMPLETE.getCode()); couponOrder.setUpdateDate(curDate); try { @@ -542,4 +548,165 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { excelService.exportExcel(list, null, "卡消费记录", WxCardSpendVo.class, "卡消费记录.xlsx", response, false); } + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public void cardSpendForPosPrePay(WxCardSpend record) throws MallinkException { + Date curDate = new Date(); + final IdWorker idWorker = IdWorker.get(); + // 1. get card info + WxCardInfo cardInfo = wxCardInfoMapper.selectByPrimaryKey(record.getCardId()); + if (cardInfo == null) { + logger.error("card not found: " + record.getCardId()); + throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND); + } + // 2. coupon + Integer subsidyRate = 0; + WxCoupon coupon = wxCouponMapper.selectByPrimaryKey(cardInfo.getCouponId()); + if (coupon == null) { + logger.error("card's coupon not found: " + cardInfo.getCouponId()); + throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND); + } + if (coupon.getSubsidyNum() == null) { + logger.error("卡补贴额未填写: " + cardInfo.getCouponId()); + throw new MallinkException(ErrorCode.CARD_SUBSIDY_NOT_SET); + } + + // 3. get pay account + WxPayAccount payAccount = null; + WxPayAccount payAccountQ = new WxPayAccount(); + payAccountQ.setTenantId(record.getTenantId()); + try { + payAccount = payAccountMapper.selectOne(payAccountQ); + } catch (Exception e) { + logger.error("获取payAccount error: " + record.getTenantId()); + throw new MallinkException(ErrorCode.SYS_MCH_NOT_FOUND); + } + + // 4. 扣减计算 + Double paymentD = 1.0 * cardInfo.getSaleAmount() * record.getDeductionAmount() / cardInfo.getAmount(); + Integer payment = paymentD.intValue(); + int iChargeFee = PayUtils.getPayRate(payment, payAccount.getRate()); + Integer real_payment = payment - iChargeFee; + Integer remain_real_pament = cardInfo.getRemainingShareFeeAmount() - real_payment; + Integer remaingAmount = cardInfo.getRemainingAmount()-record.getDeductionAmount(); + if (remaingAmount.equals(0)) { + // 最后一次支付时 + real_payment = Math.min(real_payment, cardInfo.getRemainingShareFeeAmount()); + remain_real_pament = cardInfo.getRemainingShareFeeAmount() - real_payment; + } + + // 5 insert card_spend + record.setId(idWorker.nextId()); + record.setTenantId(cardInfo.getTenantId()); + record.setPayment(payment); + record.setRealPayment(real_payment); + record.setCardBeforeAmount(cardInfo.getRemainingAmount()); + record.setCardRemainAmount(remaingAmount); + record.setCardBeforeRealAmount(cardInfo.getRemainingShareFeeAmount()); + record.setCardRemainRealAmount(remain_real_pament); + record.setPayStatus(EnumCardSpendStatus.PREV_PAY.getCode()); + record.setCreateDate(curDate); + record.setUpdateDate(curDate); + try { + wxCardSpendMapper.insertSelective(record); + } catch (Exception e) { + logger.error("card spend insert error"); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "卡消费插入出错"); + } + + // 7. update card info + cardInfo.setRemainingAmount(remaingAmount); + cardInfo.setRemainingShareFeeAmount(remain_real_pament); + cardInfo.setUpdateDate(curDate); + // 消费后,修改卡转赠状态 + if (cardInfo.getSupportTransfer().equals(EnumCouponTransfer.YES.getCode())) { + cardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); + } + try { + wxCardInfoMapper.updateByPrimaryKeySelective(cardInfo); + } catch (Exception e) { + String errMessage = "消费卡信息更新出错: " + cardInfo.getId(); + logger.error(errMessage); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), errMessage); + } + } + + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public void cardSpendForPosPrePayCancel(WxCardSpend record) throws MallinkException { + Date curDate = new Date(); + if (record.getId() == null) { + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if (!record.getPayStatus().equals(EnumCardSpendStatus.PREV_PAY.getCode())) { + logger.error("card spend not prev pay"); + throw new MallinkException(ErrorCode.CARD_SPEND_IS_NOT_PREV); + } + // 1. get card info + WxCardInfo cardInfo = wxCardInfoMapper.selectByPrimaryKey(record.getCardId()); + if (cardInfo == null) { + logger.error("card not found: " + record.getCardId()); + throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND); + } + // 2. coupon + Integer subsidyRate = 0; + WxCoupon coupon = wxCouponMapper.selectByPrimaryKey(cardInfo.getCouponId()); + if (coupon == null) { + logger.error("card's coupon not found: " + cardInfo.getCouponId()); + throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND); + } + if (coupon.getSubsidyNum() == null) { + String errMessage = "券补贴额未填写"; + logger.error(errMessage); + throw new MallinkException(ErrorCode.SYS_PARAMETER_ERROR.getCode(), errMessage); + } + + // 3. get pay account + WxPayAccount payAccount = null; + WxPayAccount payAccountQ = new WxPayAccount(); + payAccountQ.setTenantId(record.getTenantId()); + try { + payAccount = payAccountMapper.selectOne(payAccountQ); + } catch (Exception e) { + logger.error("获取payAccount error: " + record.getTenantId()); + throw new MallinkException(ErrorCode.SYS_MCH_NOT_FOUND); + } + + // 4. 增加计算 + Double paymentD = 1.0 * cardInfo.getSaleAmount() * record.getDeductionAmount() / cardInfo.getAmount(); + Integer payment = paymentD.intValue(); + int iChargeFee = PayUtils.getPayRate(payment, payAccount.getRate()); + Integer real_payment = payment - iChargeFee; + Integer remain_real_pament = cardInfo.getRemainingShareFeeAmount() + real_payment; + Integer remaingAmount = cardInfo.getRemainingAmount()+record.getDeductionAmount(); + + // 5.、如果还是原价更改卡转赠状态 + WxCardInfo updateCardInfo = new WxCardInfo(); + updateCardInfo.setId(record.getCardId()); + if (cardInfo.getAmount().equals(remaingAmount) && + cardInfo.getSupportTransfer().equals(EnumCouponTransfer.NO.getCode())) { + updateCardInfo.setSupportTransfer(EnumCouponTransfer.YES.getCode()); + } + + // 6. update card info + cardInfo.setRemainingAmount(remaingAmount); + cardInfo.setRemainingShareFeeAmount(remain_real_pament); + cardInfo.setUpdateDate(curDate); + try { + wxCardInfoMapper.updateByPrimaryKeySelective(cardInfo); + } catch (Exception e) { + String errMessage = "卡信息更新出错"; + logger.error(errMessage); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), errMessage); + } + + // 100. delete prev card_spend + record.setTenantId(cardInfo.getTenantId()); + try { + wxCardSpendMapper.deleteForPrevCancel(record); + } catch (Exception e) { + String errMessage = "卡消费信息删除出错"; + logger.error(errMessage); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), errMessage); + } + } + } diff --git a/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml b/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml index 36a2a0eff..191b1af04 100644 --- a/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml @@ -8,6 +8,7 @@ + @@ -18,12 +19,14 @@ + + - `id`,`tenant_id`,`card_id`,`owner_id`,`merchant_id`,`order_id`,`deduction_amount`,`payment`,`real_payment`, + `id`,`tenant_id`,`card_id`,`owner_id`,`merchant_id`,`order_id`,`pos_order_id`,``deduction_amount`,`payment`,`real_payment`, `card_remain_amount`,`card_before_amount`,`card_remain_real_amount`,`card_before_real_amount`, - `create_date`,`update_date`, `pay_status` + `create_date`,`update_date`, `pay_status`, `from`, `pos_refund_status` @@ -46,6 +49,9 @@ and `order_id` = #{orderId} + + and `pos_order_id` = #{posOrderId} + and `deduction_amount` = #{deductionAmount} @@ -76,6 +82,12 @@ and `pay_status` = #{payStatus} + + and `from` = #{from} + + + and `pos_refund_status` = #{posRefundStatus} + and `create_date` between #{startdate} and #{enddate} @@ -115,6 +127,11 @@ + + delete from wx_card_spend + where `tenant_id` = #{tenantId} and `id` = #{id} and `use_status` = #{} + +