package com.doumee.jtt808.web.service; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.doumee.biz.system.SystemDictDataBiz; import com.doumee.core.constants.Constants; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.doumee.core.utils.DateUtil; import com.doumee.core.utils.PositionUtil; import com.doumee.core.utils.StringTools; import com.doumee.core.wx.WxMiniUtilService; import com.doumee.dao.business.*; import com.doumee.dao.business.join.GoodsorderJoinMapper; import com.doumee.dao.business.join.MemberRidesJoinMapper; import com.doumee.dao.business.join.RefundJoinMapper; import com.doumee.dao.business.model.*; import com.doumee.dao.business.web.request.BackElecBikeRequest; import com.doumee.dao.business.web.request.LocaltionDTO; import com.doumee.jtt808.web.endpoint.MessageManager; import com.doumee.service.business.GoodsorderService; import com.doumee.service.business.PricingRuleService; import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestBody; import org.yzh.commons.model.APIResult; import org.yzh.protocol.commons.transform.AttributeKey; import org.yzh.protocol.commons.transform.attribute.Battery; import org.yzh.protocol.t808.T0200; import org.yzh.protocol.t808.T0201_0500; import org.yzh.protocol.t808.T8500; import reactor.core.publisher.Mono; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; @Service public class Jtt808Service { @Autowired private MessageManager messageManager; @Autowired private GoodsorderService goodsorderService; @Autowired private BikesMapper bikesMapper; @Autowired private DiscountMemberMapper discountMemberMapper; @Autowired private DiscountLogMapper discountLogMapper; @Autowired GoodsorderJoinMapper goodsorderJoinMapper; @Autowired private SystemDictDataBiz systemDictDataBiz; @Autowired private MemberMapper memberMapper; @Autowired private BaseParamMapper baseParamMapper; @Autowired private RefundMapper refundMapper; @Autowired private RefundJoinMapper refundJoinMapper; @Autowired private SitesMapper sitesMapper; @Autowired private MemberRidesJoinMapper memberRidesJoinMapper; @Autowired private AdMapper adMapper; @Autowired private TransactionsMapper transactionsMapper; @Autowired private WxMiniUtilService wxMiniUtilService; @Autowired PricingRuleService pricingRuleService; public APIResult bikeControl(@RequestBody T8500 request) { Mono> result = messageManager.requestR(request, T0201_0500.class); APIResult data = result.block(); return data; } @Transactional(rollbackFor = {BusinessException.class}) public void backElecBike(BackElecBikeRequest param) { Member member = memberMapper.selectById(param.getMemberId()); if (member == null) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对不起,您的账号信息查询失败,请返回重新进入小程序再试!"); } Goodsorder gparam = new Goodsorder(); gparam.setMemberId(param.getMemberId()); gparam.setStatus(Constants.goodsorderStatus.pay); Goodsorder goodsorder = goodsorderService.findOne(gparam); if(Objects.isNull(goodsorder)){ throw new BusinessException(ResponseStatus.NO_UNCLOSEED_ORDER.getCode(),"无骑行订单记录"); } if(Constants.formatIntegerNum(goodsorder.getStatus()) != Constants.GOODSORDER_STATUS.HAVING_PAY.getKey() ){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"对不起,该订单当前状态不支持结算操作,请尝试刷新列表重试!" ); } //查询骑行记录 List memberRides = goodsorderService.getMemberRidesForClose(goodsorder.getId()); List backIds = new ArrayList<>(); if(memberRides!=null && memberRides.size()>0){ for (MemberRides rides : memberRides){ if(Constants.equalsInteger(rides.getStatus(),Constants.MEMBER_RIDES_STATUS.RIDES_RUNNING.getKey()) &&Constants.equalsInteger(rides.getType(),Constants.ONE)){ //如果是电车并且是骑行中 进行关锁处理 Bikes bike = getElecBikeByCode(rides.getBikeCode()); //查询停车站点信息 if(bike.getSiteId() ==null){ throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对不起,请按要求前往停车点停车!"); } lockBikes(bike.getDeviceSn(),Constants.ZERO);//发起关锁指令请求 backIds.add(rides.getId()); rides.setStatus(Constants.MEMBER_RIDES_STATUS.BACK_CYCLING.getKey());//已还车 rides.setBackSiteId(bike.getSiteId());//还车站点 rides.setBackDate(new Date()); rides.setEditDate(rides.getBackDate()); memberRidesJoinMapper.updateById(rides);//更新骑行状态为已还车 } } } //订单结算 Date date = new Date(); goodsorder.setEditDate(date); goodsorder.setEditor(null); goodsorderService.dealCloseGoodsorderBiz( goodsorder,Constants.REFUND_TYPE.NORMAL.getKey(),memberRides); } private Bikes getElecBikeByCode(String bikeCode) { Bikes bike = bikesMapper.selectOne(new QueryWrapper().lambda() .eq(Bikes::getType,Constants.ONE) .eq(Bikes::getIsdeleted,Constants.ZERO) .eq(Bikes::getCode,bikeCode) ); if(bike==null){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"车辆信息查询失败,请稍后重试或联系园区管理员处理!" ); } if(StringUtils.isBlank(bike.getDeviceSn()) || bike.getLongitude()==null ||bike.getLatitude() ==null){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"车辆位置信息查询失败,请稍后重试或联系园区管理员处理!" ); } if(StringUtils.isBlank(bike.getDeviceSn()) ){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"车辆控制器故障,请稍后重试或联系园区管理员处理!" ); } int expireTime = 10*1000;//默认10秒 try { expireTime = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME,Constants.HEART_TIME_EXPIRE_TIME).getCode())*1000; }catch (Exception e){ } if(bike.getHeartDate() == null || System.currentTimeMillis() - bike.getHeartDate().getTime() >expireTime){ //如果车辆上报时间超过30秒,则表示车辆控制器失效 throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"车辆控制器故障,获取定位信息失败,请稍后重试或联系园区管理员处理!" ); } return bike; } /** * 发起关锁、开锁指令请求 * @param clientId * @param type 控制标志:0.车门解锁 1.车门加锁 */ private void lockBikes(String clientId,int type) { T8500 request = new T8500(); request.setType(type);//关锁 request.setClientId(StringTools.leftPad(clientId,12,'0')); Mono> result = messageManager.requestR(request, T0201_0500.class); APIResult data = result.block(); if(!data.isSuccess()){ //如果开锁失败,则返回异常 throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对不起,"+(type ==0?"车辆开锁":"车辆关锁")+"失败,请稍后重试,或者联系园区管理人员!"); } } /** * 查询停车站点信息 * @return */ private Sites getBackSiteByPostion(double lat,double lng) { Sites site = null;//查询停车站点信息 List sitesList = sitesMapper.selectList(new QueryWrapper().lambda() .eq(Sites::getStatus,Constants.ZERO) .eq(Sites::getIsdeleted,Constants.ZERO) .eq(Sites::getType,Constants.ONE)); if(sitesList ==null ||sitesList.size() ==0){ // throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对不起,请按照要求前往停车点停车!"); return null; } for(Sites sites :sitesList){ TypeReference typeReference = new TypeReference>(){}; List array = JSONObject.parseObject(sites.getElectronicFence(), typeReference.getType()); if(array == null || array.size() ==0){ continue; } if(PositionUtil.isInPolygon(lat,lng,array)){ //如果在停车点范围内; site = sites; break; } /* if(site ==null){ throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对不起,请按照要求前往停车点停车!"); }*/ } return site; } /** * 临时停车 * @param param */ @Transactional(rollbackFor = {BusinessException.class}) public void pauseElecBike(BackElecBikeRequest param) { Member member = memberMapper.selectById(param.getMemberId()); if (member == null) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对不起,您的账号信息查询失败,请返回重新进入小程序再试!"); } Goodsorder gparam = new Goodsorder(); gparam.setMemberId(param.getMemberId()); gparam.setStatus(Constants.goodsorderStatus.pay); Goodsorder goodsorder = goodsorderService.findOne(gparam); if(Objects.isNull(goodsorder)){ throw new BusinessException(ResponseStatus.NO_UNCLOSEED_ORDER.getCode(),"对不起,未查询到您当前有骑行中订单记录"); } //查询所有骑行记录 MemberRides memberRides = memberRidesJoinMapper.selectJoinOne(MemberRides.class,new MPJLambdaWrapper() .eq(MemberRides::getOrdreId,goodsorder.getId()) .eq(MemberRides::getStatus,Constants.MEMBER_RIDES_STATUS.RIDES_RUNNING.getKey()) .selectAll(MemberRides.class) .last("limit 1")); if(memberRides ==null || memberRides.getBikeCode() == null){ throw new BusinessException(ResponseStatus.NO_UNCLOSEED_ORDER.getCode(),"对不起,未查询到您当前有骑行中记录"); } Bikes bike = getElecBikeByCode(memberRides.getBikeCode()); //查询停车位置是否符合停车位置规范 checkPausePostionBiz(bike); memberRides.setPauseDate(new Date()); memberRides.setEditDate(memberRides.getBackDate()); memberRides.setStatus(Constants.MEMBER_RIDES_STATUS.RIDES_PAUSING.getKey()); memberRidesJoinMapper.updateById(memberRides);//更新骑行状态为临停中 } private void checkPausePostionBiz(Bikes bike) { int ruleType = 0; try { ruleType =Integer.parseInt( systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME,Constants.PAUSE_BIKE_TYPE).getCode()); }catch (Exception e){ } if(ruleType == 0){ //如果仅限于园区临时停车 List array = new ArrayList<>(); try { TypeReference typeReference = new TypeReference>(){}; array = JSONObject.parseObject(systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME, Constants.PARK_LAT_LNG_LIST).getCode(), typeReference.getType()); }catch (Exception e){ } if(array == null || array.size() ==0){ throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对不起,园区运营区域配置有误,请联系园区管理员处理!"); } if( !PositionUtil.isInPolygon(bike.getLatitude().doubleValue(),bike.getLongitude().doubleValue(),array)){ //如果在停车点范围内; throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对不起,请按要求在园区运营区域范围内停车!"); } }else{ //检查是否满足停车点停车 if(bike.getSiteId() ==null){ throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对不起,请按要求前往停车点停车!"); } } } public void updateBikesInfo(List list) { Date date = new Date(); for(T0200 m : list){ Bikes bike = new Bikes(); bike.setDeviceSn(m.getClientId()); if(m.getLatitude()!=0){ bike.setLatitude(new BigDecimal(m.getLatitude()).divide(new BigDecimal(1000000),8,BigDecimal.ROUND_HALF_UP)); } if(m.getLongitude()!=0){ bike.setLongitude(new BigDecimal(m.getLongitude()).divide(new BigDecimal(1000000),8,BigDecimal.ROUND_HALF_UP)); } bike.setHeartDate(DateUtil.getDateFromLocalDateTime(m.getDeviceTime())); if(m.getAttributes()!=null ){ Battery battery= (Battery) m.getAttributes().get(AttributeKey.Battery); if(battery !=null && battery.getVoltage()!=null){ bike.setVoltage(new BigDecimal(battery.getVoltage())); } } if(StringUtils.isBlank(bike.getDeviceSn() )){ return; } String tSn = StringTools.leftPad(bike.getDeviceSn(),12,'0') ; Bikes bikes = bikesMapper.selectOne(new QueryWrapper().lambda() .eq(Bikes::getDeviceSn,tSn) .eq(Bikes::getIsdeleted,Constants.ZERO) .eq(Bikes::getType,Constants.ONE) .last("limit 1")); if(bikes == null){ return; } Sites site = null; if(bikes.getLatitude()!=null && bikes.getLongitude()!=null){ //根据定位信息查询所在站点 site = getBackSiteByPostion(bikes.getLatitude().doubleValue(),bikes.getLongitude().doubleValue()); } bikesMapper.update(null,new UpdateWrapper().lambda() .set(bike.getLatitude()!=null,Bikes::getLatitude,bike.getLatitude()) .set(bike.getVoltage()!=null,Bikes::getVoltage,bike.getVoltage()) .set(bike.getLongitude()!=null,Bikes::getLongitude,bike.getLongitude()) .set(Bikes::getSiteId,site ==null?null:site.getId()) .set( Bikes::getHeartDate,date) .eq(Bikes::getId,bikes.getId())); } } }