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 2753632f0..a25538cb6 100644 --- a/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java +++ b/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java @@ -1296,7 +1296,7 @@ public class PosServiceImpl implements PosService { 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 - String cardSpendIdStr = params.get(WxPayConstant.CARD_SPEND_ID); // 消费卡花费ID + String cardSpendIdStr = params.get(WxPayConstant.CARD_SPEND_ID); // 消费卡花费ID if (StringUtils.isBlank(tenantId)) { String errMessage = "request params[tenant_id] error."; @@ -1390,16 +1390,15 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND); } - WxCardSpend record = new WxCardSpend(); - record.setId(cardSpendId); - record.setFrom(EnumCardSpendFrom.POS.getCode()); - record.setTenantId(merchant.getTenantId()); - record.setCardId(cardId); - record.setOwnerId(couponOrder.getOwnerId()); - record.setMerchantId(merchantId); - record.setPosOrderId(posOrderId); - record.setDeductionAmount(posAmount); - record.setPayStatus(EnumCardSpendStatus.PREV_PAY.getCode()); + WxCardSpend record = cardSpendService.getById(cardSpendId); + if (record == null) { + logger.error(ErrorCode.CARD_SPEND_IS_NOT_FOUND.getMessage() + ": " + cardSpendIdStr); + throw new MallinkException(ErrorCode.CARD_SPEND_IS_NOT_FOUND); + } + if (record.getPayStatus().equals(EnumCardSpendStatus.PREV_PAY.getCode())) { + logger.error(ErrorCode.POS_CAR_PAY_NOT_CANCEL.getMessage()); + throw new MallinkException(ErrorCode.POS_CAR_PAY_NOT_CANCEL); + } try { WxCardInfo updateCardInfo = cardSpendService.cardSpendForPosPrePayCancel(cardInfo, record); @@ -1429,6 +1428,134 @@ public class PosServiceImpl implements PosService { @Override @Transactional(rollbackFor = Exception.class) public Map cardPayCancel(Map params) throws MallinkException { - return null; + 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 + String cardSpendIdStr = params.get(WxPayConstant.CARD_SPEND_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.getCard().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[card_id] error."; + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + if (StringUtils.isBlank(cardSpendIdStr)) { + String errMessage = "request params[card_spend_id] error."; + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + + Long merchantId, buUserId, posOrderId, cardId, cardSpendId; + Integer posAmount = 0; + try { + merchantId = Long.valueOf(merchantIdStr); + buUserId = Long.valueOf(buUserIdStr); + posOrderId = Long.valueOf(posOrderIdStr); + posAmount = Integer.valueOf(posAmountStr); + cardId = Long.valueOf(cardIdStr); + cardSpendId = Long.valueOf(cardSpendIdStr); + } 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); + } + + WxCardSpend record = cardSpendService.getById(cardSpendId); + if (record == null) { + logger.error(ErrorCode.CARD_SPEND_IS_NOT_FOUND.getMessage() + ": " + cardSpendIdStr); + throw new MallinkException(ErrorCode.CARD_SPEND_IS_NOT_FOUND); + } + if (!record.getPayStatus().equals(EnumCardSpendStatus.PREV_PAY.getCode())) { + logger.error(ErrorCode.POS_CAR_PAY_NOT_CANCEL.getMessage()); + throw new MallinkException(ErrorCode.POS_CAR_PAY_NOT_CANCEL); + } + + try { + WxCardInfo updateCardInfo = cardSpendService.cardSpendForPosPrePayCancel(cardInfo, record); + JSONObject retObj = new JSONObject(); + retObj.put(WxPayConstant.CARD_ID, cardId); + retObj.put(WxPayConstant.ORG_REMAIN_AMOUNT, cardInfo.getRemainingAmount()); + retObj.put(WxPayConstant.REMAIN_AMOUNT, updateCardInfo.getRemainingAmount()); + retObj.put(WxPayConstant.CANCEL, WxPayConstant.TRUE); + retMap.put(WxPayConstant.RET, JSON.toJSONString(retObj)); + } 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()); + } + + return retMap; } } diff --git a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java index b8804e424..94228d3ed 100644 --- a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java @@ -206,6 +206,7 @@ public enum ErrorCode{ */ CARD_SPEND_IS_PAID(9050, "卡消费已支付"), CARD_SPEND_IS_NOT_PREV(9051, "卡消费不是预消费订单"), + CARD_SPEND_IS_NOT_FOUND(9052, "卡消费信息未找到"), /** * 砍价 diff --git a/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java b/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java index 522ca46a2..c2aba2575 100644 --- a/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java +++ b/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java @@ -65,5 +65,6 @@ public class WxPayConstant { public final static String RET = "ret"; public final static String TRUE = "true"; + public final static String FALSE = "false"; } 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 7b5bf4c43..ca318e897 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java @@ -170,16 +170,22 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { } // 7. update card info - cardInfo.setRemainingAmount(remaingAmount); - cardInfo.setRemainingShareFeeAmount(remain_real_pament); - cardInfo.setUpdateDate(curDate); + WxCardInfo updateCardInfo = new WxCardInfo(); + updateCardInfo.setId(cardInfo.getId()); + updateCardInfo.setRemainingAmount(remaingAmount); + updateCardInfo.setRemainingShareFeeAmount(remain_real_pament); + updateCardInfo.setUpdateDate(curDate); + // 7.1、消费后修改卡转赠状态 + if (cardInfo.getSupportTransfer().equals(EnumCouponTransfer.YES.getCode())) { + updateCardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); + } try { wxCardInfoMapper.updateByPrimaryKeySelective(cardInfo); } catch (Exception e) { logger.error("card info update error"); return new ResultData(ErrorCode.DB_FAIL.getCode(), "card info 更新出错!"); } - // 7.1 update coupon card status + // 7.2 update coupon card status if(cardInfo.getRemainingAmount().equals(0)) { if (cardFinished(curDate, cardInfo)) { return new ResultData(ErrorCode.DB_FAIL.getCode(), "couponOrder status 更新出错!"); @@ -241,14 +247,6 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { } } - //10、消费后修改卡转赠状态 - WxCardInfo wxCardInfo = new WxCardInfo(); - wxCardInfo.setId(record.getCardId()); - wxCardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); - if (cardInfo.getSupportTransfer().equals(EnumCouponTransfer.YES.getCode())) { - wxCardInfoMapper.updateByPrimaryKeySelective(wxCardInfo); - } - // 成长值 try { orderUpdate.setPayment(real_payment); @@ -617,7 +615,7 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { cardInfo.setRemainingAmount(remaingAmount); cardInfo.setRemainingShareFeeAmount(remain_real_pament); cardInfo.setUpdateDate(curDate); - // 消费后,修改卡转赠状态 + // 7.1 消费后,修改卡转赠状态 if (cardInfo.getSupportTransfer().equals(EnumCouponTransfer.YES.getCode())) { cardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); } @@ -673,19 +671,18 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { Integer remain_real_pament = cardInfo.getRemainingShareFeeAmount() + real_payment; Integer remaingAmount = cardInfo.getRemainingAmount()+record.getDeductionAmount(); - // 5.、如果还是原价更改卡转赠状态 + // 5.、update card info WxCardInfo updateCardInfo = new WxCardInfo(); updateCardInfo.setId(record.getCardId()); + updateCardInfo.setRemainingAmount(remaingAmount); + updateCardInfo.setRemainingShareFeeAmount(remain_real_pament); + updateCardInfo.setUpdateDate(curDate); + // 5.1 如果还是原价更改卡转赠状态 if (cardInfo.getAmount().equals(remaingAmount) && cardInfo.getSupportTransfer().equals(EnumCouponTransfer.NO.getCode()) && coupon.getSupportTransfer().equals(EnumCouponTransfer.YES.getCode())) { updateCardInfo.setSupportTransfer(EnumCouponTransfer.YES.getCode()); } - - // 6. update card info - updateCardInfo.setRemainingAmount(remaingAmount); - updateCardInfo.setRemainingShareFeeAmount(remain_real_pament); - updateCardInfo.setUpdateDate(curDate); try { wxCardInfoMapper.updateByPrimaryKeySelective(updateCardInfo); } catch (Exception e) { @@ -707,4 +704,194 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { return updateCardInfo; } + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public WxCardSpend cardSpendForPosPay(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. card_spend + 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.NOT_PAY.getCode()); + record.setCreateDate(curDate); + record.setUpdateDate(curDate); + if (record.getId() == null) { + record.setId(idWorker.nextId()); + try { + wxCardSpendMapper.insertSelective(record); + } catch (Exception e) { + logger.error("card spend insert error"); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "卡消费插入出错"); + } + } else { + try { + wxCardSpendMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("card spend update error"); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "卡消费更新出错"); + } + } + + // 7. update card info + WxCardInfo updateCardInfo = new WxCardInfo(); + updateCardInfo.setId(cardInfo.getId()); + updateCardInfo.setRemainingAmount(remaingAmount); + updateCardInfo.setRemainingShareFeeAmount(remain_real_pament); + updateCardInfo.setUpdateDate(curDate); + // 7.1 消费后,修改卡转赠状态 + if (cardInfo.getSupportTransfer().equals(EnumCouponTransfer.YES.getCode())) { + updateCardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); + } + try { + wxCardInfoMapper.updateByPrimaryKeySelective(updateCardInfo); + } catch (Exception e) { + String errMessage = "消费卡信息更新出错: " + cardInfo.getId(); + logger.error(errMessage); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), errMessage); + } + // 7.2 update coupon card status + if(cardInfo.getRemainingAmount().equals(0)) { + if (cardFinished(curDate, cardInfo)) { + String errMessage = "消费卡信息更新出错: " + cardInfo.getId(); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), errMessage); + } + } + + /* + // 8. 补贴 + // 补贴额 = 商城补贴总额/卡券面额 * 抵扣额(本次支付额) + Double subsidyFeeD = 1.0 * record.getDeductionAmount() * coupon.getSubsidyNum() / cardInfo.getAmount(); + Integer subsidyFee = subsidyFeeD.intValue(); + logger.info("补贴额: " + subsidyFee); + if(subsidyFee > 0) { + // 有补贴时入库 + int iSubChargeFee = PayUtils.getPayRate(subsidyFee, payAccount.getRate()); + Integer realSubsidyFee = subsidyFee - iSubChargeFee; + WxMerchantSubsidy merchantSubsidy = new WxMerchantSubsidy(); + merchantSubsidy.setId(idWorker.nextId()); + merchantSubsidy.setTenantId(record.getTenantId()); + /// merchantSubsidy.setOrderId(order.getId()); TODO + merchantSubsidy.setOrderType(EnumOrderType.PREPAIDCARD.getCode()); + merchantSubsidy.setMerchantId(record.getMerchantId()); + merchantSubsidy.setCouponOrderId(cardInfo.getId()); + merchantSubsidy.setCouponType(EnumCouponType.CARD_MULTIMCH.getCode()); + merchantSubsidy.setOrderPayment(record.getDeductionAmount()); + merchantSubsidy.setReceiverPayment(payment); + merchantSubsidy.setRealPayment(real_payment); + merchantSubsidy.setSubsidy(subsidyFee); + merchantSubsidy.setRealSubsidy(realSubsidyFee); + if (coupon.getSubsidyType().equals(EnumCouponSubsidyType.WECHAT_COUPON.getCode())) { + // 立减领券 + merchantSubsidy.setStatus(EnumMerchantSubsidyStatus.AUTO_SUBSIDIED.getCode()); + } else if (coupon.getSubsidyType().equals(EnumCouponSubsidyType.WECHAT_MCHPAY.getCode())) { + // 转账倒现金 + } else { + // 未补贴 + merchantSubsidy.setStatus(EnumMerchantSubsidyStatus.NOT_SUBSIDY.getCode()); + } + + merchantSubsidy.setCreateDate(curDate); + merchantSubsidy.setUpdateDate(curDate); + try { + wxMerchantSubsidyMapper.insertSelective(merchantSubsidy); + } catch (Exception e) { + String errMessage = "商户补贴信息插入出错!"; + logger.error(errMessage); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), errMessage); + } + } + */ + + // 9. 分账 + try { + shareForCardPay(record.getTenantId(), record.getCardId(), record.getOrderId(), record.getId()); + } catch (MallinkException e) { + logger.error(e.getMessage()); + if(ErrorCode.PROFIT_SHARING_NUM_UP_LIMIT.getCode() == e.getErrorCode()) { + // 分账已到20次限制,后面只记录,无法分账 + logger.error("分账已到20次限制,后面只记录,无法分账"); + } else { + throw new MallinkException(e.getErrorCode(), e.getMessage()); + } + } + + /* + // 成长值 + try { + orderUpdate.setPayment(real_payment); + wxScoreRulesService.addScore2(EnumScoreType.CONSUMPTION, orderUpdate, coupon.getBusiness()); + } catch (Exception e) { + logger.error("成长值:" + e.getMessage()); + } + */ + + /* + // 积分 + try { + //-------此处为【现金支付】记录增加积分操作------- + WxCreditHistory creditHistory = new WxCreditHistory(); + creditHistory.setOperatorType(EnumUserType.CUSER.getCode()); + creditHistory.setOperatorId(record.getOwnerId()); + creditHistory.setCUserId(record.getOwnerId()); + creditHistory.setCreateDate(new Date()); + creditHistory.setTenantId(record.getTenantId()); + creditHistory.setCreditType(EnumScoreType.CONSUMPTION.getCode()); + creditHistory.setCouponId(coupon.getId()); + creditHistory.setBusinessId(Long.valueOf(coupon.getBusiness())); + creditHistory.setSpend(real_payment); + //如果券与商户一对一 则直接将消费商户更新为此商户 若一对多 则消费商户显示多商户 + creditHistory.setMerchantId(record.getMerchantId()); + wxCreditHistoryService.saveOrUpdate(creditHistory); + } catch (Exception e) { + logger.error("积分值:" + e.getMessage()); + } + */ + return record; + } }