package com.pj.api.open.service; import cn.hutool.cache.CacheUtil; import cn.hutool.cache.impl.TimedCache; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import cn.hutool.log.StaticLog; import com.pj.api.open.ResultJson; import com.pj.api.open.bo.CheckCarNumberBO; import com.pj.api.open.bo.InRecordBO; import com.pj.api.wx.bo.ManagerBO; import com.pj.constants.business.CarEnum; import com.pj.constants.business.GoodsEnum; import com.pj.constants.business.PayEnum; import com.pj.current.config.PartConfig; import com.pj.current.task.TaskService; import com.pj.project.sync.SyncService; import com.pj.project.sync.request.item.IOrderItem; import com.pj.project.sync.response.IOrderPriceRes; import com.pj.project.tb_account.AutomaticPay; import com.pj.project.tb_business.TbBusiness; import com.pj.project.tb_business.TbBusinessService; import com.pj.project.tb_business_car.TbBusinessCar; import com.pj.project.tb_business_car.TbBusinessCarService; import com.pj.project.tb_business_item.TbBusinessItem; import com.pj.project.tb_business_item.TbBusinessItemService; import com.pj.project.tb_car.TbCar; import com.pj.project.tb_car.TbCarService; import com.pj.project.tb_deduction_bind.TbDeductionBindService; import com.pj.project.tb_goods.TbGoods; import com.pj.project.tb_goods.TbGoodsService; import com.pj.project.tb_mild_car.TbMildCar; import com.pj.project.tb_mild_car.TbMildCarService; import com.pj.utils.cache.RedisUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @Service @Transactional @Slf4j public class OpenService { @Resource @Lazy private TbBusinessService tbBusinessService; @Resource @Lazy private TbBusinessCarService tbBusinessCarService; @Resource private TbCarService tbCarService; @Resource TaskService taskService; @Resource private TbGoodsService tbGoodsService; @Resource @Lazy AutomaticPay automaticPay; @Resource private TbDeductionBindService tbDeductionBindService; @Resource private PartConfig partConfig; @Resource private TbMildCarService tbMildCarService; @Resource private TbBusinessItemService tbBusinessItemService; @Resource private SyncService syncService; public ResultJson checkCarNumber(CheckCarNumberBO checkCarNumberBO) { String carNo = checkCarNumberBO.getCarNumber(); int inOrOut = checkCarNumberBO.getInOrOut(); String image = checkCarNumberBO.getImageData(); if (inOrOut == 1) { return handlerIn(carNo, checkCarNumberBO.getChannelName(), image); } return handlerOut(carNo, checkCarNumberBO.getChannelName(), image); } private ResultJson handlerIn(String carNo, String channel, String image) { carNo = carNo.toUpperCase(); if (StrUtil.isNotEmpty(image)) { StaticLog.error("缓存入场图片:{}", carNo); IMAGE_CACHE.put(carNo, image); } List notOutList = tbBusinessCarService.findNotOutCar(carNo); if (!notOutList.isEmpty()) { String msg = "车辆有" + notOutList.size() + "条未离场记录"; log.error("入场返回:{}", msg); return ResultJson.error(msg); } // automaticPay.unbindRun(carNo); TbBusinessCar tbBusinessCar = tbBusinessCarService.findTheLastRecord(carNo); Date now = new Date(); TbCar tbCar = tbCarService.findByCardNo(carNo); //1、记录不存在; // 2、已离场重新入场; if (tbBusinessCar == null || (tbBusinessCar.getRealInTime() != null && tbBusinessCar.getRealOutTime() != null) ) { //=======创建新的放行记录========== tbBusinessCar = new TbBusinessCar(); tbBusinessCar.setCarNo(carNo).setPay(0).setCarSize(0D).setIsLock(0).setPayType(CarEnum.PayTypeEnum.NO_PAY_TYPE.getType()) .setPay(0) .setCarCompany(tbCar != null ? tbCar.getCustomerName() : "临时").setCreateTime(now) .setInChannel(channel).setRealInTime(now).setCarType(CarEnum.CarTypeEnum.EMPTY_TYPE.getType()) .setBasePartMoney(new BigDecimal("0")).setTimeUpdate(now).setConfirmJudge(CarEnum.ConfirmJudgeEnum.NO_NEED_JUDGE.getCode()) .setNo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + RandomUtil.randomNumbers(4)); tbBusinessCarService.save(tbBusinessCar); CoverBase64ToUrl(image, tbBusinessCar.getId(), carNo, 1); String msg = "无业务车辆"; log.error("入场返回:{}", JSONUtil.toJsonStr(ResultJson.success(msg, msg))); return ResultJson.success(msg, msg); } tbBusinessCar.setRealInTime(now).setInChannel(channel).setTimeUpdate(now) .setCarCompany(tbCar != null ? tbCar.getCustomerName() : "临时"); tbBusinessCarService.saveOrUpdate(tbBusinessCar); CoverBase64ToUrl(image, tbBusinessCar.getId(), carNo, 1); return ResultJson.success(); } private void CoverBase64ToUrl(String base64image, String carId, String carNo, int inOrOut) { String cacheBase64 = IMAGE_CACHE.get(carNo); if (StrUtil.isEmpty(base64image)) { base64image = cacheBase64; } if (StrUtil.isEmpty(base64image)) { log.error("无出场图片:{}", carNo); return; } taskService.addTask(new CoverBase64ToImageTask("=======" + carId + "", 2000, carId, base64image, inOrOut)); IMAGE_CACHE.remove(carNo); } final TimedCache IMAGE_CACHE = CacheUtil.newTimedCache(30 * 60 * 1000); private ResultJson handlerOut(String carNo, String channel, String image) { carNo = carNo.toUpperCase(); TbBusinessCar tbBusinessCar = tbBusinessCarService.findTheLastRecord(carNo); if (tbBusinessCar == null || tbBusinessCar.getRealInTime() == null || tbBusinessCar.getRealOutTime() != null) { log.error("请求返回【未查询到入场记录】:{}", carNo); return ResultJson.error("未查询到入场记录"); } Date now = new Date(); Date realInTime = tbBusinessCar.getRealInTime(); if (now.getTime() / 1000 - realInTime.getTime() / 1000 < partConfig.getMinSeconds()) { log.error("请求返回【无效离场记录,返回到设备端为:“未查询到入场记录”让其停止轮询】:{}", carNo); return ResultJson.error("无效离场记录"); } if (StrUtil.isNotEmpty(image)) { StaticLog.error("缓存离场图片,{}", carNo); IMAGE_CACHE.put(carNo, image); } //判断是否4.2米以下蓝色车牌===免停车费 if (StrUtil.isNotEmpty(tbBusinessCar.getColor())) { String freeColor = partConfig.getFreeColor(); //4蓝色车辆 if (tbBusinessCar.getColor().contains(freeColor)) { log.error("请求返回【蓝牌未备案车辆,放行】:{},{}", carNo, ResultJson.success()); freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } } //是否行政车辆===== if (checkFree(carNo, 2, now)) { freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } String businessCarId = tbBusinessCar.getId(); String carType = tbBusinessCar.getCarType(); IOrderPriceRes partMoneyRes; IOrderPriceRes businessRes = new IOrderPriceRes(); List expenses = new ArrayList<>(); List businessList = tbBusinessService.findOtherBusinessByCarId(businessCarId); long judgeCount = businessList.stream().filter(tbBusiness -> tbBusiness.getConfirmJudge() == CarEnum.ConfirmJudgeEnum.JUDGE_PASS.getCode()).count(); int size = businessList.size(); if (size > judgeCount) { //业务未审核完 log.error("请求返回【业务未审核】:{}", carNo); return ResultJson.error("业务未审核"); } BigDecimal hasPayPartMoney = tbBusinessCar.getMoney(); if (businessList.isEmpty()) { //无业务车辆===>计算停车费 //如果已经支付过,则从支付时间算起,重新计算停车费 Date inTime = tbBusinessCar.getRealInTime(); if (hasPayPartMoney.compareTo(BigDecimal.ZERO) > 0) { inTime = now; } IOrderPriceRes res = tbBusinessService.getPartMoney(inTime, now, carNo, tbBusinessCar.getColor()); double dif = res.getTotalOrderPrice().subtract(tbBusinessCar.getMoney()).doubleValue(); if (dif > 0) { RedisUtil.setByMINUTES(channel, carNo, 5); log.error("请求返回:请缴停车费:{},{}元", carNo, dif); //是否可以预充值缴费 true扣款成功 false否 return ResultJson.error("请缴停车费" + dif + "元"); } else { //无需交停车费,又没有支付的--->设置成免费车辆 if (tbBusinessCar.getPayTime() == null) { tbBusinessCar.setPayType(CarEnum.PayTypeEnum.FEE_TYPE.getType()).setPay(1); } freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } } else { //有业务的车--->都要交停车费 //该车所有的业务都是到达卡口才进行扣费才会进入自动扣费 Date inTime = tbBusinessCar.getRealInTime(); if (hasPayPartMoney.compareTo(BigDecimal.ZERO) > 0) { inTime = now; } partMoneyRes = tbBusinessService.getPartMoney(inTime, now, carNo, tbBusinessCar.getColor()); double dif = partMoneyRes.getTotalOrderPrice().doubleValue(); if (dif > 0) { RedisUtil.setByMINUTES(channel, carNo, 5); log.error("停车费:{},{}元", carNo, dif); } else { if (tbBusinessCar.getPayTime() == null) { tbBusinessCar.setPayType(CarEnum.PayTypeEnum.FEE_TYPE.getType()).setPay(1); } } } //============业务费计算是否交完 //businessList = businessList.stream().filter(tbBusiness -> tbBusiness.getPayStatus() != PayEnum.PayStatusEnum.HAS_PAY_CONFIRM.getCode()).collect(Collectors.toList()); List businessIds = businessList.stream().map(TbBusiness::getId).collect(Collectors.toList()); List businessItems = tbBusinessItemService.findByBusinessId(businessIds); for (TbBusiness tbBusiness : businessList) { TbGoods tbGoods = tbGoodsService.getById(tbBusiness.getGoodsId()); //重车离场限制 int weiCarLeave = tbGoods.getVietnamCarLeave(); //空车离场限制 int emptyCarLeave = tbGoods.getChinaCarLeave(); boolean pay = tbBusiness.getPayMoney().doubleValue() >= tbBusiness.getItemPrice().doubleValue(); //需要交业务费 if (CarEnum.CarTypeEnum.WEIGHT_TYPE.getType().equals(carType)) {//==重车 if (GoodsEnum.LeaveEnum.PART_MONEY.getCode() != weiCarLeave && !pay) { RedisUtil.setByMINUTES(channel, carNo, 5); tbBusinessItemService.buildExpenses(businessItems, expenses); log.error("越南车==重车:缴纳业务费用:{}", carNo); } } else { if (GoodsEnum.LeaveEnum.PART_MONEY.getCode() != emptyCarLeave && !pay) { RedisUtil.setByMINUTES(channel, carNo, 5); tbBusinessItemService.buildExpenses(businessItems, expenses); } } } if (!expenses.isEmpty()) { businessRes = syncService.orderPriceCal(expenses); } BigDecimal carMoney = partMoneyRes.getTotalOrderPrice(); BigDecimal businessMoney = businessRes.getTotalOrderPrice(); BigDecimal total = businessMoney.add(carMoney); //入场管理费。。。。 //ManagerBO dto = tbBusinessService.needPayManagerMoney(carNo, businessCarId, businessItems); // total = dto.getPrice().add(total); if (total.doubleValue() > 0) { String desc = "请缴"; if (businessMoney.doubleValue() > 0) { desc += "业务费" + businessMoney.toString() + "元"; } // if (dto.getPrice().doubleValue() > 0) { // desc += " 入场管理费" + dto.getPrice().toString() + "元"; // } if (carMoney.doubleValue() > 0) { desc += " 停车费" + carMoney.toString() + "元"; } RedisUtil.setByMINUTES(channel, carNo, 5); // boolean flag = automaticPay.payBusinessAndPartMoney(businessList, tbBusinessCar, partMoneyRes); // if (flag) { // // log.error("预存款扣款成功,返回:{},{}", carNo, desc); // freeOut(tbBusinessCar, now, channel, image); // return ResultJson.success(); // } log.error("请求返回:{},{}", carNo, desc); return ResultJson.error(desc); } freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } private void freeOut(TbBusinessCar tbBusinessCar, Date now, String outChannel, String base64Image) { tbBusinessCar.setRealOutTime(now).setTimeUpdate(now).setOutChannel(outChannel); if (tbBusinessCar.getPay() == 0) { tbBusinessCar.setPay(1); } tbBusinessCarService.updateById(tbBusinessCar); String carNo = tbBusinessCar.getCarNo(); CoverBase64ToUrl(base64Image, tbBusinessCar.getId(), carNo, 2); RedisUtil.del(outChannel); log.error("请求返回【放行】:{}", carNo); } private boolean checkFree(String carNo, int inOrOut, Date now) { TbCar tbCar = tbCarService.findByCardNo(carNo); if (tbCar != null) { if (inOrOut == 1) { tbCar.setLastInTime(now); } else { tbCar.setLastOutTime(now); } tbCarService.updateById(tbCar); } return tbCar != null && !TbCar.CarTypeEnum.BUSINESS_CAR.getType().equals(tbCar.getCarType()); } @Async public void handlerInRecord(InRecordBO inRecordBO) { String carNo = inRecordBO.getCarNumber().trim().toUpperCase(); // 入场==>取车牌颜色 TbBusinessCar tbBusinessCar = tbBusinessCarService.findTheLastRecord(carNo); if (tbBusinessCar != null) { String color = inRecordBO.getCarColor(); TbMildCar tbMildCar = tbMildCarService.findByCarNo(carNo); if (tbMildCar != null) {//车长 tbBusinessCar.setCarSize(tbMildCar.getCarLength()); } //蓝牌 4.2米以及以下 if (color.contains(partConfig.getFreeColor())) { if (tbMildCar == null) { tbBusinessCar.setPayType(CarEnum.PayTypeEnum.FEE_TYPE.getType()).setPay(1); } } TbCar tbCar = tbCarService.findByCardNo(tbBusinessCar.getCarNo()); if (tbCar != null && !TbCar.CarTypeEnum.BUSINESS_CAR.getType().equals(tbCar.getCarType())) { tbBusinessCar.setPayType(CarEnum.PayTypeEnum.FEE_TYPE.getType()); List businessList = tbBusinessService.findOtherBusinessByCarId(tbBusinessCar.getId()); if (businessList.isEmpty()) { //无业务&免费车===>无需审核 tbBusinessCar.setConfirmJudge(CarEnum.ConfirmJudgeEnum.NO_NEED_JUDGE.getCode()); } } tbBusinessCar.setColor(color); tbBusinessCarService.updateById(tbBusinessCar); } } }