package com.newfiber.api.pc.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.newfiber.api.core.commons.CustomException; import com.newfiber.api.core.commons.PageRequestObject; import com.newfiber.api.core.commons.PageResultObject; import com.newfiber.api.core.commons.ResultCode; import com.newfiber.api.core.redis.lock.RedisLock; import com.newfiber.api.pc.dao.HouseSiteSuppliesMapper; import com.newfiber.api.pc.dto.SiteDataOperationDTO; import com.newfiber.api.pc.dto.SiteSubDTO; import com.newfiber.api.pc.dto.DataOperationDTO; import com.newfiber.api.pc.model.meet.HouseSiteSupplies; import com.newfiber.api.pc.model.meet.MeetAlter; import com.newfiber.api.pc.model.meet.ReturnGoods; import com.newfiber.api.pc.service.HouseSiteSuppliesService; import com.newfiber.api.pc.service.MeetAlterService; import com.newfiber.api.pc.service.ReturnGoodsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundValueOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.*; import java.util.concurrent.TimeUnit; /** * @Author:zzh * @CreateDate:2020/11/25 13:43 * @Description: */ @Service @Transactional(rollbackFor = Exception.class) public class HouseSiteSuppliesServiceImpl extends ServiceImpl<HouseSiteSuppliesMapper,HouseSiteSupplies> implements HouseSiteSuppliesService { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private ReturnGoodsService returnGoodsService; @Autowired private RedisLock redisLock; @Autowired private MeetAlterService meetAlterService; @Override public List<HouseSiteSupplies> querySupByHouseSiteId(Integer hId) { if(StringUtils.isEmpty(hId)){ throw new CustomException(ResultCode.PARAM_NULL); } BoundValueOperations<String, String> boundValueOps = stringRedisTemplate.boundValueOps("supplies:"+hId.toString()); if(stringRedisTemplate.hasKey("supplies:"+hId.toString())){ String json = boundValueOps.get(); List<HouseSiteSupplies> houseSiteSupplies = JSON.parseArray(json, HouseSiteSupplies.class); return houseSiteSupplies; } EntityWrapper<HouseSiteSupplies> wrapper = new EntityWrapper<>(); wrapper.eq("h_id",hId); List<HouseSiteSupplies> houseSiteSupplies = this.selectList(wrapper); //没有就将新添加的内容存入reids boundValueOps.set(JSONObject.toJSONString(houseSiteSupplies)); boundValueOps.expire(20,TimeUnit.MINUTES); return houseSiteSupplies; } @Override public PageResultObject<HouseSiteSupplies> queryPage(PageRequestObject<SiteSubDTO> pageRequestObject) { int current = pageRequestObject.getCurrent(); int size = pageRequestObject.getSize(); if(size == 0){ return null; } Page<HouseSiteSupplies> objectPage = new Page<>(); SiteSubDTO object = pageRequestObject.getObject(); String key = "supPage:" + current + size + "+" + object.getSiteId() + "-" + object.getSubName(); BoundValueOperations<String, String> boundValueOps = stringRedisTemplate.boundValueOps(key); if(stringRedisTemplate.hasKey(key)){ String json = boundValueOps.get(); PageResultObject<HouseSiteSupplies> suplies = JSON.parseObject(json,PageResultObject.class); return suplies; } //不存在则查找 EntityWrapper<HouseSiteSupplies> wrapper = new EntityWrapper<>(); if(!StringUtils.isEmpty(object.getSubName())){ wrapper.like("sup_name",object.getSubName()); } wrapper.eq("h_id",object.getSiteId()); Page<HouseSiteSupplies> houseSitePage = this.selectPage(objectPage, wrapper); int count = this.selectCount(wrapper); PageResultObject<HouseSiteSupplies> resultObject = new PageResultObject<HouseSiteSupplies>(current, size, (long) count, houseSitePage.getRecords()); String resultJson = JSONObject.toJSONString(resultObject); //存入redis中 boundValueOps.set(resultJson); //设置超时时间为10分钟 boundValueOps.expire(10, TimeUnit.MINUTES); return resultObject; } @Override public void addHouseSiteSup(HouseSiteSupplies houseSiteSupplies) { boolean insert = this.insert(houseSiteSupplies); List<HouseSiteSupplies> houseSiteSupplies1 = null; //更新 String key = "supplies:"+houseSiteSupplies.getHId(); BoundValueOperations<String, String> boundValueOps = stringRedisTemplate.boundValueOps(key); if(stringRedisTemplate.hasKey(key)){ String json = boundValueOps.get(); houseSiteSupplies1 = JSON.parseArray(json, HouseSiteSupplies.class); }else{ houseSiteSupplies1 = new ArrayList<>(); } houseSiteSupplies1.add(houseSiteSupplies); //添加更新 boundValueOps.set(JSONObject.toJSONString(houseSiteSupplies1)); if(!insert){ throw new CustomException(ResultCode.SAVE_ERROR); } } @Override public void updateHouseSiteSup(HouseSiteSupplies houseSiteSupplies) { //更新 String key ="supplies:"+houseSiteSupplies.getHId(); BoundValueOperations<String, String> boundValueOps = stringRedisTemplate.boundValueOps(key); if(stringRedisTemplate.hasKey(key)){ String json = boundValueOps.get(); List<HouseSiteSupplies> siteSupplies = JSON.parseArray(json,HouseSiteSupplies.class); for(int i = 0; i < siteSupplies.size(); i++){ HouseSiteSupplies supplies = siteSupplies.get(i); if(supplies.getSupId().equals(houseSiteSupplies.getSupId())){ siteSupplies.set(i,houseSiteSupplies); break; } } boundValueOps.set(JSONObject.toJSONString(siteSupplies)); } boolean update = this.updateById(houseSiteSupplies); if(!update){ throw new CustomException(ResultCode.UPDATE_ERROR); } } @Override public boolean deductionSupplies(Integer alertId,Integer hId,List<DataOperationDTO> dataOperationDTO) { //取出传入的里面所有数据 String key = "supplies:" + hId; //利用redis实现一个简单的同步方法 //循环去判断是否获取到了锁 int number = 0; while(!redisLock.lock(key)){ if(number == 6){ return false; } number++; try{ Thread.sleep(1000); }catch (Exception e){ throw new CustomException(ResultCode.THRED_SLEEP); } } //调用查询方法,从Redis中拿数据,拿的是存放点下的数据 List<HouseSiteSupplies> houseSiteSupplies = this.querySupByHouseSiteId(hId); //创建需要归还的物资数据集合 List<ReturnGoods> reGoods = new ArrayList<>(); //扣除相对应的数量 for(DataOperationDTO dto : dataOperationDTO){ for(HouseSiteSupplies supplies : houseSiteSupplies){ //如果这两个物资编号相等 if(dto.getSupId().equals(supplies.getSupId())){ //扣除物资数据 //如果需要使用到的物资数量小于存放点现有的数据时,先只给存放点已有的,然后在由调度人员去申请调度 if(supplies.getSupCount() < dto.getCount()){ supplies.setSupCount(0); //发布一条调度消息(调度方法)未实现 }else{ supplies.setSupCount(supplies.getSupCount() - dto.getCount()); } //判断要使用的物资类型(非一次性物资到最后是需要归还的) if(!StringUtils.isEmpty(alertId)){ if(supplies.getNature().equals(2)){ ReturnGoods goods = new ReturnGoods(); goods.setHId(hId); goods.setAId(alertId); goods.setSupId(supplies.getSupId()); goods.setSupCount(dto.getCount()); //添加一个物资 reGoods.add(goods); //找到匹配的就退出内层循环,加快执行效率 break; } } } } } //将更新数据重新写入Redis中 stringRedisTemplate.opsForValue().set(key,JSONObject.toJSONString(houseSiteSupplies)); //数据库的数据也需要同步写入(不需要写定时任务,写定时任务浪费,因为使用警情的使用频率是不很高。) this.updateBatchById(houseSiteSupplies); //将需要归还的数据写入数据库中 if(!StringUtils.isEmpty(alertId)){ returnGoodsService.insertBatch(reGoods); } //数据更新完毕 //释放锁 redisLock.delete(key); return true; } @Override public boolean returnSupplies(Integer alertId,List<SiteDataOperationDTO> dataOperationDTOs) { if(StringUtils.isEmpty(alertId)){ throw new CustomException(ResultCode.PARAM_NULL); } List<String> redisKeys = new ArrayList<>(); List<ReturnGoods> returnGoods = new ArrayList<>(); //保存需要归还的物资id集合,用来查询物资表中的数据 List<Integer> supIds = new ArrayList<>(); for(SiteDataOperationDTO dto : dataOperationDTOs){ ReturnGoods goods = new ReturnGoods(); goods.setAId(alertId); goods.setHId(dto.getHId()); //添加需要删除的redis key redisKeys.add("supplies:"+dto.getHId()); for(DataOperationDTO operation : dto.getDataOperationDTO()){ supIds.add(operation.getSupId()); goods.setSupId(operation.getSupId()); goods.setSupCount(operation.getCount()); } returnGoods.add(goods); } //根据需要归还的物资id查询物资在表中的数据 List<HouseSiteSupplies> houseSiteSupplies = this.selectBatchIds(supIds); EntityWrapper<ReturnGoods> wrapper = new EntityWrapper<>(); wrapper.eq("a_id",alertId); List<ReturnGoods> goodsList = returnGoodsService.selectList(wrapper); for(ReturnGoods tableGoods : goodsList){ for(ReturnGoods paramGoods : returnGoods){ if(tableGoods.equals(paramGoods)){ // 如果归还的数量大于需要归还的数量,就抛出异常 if(paramGoods.getSupCount() > tableGoods.getSupCount()){ throw new CustomException(500,"归还的数量不能大于需要归还的数量"); }else{ tableGoods.setSupCount(tableGoods.getSupCount() - paramGoods.getSupCount()); //将查询出来的物资表中的数据 更新 for(HouseSiteSupplies housesite :houseSiteSupplies){ if(tableGoods.getSupId().equals(housesite.getSupId())){ housesite.setSupCount(housesite.getSupCount() + paramGoods.getSupCount()); //找到了就跳出本层循环 break; } } } //找到了就跳出内层循环 break; } } } //批量更新表中数据 returnGoodsService.updateBatchById(goodsList); //更改警情状态 MeetAlter meetAlter = meetAlterService.selectById(alertId); //设置物资为归还状态 meetAlter.setIsReturnSup(1); meetAlterService.updateById(meetAlter); //增加物资表中的数量 this.updateBatchById(houseSiteSupplies); //直接清空Redis中对应的站点id stringRedisTemplate.delete(redisKeys); return true; } @Override public void deleteHouseSiteSup(Integer id, Integer hId) { boolean b = this.deleteById(id); if(b){ if(stringRedisTemplate.hasKey("supplies:"+hId)){ List<HouseSiteSupplies> siteSupplies = JSON.parseArray(stringRedisTemplate.opsForValue().get("supplies:" + hId), HouseSiteSupplies.class); Optional<HouseSiteSupplies> first = siteSupplies.stream().filter(sup -> sup.getSupId().equals(id)).findFirst(); if(first.isPresent()){ siteSupplies.remove(first.get()); } } }else{ throw new CustomException(ResultCode.DELETE_ERROR); } } }