server/services/src/main/java/com/doumee/core/constants/Constants.java
@@ -1,6 +1,7 @@ package com.doumee.core.constants; import ch.qos.logback.core.util.COWArrayList; import com.doumee.dao.business.web.request.LocaltionDTO; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.StringUtils; @@ -214,11 +215,7 @@ //éééç¥å°å public static final String DINGDING_URL = "DINGDING_URL"; //ééç¾å public static void main(String[] args) { double[][] polygon = {{120, 30}, {121, 30}, {121, 31}, {120, 31}}; // ç»çº¬åº¦å表表示å¤è¾¹å½¢é¡¶ç¹ boolean isInside = isPointInPolygon(122.5, 30.5, polygon); System.out.println("Is inside: " + isInside); } //å°ç¨åºæ»¡è½½é¢è¦(%)æå¤§å¼ public static final String WARN_MAX = "WARN_MAX"; //å°ç¨åºæ»¡è½½é¢è¦(%)æå°å¼ @@ -606,19 +603,6 @@ return Constants.formatDecimalNum(money).divide(new BigDecimal(100), 2, BigDecimal.ROUND_UP); } public static boolean isPointInPolygon(double px, double py, double[]... polygon) { int i, j; boolean result = false; for (i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { if ((polygon[i][1] > py) != (polygon[j][1] > py) && (px < (polygon[j][0] - polygon[i][0]) * (py - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) + polygon[i][0])) { result = !result; } } return result; } } server/services/src/main/java/com/doumee/core/utils/PositionUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,72 @@ package com.doumee.core.utils; import com.doumee.dao.business.web.request.LocaltionDTO; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; /** * 计ç®è·ç¦» */ public class PositionUtil { /** * å¤æåæ ç¹æ¯å¦å¨å¤è¾¹å½¢åºåå * * @param pointLon è¦å¤æçç¹çç»åº¦ * @param pointLat è¦å¤æçç¹ç纬度 * @return trueï¼èå´å ; falseï¼èå´å¤ */ public static boolean isInPolygon(double pointLon, double pointLat, List<LocaltionDTO> list) { if(list==null ||list.size()==0){ return false; } double[] lon = new double[list.size()]; double[] lat = new double[list.size()]; for (int i = 0; i < list.size(); i++) { lon[i] = list.get(i).getLng() ==null?0:list.get(i).getLng(); lat[i] = list.get(i).getLat() ==null?0:list.get(i).getLat(); } // å°è¦å¤æçæ¨ªçºµåæ ç»æä¸ä¸ªç¹ Point2D.Double point = new Point2D.Double(pointLon, pointLat); // å°åºååé¡¶ç¹çæ¨ªçºµåæ æ¾å°ä¸ä¸ªç¹éåéé¢ List<Point2D.Double> pointList = new ArrayList<>(); double polygonPointToX; double polygonPointToY; for (int i = 0; i < lon.length; i++) { polygonPointToX = lon[i]; polygonPointToY = lat[i]; Point2D.Double polygonPoint = new Point2D.Double(polygonPointToX, polygonPointToY); pointList.add(polygonPoint); } return check(point, pointList); } /** * åæ ç¹æ¯å¦å¨å¤è¾¹å½¢å * * @param point è¦å¤æçç¹çæ¨ªçºµåæ * @param polygon ç»æçé¡¶ç¹åæ éå */ private static boolean check(Point2D.Double point, List<Point2D.Double> polygon) { GeneralPath generalPath = new GeneralPath(); Point2D.Double first = polygon.get(0); // éè¿ç§»å¨å°æå®åæ ï¼ä»¥å精度æå®ï¼ï¼å°ä¸ä¸ªç¹æ·»å å°è·¯å¾ä¸ generalPath.moveTo(first.x, first.y); polygon.remove(0); for (Point2D.Double d : polygon) { // éè¿ç»å¶ä¸æ¡ä»å½ååæ å°æ°æå®åæ ï¼ä»¥å精度æå®ï¼çç´çº¿ï¼å°ä¸ä¸ªç¹æ·»å å°è·¯å¾ä¸ã generalPath.lineTo(d.x, d.y); } // å°å ä½å¤è¾¹å½¢å°é generalPath.lineTo(first.x, first.y); generalPath.closePath(); // æµè¯æå®ç Point2D æ¯å¦å¨ Shape çè¾¹çå ã return generalPath.contains(point); } } server/services/src/main/java/com/doumee/dao/business/model/MemberRides.java
@@ -164,6 +164,9 @@ @ApiModelProperty(value = "éªè¡æ¶é¿") @TableField(exist = false) private Integer rideTime; @ApiModelProperty(value = "æ§å¶å¨ç¼ç ") @TableField(exist = false) private String deviceSn; @ApiModelProperty(value = "æåºç ï¼ååºï¼", example = "1") @TableField(exist = false) private Integer sortnum; server/services/src/main/java/com/doumee/dao/business/web/request/BackElecBikeRequest.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,30 @@ package com.doumee.dao.business.web.request; import com.doumee.core.annotation.excel.ExcelColumn; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; import java.util.List; /** * Created by IntelliJ IDEA. * * @Author : Rk * @create 2023/10/9 11:04 */ @Data @ApiModel("çµè½¦ç«ç¹è¿è½¦è¯·æ±åæ°") public class BackElecBikeRequest { @ApiModelProperty(value = "纬度") private Double latitude; @ApiModelProperty(value = "ç»åº¦") private Double longitude; @ApiModelProperty(value = "ç¨æ·ç¼ç ï¼å ³èmember表ï¼",hidden = true) private String memberId; } server/services/src/main/java/com/doumee/dao/business/web/request/LocaltionDTO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ package com.doumee.dao.business.web.request; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; /** * Created by IntelliJ IDEA. * * @Author : Rk * @create 2023/10/9 11:04 */ @Data @ApiModel("å®ä½å°åå¯¹è±¡åæ°") public class LocaltionDTO { @ApiModelProperty(value = "纬度") private Double lat; @ApiModelProperty(value = "ç»åº¦") private Double lng; } server/services/src/main/java/com/doumee/service/business/GoodsorderService.java
@@ -6,14 +6,17 @@ import com.doumee.core.model.PageWrap; import com.doumee.dao.business.model.Bikes; import com.doumee.dao.business.model.Goodsorder; import com.doumee.dao.business.model.MemberRides; import com.doumee.dao.business.vo.GoodsorderExportVO; import com.doumee.dao.business.vo.GoodsorderTotalDataVO; import com.doumee.dao.business.web.request.BackElecBikeRequest; import com.doumee.dao.business.web.request.GoodsorderBackDTO; import com.doumee.dao.business.web.request.GoodsorderCanBanlanceDTO; import com.doumee.dao.business.web.response.HomeResponse; import com.doumee.dao.business.web.response.GoodsorderDetailDTO; import com.doumee.dao.business.web.response.RidesDetailResponse; import com.wechat.pay.java.service.refund.model.RefundNotification; import io.swagger.models.auth.In; import java.math.BigDecimal; import java.util.List; @@ -147,6 +150,7 @@ * @return */ void closeGoodsorder(Goodsorder order,int type ); void dealCloseGoodsorderBiz(Goodsorder goodsorder, int type, List<MemberRides> memberRides) ; void closeGoodsorderDone(RefundNotification param); void forceCloseGoodsorder(String orderId); @@ -155,7 +159,7 @@ * @param orderId */ void backGoodsorder(GoodsorderBackDTO goodsorderBackDTO); List<MemberRides> getMemberRidesForClose(String orderid ); /** * è·åå¯éæ¬¾ä¿¡æ¯ * @param orderId @@ -191,4 +195,5 @@ void autoCloseOrder(); void autoCancelRefunOrder(); } server/services/src/main/java/com/doumee/service/business/impl/GoodsorderServiceImpl.java
@@ -89,6 +89,7 @@ private SystemDictDataBiz systemDictDataBiz; @Autowired private MemberMapper memberMapper; @Autowired @@ -531,7 +532,11 @@ if(r != null){ throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订ååå¨é款ç³è¯·æ£å¨å¤çä¸ï¼è¯·ç¨åæ¥ç订åä¿¡æ¯å¦~"); } List<MemberRides> memberRides = getMemberRidesForClose(goodsorder.getId()); List<MemberRides> memberRides = getMemberRidesForClose(goodsorder.getId());//æè½¦éªè¡è®°å½ dealCloseGoodsorderBiz(goodsorder,type,memberRides); } @Override public void dealCloseGoodsorderBiz(Goodsorder goodsorder, int type, List<MemberRides> memberRides) { //é»è®¤ç»ç®ä¸ºæ¼ééé¢ BigDecimal closeMoney = new BigDecimal(0.00); if (!CollectionUtils.isEmpty(memberRides)){ @@ -563,7 +568,8 @@ closeGoodsorderDoneNoRefund(goodsorder,type,new BigDecimal(0),null,memberRides); } } public void closeGoodsorderDoneNoRefund(Goodsorder goodsorder,int type,BigDecimal refundMoney,String closeId,List<MemberRides> memberRides ) { public void closeGoodsorderDoneNoRefund(Goodsorder goodsorder,int type,BigDecimal refundMoney,String closeId,List<MemberRides> memberRides) { log.error("========================================"+JSONObject.toJSONString(goodsorder)); if(goodsorder ==null || Constants.formatIntegerNum(goodsorder.getStatus()) != Constants.GOODSORDER_STATUS.HAVING_PAY.getKey()){ return; @@ -806,19 +812,20 @@ return ridesDetailResponse; } private List<MemberRides> getMemberRidesForClose(String id) { @Override public List<MemberRides> getMemberRidesForClose(String id) { MPJLambdaWrapper<MemberRides> wrapper = new MPJLambdaWrapper<>(); wrapper.eq(MemberRides::getOrdreId,id); wrapper.ne(MemberRides::getStatus,Constants.MEMBER_RIDES_STATUS.LOCKING_DEFEAT.getKey()); wrapper.selectAll(MemberRides.class) .select("select b.device_sn from bikes b where b.isdeleted=0 and b.code = t.bike_code limit 1",MemberRides::getDeviceSn) .selectAs(BaseParam::getSortnum, MemberRides::getSortnum) .selectAs(BaseParam::getName, MemberRides::getParamName); wrapper.leftJoin(BaseParam.class, BaseParam::getId, MemberRides::getParamId); wrapper.orderByDesc(BaseParam::getSortnum); //åæé«è½¦åä½ä¸ºè®¡ä»·æ¹æ¡ //æ¥è¯¢ææéªè¡è®°å½ List<MemberRides> memberRides = memberRidesJoinMapper.selectList(wrapper); List<MemberRides> memberRides = memberRidesJoinMapper.selectJoinList(MemberRides.class,wrapper); return memberRides; } @@ -1187,7 +1194,7 @@ @Override public void autoCloseOrder( ) { Goodsorder goodsorder = new Goodsorder(); Goodsorder goodsorder = new Goodsorder(); goodsorder.setIsdeleted(Constants.ZERO); goodsorder.setStatus(Constants.goodsorderStatus.pay); List<Goodsorder> list = findList(goodsorder); server/services/src/main/java/com/doumee/service/system/impl/SystemDictDataServiceImpl.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.doumee.dao.business.web.request.LocaltionDTO; import com.doumee.dao.business.web.response.MiniProgrammeDTO; import com.doumee.dao.system.SystemDictMapper; import com.doumee.dao.system.model.SystemDict; @@ -143,8 +144,8 @@ try { if(miniProgrammeDTO.getParkLatLngList()!=null){ try { TypeReference typeReference = new TypeReference<List<Map<String,BigDecimal>>>(){}; List<Map<String,BigDecimal>> response = JSONObject.parseObject(miniProgrammeDTO.getParkLatLngList(), typeReference.getType()); TypeReference typeReference = new TypeReference<List<LocaltionDTO>>(){}; List<LocaltionDTO> response = JSONObject.parseObject(miniProgrammeDTO.getParkLatLngList(), typeReference.getType()); }catch (Exception e){ e.printStackTrace(); throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"è¿è¥åºååæ°è§£ææè¯¯ï¼"); server/web/src/main/java/com/doumee/api/web/BusinessApi.java
@@ -10,10 +10,12 @@ import com.doumee.core.model.PageData; import com.doumee.core.model.PageWrap; import com.doumee.dao.business.model.*; import com.doumee.dao.business.web.request.BackElecBikeRequest; import com.doumee.dao.business.web.request.RepairRequest; import com.doumee.dao.business.web.response.MemberRidesDetailResponse; import com.doumee.dao.business.web.response.RidesDetailResponse; import com.doumee.dao.system.model.SystemDictData; import com.doumee.jtt808.web.service.Jtt808Service; import com.doumee.service.business.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -22,6 +24,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.yzh.commons.model.APIResult; import org.yzh.protocol.t808.T0201_0500; import org.yzh.protocol.t808.T8500; import java.util.List; @@ -41,6 +46,8 @@ @Autowired private GoodsorderService goodsorderService; @Autowired private Jtt808Service jtt808Service; @Autowired private RentSiteService rentSiteService; @@ -188,4 +195,12 @@ public ApiResponse<SystemDictData> getSysDict(@RequestParam String dicCode, @RequestParam String label) { return ApiResponse.success("æ¥è¯¢æå",systemDictDataBiz.queryByCode(dicCode,label)); } @ApiOperation(value = "çµè½¦ç«ç¹è¿è½¦", notes = "çµè½¦ç«ç¹è¿è½¦") @PostMapping("/backElecBike") public ApiResponse backElecBike(@RequestBody BackElecBikeRequest param) { param.setMemberId(getMemberId()); jtt808Service.backElecBike(param); return ApiResponse.success( null); } } server/web/src/main/java/com/doumee/jtt808/web/service/Jtt808Service.java
@@ -1,23 +1,177 @@ 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.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.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.t808.T0201_0500; import org.yzh.protocol.t808.T8500; import reactor.core.publisher.Mono; 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 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<T0201_0500> bikeControl(@RequestBody T8500 request) { Mono<APIResult<T0201_0500>> result = messageManager.requestR(request, T0201_0500.class); APIResult<T0201_0500> data = result.block(); return data; } @Transactional(rollbackFor = {BusinessException.class}) public void backElecBike(BackElecBikeRequest param) { if (param.getLatitude() == null || param.getLongitude() == null || StringUtils.isBlank(param.getMemberId())) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼å®ä½ä¿¡æ¯æè¯¯ï¼è¯·ç¡®è®¤å®ä½æéå·²å¼å¯ï¼"); } 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> memberRides = goodsorderService.getMemberRidesForClose(goodsorder.getId()); if(memberRides!=null && memberRides.size()>0){ for (MemberRides rides : memberRides){ if(Constants.equalsInteger(rides.getStatus(),Constants.MEMBER_RIDES_STATUS.RIDES_RUNNING.getKey())){ if(StringUtils.isNotBlank(rides.getDeviceSn()) &&Constants.equalsInteger(rides.getType(),Constants.ONE) ){ Sites site = getBackSiteByPostion(param);//æ¥è¯¢å车ç«ç¹ä¿¡æ¯ //妿æ¯çµè½¦å¹¶ä¸æ¯éªè¡ä¸ è¿è¡å ³éå¤ç lockBikes(rides.getDeviceSn(),Constants.ZERO);//åèµ·å ³éæä»¤è¯·æ± } } } } //订åç»ç® Date date = new Date(); goodsorder.setEditDate(date); goodsorder.setEditor(null); goodsorderService.dealCloseGoodsorderBiz( goodsorder,Constants.REFUND_TYPE.NORMAL.getKey(),memberRides); } /** * åèµ·å ³éãå¼éæä»¤è¯·æ± * @param clientId */ private void lockBikes(String clientId,int type) { T8500 request = new T8500(); request.setType(type);//å ³é request.setClientId(StringTools.leftPad(clientId,12,'0')); Mono<APIResult<T0201_0500>> result = messageManager.requestR(request, T0201_0500.class); APIResult<T0201_0500> data = result.block(); if(!data.isSuccess()){ //妿å¼é失败ï¼åè¿åå¼å¸¸ throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼è¿è½¦å ³é失败ï¼è¯·ç¨åéè¯ï¼æè èç³»ååºç®¡ç人åï¼"); } } /** * æ¥è¯¢å车ç«ç¹ä¿¡æ¯ * @param param * @return */ private Sites getBackSiteByPostion(BackElecBikeRequest param) { Sites site = null;//æ¥è¯¢å车ç«ç¹ä¿¡æ¯ List<Sites> sitesList = sitesMapper.selectList(new QueryWrapper<Sites>().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(), "对ä¸èµ·ï¼è¯·æç §è¦æ±åå¾å车ç¹å车ï¼"); } for(Sites sites :sitesList){ TypeReference typeReference = new TypeReference<List<LocaltionDTO>>(){}; List<LocaltionDTO> array = JSONObject.parseObject(sites.getElectronicFence(), typeReference.getType()); if(array == null || array.size() ==0){ continue; } if(PositionUtil.isInPolygon(param.getLongitude(),param.getLatitude(),array)){ //妿å¨å车ç¹èå´å ï¼ site = sites; break; } if(site ==null){ throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "对ä¸èµ·ï¼è¯·æç §è¦æ±åå¾å车ç¹å车ï¼"); } } return site; } }