From d4fbb60bdf777074c6706db2ee20ab4e56a48285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E8=99=B9?= Date: Wed, 29 May 2019 19:02:31 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=B8=8D=E7=AE=A1=E4=BD=A0=E6=99=95?= =?UTF-8?q?=E4=B8=8D=E6=99=95=EF=BC=8C=E5=8F=8D=E6=AD=A3=E6=88=91=E6=98=AF?= =?UTF-8?q?=E6=99=95=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QuartzUrgeRepayUserAlloca.java | 376 +++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 QuartzUrgeRepayUserAlloca.java diff --git a/QuartzUrgeRepayUserAlloca.java b/QuartzUrgeRepayUserAlloca.java new file mode 100644 index 0000000..a13e52d --- /dev/null +++ b/QuartzUrgeRepayUserAlloca.java @@ -0,0 +1,376 @@ +package com.nmoney.cashloan.manage.job; + +import com.nmoney.cashloan.cl.domain.BorrowRepayLog; +import com.nmoney.cashloan.cl.domain.UrgeRepayOrder; +import com.nmoney.cashloan.cl.domain.UrgeRepayOrderFlow; +import com.nmoney.cashloan.cl.domain.UrgeRepayUserAlloca; +import com.nmoney.cashloan.cl.enums.UrgeRepayType; +import com.nmoney.cashloan.cl.model.UrgeRepayOrderModel; +import com.nmoney.cashloan.cl.service.BorrowRepayLogService; +import com.nmoney.cashloan.cl.service.ClUrgeRepayUserAllocaService; +import com.nmoney.cashloan.cl.service.UrgeRepayOrderFlowService; +import com.nmoney.cashloan.cl.service.UrgeRepayOrderService; +import com.nmoney.cashloan.core.common.context.Global; +import com.nmoney.cashloan.core.common.exception.ServiceException; +import com.nmoney.cashloan.core.domain.User; +import com.nmoney.cashloan.core.service.CloanUserService; +import com.nmoney.cashloan.manage.domain.QuartzInfo; +import com.nmoney.cashloan.manage.domain.QuartzLog; +import com.nmoney.cashloan.manage.service.QuartzInfoService; +import com.nmoney.cashloan.manage.service.QuartzLogService; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import tool.util.BeanUtil; +import tool.util.DateUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * 催收员动态分配 + * + * @author xym + */ +@Component +@Lazy(value = false) +public class QuartzUrgeRepayUserAlloca implements Job { + + private static final Logger logger = LoggerFactory.getLogger(QuartzUrgeRepayUserAlloca.class); + + /** + * 催收员动态分配催收单 + * + * @throws ServiceException + */ + public String urgeUserAlloca() throws ServiceException { + + long startTime = System.currentTimeMillis(); + final UrgeRepayOrderService urgeRepayOrderService = (UrgeRepayOrderService) BeanUtil.getBean("urgeRepayOrderService"); + final UrgeRepayOrderFlowService urgeRepayOrderFlowService = (UrgeRepayOrderFlowService) BeanUtil.getBean("urgeRepayOrderFlowService"); + final BorrowRepayLogService borrowRepayLogService = (BorrowRepayLogService) BeanUtil.getBean("borrowRepayLogService"); + final ClUrgeRepayUserAllocaService urgeRepayUserAllocaService = (ClUrgeRepayUserAllocaService) BeanUtil.getBean("urgeRepayUserAllocaService"); + final CloanUserService cloanUserService = (CloanUserService) BeanUtil.getBean("cloanUserService"); + boolean isDev = "dev".equals(Global.getValue("app_environment")); + //所有催收计划 + List urgeRepayOrders = urgeRepayOrderService.listAll(new HashMap()); + /** + * 前手的规则可以动态调整 + */ + String[] frontHandRule = Global.getValue("urgeRepay_fronthand_rule").split(","); + + /** + * 用户归类分类 + */ + Map> classifyUserMap = new HashMap>(4) {{ + put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + }}; + + Map> classifyVacationUserMap = new HashMap>(4) {{ + put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + }}; + + /** + * 筛选具有权限的用户 + */ + HashMap paramsMap = new HashMap<>(); + paramsMap.put("state", 0); + List urgeRepayUserAllocas = urgeRepayUserAllocaService.selectAll(paramsMap); + if (urgeRepayUserAllocas != null && urgeRepayUserAllocas.size() > 0) { + for (UrgeRepayUserAlloca urgeRepayUserAlloca : urgeRepayUserAllocas) { + boolean isFront = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.FRONT_HAND.getCode())); + boolean isNew = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.NEW_CUSTOMER.getCode())); + if (isFront && isNew) { + classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (isFront && !isNew) { + classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (!isFront && !isNew) { + classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else { + classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } + } + } + + paramsMap.put("state", 1); + List urgeRepayVacationUserAllocas = urgeRepayUserAllocaService.selectAll(paramsMap); + if (urgeRepayVacationUserAllocas != null && urgeRepayVacationUserAllocas.size() > 0) { + for (UrgeRepayUserAlloca urgeRepayUserAlloca : urgeRepayVacationUserAllocas) { + boolean isFront = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.FRONT_HAND.getCode())); + boolean isNew = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.NEW_CUSTOMER.getCode())); + if (isFront && isNew) { + classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (isFront && !isNew) { + classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (!isFront && !isNew) { + classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else { + classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } + } + } + + /** + * 催收分类 + */ + Map> classifyUrgeRepayMap = new HashMap>(4) {{ + put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + }}; + + /** + * 筛选单子 + */ + if (null != urgeRepayOrders && urgeRepayOrders.size() > 0) { + List borrowUserList = cloanUserService.listSelective(new HashMap()); + List borrowUserPhoneList = new ArrayList(); + Map phone2IdMap=new HashMap(); + for(User user : borrowUserList){ + borrowUserPhoneList.add(user.getLoginName()); + phone2IdMap.put(user.getLoginName(),user.getId()); + } + + List borrowRepayLogList = borrowRepayLogService.listSelective(new HashMap()); + List borrowUserIdList = new ArrayList(); + for(BorrowRepayLog borrowRepayLog : borrowRepayLogList){ + borrowUserIdList.add(borrowRepayLog.getUserId()); + } + + + for (UrgeRepayOrder urgeRepayOrder : urgeRepayOrders) { + if(UrgeRepayOrderModel.STATE_ORDER_SUCCESS.equals(urgeRepayOrder.getState()) || UrgeRepayOrderModel.STATE_ORDER_LOCK.equals(urgeRepayOrder.getState())) { + continue; + } + +// User borrowUser = cloanUserService.findByPhone(urgeRepayOrder.getPhone()); +// if (null == borrowUser) { + if (!borrowUserPhoneList.contains(urgeRepayOrder.getPhone())) { + logger.error("未找到当前借款用户 {}", urgeRepayOrder.getPhone()); + continue; + } + +// boolean hasRepay = borrowRepayLogService.existByUserId(borrowUser.getId()); + boolean hasRepay=false; + if(borrowUserIdList.contains(phone2IdMap.get(urgeRepayOrder.getPhone()))){ + hasRepay = true; + } + boolean isFront = ((urgeRepayOrder.getPenaltyDay() >= Integer.valueOf(frontHandRule[0]) && urgeRepayOrder.getPenaltyDay() <= Integer.valueOf(frontHandRule[1]))); + if (hasRepay && isFront) { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } + + } else if (!hasRepay && isFront) { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } + } else if (hasRepay && !isFront) { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } else if(urgeRepayOrder.getPenaltyDay().intValue()%Integer.valueOf(frontHandRule[2]) == 0){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //达到最大持单时间,重新分配 + } + } else { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } else if(urgeRepayOrder.getPenaltyDay().intValue()%Integer.valueOf(frontHandRule[2]) == 0){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //达到最大持单时间,重新分配 + } + + } + } + } + + + + if (isDev) { + logger.info("开始自动分配催收任务,催收数据明细:"); + logger.info("符合[前手新客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[前手老客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("符合[后手新客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[后手老客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("\n\n"); + logger.info("符合[前手新客]用户个数:{}", classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[前手老客]用户个数:{}", classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("符合[后手新客]用户个数:{}", classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[后手老客]用户个数:{}", classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("\n\n"); + } + ExecutorService executorService = null; + String quartzRemark = null; + try { + /** + * 开启4个线程 + */ + executorService = Executors.newFixedThreadPool(classifyUrgeRepayMap.size()); + final CountDownLatch latch=new CountDownLatch(4); + for (UrgeRepayType urgeRepayType : UrgeRepayType.getGroupClassify()) { + final List urgeRepayOrders1 = classifyUrgeRepayMap.get(urgeRepayType.getCode()); + final List users = classifyUserMap.get(urgeRepayType.getCode()); + //单子和催收员都要有数据 + int usize = users.size(); + int osize = urgeRepayOrders1.size(); + if (usize > 0 && osize > 0) { + //分配 + rectificateProcess(executorService, urgeRepayOrders1, urgeRepayOrderService,urgeRepayOrderFlowService, users,latch); + } else { + logger.info("当前没有要进行分配的逾期单或者催收人员,osize={},usize={}", osize, usize); + latch.countDown(); + continue; + } + } + //当前线程挂起等待 + latch.await(9, TimeUnit.HOURS); + } catch (Exception e) { + e.printStackTrace(); + logger.error("定时扣款计数器出错", e); + } + //线程池中所有任务都执行完毕后,线程池关闭 + executorService.shutdown(); + quartzRemark = "催收单自动分配完毕,当前耗时 " + (System.currentTimeMillis() - startTime) + "ms"; + return quartzRemark; + } + + private Boolean checkUserExist(Long userId, List users, List vacationUsers){ + Boolean ret=false; + for(UrgeRepayUserAlloca user : users){ + if(userId!=null && user.getUserId()!=null && userId.longValue()==user.getUserId().longValue()){ + ret=true; + break; + } + } + for(UrgeRepayUserAlloca user : vacationUsers){ + if(userId!=null && user.getUserId()!=null && userId.longValue()==user.getUserId().longValue()){ + ret=true; + break; + } + } + return ret; + } + + + /** + * 分配均衡时,数量较大,多线程代劳 + * + * @param executorService + * @param urgeRepayOrders + * @param urgeRepayOrderService + * @param users + */ + private void rectificateProcess(ExecutorService executorService, final List urgeRepayOrders, final UrgeRepayOrderService urgeRepayOrderService, final UrgeRepayOrderFlowService urgeRepayOrderFlowService, final List users, final CountDownLatch latch) { + final int osize = urgeRepayOrders.size(); + final int usize = users.size(); + + executorService.submit(new Runnable() { + @Override + public void run() { + List usersIndexList=new ArrayList(); + int m=0; + for (int i = 0; i < osize; i++) { + UrgeRepayOrder order = urgeRepayOrders.get(i); + if(m%usize==0){ + //生成一组随机整数 + usersIndexList= gerateIntArray(usize); + } + + if(UrgeRepayOrderModel.STATE_ORDER_SUCCESS.equals(urgeRepayOrderService.getById(order.getId()).getState())){ + continue; + } + UrgeRepayUserAlloca urgeRepayUserAlloca = users.get(Integer.parseInt(usersIndexList.get(m%usize))); + Map params = new HashMap<>(); + params.put("userId", urgeRepayUserAlloca.getUserId()); + params.put("userName", urgeRepayUserAlloca.getRealName()); + if("".equals(order.getState()) || UrgeRepayOrderModel.STATE_ORDER_PRE.equals(order.getState())){ + params.put("state",UrgeRepayOrderModel.STATE_ORDER_WAIT); + } + params.put("id",order.getId()); + urgeRepayOrderService.orderAllotUser(params); + + UrgeRepayOrderFlow record=new UrgeRepayOrderFlow(); + record.setDueId(order.getId()); + record.setBorrowId(order.getBorrowId()); + record.setUserId(urgeRepayUserAlloca.getUserId()); + record.setUserName(urgeRepayUserAlloca.getRealName()); + record.setCreateTime(DateUtil.getNow()); + record.setState(order.getState()); + record.setPenaltyDay(order.getPenaltyDay()); + urgeRepayOrderFlowService.addflowRecord(record); + m++; + } + latch.countDown(); + } + }); + } + + private List gerateIntArray(int length){ + List retArray=new ArrayList(); + for(int i=0;retArray.size() qiData = new HashMap<>(); + qiData.put("id", quartzInfo.getId()); + + QuartzLog quartzLog = new QuartzLog(); + quartzLog.setQuartzId(quartzInfo.getId()); + quartzLog.setStartTime(DateUtil.getNow()); + try { + String remark = urgeUserAlloca(); + + quartzLog.setTime(DateUtil.getNow().getTime() - quartzLog.getStartTime().getTime()); + quartzLog.setResult("10"); + quartzLog.setRemark(remark); + qiData.put("succeed", quartzInfo.getSucceed() + 1); + } catch (Exception e) { + quartzLog.setResult("20"); + qiData.put("fail", quartzInfo.getFail() + 1); + logger.error(e.getMessage(), e); + } finally { + logger.info("保存定时任务日志"); + quartzLogService.save(quartzLog); + quartzInfoService.update(qiData); + } + } +} -- Gitee From a9407e529c81abf1133ce77bba94a6af58229f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E8=99=B9?= Date: Wed, 29 May 2019 19:03:07 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6QuartzU?= =?UTF-8?q?rgeRepayUserAlloca.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QuartzUrgeRepayUserAlloca.java | 376 --------------------------------- 1 file changed, 376 deletions(-) delete mode 100644 QuartzUrgeRepayUserAlloca.java diff --git a/QuartzUrgeRepayUserAlloca.java b/QuartzUrgeRepayUserAlloca.java deleted file mode 100644 index a13e52d..0000000 --- a/QuartzUrgeRepayUserAlloca.java +++ /dev/null @@ -1,376 +0,0 @@ -package com.nmoney.cashloan.manage.job; - -import com.nmoney.cashloan.cl.domain.BorrowRepayLog; -import com.nmoney.cashloan.cl.domain.UrgeRepayOrder; -import com.nmoney.cashloan.cl.domain.UrgeRepayOrderFlow; -import com.nmoney.cashloan.cl.domain.UrgeRepayUserAlloca; -import com.nmoney.cashloan.cl.enums.UrgeRepayType; -import com.nmoney.cashloan.cl.model.UrgeRepayOrderModel; -import com.nmoney.cashloan.cl.service.BorrowRepayLogService; -import com.nmoney.cashloan.cl.service.ClUrgeRepayUserAllocaService; -import com.nmoney.cashloan.cl.service.UrgeRepayOrderFlowService; -import com.nmoney.cashloan.cl.service.UrgeRepayOrderService; -import com.nmoney.cashloan.core.common.context.Global; -import com.nmoney.cashloan.core.common.exception.ServiceException; -import com.nmoney.cashloan.core.domain.User; -import com.nmoney.cashloan.core.service.CloanUserService; -import com.nmoney.cashloan.manage.domain.QuartzInfo; -import com.nmoney.cashloan.manage.domain.QuartzLog; -import com.nmoney.cashloan.manage.service.QuartzInfoService; -import com.nmoney.cashloan.manage.service.QuartzLogService; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; -import tool.util.BeanUtil; -import tool.util.DateUtil; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * 催收员动态分配 - * - * @author xym - */ -@Component -@Lazy(value = false) -public class QuartzUrgeRepayUserAlloca implements Job { - - private static final Logger logger = LoggerFactory.getLogger(QuartzUrgeRepayUserAlloca.class); - - /** - * 催收员动态分配催收单 - * - * @throws ServiceException - */ - public String urgeUserAlloca() throws ServiceException { - - long startTime = System.currentTimeMillis(); - final UrgeRepayOrderService urgeRepayOrderService = (UrgeRepayOrderService) BeanUtil.getBean("urgeRepayOrderService"); - final UrgeRepayOrderFlowService urgeRepayOrderFlowService = (UrgeRepayOrderFlowService) BeanUtil.getBean("urgeRepayOrderFlowService"); - final BorrowRepayLogService borrowRepayLogService = (BorrowRepayLogService) BeanUtil.getBean("borrowRepayLogService"); - final ClUrgeRepayUserAllocaService urgeRepayUserAllocaService = (ClUrgeRepayUserAllocaService) BeanUtil.getBean("urgeRepayUserAllocaService"); - final CloanUserService cloanUserService = (CloanUserService) BeanUtil.getBean("cloanUserService"); - boolean isDev = "dev".equals(Global.getValue("app_environment")); - //所有催收计划 - List urgeRepayOrders = urgeRepayOrderService.listAll(new HashMap()); - /** - * 前手的规则可以动态调整 - */ - String[] frontHandRule = Global.getValue("urgeRepay_fronthand_rule").split(","); - - /** - * 用户归类分类 - */ - Map> classifyUserMap = new HashMap>(4) {{ - put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); - }}; - - Map> classifyVacationUserMap = new HashMap>(4) {{ - put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); - }}; - - /** - * 筛选具有权限的用户 - */ - HashMap paramsMap = new HashMap<>(); - paramsMap.put("state", 0); - List urgeRepayUserAllocas = urgeRepayUserAllocaService.selectAll(paramsMap); - if (urgeRepayUserAllocas != null && urgeRepayUserAllocas.size() > 0) { - for (UrgeRepayUserAlloca urgeRepayUserAlloca : urgeRepayUserAllocas) { - boolean isFront = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.FRONT_HAND.getCode())); - boolean isNew = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.NEW_CUSTOMER.getCode())); - if (isFront && isNew) { - classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } else if (isFront && !isNew) { - classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } else if (!isFront && !isNew) { - classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } else { - classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } - } - } - - paramsMap.put("state", 1); - List urgeRepayVacationUserAllocas = urgeRepayUserAllocaService.selectAll(paramsMap); - if (urgeRepayVacationUserAllocas != null && urgeRepayVacationUserAllocas.size() > 0) { - for (UrgeRepayUserAlloca urgeRepayUserAlloca : urgeRepayVacationUserAllocas) { - boolean isFront = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.FRONT_HAND.getCode())); - boolean isNew = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.NEW_CUSTOMER.getCode())); - if (isFront && isNew) { - classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } else if (isFront && !isNew) { - classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } else if (!isFront && !isNew) { - classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } else { - classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); - } - } - } - - /** - * 催收分类 - */ - Map> classifyUrgeRepayMap = new HashMap>(4) {{ - put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); - put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); - }}; - - /** - * 筛选单子 - */ - if (null != urgeRepayOrders && urgeRepayOrders.size() > 0) { - List borrowUserList = cloanUserService.listSelective(new HashMap()); - List borrowUserPhoneList = new ArrayList(); - Map phone2IdMap=new HashMap(); - for(User user : borrowUserList){ - borrowUserPhoneList.add(user.getLoginName()); - phone2IdMap.put(user.getLoginName(),user.getId()); - } - - List borrowRepayLogList = borrowRepayLogService.listSelective(new HashMap()); - List borrowUserIdList = new ArrayList(); - for(BorrowRepayLog borrowRepayLog : borrowRepayLogList){ - borrowUserIdList.add(borrowRepayLog.getUserId()); - } - - - for (UrgeRepayOrder urgeRepayOrder : urgeRepayOrders) { - if(UrgeRepayOrderModel.STATE_ORDER_SUCCESS.equals(urgeRepayOrder.getState()) || UrgeRepayOrderModel.STATE_ORDER_LOCK.equals(urgeRepayOrder.getState())) { - continue; - } - -// User borrowUser = cloanUserService.findByPhone(urgeRepayOrder.getPhone()); -// if (null == borrowUser) { - if (!borrowUserPhoneList.contains(urgeRepayOrder.getPhone())) { - logger.error("未找到当前借款用户 {}", urgeRepayOrder.getPhone()); - continue; - } - -// boolean hasRepay = borrowRepayLogService.existByUserId(borrowUser.getId()); - boolean hasRepay=false; - if(borrowUserIdList.contains(phone2IdMap.get(urgeRepayOrder.getPhone()))){ - hasRepay = true; - } - boolean isFront = ((urgeRepayOrder.getPenaltyDay() >= Integer.valueOf(frontHandRule[0]) && urgeRepayOrder.getPenaltyDay() <= Integer.valueOf(frontHandRule[1]))); - if (hasRepay && isFront) { - if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ - classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 - }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()))){ - classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 - } - - } else if (!hasRepay && isFront) { - if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ - classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 - }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()))){ - classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 - } - } else if (hasRepay && !isFront) { - if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ - classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 - }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()))){ - classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 - } else if(urgeRepayOrder.getPenaltyDay().intValue()%Integer.valueOf(frontHandRule[2]) == 0){ - classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //达到最大持单时间,重新分配 - } - } else { - if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ - classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 - }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()))){ - classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 - } else if(urgeRepayOrder.getPenaltyDay().intValue()%Integer.valueOf(frontHandRule[2]) == 0){ - classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //达到最大持单时间,重新分配 - } - - } - } - } - - - - if (isDev) { - logger.info("开始自动分配催收任务,催收数据明细:"); - logger.info("符合[前手新客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).size()); - logger.info("符合[前手老客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).size()); - logger.info("符合[后手新客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).size()); - logger.info("符合[后手老客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).size()); - logger.info("\n\n"); - logger.info("符合[前手新客]用户个数:{}", classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).size()); - logger.info("符合[前手老客]用户个数:{}", classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).size()); - logger.info("符合[后手新客]用户个数:{}", classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).size()); - logger.info("符合[后手老客]用户个数:{}", classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).size()); - logger.info("\n\n"); - } - ExecutorService executorService = null; - String quartzRemark = null; - try { - /** - * 开启4个线程 - */ - executorService = Executors.newFixedThreadPool(classifyUrgeRepayMap.size()); - final CountDownLatch latch=new CountDownLatch(4); - for (UrgeRepayType urgeRepayType : UrgeRepayType.getGroupClassify()) { - final List urgeRepayOrders1 = classifyUrgeRepayMap.get(urgeRepayType.getCode()); - final List users = classifyUserMap.get(urgeRepayType.getCode()); - //单子和催收员都要有数据 - int usize = users.size(); - int osize = urgeRepayOrders1.size(); - if (usize > 0 && osize > 0) { - //分配 - rectificateProcess(executorService, urgeRepayOrders1, urgeRepayOrderService,urgeRepayOrderFlowService, users,latch); - } else { - logger.info("当前没有要进行分配的逾期单或者催收人员,osize={},usize={}", osize, usize); - latch.countDown(); - continue; - } - } - //当前线程挂起等待 - latch.await(9, TimeUnit.HOURS); - } catch (Exception e) { - e.printStackTrace(); - logger.error("定时扣款计数器出错", e); - } - //线程池中所有任务都执行完毕后,线程池关闭 - executorService.shutdown(); - quartzRemark = "催收单自动分配完毕,当前耗时 " + (System.currentTimeMillis() - startTime) + "ms"; - return quartzRemark; - } - - private Boolean checkUserExist(Long userId, List users, List vacationUsers){ - Boolean ret=false; - for(UrgeRepayUserAlloca user : users){ - if(userId!=null && user.getUserId()!=null && userId.longValue()==user.getUserId().longValue()){ - ret=true; - break; - } - } - for(UrgeRepayUserAlloca user : vacationUsers){ - if(userId!=null && user.getUserId()!=null && userId.longValue()==user.getUserId().longValue()){ - ret=true; - break; - } - } - return ret; - } - - - /** - * 分配均衡时,数量较大,多线程代劳 - * - * @param executorService - * @param urgeRepayOrders - * @param urgeRepayOrderService - * @param users - */ - private void rectificateProcess(ExecutorService executorService, final List urgeRepayOrders, final UrgeRepayOrderService urgeRepayOrderService, final UrgeRepayOrderFlowService urgeRepayOrderFlowService, final List users, final CountDownLatch latch) { - final int osize = urgeRepayOrders.size(); - final int usize = users.size(); - - executorService.submit(new Runnable() { - @Override - public void run() { - List usersIndexList=new ArrayList(); - int m=0; - for (int i = 0; i < osize; i++) { - UrgeRepayOrder order = urgeRepayOrders.get(i); - if(m%usize==0){ - //生成一组随机整数 - usersIndexList= gerateIntArray(usize); - } - - if(UrgeRepayOrderModel.STATE_ORDER_SUCCESS.equals(urgeRepayOrderService.getById(order.getId()).getState())){ - continue; - } - UrgeRepayUserAlloca urgeRepayUserAlloca = users.get(Integer.parseInt(usersIndexList.get(m%usize))); - Map params = new HashMap<>(); - params.put("userId", urgeRepayUserAlloca.getUserId()); - params.put("userName", urgeRepayUserAlloca.getRealName()); - if("".equals(order.getState()) || UrgeRepayOrderModel.STATE_ORDER_PRE.equals(order.getState())){ - params.put("state",UrgeRepayOrderModel.STATE_ORDER_WAIT); - } - params.put("id",order.getId()); - urgeRepayOrderService.orderAllotUser(params); - - UrgeRepayOrderFlow record=new UrgeRepayOrderFlow(); - record.setDueId(order.getId()); - record.setBorrowId(order.getBorrowId()); - record.setUserId(urgeRepayUserAlloca.getUserId()); - record.setUserName(urgeRepayUserAlloca.getRealName()); - record.setCreateTime(DateUtil.getNow()); - record.setState(order.getState()); - record.setPenaltyDay(order.getPenaltyDay()); - urgeRepayOrderFlowService.addflowRecord(record); - m++; - } - latch.countDown(); - } - }); - } - - private List gerateIntArray(int length){ - List retArray=new ArrayList(); - for(int i=0;retArray.size() qiData = new HashMap<>(); - qiData.put("id", quartzInfo.getId()); - - QuartzLog quartzLog = new QuartzLog(); - quartzLog.setQuartzId(quartzInfo.getId()); - quartzLog.setStartTime(DateUtil.getNow()); - try { - String remark = urgeUserAlloca(); - - quartzLog.setTime(DateUtil.getNow().getTime() - quartzLog.getStartTime().getTime()); - quartzLog.setResult("10"); - quartzLog.setRemark(remark); - qiData.put("succeed", quartzInfo.getSucceed() + 1); - } catch (Exception e) { - quartzLog.setResult("20"); - qiData.put("fail", quartzInfo.getFail() + 1); - logger.error(e.getMessage(), e); - } finally { - logger.info("保存定时任务日志"); - quartzLogService.save(quartzLog); - quartzInfoService.update(qiData); - } - } -} -- Gitee From c186bd7b96d9aad0d6c1520da9cff08fc606fd95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E8=99=B9?= Date: Wed, 29 May 2019 19:03:28 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=B8=8D=E7=AE=A1=E4=BD=A0=E6=99=95?= =?UTF-8?q?=E4=B8=8D=E6=99=95=EF=BC=8C=E5=8F=8D=E6=AD=A3=E6=88=91=E6=98=AF?= =?UTF-8?q?=E6=99=95=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/QuartzUrgeRepayUserAlloca.java | 376 ++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 java/QuartzUrgeRepayUserAlloca.java diff --git a/java/QuartzUrgeRepayUserAlloca.java b/java/QuartzUrgeRepayUserAlloca.java new file mode 100644 index 0000000..a13e52d --- /dev/null +++ b/java/QuartzUrgeRepayUserAlloca.java @@ -0,0 +1,376 @@ +package com.nmoney.cashloan.manage.job; + +import com.nmoney.cashloan.cl.domain.BorrowRepayLog; +import com.nmoney.cashloan.cl.domain.UrgeRepayOrder; +import com.nmoney.cashloan.cl.domain.UrgeRepayOrderFlow; +import com.nmoney.cashloan.cl.domain.UrgeRepayUserAlloca; +import com.nmoney.cashloan.cl.enums.UrgeRepayType; +import com.nmoney.cashloan.cl.model.UrgeRepayOrderModel; +import com.nmoney.cashloan.cl.service.BorrowRepayLogService; +import com.nmoney.cashloan.cl.service.ClUrgeRepayUserAllocaService; +import com.nmoney.cashloan.cl.service.UrgeRepayOrderFlowService; +import com.nmoney.cashloan.cl.service.UrgeRepayOrderService; +import com.nmoney.cashloan.core.common.context.Global; +import com.nmoney.cashloan.core.common.exception.ServiceException; +import com.nmoney.cashloan.core.domain.User; +import com.nmoney.cashloan.core.service.CloanUserService; +import com.nmoney.cashloan.manage.domain.QuartzInfo; +import com.nmoney.cashloan.manage.domain.QuartzLog; +import com.nmoney.cashloan.manage.service.QuartzInfoService; +import com.nmoney.cashloan.manage.service.QuartzLogService; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import tool.util.BeanUtil; +import tool.util.DateUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * 催收员动态分配 + * + * @author xym + */ +@Component +@Lazy(value = false) +public class QuartzUrgeRepayUserAlloca implements Job { + + private static final Logger logger = LoggerFactory.getLogger(QuartzUrgeRepayUserAlloca.class); + + /** + * 催收员动态分配催收单 + * + * @throws ServiceException + */ + public String urgeUserAlloca() throws ServiceException { + + long startTime = System.currentTimeMillis(); + final UrgeRepayOrderService urgeRepayOrderService = (UrgeRepayOrderService) BeanUtil.getBean("urgeRepayOrderService"); + final UrgeRepayOrderFlowService urgeRepayOrderFlowService = (UrgeRepayOrderFlowService) BeanUtil.getBean("urgeRepayOrderFlowService"); + final BorrowRepayLogService borrowRepayLogService = (BorrowRepayLogService) BeanUtil.getBean("borrowRepayLogService"); + final ClUrgeRepayUserAllocaService urgeRepayUserAllocaService = (ClUrgeRepayUserAllocaService) BeanUtil.getBean("urgeRepayUserAllocaService"); + final CloanUserService cloanUserService = (CloanUserService) BeanUtil.getBean("cloanUserService"); + boolean isDev = "dev".equals(Global.getValue("app_environment")); + //所有催收计划 + List urgeRepayOrders = urgeRepayOrderService.listAll(new HashMap()); + /** + * 前手的规则可以动态调整 + */ + String[] frontHandRule = Global.getValue("urgeRepay_fronthand_rule").split(","); + + /** + * 用户归类分类 + */ + Map> classifyUserMap = new HashMap>(4) {{ + put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + }}; + + Map> classifyVacationUserMap = new HashMap>(4) {{ + put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + }}; + + /** + * 筛选具有权限的用户 + */ + HashMap paramsMap = new HashMap<>(); + paramsMap.put("state", 0); + List urgeRepayUserAllocas = urgeRepayUserAllocaService.selectAll(paramsMap); + if (urgeRepayUserAllocas != null && urgeRepayUserAllocas.size() > 0) { + for (UrgeRepayUserAlloca urgeRepayUserAlloca : urgeRepayUserAllocas) { + boolean isFront = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.FRONT_HAND.getCode())); + boolean isNew = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.NEW_CUSTOMER.getCode())); + if (isFront && isNew) { + classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (isFront && !isNew) { + classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (!isFront && !isNew) { + classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else { + classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } + } + } + + paramsMap.put("state", 1); + List urgeRepayVacationUserAllocas = urgeRepayUserAllocaService.selectAll(paramsMap); + if (urgeRepayVacationUserAllocas != null && urgeRepayVacationUserAllocas.size() > 0) { + for (UrgeRepayUserAlloca urgeRepayUserAlloca : urgeRepayVacationUserAllocas) { + boolean isFront = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.FRONT_HAND.getCode())); + boolean isNew = urgeRepayUserAlloca.getAllocastr().contains(String.valueOf(UrgeRepayType.NEW_CUSTOMER.getCode())); + if (isFront && isNew) { + classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (isFront && !isNew) { + classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else if (!isFront && !isNew) { + classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } else { + classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayUserAlloca); + } + } + } + + /** + * 催收分类 + */ + Map> classifyUrgeRepayMap = new HashMap>(4) {{ + put(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode(), new ArrayList()); + put(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode(), new ArrayList()); + }}; + + /** + * 筛选单子 + */ + if (null != urgeRepayOrders && urgeRepayOrders.size() > 0) { + List borrowUserList = cloanUserService.listSelective(new HashMap()); + List borrowUserPhoneList = new ArrayList(); + Map phone2IdMap=new HashMap(); + for(User user : borrowUserList){ + borrowUserPhoneList.add(user.getLoginName()); + phone2IdMap.put(user.getLoginName(),user.getId()); + } + + List borrowRepayLogList = borrowRepayLogService.listSelective(new HashMap()); + List borrowUserIdList = new ArrayList(); + for(BorrowRepayLog borrowRepayLog : borrowRepayLogList){ + borrowUserIdList.add(borrowRepayLog.getUserId()); + } + + + for (UrgeRepayOrder urgeRepayOrder : urgeRepayOrders) { + if(UrgeRepayOrderModel.STATE_ORDER_SUCCESS.equals(urgeRepayOrder.getState()) || UrgeRepayOrderModel.STATE_ORDER_LOCK.equals(urgeRepayOrder.getState())) { + continue; + } + +// User borrowUser = cloanUserService.findByPhone(urgeRepayOrder.getPhone()); +// if (null == borrowUser) { + if (!borrowUserPhoneList.contains(urgeRepayOrder.getPhone())) { + logger.error("未找到当前借款用户 {}", urgeRepayOrder.getPhone()); + continue; + } + +// boolean hasRepay = borrowRepayLogService.existByUserId(borrowUser.getId()); + boolean hasRepay=false; + if(borrowUserIdList.contains(phone2IdMap.get(urgeRepayOrder.getPhone()))){ + hasRepay = true; + } + boolean isFront = ((urgeRepayOrder.getPenaltyDay() >= Integer.valueOf(frontHandRule[0]) && urgeRepayOrder.getPenaltyDay() <= Integer.valueOf(frontHandRule[1]))); + if (hasRepay && isFront) { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } + + } else if (!hasRepay && isFront) { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } + } else if (hasRepay && !isFront) { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } else if(urgeRepayOrder.getPenaltyDay().intValue()%Integer.valueOf(frontHandRule[2]) == 0){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).add(urgeRepayOrder); //达到最大持单时间,重新分配 + } + } else { + if("".equals(urgeRepayOrder.getState()) || "10".equals(urgeRepayOrder.getState())){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //无状态或者状态为未分配的催单 + }else if(!checkUserExist(urgeRepayOrder.getUserId(),classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()),classifyVacationUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()))){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //催单员不存在或者状态异常 + } else if(urgeRepayOrder.getPenaltyDay().intValue()%Integer.valueOf(frontHandRule[2]) == 0){ + classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).add(urgeRepayOrder); //达到最大持单时间,重新分配 + } + + } + } + } + + + + if (isDev) { + logger.info("开始自动分配催收任务,催收数据明细:"); + logger.info("符合[前手新客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[前手老客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("符合[后手新客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[后手老客]数据条数:{}", classifyUrgeRepayMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("\n\n"); + logger.info("符合[前手新客]用户个数:{}", classifyUserMap.get(UrgeRepayType.FRONT_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[前手老客]用户个数:{}", classifyUserMap.get(UrgeRepayType.FRONT_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("符合[后手新客]用户个数:{}", classifyUserMap.get(UrgeRepayType.BACK_HAND_NEW_CUSTOMER.getCode()).size()); + logger.info("符合[后手老客]用户个数:{}", classifyUserMap.get(UrgeRepayType.BACK_HAND_OLD_CUSTOMER.getCode()).size()); + logger.info("\n\n"); + } + ExecutorService executorService = null; + String quartzRemark = null; + try { + /** + * 开启4个线程 + */ + executorService = Executors.newFixedThreadPool(classifyUrgeRepayMap.size()); + final CountDownLatch latch=new CountDownLatch(4); + for (UrgeRepayType urgeRepayType : UrgeRepayType.getGroupClassify()) { + final List urgeRepayOrders1 = classifyUrgeRepayMap.get(urgeRepayType.getCode()); + final List users = classifyUserMap.get(urgeRepayType.getCode()); + //单子和催收员都要有数据 + int usize = users.size(); + int osize = urgeRepayOrders1.size(); + if (usize > 0 && osize > 0) { + //分配 + rectificateProcess(executorService, urgeRepayOrders1, urgeRepayOrderService,urgeRepayOrderFlowService, users,latch); + } else { + logger.info("当前没有要进行分配的逾期单或者催收人员,osize={},usize={}", osize, usize); + latch.countDown(); + continue; + } + } + //当前线程挂起等待 + latch.await(9, TimeUnit.HOURS); + } catch (Exception e) { + e.printStackTrace(); + logger.error("定时扣款计数器出错", e); + } + //线程池中所有任务都执行完毕后,线程池关闭 + executorService.shutdown(); + quartzRemark = "催收单自动分配完毕,当前耗时 " + (System.currentTimeMillis() - startTime) + "ms"; + return quartzRemark; + } + + private Boolean checkUserExist(Long userId, List users, List vacationUsers){ + Boolean ret=false; + for(UrgeRepayUserAlloca user : users){ + if(userId!=null && user.getUserId()!=null && userId.longValue()==user.getUserId().longValue()){ + ret=true; + break; + } + } + for(UrgeRepayUserAlloca user : vacationUsers){ + if(userId!=null && user.getUserId()!=null && userId.longValue()==user.getUserId().longValue()){ + ret=true; + break; + } + } + return ret; + } + + + /** + * 分配均衡时,数量较大,多线程代劳 + * + * @param executorService + * @param urgeRepayOrders + * @param urgeRepayOrderService + * @param users + */ + private void rectificateProcess(ExecutorService executorService, final List urgeRepayOrders, final UrgeRepayOrderService urgeRepayOrderService, final UrgeRepayOrderFlowService urgeRepayOrderFlowService, final List users, final CountDownLatch latch) { + final int osize = urgeRepayOrders.size(); + final int usize = users.size(); + + executorService.submit(new Runnable() { + @Override + public void run() { + List usersIndexList=new ArrayList(); + int m=0; + for (int i = 0; i < osize; i++) { + UrgeRepayOrder order = urgeRepayOrders.get(i); + if(m%usize==0){ + //生成一组随机整数 + usersIndexList= gerateIntArray(usize); + } + + if(UrgeRepayOrderModel.STATE_ORDER_SUCCESS.equals(urgeRepayOrderService.getById(order.getId()).getState())){ + continue; + } + UrgeRepayUserAlloca urgeRepayUserAlloca = users.get(Integer.parseInt(usersIndexList.get(m%usize))); + Map params = new HashMap<>(); + params.put("userId", urgeRepayUserAlloca.getUserId()); + params.put("userName", urgeRepayUserAlloca.getRealName()); + if("".equals(order.getState()) || UrgeRepayOrderModel.STATE_ORDER_PRE.equals(order.getState())){ + params.put("state",UrgeRepayOrderModel.STATE_ORDER_WAIT); + } + params.put("id",order.getId()); + urgeRepayOrderService.orderAllotUser(params); + + UrgeRepayOrderFlow record=new UrgeRepayOrderFlow(); + record.setDueId(order.getId()); + record.setBorrowId(order.getBorrowId()); + record.setUserId(urgeRepayUserAlloca.getUserId()); + record.setUserName(urgeRepayUserAlloca.getRealName()); + record.setCreateTime(DateUtil.getNow()); + record.setState(order.getState()); + record.setPenaltyDay(order.getPenaltyDay()); + urgeRepayOrderFlowService.addflowRecord(record); + m++; + } + latch.countDown(); + } + }); + } + + private List gerateIntArray(int length){ + List retArray=new ArrayList(); + for(int i=0;retArray.size() qiData = new HashMap<>(); + qiData.put("id", quartzInfo.getId()); + + QuartzLog quartzLog = new QuartzLog(); + quartzLog.setQuartzId(quartzInfo.getId()); + quartzLog.setStartTime(DateUtil.getNow()); + try { + String remark = urgeUserAlloca(); + + quartzLog.setTime(DateUtil.getNow().getTime() - quartzLog.getStartTime().getTime()); + quartzLog.setResult("10"); + quartzLog.setRemark(remark); + qiData.put("succeed", quartzInfo.getSucceed() + 1); + } catch (Exception e) { + quartzLog.setResult("20"); + qiData.put("fail", quartzInfo.getFail() + 1); + logger.error(e.getMessage(), e); + } finally { + logger.info("保存定时任务日志"); + quartzLogService.save(quartzLog); + quartzInfoService.update(qiData); + } + } +} -- Gitee