package com.pj.api.open.service; import cn.hutool.cache.CacheUtil; import cn.hutool.cache.impl.TimedCache; import cn.hutool.core.date.DateUtil; import cn.hutool.core.img.ImgUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; 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.constants.UserTypeEnum; import com.pj.current.config.PartConfig; import com.pj.current.config.SystemObject; import com.pj.current.task.TaskService; 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_business_people.TbBusinessPeople; import com.pj.project.tb_business_people.TbBusinessPeopleService; import com.pj.project.tb_car.TbCar; import com.pj.project.tb_car.TbCarService; import com.pj.project.tb_car_no_color.TbCarNoColor; import com.pj.project.tb_car_no_color.TbCarNoColorService; 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_item.TbItem; import com.pj.project.tb_item_type.TbItemType; import com.pj.project4sp.global.BusinessException; import com.pj.project4sp.uploadfile.UploadConfig; import com.pj.utils.cache.RedisUtil; import com.pj.utils.sg.AjaxJson; import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ; 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 sun.misc.BASE64Decoder; import javax.annotation.Resource; import javax.xml.crypto.Data; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Objects; 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 TbCarNoColorService tbCarNoColorService; @Resource private TbGoodsService tbGoodsService; @Resource @Lazy AutomaticPay automaticPay; @Resource private TbDeductionBindService tbDeductionBindService; @Resource private PartConfig partConfig; public ResultJson checkCarNumber(CheckCarNumberBO checkCarNumberBO) { String carNo = checkCarNumberBO.getCarNumber(); int inOrOut = checkCarNumberBO.getInOrOut(); String image = checkCarNumberBO.getImageData(); if (inOrOut == 1) { handlerIn(carNo, checkCarNumberBO.getChannelName(), image); return ResultJson.success(); } return handlerOut(carNo, checkCarNumberBO.getChannelName(), image); } private void handlerIn(String carNo, String channel, String image) { carNo = carNo.toUpperCase(); if (StrUtil.isNotEmpty(image)) { StaticLog.error("缓存入场图片:{}", carNo); IMAGE_CACHE.put(carNo, image); } automaticPay.unbindRun(carNo); TbBusinessCar tbBusinessCar = tbBusinessCarService.findTheLastRecord(carNo); Date now = new Date(); TbCar tbCar = tbCarService.findByCardNo(carNo); //1、记录不存在; // 2、已离场重新入场; // 3、抬杆离场 if (tbBusinessCar == null || (tbBusinessCar.getRealInTime() != null && tbBusinessCar.getRealOutTime() != null) || (tbBusinessCar.getRealInTime() != null && tbBusinessCar.getRealOutTime() == null)) { //=======创建新的放行记录========== tbBusinessCar = new TbBusinessCar(); tbBusinessCar.setCarNo(carNo).setPay(0).setCarSize(0D).setIsLock(0) .setCarCompany(tbCar != null ? tbCar.getCustomerName() : "临时") .setInChannel(channel).setRealInTime(now).setCarType(TbItem.ItemTypeEnum.EMPTY_TYPE.getType()) .setBasePartMoney(new BigDecimal("0")).setTimeUpdate(now) .setNo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + RandomUtil.randomNumbers(4)); tbBusinessCarService.save(tbBusinessCar); CoverBase64ToUrl(image, tbBusinessCar.getId(), carNo, 1); return; } tbBusinessCar.setRealInTime(now).setInChannel(channel).setTimeUpdate(now) .setCarCompany(tbCar != null ? tbCar.getCustomerName() : "临时"); tbBusinessCarService.saveOrUpdate(tbBusinessCar); CoverBase64ToUrl(image, tbBusinessCar.getId(), carNo, 1); } 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); } //判断是否蓝色车牌===免停车费 if (StrUtil.isNotEmpty(tbBusinessCar.getColor())) { List freeList = tbCarNoColorService.getFreeColor(); List colorList = freeList.stream().map(f -> f.getCarNoColor().substring(0, 1)).collect(Collectors.toList()); String color = tbBusinessCar.getColor().substring(0, 1); if (colorList.contains(color)) { freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } } //是否行政车辆===== if (checkFree(carNo, 2, now)) { freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } if (tbBusinessCar.getIsLock() == 1) { RedisUtil.setByMINUTES(channel, carNo, 2); log.error("请求返回:车辆已锁定:{}", carNo); return ResultJson.error("车辆已锁定"); } String businessCarId = tbBusinessCar.getId(); //String carNoPrefix = StrUtil.sub(carNo, 0, 1); String carType = tbBusinessCar.getCarType(); BigDecimal carMoney = new BigDecimal(0); List businessList = tbBusinessService.findOtherBusinessByCarId(businessCarId); if (businessList.isEmpty()) {//无业务车辆===>计算停车费 //如果已经支付过,则从支付时间算起,重新计算停车费 double dif = caulatePrice(tbBusinessCar, now); if (dif > 0) { RedisUtil.setByMINUTES(channel, carNo, 1); log.error("请求返回:请缴停车费:{},{}元", carNo, dif); automaticPay.run(null, tbBusinessCar.getCarNo(), 1); return ResultJson.error("请缴停车费" + dif + "元"); } else { //无需交停车费,又没有支付的--->设置成免费车辆 if (tbBusinessCar.getPayTime() == null) { tbBusinessCar.setPayType(TbBusinessCar.PayTypeEnum.FEE_TYPE.getType()).setPay(1); } freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } } else { //有业务的车 //1、分越重车和空车 //空车是否收费 //该车所有的业务都是到达卡口才进行扣费才会进入自动扣费 int autoPayCount = 0; for (TbBusiness business : businessList) { TbGoods tbGoods = tbGoodsService.getById(business.getGoodsId()); if (TbGoods.DeductionTypeEnum.OUT_KK.getCode().equals(tbGoods.getAutoDeductionType())) { autoPayCount++; } } if (autoPayCount == businessList.size()) { log.info("车辆到达卡口进行扣停车费和业务费:{}", carNo); //自动缴费 automaticPay.run(null, tbBusinessCar.getCarNo(), 3); tbDeductionBindService.autoUnbindCar(tbBusinessCar.getCarNo()); freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } if (TbItem.ItemTypeEnum.EMPTY_TYPE.getType().equals(carType)) { boolean chinaCarPay = businessList.stream().anyMatch(tbBusiness -> { TbGoods tbGoods = tbGoodsService.getById(tbBusiness.getGoodsId()); return tbGoods.getChinaCarPay() == 1; }); if (chinaCarPay) { double dif = caulatePrice(tbBusinessCar, now); if (dif > 0) { RedisUtil.setByMINUTES(channel, carNo, 1); log.error("中国车停车费:{},{}元", carNo, dif); carMoney = new BigDecimal(dif); // return ResultJson.error("请缴停车费" + dif + "元"); } else { if (tbBusinessCar.getPayTime() == null) { tbBusinessCar.setPayType(TbBusinessCar.PayTypeEnum.FEE_TYPE.getType()).setPay(1); } } } } else {//越南车=重车 boolean vietnamCarPay = businessList.stream().anyMatch(tbBusiness -> { TbGoods tbGoods = tbGoodsService.getById(tbBusiness.getGoodsId()); return tbGoods.getVietnamCarPay() == 1; }); if (vietnamCarPay) { double dif = caulatePrice(tbBusinessCar, now); if (dif > 0) { RedisUtil.setByMINUTES(channel, carNo, 1); log.error("越南车停车费:{},{}元", carNo, dif); carMoney = new BigDecimal(dif); // return ResultJson.error("请缴停车费" + dif + "元"); } else { if (tbBusinessCar.getPayTime() == null) { tbBusinessCar.setPayType(TbBusinessCar.PayTypeEnum.FEE_TYPE.getType()).setPay(1); } } } } } //============业务费计算是否交完 BigDecimal businessMoney = new BigDecimal(0); for (TbBusiness tbBusiness : businessList) { TbGoods tbGoods = tbGoodsService.getById(tbBusiness.getGoodsId()); int vietnamLeave = tbGoods.getVietnamCarLeave(); int chinaCarLeave = tbGoods.getChinaCarLeave(); boolean pay = tbBusiness.getPayMoney().doubleValue() >= tbBusiness.getItemPrice().doubleValue(); //需要交业务费 if (TbItem.ItemTypeEnum.WEIGHT_TYPE.getType().equals(carType)) {//越南车==重车 if (TbGoods.LeaveEnum.PART_MONEY.getCode() != vietnamLeave && !pay) { RedisUtil.setByMINUTES(channel, carNo, 1); log.error("越南车==重车:缴纳业务费用:{}", carNo); businessMoney = businessMoney.add(tbBusiness.getItemPrice()); // return ResultJson.error("请缴纳业务费用"); } } else { if (TbGoods.LeaveEnum.PART_MONEY.getCode() != chinaCarLeave && !pay) { RedisUtil.setByMINUTES(channel, carNo, 1); businessMoney = businessMoney.add(tbBusiness.getItemPrice()); log.error("请求返回:请缴纳业务费用:{}", carNo); // return ResultJson.error("请缴纳业务费用"); } } } BigDecimal total = businessMoney.add(carMoney); if (total.doubleValue() > 0) { log.error("请求返回:请缴费用:{},{}元", carNo, total.doubleValue()); return ResultJson.error("请缴费用" + total.doubleValue() + "元"); } //离场直接解绑 tbDeductionBindService.autoUnbindCar(tbBusinessCar.getCarNo()); freeOut(tbBusinessCar, now, channel, image); return ResultJson.success(); } private double caulatePrice(TbBusinessCar tbBusinessCar, Date now) { Date inTime = tbBusinessCar.getRealInTime(); if (tbBusinessCar.getPay() == 1 && tbBusinessCar.getRealOutTime() == null && tbBusinessCar.getPayTime() != null) { inTime = tbBusinessCar.getPayTime(); } BigDecimal price = tbBusinessService.calculationPartMoney(inTime, now); return price.doubleValue(); } private void freeOut(TbBusinessCar tbBusinessCar, Date now, String outChannel, String base64Image) { tbBusinessCar.setRealOutTime(now).setTimeUpdate(now).setOutChannel(outChannel); 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) { List carNoColorList = tbCarNoColorService.getFreeColor(); String freeColors = carNoColorList.stream().map(TbCarNoColor::getCarNoColor).collect(Collectors.joining(",")); String carNo = inRecordBO.getCarNumber().trim().toUpperCase(); // 入场==>取车牌颜色 List cars = tbBusinessCarService.findByCarNo(carNo); cars.stream().filter(obj -> StrUtil.isEmpty(obj.getColor())) .forEach(tbBusinessCar -> { String color = inRecordBO.getCarColor(); String prefixColor = StrUtil.sub(color, 0, 1); if (StrUtil.contains(freeColors, prefixColor)) { tbBusinessCar.setPayType(TbBusinessCar.PayTypeEnum.FEE_TYPE.getType()); } TbCar tbCar = tbCarService.findByCardNo(tbBusinessCar.getCarNo()); if (tbCar != null && !TbCar.CarTypeEnum.BUSINESS_CAR.getType().equals(tbCar.getCarType())) { tbBusinessCar.setPayType(TbBusinessCar.PayTypeEnum.FEE_TYPE.getType()); } tbBusinessCar.setColor(color); tbBusinessCarService.updateById(tbBusinessCar); }); } }