package org.springblade.modules.api.controller; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.http.ContentType; import cn.hutool.json.JSONUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springblade.common.aspect.VendingFlag; import org.springblade.common.aspect.VendingLog; import org.springblade.common.constant.CommonConstant; import org.springblade.common.enums.FacilityStatusEnum; import org.springblade.common.enums.OrderStateEnum; import org.springblade.common.enums.VargoWayStatusEnum; import org.springblade.common.enums.VendingLogEnum; import org.springblade.modules.api.request.VendingHeartReq; import org.springblade.modules.api.request.VendingOrderReq; import org.springblade.modules.api.request.VendingShipReq; import org.springblade.modules.api.response.VendingOrderGoodsRes; import org.springblade.modules.api.response.VendingOrderRes; import org.springblade.modules.api.service.VendingOrderService; import org.springblade.modules.business.entity.Facility; import org.springblade.modules.business.service.IFacilityCargoWayService; import org.springblade.modules.business.service.IFacilityService; import org.springblade.modules.finance.entity.Order; import org.springblade.modules.finance.entity.OrderGoods; import org.springblade.modules.finance.service.IOrderGoodsService; import org.springblade.modules.finance.service.IOrderService; import org.springblade.modules.finance.vo.OrderGoodsVO; import org.springblade.modules.finance.vo.OrderVO; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * 售货机硬件对接接口 */ @RestController @AllArgsConstructor @RequestMapping(CommonConstant.API_URL + "/vending") @Api(value = "售货机硬件对接接口", tags = "售货机硬件对接接口") @Slf4j public class ApiVendingController { private final VendingOrderService vendingOrderService; private final IOrderGoodsService orderGoodsService; private final IOrderService orderService; private final IFacilityService facilityService; private final IFacilityCargoWayService facilityCargoWayService; @VendingLog(VendingLogEnum.ORDER) @VendingFlag @ApiOperation(value = "查询订单信息", notes = "传入售货机编号") @PostMapping("/getOrder") public void getOrder(@Valid @RequestBody VendingOrderReq vendingOrderReq, HttpServletResponse response) throws IOException { List vendingOrderVOs = vendingOrderService.getVendingOrder(vendingOrderReq); //封装返回 VendingOrderRes vendingOrderRes = new VendingOrderRes(); vendingOrderRes.setMachineId(vendingOrderReq.getMachineId()); if (CollectionUtil.isEmpty(vendingOrderVOs)) { vendingOrderRes.setSaleSn(""); vendingOrderRes.setChannelNum("0"); vendingOrderRes.setSaleData(new ArrayList<>()); this.notifyReturn(response, vendingOrderRes); } else { //一次只返回一个订单 //按订单分组 Map> vendingOrderGoodMap = vendingOrderVOs.stream().collect(Collectors.groupingBy(OrderGoodsVO::getOrderId)); OrderVO backOrder = vendingOrderService.getBackOrder(vendingOrderReq); if (Objects.isNull(backOrder)) { vendingOrderRes.setSaleSn(""); vendingOrderRes.setChannelNum("0"); vendingOrderRes.setSaleData(new ArrayList<>()); this.notifyReturn(response, vendingOrderRes); return; } List orderGoodsVOS = vendingOrderGoodMap.get(backOrder.getId()); vendingOrderRes.setSaleSn(backOrder.getId() + ""); vendingOrderRes.setChannelNum(orderGoodsVOS.size() + ""); List saledataList = new ArrayList<>(); //补充货道信息 for (OrderGoodsVO orderGoodsVO : orderGoodsVOS) { VendingOrderGoodsRes vendingOrderGoodsRes = new VendingOrderGoodsRes(); vendingOrderGoodsRes.setOrderGoodsId(String.valueOf(orderGoodsVO.getId())); vendingOrderGoodsRes.setChannel(orderGoodsVO.getCargoWayNo()); vendingOrderGoodsRes.setChannelNum(String.valueOf(orderGoodsVO.getGoodsNum())); saledataList.add(vendingOrderGoodsRes); } vendingOrderRes.setSaleData(saledataList); this.notifyReturn(response, vendingOrderRes); } } /** * 硬件接口订单信息返回通用响应 * * @param response HttpServletResponse * @param vendingOrderRes 返值 */ private void notifyReturn(HttpServletResponse response, VendingOrderRes vendingOrderRes) throws IOException { Map map = BeanUtil.beanToMap(vendingOrderRes); response.setHeader("Content-type", ContentType.JSON.toString()); response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); response.flushBuffer(); } @VendingLog(VendingLogEnum.OQC) @ApiOperation(value = "出货成功回调", notes = "出货成功回调") @PostMapping("callback") public void callback(@Valid @RequestBody VendingShipReq req) { //设备出货成功回调 OrderGoods orderGoods = orderGoodsService.getById(req.getOrderGoodsId()); if (Objects.isNull(orderGoods)) { log.info("设备出货成功回调,未找到货品信息"); return; } //出货量校验 if (orderGoods.getGoodsNum() < orderGoods.getShipmentNum() + 1) { log.info("设备出货成功回调,出货量过多"); } if ("OK".equals(req.getStatus())) { orderGoodsService.lambdaUpdate() .set(OrderGoods::getShipmentNum, orderGoods.getShipmentNum() + 1) .set(OrderGoods::getShippingTime, LocalDateTime.now()) .eq(OrderGoods::getId, req.getOrderGoodsId()) .update(); if (orderGoods.getGoodsNum() == orderGoods.getShipmentNum() + 1) { orderService.lambdaUpdate() .set(Order::getOrderState, OrderStateEnum.COMPLETED.getValue()) .eq(Order::getId, req.getSaleSn()) .update(); orderGoodsService.lambdaUpdate() .set(OrderGoods::getShipment, 1) .eq(OrderGoods::getId, req.getOrderGoodsId()) .update(); } } else {//出货故障处理 //将订单状态改为出货失败 orderService.lambdaUpdate() .set(Order::getOrderState, OrderStateEnum.SHIP_FAIL.getValue()) .eq(Order::getId, req.getSaleSn()) .update(); orderGoodsService.lambdaUpdate() .set(OrderGoods::getShipment, 0) .eq(OrderGoods::getId, req.getOrderGoodsId()) .update(); //将货道改为异常,该货道不可购买 facilityCargoWayService.updateCargoWayStatus(req.getMachineId(), req.getChannel(), VargoWayStatusEnum.FAULT); } } @VendingLog(VendingLogEnum.HEARTBEAT) @ApiOperation(value = "设备心跳", notes = "设备心跳") @PostMapping("heartbeat") public void heartbeat(@Valid @RequestBody VendingHeartReq req) { Facility facility = facilityService.getById(req.getMachineId()); if (Objects.isNull(facility)) { log.info("设备心跳,未找到设备信息"); return; } Date now = new Date(); facility.setHeartbeatTime(now); if ("0".equals(req.getErrorNum()) || "OK".equals(req.getStatus())) { facility.setFacilityStatus(FacilityStatusEnum.ON_LINE.getValue()); //将异常货道恢复 facilityCargoWayService.updateCargoWayStatus(String.valueOf(facility.getId()), null, VargoWayStatusEnum.NORMAL); //位置校验 //"location": "N,22.97637,E,113.37804" String[] split = req.getLocation().split(","); //TODO 2024/9/26 LuoDLeo 位置过大,发短信提醒 //double distance = DistanceUtils.getDistance(Double.parseDouble(facility.getLongitude()), Double.parseDouble(facility.getLatitude()), Double.parseDouble(split[3]), Double.parseDouble(split[1])); //更新位置 facility.setLatitude(split[1]);//纬度N facility.setLongitude(split[3]);//经度E facilityService.updateById(facility); return; } else { //设备故障 facility.setFacilityStatus(FacilityStatusEnum.FAULT.getValue()); facilityService.updateById(facility); //录入故障信息 String[] split = req.getErrorArray().replace("{", "").replace("}", "").split(","); for (String status : split) { //判断是不是货道异常,是的话将该货道设置为不可购买 if (status.startsWith("10")) { facilityCargoWayService.updateCargoWayStatus(String.valueOf(facility.getId()), status.substring(2), VargoWayStatusEnum.FAULT); } } } } }