| @@ -0,0 +1,2 @@ | |||
| alter table pos_mall_config | |||
| add column `card` tinyint(6) NOT NULL DEFAULT '0' COMMENT '会员优惠券状态,0-使用中,1-禁用'; | |||
| @@ -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))'; | |||
| @@ -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<String, String> cardPay(@RequestBody Map<String, String> params) { | |||
| JSONObject payContent = new JSONObject(); | |||
| // 1. check sign | |||
| Map<String, String> 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<String, String> cardPayCancel(@RequestBody Map<String, String> params) { | |||
| JSONObject payContent = new JSONObject(); | |||
| // 1. check sign | |||
| Map<String, String> 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,无签名, 有错误 | |||
| @@ -55,4 +55,20 @@ public interface PosService { | |||
| * @throws MallinkException | |||
| */ | |||
| Map<String, String> couponOrderVerifyListDo(@RequestBody Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException; | |||
| /** | |||
| * 消费卡POS支付 | |||
| * @param params | |||
| * @return | |||
| * @throws MallinkException | |||
| */ | |||
| Map<String, String> cardPay(@RequestBody Map<String, String> params) throws MallinkException; | |||
| /** | |||
| * 消费卡POS支付取消 | |||
| * @param params | |||
| * @return | |||
| * @throws MallinkException | |||
| */ | |||
| Map<String, String> cardPayCancel(@RequestBody Map<String, String> params) throws MallinkException; | |||
| } | |||
| @@ -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<String, String> cardPay(@RequestBody Map<String, String> params) throws MallinkException { | |||
| Map<String, String> 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<String, String> cardPayCancel(@RequestBody Map<String, String> params) throws MallinkException { | |||
| return null; | |||
| } | |||
| } | |||
| @@ -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, "卡消费不是预消费订单"), | |||
| /** | |||
| * 砍价 | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -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) { | |||
| @@ -22,7 +22,10 @@ public interface WxCardSpendMapper extends CommonMapper<WxCardSpend, Long> { | |||
| List<Map<String,Object>> sumCardSpendVoForOwner(WxCardSpendVo wxCardSpend); | |||
| /** | |||
| * POS | |||
| */ | |||
| int deleteForPrevCancel(WxCardSpend record); | |||
| } | |||
| @@ -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"; | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||
| } | |||
| @@ -8,6 +8,7 @@ | |||
| <result column="owner_id" jdbcType="BIGINT" property="ownerId"/> | |||
| <result column="merchant_id" jdbcType="BIGINT" property="merchantId"/> | |||
| <result column="order_id" jdbcType="BIGINT" property="orderId"/> | |||
| <result column="pos_order_id" jdbcType="BIGINT" property="posOrderId"/> | |||
| <result column="deduction_amount" jdbcType="INTEGER" property="deductionAmount"/> | |||
| <result column="payment" jdbcType="INTEGER" property="payment"/> | |||
| <result column="real_payment" jdbcType="INTEGER" property="realPayment"/> | |||
| @@ -18,12 +19,14 @@ | |||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate"/> | |||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate"/> | |||
| <result column="pay_status" jdbcType="INTEGER" property="payStatus"/> | |||
| <result column="from" jdbcType="INTEGER" property="from"/> | |||
| <result column="pos_refund_status" jdbcType="INTEGER" property="posRefundStatus"/> | |||
| </resultMap> | |||
| <sql id="allColumns"> | |||
| `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` | |||
| </sql> | |||
| <sql id="dynamicWhereConditions"> | |||
| @@ -46,6 +49,9 @@ | |||
| <if test=" null != orderId "> | |||
| and `order_id` = #{orderId} | |||
| </if> | |||
| <if test=" null != posOrderId "> | |||
| and `pos_order_id` = #{posOrderId} | |||
| </if> | |||
| <if test=" null != deductionAmount "> | |||
| and `deduction_amount` = #{deductionAmount} | |||
| </if> | |||
| @@ -76,6 +82,12 @@ | |||
| <if test=" null != payStatus "> | |||
| and `pay_status` = #{payStatus} | |||
| </if> | |||
| <if test=" null != from "> | |||
| and `from` = #{from} | |||
| </if> | |||
| <if test=" null != posRefundStatus "> | |||
| and `pos_refund_status` = #{posRefundStatus} | |||
| </if> | |||
| <if test=" null != startdate and null!=enddate"> | |||
| and `create_date` between #{startdate} and #{enddate} | |||
| </if> | |||
| @@ -115,6 +127,11 @@ | |||
| </where> | |||
| </select> | |||
| <delete id="deleteForPrevCancel" parameterType="com.iformall.domain.po.WxCardSpend"> | |||
| delete from wx_card_spend | |||
| where `tenant_id` = #{tenantId} and `id` = #{id} and `use_status` = #{} | |||
| </delete> | |||
| <select id="findCount" parameterType="com.iformall.domain.po.WxCardSpend" resultType="Integer"> | |||
| select count(*) | |||
| from wx_card_spend cs | |||
| @@ -263,6 +280,7 @@ | |||
| <result column="owner_id" jdbcType="BIGINT" property="ownerId"/> | |||
| <result column="merchant_id" jdbcType="BIGINT" property="merchantId"/> | |||
| <result column="order_id" jdbcType="BIGINT" property="orderId"/> | |||
| <result column="pos_order_id" jdbcType="BIGINT" property="posOrderId"/> | |||
| <result column="deduction_amount" jdbcType="INTEGER" property="deductionAmount"/> | |||
| <result column="payment" jdbcType="INTEGER" property="payment"/> | |||
| <result column="real_payment" jdbcType="INTEGER" property="realPayment"/> | |||