|
|
@@ -1,19 +1,28 @@
|
|
|
package org.dromara.backstage.business.card;
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.dromara.backstage.basics.domain.vo.PtWorkstationVo;
|
|
|
+import org.dromara.backstage.basics.service.IPtParameterService;
|
|
|
+import org.dromara.backstage.basics.service.IPtWorkstationService;
|
|
|
import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
|
|
|
+import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
|
|
|
import org.dromara.backstage.cardCenter.service.IPtCardService;
|
|
|
import org.dromara.backstage.payment.domain.bo.PtBagBo;
|
|
|
import org.dromara.backstage.payment.domain.vo.PtBagVo;
|
|
|
import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
|
|
|
import org.dromara.backstage.payment.service.IPtBagService;
|
|
|
import org.dromara.backstage.payment.service.IPtUserAccountService;
|
|
|
+import org.dromara.common.core.constant.DefaultConstants;
|
|
|
import org.dromara.common.core.domain.R;
|
|
|
+import org.dromara.common.core.domain.model.ResultInfo;
|
|
|
import org.dromara.common.core.enums.CardOpenEnum;
|
|
|
import org.dromara.common.core.enums.CardStatusEnum;
|
|
|
+import org.dromara.common.core.enums.ResultCodeEnum;
|
|
|
import org.dromara.common.core.enums.UserAccountStatusEnum;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
@@ -38,24 +47,27 @@ public class CardBusiness {
|
|
|
private final IPtUserAccountService userAccountService;
|
|
|
private final CardNoBusiness cardNoBusiness;
|
|
|
private final IPtBagService ptBagService;
|
|
|
- public R<String> openVirtualCard(PtCardBo cardBo){
|
|
|
+ private final IPtWorkstationService workstationService;
|
|
|
+ private final IPtParameterService ptParameterService;
|
|
|
+
|
|
|
+ public R<String> openVirtualCard(PtCardBo cardBo) {
|
|
|
String resultMsg;
|
|
|
- //验证是否存在开通虚拟卡的账户
|
|
|
+ // 验证是否存在开通虚拟卡的账户
|
|
|
PtUserAccountVo userAccountVo = userAccountService.queryById(cardBo.getUserId());
|
|
|
- if(userAccountVo == null){
|
|
|
+ if (userAccountVo == null) {
|
|
|
resultMsg = MessageFormat.format("[开通虚拟卡]-[失败]-[无此账户,账户Id:{0}]", cardBo.getUserId());
|
|
|
log.info(resultMsg);
|
|
|
return R.fail(resultMsg);
|
|
|
}
|
|
|
- if(Integer.parseInt(userAccountVo.getAccountStatus())!= UserAccountStatusEnum.IS_OPEN.code()){
|
|
|
+ if (Integer.parseInt(userAccountVo.getAccountStatus()) != UserAccountStatusEnum.IS_OPEN.code()) {
|
|
|
resultMsg = MessageFormat.format("[开通虚拟卡]-[失败]-[此账户尚未开户,账户Id:{0}]", cardBo.getUserId());
|
|
|
log.info(resultMsg);
|
|
|
return R.fail(resultMsg);
|
|
|
}
|
|
|
- //检查当前账户是否存在正常、挂失或冻结的卡片,如果有这些卡片,表明账户是发过卡的,无须再开通虚拟卡
|
|
|
+ // 检查当前账户是否存在正常、挂失或冻结的卡片,如果有这些卡片,表明账户是发过卡的,无须再开通虚拟卡
|
|
|
String cardInfo = ptCardService.selectAccountCardByIds(cardBo.getUserId().toString());
|
|
|
- if(CardOpenEnum.NO.message().equals(cardInfo)){
|
|
|
- //没有卡片,开通虚拟卡
|
|
|
+ if (CardOpenEnum.NO.message().equals(cardInfo)) {
|
|
|
+ // 没有卡片,开通虚拟卡
|
|
|
PtCardBo addBo = BeanUtil.copyProperties(cardBo, PtCardBo.class);
|
|
|
addBo.setMainCard("Y");
|
|
|
addBo.setStatus(CardStatusEnum.NORMAL.code().toString());
|
|
|
@@ -73,9 +85,9 @@ public class CardBusiness {
|
|
|
PtBagBo bagBo = new PtBagBo();
|
|
|
bagBo.setUserId(cardBo.getUserId());
|
|
|
List<PtBagVo> bagVos = ptBagService.queryList(bagBo);
|
|
|
- if(bagVos==null || bagVos.isEmpty()){
|
|
|
- //如果没有钱包数据,初始化钱包数据
|
|
|
- if(ptBagService.initAccountBag(cardBo.getUserId())){
|
|
|
+ if (bagVos == null || bagVos.isEmpty()) {
|
|
|
+ // 如果没有钱包数据,初始化钱包数据
|
|
|
+ if (ptBagService.initAccountBag(cardBo.getUserId())) {
|
|
|
resultMsg = MessageFormat.format("[开通虚拟卡]-[成功]-[开卡账户Id:{0}]", cardBo.getUserId());
|
|
|
return R.ok(resultMsg);
|
|
|
} else {
|
|
|
@@ -84,7 +96,7 @@ public class CardBusiness {
|
|
|
return R.fail(resultMsg);
|
|
|
}
|
|
|
} else {
|
|
|
- //已有钱包数据,不需要再初始化钱包,直接返回成功
|
|
|
+ // 已有钱包数据,不需要再初始化钱包,直接返回成功
|
|
|
resultMsg = MessageFormat.format("[开通虚拟卡]-[成功]-[开卡账户Id:{0}]", cardBo.getUserId());
|
|
|
return R.ok(resultMsg);
|
|
|
}
|
|
|
@@ -94,9 +106,225 @@ public class CardBusiness {
|
|
|
return R.fail(resultMsg);
|
|
|
}
|
|
|
} else {
|
|
|
- //已开过卡了,无须再开虚拟卡,直接返回成功
|
|
|
+ // 已开过卡了,无须再开虚拟卡,直接返回成功
|
|
|
resultMsg = MessageFormat.format("[开通虚拟卡]-[成功]-[账户已有卡片,开卡账户Id:{0}]", cardBo.getUserId());
|
|
|
return R.ok(resultMsg);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public R<ResultInfo> initEntityCard(PtCardBo cardBo) {
|
|
|
+ PtUserAccountVo userAccountVo = new PtUserAccountVo();
|
|
|
+ PtWorkstationVo workstationVo = new PtWorkstationVo();
|
|
|
+ // 基本的参数校验
|
|
|
+ R<ResultInfo> result = checkParam(cardBo, userAccountVo, workstationVo);
|
|
|
+ if (R.isError(result)) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ // 发卡业务逻辑校验
|
|
|
+ // 1.物理卡号校验
|
|
|
+ result = checkFactoryId(cardBo.getFactoryId());
|
|
|
+ if (R.isError(result)) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ // 用户持有卡片情况校验
|
|
|
+ PtCardBo queryBo = new PtCardBo();
|
|
|
+ queryBo.setUserId(userAccountVo.getUserId());
|
|
|
+ List<PtCardVo> uesrCardList = ptCardService.queryList(queryBo);
|
|
|
+ result = switch (cardBo.getOperateType()) {
|
|
|
+ // 发卡
|
|
|
+ case 2 -> checkUserNewCard(uesrCardList, cardBo);
|
|
|
+ // 换卡
|
|
|
+ case 3 -> checkUserChangeCard(uesrCardList, cardBo);
|
|
|
+ // 补卡
|
|
|
+ case 4 -> checkUserReIssueCard(uesrCardList, cardBo);
|
|
|
+ default -> R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ };
|
|
|
+ // 所有逻辑校验通过,入库
|
|
|
+ cardBo.setCardNo(cardNoBusiness.getCardNo());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private R<ResultInfo> checkParam(PtCardBo cardBo, PtUserAccountVo userAccountVo, PtWorkstationVo workstationVo) {
|
|
|
+ Long factoryId = cardBo.getFactoryId();
|
|
|
+ Long userId = cardBo.getUserId();
|
|
|
+ String mainCard = cardBo.getMainCard();
|
|
|
+ Long stationNumb = cardBo.getStationNumb();
|
|
|
+ Integer operateType = cardBo.getOperateType();
|
|
|
+ String tenantId = cardBo.getTenantId() == null ? DefaultConstants.TENANT_ID : cardBo.getTenantId();
|
|
|
+
|
|
|
+ if (ObjectUtil.isEmpty(factoryId) || factoryId == 0) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "物理卡号必须大于0"));
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(userId) || userId == 0) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "人员Id必须大于0"));
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(mainCard)) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "需要设置主副卡类型:Y为主卡,N为副卡"));
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(stationNumb) || stationNumb == 0) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "工作站编号必须大于0"));
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(operateType)) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "操作类型必须为[2-发卡|3-换卡|4-补卡]中至少一种"));
|
|
|
+ }
|
|
|
+ PtUserAccountVo accountVo = userAccountService.queryById(userId);
|
|
|
+ if (ObjectUtil.isEmpty(accountVo)) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND, MessageFormat.format("没有和Id[{0}]对应的人员信息", userId)));
|
|
|
+ }
|
|
|
+ PtWorkstationVo workstation = workstationService.queryVoByNumber(stationNumb, tenantId);
|
|
|
+ if (ObjectUtil.isEmpty(workstation)) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND, String.format("没有和编号[%d]对应的工作站", stationNumb)));
|
|
|
+ }
|
|
|
+
|
|
|
+ BeanUtil.copyProperties(accountVo, userAccountVo);
|
|
|
+ BeanUtil.copyProperties(workstation, workstationVo);
|
|
|
+
|
|
|
+ return R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查物理卡号的使用情况
|
|
|
+ * 1.物理卡号在系统不存在,可以使用
|
|
|
+ * 2.物理卡号存在,系统参数不支持复用卡片则不可使用
|
|
|
+ * 3.物理卡号存在,系统参数支持复用,但此卡在系统中的状态为正常也不可使用
|
|
|
+ *
|
|
|
+ * @param factoryId 物理卡号
|
|
|
+ * @return 检查结果
|
|
|
+ */
|
|
|
+ private R<ResultInfo> checkFactoryId(Long factoryId) {
|
|
|
+ // 卡片可复用
|
|
|
+ String isReuse = "1";
|
|
|
+ // 根据物理卡号查询发卡信息
|
|
|
+ PtCardBo bo = new PtCardBo();
|
|
|
+ bo.setFactoryId(factoryId);
|
|
|
+ List<PtCardVo> cardVos = ptCardService.queryList(bo);
|
|
|
+ if (CollectionUtil.isNotEmpty(cardVos)) {
|
|
|
+ // 物理卡号有使用时获取卡片否可复用的系统参数
|
|
|
+ String reuseCard = ptParameterService.selectParamByCode("REUSE_CARD");
|
|
|
+ if (ObjectUtil.equal(reuseCard, isReuse)) {
|
|
|
+ // 可复用,检查当前卡片是否有状态为正常的对应卡片,如有则不能再使用
|
|
|
+ if (cardVos.stream().anyMatch(p -> ObjectUtil.equal(p.getStatus(), CardStatusEnum.NORMAL.code()))) {
|
|
|
+ new ResultInfo(ResultCodeEnum.DATA_ALREADY_EXISTED, MessageFormat.format("此卡在正常使用,物理卡号[{0}],不能重新发卡", factoryId));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 不能复用
|
|
|
+ return R.fail(
|
|
|
+ new ResultInfo(ResultCodeEnum.DATA_ALREADY_EXISTED, MessageFormat.format("物理卡号[{0}]已使用过,系统不支持卡片复用", factoryId)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查用户的新卡情况
|
|
|
+ * 1.如果当前用户没有卡片,可以发卡
|
|
|
+ * 2.如果当前用户有正常的主卡,而且是将要发的主卡,则不能发卡
|
|
|
+ * 3.如果当前用户是有虚拟卡了,则则虚拟卡转为实体卡(将虚拟卡对应的cardI和cardNo赋给新卡)
|
|
|
+ *
|
|
|
+ * @param userCardList 用户持卡列表
|
|
|
+ * @param cardBo 发卡业务对象
|
|
|
+ * @return 检查结果
|
|
|
+ */
|
|
|
+ private R<ResultInfo> checkUserNewCard(List<PtCardVo> userCardList, PtCardBo cardBo) {
|
|
|
+ if (CollectionUtil.isEmpty(userCardList)) {
|
|
|
+ // 如人员已有正常的主卡,不能再发主卡
|
|
|
+ if (userCardList.stream().anyMatch(p -> ObjectUtil.equals(p.getMainCard(), "Y")
|
|
|
+ && ObjectUtil.equals(p.getStatus(), CardStatusEnum.NORMAL.code())
|
|
|
+ && p.getFactoryId() > 0 && cardBo.getMainCard().equals("Y"))) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.DATA_ALREADY_EXISTED, MessageFormat.format("Id为[{0}]的人员已有正常主卡,无法再发新卡",
|
|
|
+ cardBo.getUserId())));
|
|
|
+ }
|
|
|
+ // 如果人员已发虚拟卡,此时将虚拟卡转为实体卡
|
|
|
+ userCardList.stream().filter(p -> ObjectUtil.equals(p.getMainCard(), "Y")
|
|
|
+ && ObjectUtil.equals(p.getStatus(), CardStatusEnum.NORMAL.code())
|
|
|
+ && p.getFactoryId() == 0).findFirst().ifPresent(k -> {
|
|
|
+ cardBo.setCardNo(k.getCardNo());
|
|
|
+ cardBo.setCardId(k.getCardId());
|
|
|
+ cardBo.setStatus(k.getStatus());
|
|
|
+ cardBo.setMainCard(k.getMainCard());
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ }
|
|
|
+
|
|
|
+ private R<ResultInfo> checkUserChangeCard(List<PtCardVo> userCardList, PtCardBo cardBo) {
|
|
|
+ Long userId = cardBo.getUserId();
|
|
|
+ if (CollectionUtil.isEmpty(userCardList)) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND, MessageFormat.format("Id为[{0}]的人员没有发过卡,无法换卡", userId)));
|
|
|
+ }
|
|
|
+ Long oldCardNo = cardBo.getOldCardNo();
|
|
|
+ Long oldFactoryId = cardBo.getOldFactoryId();
|
|
|
+ PtCardVo oldCardVo = new PtCardVo();
|
|
|
+ // 换卡时,必须有原卡的发卡记录
|
|
|
+ R<ResultInfo> result = checkUserOldCard(userCardList, oldCardNo, oldFactoryId, oldCardVo);
|
|
|
+ if (R.isError(result)) {
|
|
|
+ return R.fail(MessageFormat.format("无法换卡,{0}", result.getData()));
|
|
|
+ }
|
|
|
+ // 换卡时,原卡必须是正常状态
|
|
|
+ if (ObjectUtil.notEqual(oldCardVo.getStatus(), CardStatusEnum.NORMAL.code())) {
|
|
|
+ return R.fail(
|
|
|
+ new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND,
|
|
|
+ MessageFormat.format("物理卡号[{0}]和卡流水号[{1}]对应旧卡是正常卡片", oldFactoryId, oldCardNo)));
|
|
|
+ }
|
|
|
+ // 将原卡的信息复制到新卡 卡类、有效期和是否主卡
|
|
|
+ userCardList.stream().filter(
|
|
|
+ p -> ObjectUtil.equals(p.getCardNo(), oldCardNo) && ObjectUtil.equals(p.getFactoryId(), oldFactoryId)).findFirst().ifPresent(k -> {
|
|
|
+ cardBo.setCardType(k.getCardType());
|
|
|
+ cardBo.setLifespan(k.getLifespan());
|
|
|
+ cardBo.setMainCard(k.getMainCard());
|
|
|
+ });
|
|
|
+ return R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ }
|
|
|
+
|
|
|
+ private R<ResultInfo> checkUserReIssueCard(List<PtCardVo> userCardList, PtCardBo cardBo) {
|
|
|
+ Long userId = cardBo.getUserId();
|
|
|
+ if (CollectionUtil.isEmpty(userCardList)) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND, MessageFormat.format("Id为[{0}]的人员没有发过卡,无法补卡", userId)));
|
|
|
+ }
|
|
|
+ Long oldCardNo = cardBo.getOldCardNo();
|
|
|
+ Long oldFactoryId = cardBo.getOldFactoryId();
|
|
|
+ PtCardVo oldCardVo = new PtCardVo();
|
|
|
+ // 补卡时,必须有原卡的发卡记录
|
|
|
+ R<ResultInfo> result = checkUserOldCard(userCardList, oldCardNo, oldFactoryId, oldCardVo);
|
|
|
+ if (R.isError(result)) {
|
|
|
+ return R.fail(MessageFormat.format("无法补卡,{0}", result.getData()));
|
|
|
+ }
|
|
|
+ // 补卡时,原卡必须是挂失状态
|
|
|
+ if (ObjectUtil.notEqual(oldCardVo.getStatus(), CardStatusEnum.LOCK.code())) {
|
|
|
+ return R.fail(
|
|
|
+ new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND,
|
|
|
+ MessageFormat.format("没有物理卡号[{0}]和卡流水号[{1}]对应的挂失卡片", oldFactoryId, oldCardNo)));
|
|
|
+ }
|
|
|
+ // 如果待补的旧卡是主卡,检查人员是否有正常主卡
|
|
|
+ if (ObjectUtil.equals(oldCardVo.getMainCard(), "Y")) {
|
|
|
+ if (userCardList.stream().anyMatch(
|
|
|
+ p -> ObjectUtil.equals(p.getStatus(), CardStatusEnum.NORMAL.code()) && ObjectUtil.equals(p.getMainCard(), "Y"))) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.DATA_ALREADY_EXISTED,
|
|
|
+ MessageFormat.format("物理卡号[{0}]和卡流水号[{1}]的挂失卡片为主卡,但人员已有正常的主卡", oldFactoryId,
|
|
|
+ oldCardNo)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ }
|
|
|
+
|
|
|
+ private R<ResultInfo> checkUserOldCard(List<PtCardVo> userCardList, Long oldCardNo, Long oldFactoryId, PtCardVo oldCardVo) {
|
|
|
+ if (ObjectUtil.isEmpty(oldCardNo) || oldCardNo == 0) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "旧卡的卡流水号必须大于0"));
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(oldFactoryId) || oldFactoryId == 0) {
|
|
|
+ return R.fail(new ResultInfo(ResultCodeEnum.PARAM_IS_INVALID, "旧卡的物理卡号必须大于0"));
|
|
|
+ }
|
|
|
+ if (userCardList.stream().noneMatch(p -> ObjectUtil.equals(p.getCardNo(), oldCardNo) && ObjectUtil.equals(p.getFactoryId(), oldFactoryId))) {
|
|
|
+ return R.fail(
|
|
|
+ new ResultInfo(ResultCodeEnum.DATA_NOT_FOUND,
|
|
|
+ MessageFormat.format("无物理卡号[{0}]和卡流水号[{1}]对应的旧卡记录", oldFactoryId, oldCardNo)));
|
|
|
+ }
|
|
|
+ // 取出旧卡信息
|
|
|
+ PtCardVo oldCard = userCardList.stream().filter(
|
|
|
+ p -> ObjectUtil.equals(p.getCardNo(), oldCardNo) && ObjectUtil.equals(p.getFactoryId(), oldFactoryId)).findFirst().orElse(null);
|
|
|
+
|
|
|
+ BeanUtil.copyProperties(oldCard, oldCardVo);
|
|
|
+ return R.ok(new ResultInfo(ResultCodeEnum.SUCCESS));
|
|
|
+ }
|
|
|
}
|