| @@ -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,无签名, 有错误 | * 构造返回map,无签名, 有错误 | ||||
| @@ -55,4 +55,20 @@ public interface PosService { | |||||
| * @throws MallinkException | * @throws MallinkException | ||||
| */ | */ | ||||
| Map<String, String> couponOrderVerifyListDo(@RequestBody Map<String, String> params, EnumVerifyActionType actionType) 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 PosCouponOrderVerifyService posCouponOrderVerifyService; | ||||
| private final WxScoreRulesService scoreRulesService; | private final WxScoreRulesService scoreRulesService; | ||||
| private final WxCreditHistoryService creditHistoryService; | private final WxCreditHistoryService creditHistoryService; | ||||
| private final WxCardInfoService cardInfoService; | |||||
| private final WxCardSpendService cardSpendService; | |||||
| private final WxOrderMapper orderMapper; | private final WxOrderMapper orderMapper; | ||||
| private final WxCouponOrderMapper couponOrderMapper; | private final WxCouponOrderMapper couponOrderMapper; | ||||
| @@ -1148,4 +1150,134 @@ public class PosServiceImpl implements PosService { | |||||
| } | } | ||||
| logger.info("核销已取消: " + couponOrderCVo.getId()); | 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_EXTEND_JSON_ERROR(1012, "JSON格式异常"), | ||||
| SYS_REPEAT_SUBMIT_EXCEPTION(1013, "请勿重复操作"), | SYS_REPEAT_SUBMIT_EXCEPTION(1013, "请勿重复操作"), | ||||
| REPORT_TYPE_UNKNOWN(1014, "不支持的报表类型"), | REPORT_TYPE_UNKNOWN(1014, "不支持的报表类型"), | ||||
| SYS_MCH_NOT_FOUND(1015, "微信商户号未找到"), | |||||
| /** | /** | ||||
| * 菜单 | * 菜单 | ||||
| @@ -198,11 +199,13 @@ public enum ErrorCode{ | |||||
| CARD_IS_NOT_COST(9003, "优惠卡未消费,退款请用卡券退款,钱直接退回购买人手里"), | CARD_IS_NOT_COST(9003, "优惠卡未消费,退款请用卡券退款,钱直接退回购买人手里"), | ||||
| CARD_TRANSFERED(9004, "卡已被领取"), | CARD_TRANSFERED(9004, "卡已被领取"), | ||||
| CARD_TRANSFER_INVALID(9005, "卡转赠已失效"), | CARD_TRANSFER_INVALID(9005, "卡转赠已失效"), | ||||
| CARD_SUBSIDY_NOT_SET(9006, "卡补贴未设置"), | |||||
| /** | /** | ||||
| * 卡消费 | * 卡消费 | ||||
| */ | */ | ||||
| CARD_SPEND_IS_PAID(9050, "卡消费已支付"), | 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") | @Excel(name = "订单号", width = 20, orderNum = "5") | ||||
| @io.swagger.annotations.ApiModelProperty(value="订单账号",name="orderId") | @io.swagger.annotations.ApiModelProperty(value="订单账号",name="orderId") | ||||
| private Long orderId; | private Long orderId; | ||||
| @io.swagger.annotations.ApiModelProperty(value="POS订单账号",name="posOrderId") | |||||
| private Long posOrderId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="ip地址",name="ip") | @io.swagger.annotations.ApiModelProperty(value="ip地址",name="ip") | ||||
| private String ip; | private String ip; | ||||
| @io.swagger.annotations.ApiModelProperty(value="抵扣金额",name="deductionAmount") | @io.swagger.annotations.ApiModelProperty(value="抵扣金额",name="deductionAmount") | ||||
| @@ -60,9 +62,15 @@ public class WxCardSpend extends BaseEntity { | |||||
| private Date updateDate; | private Date updateDate; | ||||
| @Excel(name = "支付状态", width = 20, orderNum = "11", replace = {"未支付_0", "已分账_1", "已人工分账_2"}) | @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; | 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 | @Transient | ||||
| @Excel(name = "消费金额(元)", width = 20, orderNum = "7") | @Excel(name = "消费金额(元)", width = 20, orderNum = "7") | ||||
| private String deductionAmountStr; | 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:已人工分账; | // 0-未支付;1-已分账;2:已人工分账; | ||||
| NOT_PAY(0, "未支付"), | |||||
| NOT_PAY(0, "未支付,开始记录"), | |||||
| PS_SHARED(1, "已分账"), | PS_SHARED(1, "已分账"), | ||||
| MANUAL_PAY(2, "已人工分账") | |||||
| MANUAL_PAY(2, "已人工分账"), | |||||
| PREV_PAY(10, "预支付(POS短期内占用)"), | |||||
| ; | ; | ||||
| public static EnumCardSpendStatus getEnum(Integer code) { | public static EnumCardSpendStatus getEnum(Integer code) { | ||||
| @@ -22,7 +22,10 @@ public interface WxCardSpendMapper extends CommonMapper<WxCardSpend, Long> { | |||||
| List<Map<String,Object>> sumCardSpendVoForOwner(WxCardSpendVo wxCardSpend); | 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_INDEPENT = "independent"; | ||||
| public final static String VERIFY_PAY = "pay"; | 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 REG_QRCODE_URL = "qrcode_url"; | ||||
| public final static String POS_QRCODE_RULE = "pos_qrcode_rule"; | 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 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.common.ResultData; | ||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| import com.iformall.domain.vo.WxCardSpendVo; | import com.iformall.domain.vo.WxCardSpendVo; | ||||
| import com.iformall.exception.MallinkException; | |||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
| @@ -102,5 +103,9 @@ public interface WxCardSpendService { | |||||
| */ | */ | ||||
| void exportData(WxCardSpendVo wxCardSpendVo, HttpServletRequest request, HttpServletResponse response); | 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()); | int iChargeFee = PayUtils.getPayRate(payment, payAccount.getRate()); | ||||
| Integer real_payment = payment - iChargeFee; | Integer real_payment = payment - iChargeFee; | ||||
| Integer remain_real_pament = cardInfo.getRemainingShareFeeAmount() - real_payment; | Integer remain_real_pament = cardInfo.getRemainingShareFeeAmount() - real_payment; | ||||
| Integer remaingAmount = cardInfo.getRemainingAmount()-record.getDeductionAmount(); | Integer remaingAmount = cardInfo.getRemainingAmount()-record.getDeductionAmount(); | ||||
| if(remaingAmount.equals(0)) { | if(remaingAmount.equals(0)) { | ||||
| // 最后一次支付时 | // 最后一次支付时 | ||||
| @@ -137,6 +136,8 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { | |||||
| // 5 insert card_spend | // 5 insert card_spend | ||||
| record.setId(idWorker.nextId()); | record.setId(idWorker.nextId()); | ||||
| record.setTenantId(cardInfo.getTenantId()); | |||||
| record.setFrom(EnumCardSpendFrom.C.getCode()); | |||||
| record.setPayment(payment); | record.setPayment(payment); | ||||
| record.setRealPayment(real_payment); | record.setRealPayment(real_payment); | ||||
| record.setCardBeforeAmount(cardInfo.getRemainingAmount()); | record.setCardBeforeAmount(cardInfo.getRemainingAmount()); | ||||
| @@ -180,7 +181,7 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { | |||||
| } | } | ||||
| // 7.1 update coupon card status | // 7.1 update coupon card status | ||||
| if(cardInfo.getRemainingAmount().equals(0)) { | if(cardInfo.getRemainingAmount().equals(0)) { | ||||
| if (cardFinished(order, curDate, cardInfo)) { | |||||
| if (cardFinished(curDate, cardInfo)) { | |||||
| return new ResultData(ErrorCode.DB_FAIL.getCode(), "couponOrder status 更新出错!"); | return new ResultData(ErrorCode.DB_FAIL.getCode(), "couponOrder status 更新出错!"); | ||||
| } | } | ||||
| } | } | ||||
| @@ -279,11 +280,16 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { | |||||
| return new ResultData(record); | 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(); | WxCouponOrder couponOrder = new WxCouponOrder(); | ||||
| couponOrder.setId(cardInfo.getId()); | couponOrder.setId(cardInfo.getId()); | ||||
| couponOrder.setCouponId(cardInfo.getCouponId()); | couponOrder.setCouponId(cardInfo.getCouponId()); | ||||
| couponOrder.setOrderId(order.getId()); | |||||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.CARD_COMPLETE.getCode()); | couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.CARD_COMPLETE.getCode()); | ||||
| couponOrder.setUpdateDate(curDate); | couponOrder.setUpdateDate(curDate); | ||||
| try { | try { | ||||
| @@ -542,4 +548,165 @@ public class WxCardSpendServiceImpl implements WxCardSpendService { | |||||
| excelService.exportExcel(list, null, "卡消费记录", WxCardSpendVo.class, "卡消费记录.xlsx", response, false); | 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="owner_id" jdbcType="BIGINT" property="ownerId"/> | ||||
| <result column="merchant_id" jdbcType="BIGINT" property="merchantId"/> | <result column="merchant_id" jdbcType="BIGINT" property="merchantId"/> | ||||
| <result column="order_id" jdbcType="BIGINT" property="orderId"/> | <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="deduction_amount" jdbcType="INTEGER" property="deductionAmount"/> | ||||
| <result column="payment" jdbcType="INTEGER" property="payment"/> | <result column="payment" jdbcType="INTEGER" property="payment"/> | ||||
| <result column="real_payment" jdbcType="INTEGER" property="realPayment"/> | <result column="real_payment" jdbcType="INTEGER" property="realPayment"/> | ||||
| @@ -18,12 +19,14 @@ | |||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate"/> | <result column="create_date" jdbcType="TIMESTAMP" property="createDate"/> | ||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate"/> | <result column="update_date" jdbcType="TIMESTAMP" property="updateDate"/> | ||||
| <result column="pay_status" jdbcType="INTEGER" property="payStatus"/> | <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> | </resultMap> | ||||
| <sql id="allColumns"> | <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`, | `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> | ||||
| <sql id="dynamicWhereConditions"> | <sql id="dynamicWhereConditions"> | ||||
| @@ -46,6 +49,9 @@ | |||||
| <if test=" null != orderId "> | <if test=" null != orderId "> | ||||
| and `order_id` = #{orderId} | and `order_id` = #{orderId} | ||||
| </if> | </if> | ||||
| <if test=" null != posOrderId "> | |||||
| and `pos_order_id` = #{posOrderId} | |||||
| </if> | |||||
| <if test=" null != deductionAmount "> | <if test=" null != deductionAmount "> | ||||
| and `deduction_amount` = #{deductionAmount} | and `deduction_amount` = #{deductionAmount} | ||||
| </if> | </if> | ||||
| @@ -76,6 +82,12 @@ | |||||
| <if test=" null != payStatus "> | <if test=" null != payStatus "> | ||||
| and `pay_status` = #{payStatus} | and `pay_status` = #{payStatus} | ||||
| </if> | </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"> | <if test=" null != startdate and null!=enddate"> | ||||
| and `create_date` between #{startdate} and #{enddate} | and `create_date` between #{startdate} and #{enddate} | ||||
| </if> | </if> | ||||
| @@ -115,6 +127,11 @@ | |||||
| </where> | </where> | ||||
| </select> | </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 id="findCount" parameterType="com.iformall.domain.po.WxCardSpend" resultType="Integer"> | ||||
| select count(*) | select count(*) | ||||
| from wx_card_spend cs | from wx_card_spend cs | ||||
| @@ -263,6 +280,7 @@ | |||||
| <result column="owner_id" jdbcType="BIGINT" property="ownerId"/> | <result column="owner_id" jdbcType="BIGINT" property="ownerId"/> | ||||
| <result column="merchant_id" jdbcType="BIGINT" property="merchantId"/> | <result column="merchant_id" jdbcType="BIGINT" property="merchantId"/> | ||||
| <result column="order_id" jdbcType="BIGINT" property="orderId"/> | <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="deduction_amount" jdbcType="INTEGER" property="deductionAmount"/> | ||||
| <result column="payment" jdbcType="INTEGER" property="payment"/> | <result column="payment" jdbcType="INTEGER" property="payment"/> | ||||
| <result column="real_payment" jdbcType="INTEGER" property="realPayment"/> | <result column="real_payment" jdbcType="INTEGER" property="realPayment"/> | ||||