Selaa lähdekoodia

Merge branch 'dev_v1.0.0' into release_v1.0.0
merge

wangliang 1 vuosi sitten
vanhempi
commit
6fcd1a1232
20 muutettua tiedostoa jossa 672 lisäystä ja 30 poistoa
  1. 0 1
      sop-api/src/main/java/com/qmth/sop/server/api/CrmAnalyseController.java
  2. 78 0
      sop-api/src/main/java/com/qmth/sop/server/api/DeviceMonitorController.java
  3. 1 2
      sop-api/src/main/java/com/qmth/sop/server/api/FxxkAsyncController.java
  4. 16 1
      sop-business/src/main/java/com/qmth/sop/business/bean/params/DeviceInOutForm.java
  5. 17 2
      sop-business/src/main/java/com/qmth/sop/business/bean/params/DeviceInOutSubmitParam.java
  6. 50 0
      sop-business/src/main/java/com/qmth/sop/business/bean/result/DeviceInOutResult.java
  7. 12 0
      sop-business/src/main/java/com/qmth/sop/business/entity/SysDevice.java
  8. 12 0
      sop-business/src/main/java/com/qmth/sop/business/entity/TBDeviceInOut.java
  9. 27 0
      sop-business/src/main/java/com/qmth/sop/business/mapper/DeviceMonitorMapper.java
  10. 17 0
      sop-business/src/main/java/com/qmth/sop/business/service/DeviceMonitorService.java
  11. 12 3
      sop-business/src/main/java/com/qmth/sop/business/service/TBSopInfoService.java
  12. 40 0
      sop-business/src/main/java/com/qmth/sop/business/service/impl/DeviceMonitorServiceImpl.java
  13. 42 6
      sop-business/src/main/java/com/qmth/sop/business/service/impl/TBDeviceInOutServiceImpl.java
  14. 83 10
      sop-business/src/main/java/com/qmth/sop/business/service/impl/TBSopInfoServiceImpl.java
  15. 42 1
      sop-business/src/main/java/com/qmth/sop/business/sync/FxxkApiUtils.java
  16. 137 0
      sop-business/src/main/java/com/qmth/sop/business/sync/been/FxxkCrm.java
  17. 7 1
      sop-business/src/main/resources/db/log/caozixuan_update_log.sql
  18. 65 0
      sop-business/src/main/resources/mapper/DeviceMonitorMapper.xml
  19. 9 3
      sop-business/src/main/resources/mapper/TBDeviceInOutMapper.xml
  20. 5 0
      sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java

+ 0 - 1
sop-api/src/main/java/com/qmth/sop/server/api/CrmAnalyseController.java

@@ -2,7 +2,6 @@ package com.qmth.sop.server.api;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.sop.business.bean.result.CrmAnalyseResult;
 import com.qmth.sop.business.bean.result.TBCrmResult;

+ 78 - 0
sop-api/src/main/java/com/qmth/sop/server/api/DeviceMonitorController.java

@@ -0,0 +1,78 @@
+package com.qmth.sop.server.api;
+
+import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.sop.business.service.DeviceMonitorService;
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.util.Result;
+import com.qmth.sop.common.util.ResultUtil;
+import io.swagger.annotations.*;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 设备保障监控 控制器
+ *
+ * @author: shudonghui
+ * @date: 2023-08-14 15:55:18
+ * @version: 1.0
+ * @email: shudonghui@qmth.com.cn
+ * @Company: www.qmth.com.cn
+ */
+@Api(tags = "设备保障监控 Controller")
+@RestController
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_DEVICE + "/monitor")
+public class DeviceMonitorController {
+
+
+    @Resource
+    DeviceMonitorService deviceMonitorService;
+
+    
+    @ApiOperation(value = "库存监控统计接口")
+    @RequestMapping(value = "/count", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "库存监控统计", response = Map.class)})
+    public Result count(@ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
+                        @ApiParam(value = "型号", required = false) @RequestParam(required = false) String model
+    ) {
+        Map<String, Object> map = deviceMonitorService.count(supplierId, model);
+
+        return ResultUtil.ok(map);
+    }
+
+    //按型号统计状态明细
+    
+    @ApiOperation(value = "按型号统计状态明细")
+    @RequestMapping(value = "/countByModel", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "按型号统计状态明细", response = List.class)})
+    public Result countByModel(@ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId) {
+        List<Map<String, Object>> list = deviceMonitorService.countByModel(supplierId);
+
+        return ResultUtil.ok(list);
+    }
+
+    //按服务单元统计设备状态
+    
+    @ApiOperation(value = "按服务单元统计设备状态")
+    @RequestMapping(value = "/countByServiceUnit", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "按服务单元统计设备状态", response = Map.class)})
+    public Result countByServiceUnit() {
+        Map<String, Object> map = deviceMonitorService.countByServiceUnit();
+        return ResultUtil.ok(map);
+    }
+    //按服务单元统计设备状态明细
+    
+    @ApiOperation(value = "按服务单元统计设备状态明细")
+    @RequestMapping(value = "/countByServiceUnitDetail", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "按服务单元统计设备状态明细", response = List.class)})
+    public Result countByServiceUnitDetail() {
+        List<Map<String, Object>> list = deviceMonitorService.countByServiceUnitDetail();
+        return ResultUtil.ok(list);
+    }
+
+}

+ 1 - 2
sop-api/src/main/java/com/qmth/sop/server/api/FxxkAsyncController.java

@@ -60,7 +60,6 @@ public class FxxkAsyncController {
     @RequestMapping(value = "/find/custom_list", method = RequestMethod.POST)
     @Aac(auth = false)
     public Result findCustomList() {
-        fxxkApiUtils.findCustomList();
-        return ResultUtil.ok();
+        return ResultUtil.ok(fxxkApiUtils.findCustomList());
     }
 }

+ 16 - 1
sop-business/src/main/java/com/qmth/sop/business/bean/params/DeviceInOutForm.java

@@ -3,12 +3,16 @@ package com.qmth.sop.business.bean.params;
 import com.qmth.sop.common.enums.DeviceStatusEnum;
 import io.swagger.annotations.ApiModelProperty;
 
+import java.io.Serializable;
+import java.util.List;
+
 /**
  * @Description: 设备出入库登记表单
  * @Author: CaoZixuan
  * @Date: 2023-08-24
  */
-public class DeviceInOutForm {
+public class DeviceInOutForm implements Serializable {
+
     @ApiModelProperty("设备编号")
     private String deviceNo;
 
@@ -30,6 +34,9 @@ public class DeviceInOutForm {
     @ApiModelProperty("发往地")
     private String address;
 
+    @ApiModelProperty("发往地(回显)")
+    private List<String> addressArr;
+
     @ApiModelProperty("快递单拍照")
     private String basePhotoPath;
 
@@ -89,6 +96,14 @@ public class DeviceInOutForm {
         this.address = address;
     }
 
+    public List<String> getAddressArr() {
+        return addressArr;
+    }
+
+    public void setAddressArr(List<String> addressArr) {
+        this.addressArr = addressArr;
+    }
+
     public String getBasePhotoPath() {
         return basePhotoPath;
     }

+ 17 - 2
sop-business/src/main/java/com/qmth/sop/business/bean/params/DeviceInOutSubmitParam.java

@@ -8,6 +8,7 @@ import org.hibernate.validator.constraints.Range;
 
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
 import java.util.List;
 
 /**
@@ -15,7 +16,8 @@ import java.util.List;
  * @Author: CaoZixuan
  * @Date: 2023-08-24
  */
-public class DeviceInOutSubmitParam {
+public class DeviceInOutSubmitParam implements Serializable {
+
     @ApiModelProperty("服务单元id")
     @JsonSerialize(using = ToStringSerializer.class)
     private Long serviceUnitId;
@@ -28,7 +30,7 @@ public class DeviceInOutSubmitParam {
 
     @ApiModelProperty("出入库时间")
     @NotNull(message = "缺少出入库时间")
-    @Range(min = 1L,message = "缺少出入库时间")
+    @Range(min = 1L, message = "缺少出入库时间")
     private Long inOutTime;
 
     @ApiModelProperty("出入库类型")
@@ -39,6 +41,19 @@ public class DeviceInOutSubmitParam {
     @NotEmpty(message = "缺少出入库登记单")
     private List<DeviceInOutForm> deviceInOutFormList;
 
+    public DeviceInOutSubmitParam() {
+
+    }
+
+    public DeviceInOutSubmitParam(Long serviceUnitId, String crmNo, String sopNo, Long inOutTime, InOutTypeEnum inOutType, List<DeviceInOutForm> deviceInOutFormList) {
+        this.serviceUnitId = serviceUnitId;
+        this.crmNo = crmNo;
+        this.sopNo = sopNo;
+        this.inOutTime = inOutTime;
+        this.inOutType = inOutType;
+        this.deviceInOutFormList = deviceInOutFormList;
+    }
+
     public Long getServiceUnitId() {
         return serviceUnitId;
     }

+ 50 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/result/DeviceInOutResult.java

@@ -1,5 +1,6 @@
 package com.qmth.sop.business.bean.result;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.sop.common.enums.DeviceStatusEnum;
@@ -7,6 +8,8 @@ import com.qmth.sop.common.enums.DeviceUsageTypeEnum;
 import com.qmth.sop.common.enums.InOutTypeEnum;
 import io.swagger.annotations.ApiModelProperty;
 
+import java.util.List;
+
 /**
  * @Description: 设备出入库记录查询结果
  * @Author: CaoZixuan
@@ -62,9 +65,24 @@ public class DeviceInOutResult {
 
     @ApiModelProperty("当前地")
     private String location;
+
+    @ApiModelProperty("当前地(回显)")
+    @JsonIgnore
+    private String locationArrTemp;
+
+    @ApiModelProperty("当前地(回显)")
+    private List<String> locationArr;
+
     @ApiModelProperty("发往地")
     private String address;
 
+    @ApiModelProperty("发往地(回显)")
+    @JsonIgnore
+    private String addressArrTemp;
+
+    @ApiModelProperty("发往地(回显)")
+    private List<String> addressArr;
+
     @ApiModelProperty("供应商id")
     @JsonSerialize(using = ToStringSerializer.class)
     private Long supplierId;
@@ -218,6 +236,22 @@ public class DeviceInOutResult {
         this.location = location;
     }
 
+    public String getLocationArrTemp() {
+        return locationArrTemp;
+    }
+
+    public void setLocationArrTemp(String locationArrTemp) {
+        this.locationArrTemp = locationArrTemp;
+    }
+
+    public List<String> getLocationArr() {
+        return locationArr;
+    }
+
+    public void setLocationArr(List<String> locationArr) {
+        this.locationArr = locationArr;
+    }
+
     public String getAddress() {
         return address;
     }
@@ -226,6 +260,22 @@ public class DeviceInOutResult {
         this.address = address;
     }
 
+    public String getAddressArrTemp() {
+        return addressArrTemp;
+    }
+
+    public void setAddressArrTemp(String addressArrTemp) {
+        this.addressArrTemp = addressArrTemp;
+    }
+
+    public List<String> getAddressArr() {
+        return addressArr;
+    }
+
+    public void setAddressArr(List<String> addressArr) {
+        this.addressArr = addressArr;
+    }
+
     public Long getSupplierId() {
         return supplierId;
     }

+ 12 - 0
sop-business/src/main/java/com/qmth/sop/business/entity/SysDevice.java

@@ -11,6 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * <p>
@@ -55,6 +56,9 @@ public class SysDevice extends BaseEntity implements Serializable {
     @ApiModelProperty(value = "当前所在地")
     private String location;
 
+    @ApiModelProperty(value = "当前所在地(回显)")
+    private String locationArr;
+
     @ApiModelProperty(value = "总扫描量")
     private Long scanCount;
 
@@ -118,6 +122,14 @@ public class SysDevice extends BaseEntity implements Serializable {
         this.location = location;
     }
 
+    public String getLocationArr() {
+        return locationArr;
+    }
+
+    public void setLocationArr(String locationArr) {
+        this.locationArr = locationArr;
+    }
+
     public Long getScanCount() {
         return scanCount;
     }

+ 12 - 0
sop-business/src/main/java/com/qmth/sop/business/entity/TBDeviceInOut.java

@@ -9,6 +9,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * <p>
@@ -65,6 +66,9 @@ public class TBDeviceInOut implements Serializable {
     @ApiModelProperty(value = "发往地")
     private String address;
 
+    @ApiModelProperty(value = "发往地(回显)")
+    private String addressArr;
+
     @ApiModelProperty(value = "运行状态,NORMAL:正常,BREAK_DOWN:故障")
     private DeviceStatusEnum status;
 
@@ -185,6 +189,14 @@ public class TBDeviceInOut implements Serializable {
         this.address = address;
     }
 
+    public String getAddressArr() {
+        return addressArr;
+    }
+
+    public void setAddressArr(String addressArr) {
+        this.addressArr = addressArr;
+    }
+
     public DeviceStatusEnum getStatus() {
         return status;
     }

+ 27 - 0
sop-business/src/main/java/com/qmth/sop/business/mapper/DeviceMonitorMapper.java

@@ -0,0 +1,27 @@
+package com.qmth.sop.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.sop.business.entity.SysDevice;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * </p>
+ *
+ * @author dhshu
+ *
+ */
+public interface DeviceMonitorMapper extends BaseMapper<SysDevice> {
+
+
+    Map<String, Object> count(@Param("supplierId") Long supplierId,@Param("model") String model);
+
+    List<Map<String, Object>> countByModel(@Param("supplierId") Long supplierId);
+
+    Map<String, Object> countByServiceUnit();
+
+    List<Map<String, Object>> countByServiceUnitDetail();
+}

+ 17 - 0
sop-business/src/main/java/com/qmth/sop/business/service/DeviceMonitorService.java

@@ -0,0 +1,17 @@
+package com.qmth.sop.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.sop.business.entity.SysDevice;
+
+import java.util.List;
+import java.util.Map;
+
+public interface DeviceMonitorService extends IService<SysDevice> {
+    Map<String, Object> count(Long supplierId, String model);
+
+    List<Map<String, Object>> countByModel(Long supplierId);
+
+    Map<String, Object> countByServiceUnit();
+
+    List<Map<String, Object>> countByServiceUnitDetail();
+}

+ 12 - 3
sop-business/src/main/java/com/qmth/sop/business/service/TBSopInfoService.java

@@ -129,7 +129,16 @@ public interface TBSopInfoService extends IService<TBSopInfo> {
      *
      * @param map
      */
-    public void saveJobRemind(Map<String, Object> map);
+    public void saveJobRemind(Map<String, Object> map) throws InterruptedException;
+
+    /**
+     * sop保存设备信息
+     *
+     * @param map
+     * @param setup
+     * @throws InterruptedException
+     */
+    public void sopDeviceInOutSave(Map<String, Object> map, Integer setup) throws InterruptedException;
 
     /**
      * sop编辑
@@ -137,7 +146,7 @@ public interface TBSopInfoService extends IService<TBSopInfo> {
      * @param id
      * @return
      */
-    public FlowResult sopEdit(Long id);
+    public FlowResult sopEdit(Long id) throws InterruptedException;
 
     /**
      * sop保存
@@ -145,7 +154,7 @@ public interface TBSopInfoService extends IService<TBSopInfo> {
      * @param sopSaveParam
      * @return
      */
-    public Boolean sopSave(SopSaveParam sopSaveParam);
+    public Boolean sopSave(SopSaveParam sopSaveParam) throws InterruptedException;
 
     List<SysUser> userList(Long id);
 }

+ 40 - 0
sop-business/src/main/java/com/qmth/sop/business/service/impl/DeviceMonitorServiceImpl.java

@@ -0,0 +1,40 @@
+package com.qmth.sop.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.sop.business.entity.SysDevice;
+import com.qmth.sop.business.mapper.DeviceMonitorMapper;
+import com.qmth.sop.business.service.DeviceMonitorService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @author dhshu
+ * @date:
+ */
+@Service
+public class DeviceMonitorServiceImpl extends ServiceImpl<DeviceMonitorMapper, SysDevice> implements DeviceMonitorService {
+
+
+    @Override
+    public Map<String, Object> count(Long supplierId, String model) {
+        return this.baseMapper.count(supplierId, model);
+    }
+
+    @Override
+    public List<Map<String, Object>> countByModel(Long supplierId) {
+        return this.baseMapper.countByModel(supplierId);
+    }
+
+    @Override
+    public Map<String, Object> countByServiceUnit() {
+        return this.baseMapper.countByServiceUnit();
+    }
+
+    @Override
+    public List<Map<String, Object>> countByServiceUnitDetail() {
+        return this.baseMapper.countByServiceUnitDetail();
+    }
+}

+ 42 - 6
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBDeviceInOutServiceImpl.java

@@ -1,5 +1,6 @@
 package com.qmth.sop.business.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -54,19 +55,40 @@ public class TBDeviceInOutServiceImpl extends ServiceImpl<TBDeviceInOutMapper, T
 
         SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
         DataPermissionDto dpr = sysUserService.buildUserDataPermission(requestUser.getId());
-
-        return this.baseMapper.findDeviceInOutPageBySop(new Page<>(pageNumber, pageSize), serviceUnitId, usageType,
+        IPage<DeviceInOutResult> result = this.baseMapper.findDeviceInOutPageBySop(new Page<>(pageNumber, pageSize), serviceUnitId, usageType,
                 userId, deviceStatus, inOutTimeStart, inOutTimeEnd, deviceNo, customName, location, address, serialNo, dpr);
+        result.getRecords().forEach(e -> {
+            String addressArrTemp = e.getAddressArrTemp();
+            String locationArrTemp = e.getLocationArrTemp();
+            if (addressArrTemp != null && addressArrTemp.length() > 0) {
+                e.setAddressArr(JSON.parseArray(addressArrTemp, String.class));
+            }
+            if (locationArrTemp != null && locationArrTemp.length() > 0) {
+                e.setLocationArr(JSON.parseArray(locationArrTemp, String.class));
+            }
+        });
+
+        return result;
     }
 
     @Override
     public List<DeviceInOutResult> findDeviceCanOutInfo(Long supplierId) {
-        return this.baseMapper.findDeviceCanOutInfo(supplierId, DeviceStatusEnum.NORMAL, InOutTypeEnum.IN);
+        return this.baseMapper.findDeviceCanOutInfo(supplierId, DeviceStatusEnum.NORMAL, InOutTypeEnum.IN).stream().peek(e -> {
+            String locationArrTemp = e.getLocationArrTemp();
+            if (locationArrTemp != null && locationArrTemp.length() > 0) {
+                e.setLocationArr(JSON.parseArray(locationArrTemp, String.class));
+            }
+        }).collect(Collectors.toList());
     }
 
     @Override
     public List<DeviceInOutResult> findDeviceCanInInfo(Long supplierId, String crmNo) {
-        return this.baseMapper.findDeviceCanInInfo(supplierId, InOutTypeEnum.OUT, crmNo);
+        return this.baseMapper.findDeviceCanInInfo(supplierId, InOutTypeEnum.OUT, crmNo).stream().peek(e -> {
+            String locationArrTemp = e.getLocationArrTemp();
+            if (locationArrTemp != null && locationArrTemp.length() > 0) {
+                e.setLocationArr(JSON.parseArray(locationArrTemp, String.class));
+            }
+        }).collect(Collectors.toList());
     }
 
 
@@ -115,6 +137,7 @@ public class TBDeviceInOutServiceImpl extends ServiceImpl<TBDeviceInOutMapper, T
             tbDeviceInOut.setSupplierName(e.getSupplierName());
             tbDeviceInOut.setLocation(e.getLocation());
             tbDeviceInOut.setAddress(e.getAddress());
+            tbDeviceInOut.setAddressArr(JSON.toJSONString(e.getAddressArr()));
             tbDeviceInOut.setStatus(e.getDeviceStatus());
             tbDeviceInOut.setUsageType(usageType);
             tbDeviceInOut.setBasePhotoPath(e.getBasePhotoPath());
@@ -123,10 +146,11 @@ public class TBDeviceInOutServiceImpl extends ServiceImpl<TBDeviceInOutMapper, T
             UpdateWrapper<SysDevice> updateWrapper = new UpdateWrapper<>();
             updateWrapper.lambda()
                     .set(SysDevice::getLocation, e.getAddress())
+                    .set(SysDevice::getLocationArr, JSON.toJSONString(e.getAddressArr()))
                     .set(SysDevice::getScanCount, e.getScanCount())
                     .set(SysDevice::getStatus, e.getDeviceStatus())
                     .set(SysDevice::getBound, inOutType)
-                    .eq(SysDevice::getSerialNo, e.getDeviceNo());
+                    .eq(SysDevice::getDeviceCode, e.getDeviceNo());
             sysDeviceService.update(updateWrapper);
 
             return Stream.of(tbDeviceInOut);
@@ -145,7 +169,19 @@ public class TBDeviceInOutServiceImpl extends ServiceImpl<TBDeviceInOutMapper, T
         SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
         DataPermissionDto dpr = sysUserService.buildUserDataPermission(requestUser.getId());
 
-        return this.baseMapper.findDeviceInOutPageBySource(new Page<>(pageNumber, pageSize), serviceUnitId, usageType,
+        IPage<DeviceInOutResult> result = this.baseMapper.findDeviceInOutPageBySource(new Page<>(pageNumber, pageSize), serviceUnitId, usageType,
                 userId, deviceStatus, inOutTimeStart, inOutTimeEnd, deviceNo, customName, location, address, serialNo, dpr);
+
+        result.getRecords().forEach(e -> {
+            String addressArrTemp = e.getAddressArrTemp();
+            String locationArrTemp = e.getLocationArrTemp();
+            if (addressArrTemp != null && addressArrTemp.length() > 0) {
+                e.setAddressArr(JSON.parseArray(addressArrTemp, String.class));
+            }
+            if (locationArrTemp != null && locationArrTemp.length() > 0) {
+                e.setLocationArr(JSON.parseArray(locationArrTemp, String.class));
+            }
+        });
+        return result;
     }
 }

+ 83 - 10
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBSopInfoServiceImpl.java

@@ -80,6 +80,12 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
     @Value("${db.name}")
     String databaseName;
 
+    @Resource
+    TBDeviceInOutService tbDeviceInOutService;
+
+    @Resource
+    TFFlowLogService tfFlowLogService;
+
     /**
      * 查询动态sop表名是否存在
      *
@@ -309,8 +315,12 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
             flowApproveParam.setFormProperties(JacksonUtil.parseJson(flowTaskResult));
         }
 
+        CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(tfCustomFlowEntity.getCode(), tfCustomFlowEntity.getCrmNo());
+        Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());
+
         Map<String, Object> map = activitiService.taskApprove(flowApproveParam);
         if (flowApproveParam.getApprove() != FlowApprovePassEnum.DRAFT) {
+            map.put(SystemConstant.CRM_INFO, crmProjectResult);
             tbSopInfoService.saveJobRemind(map);
         }
         TFFlowApprove tfFlowApprove = (TFFlowApprove) map.get(SystemConstant.FLOW_APPROVE);
@@ -634,6 +644,7 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
 
         Map<String, Object> map = activitiService.taskApprove(new FlowApproveParam(flowDeploymentId, approve, approveUserIds, crmNo, formProperties));
         if (approve != FlowApprovePassEnum.DRAFT) {
+            map.put(SystemConstant.CRM_INFO, crmProjectResult);
             tbSopInfoService.saveJobRemind(map);
         }
 
@@ -660,7 +671,7 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
      */
     @Override
     @Transactional
-    public void saveJobRemind(Map<String, Object> map) {
+    public void saveJobRemind(Map<String, Object> map) throws InterruptedException {
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         TFCustomFlow tfCustomFlow = (TFCustomFlow) map.get(SystemConstant.FLOW_CUSTOM);
         Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());
@@ -686,6 +697,7 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
                 } else if (tfFlowApprove.getSetup().intValue() == 3) {//内审
                     processLimitedTime = tfFlowApprove.getUpdateTime();
                 } else if (tfFlowApprove.getSetup().intValue() == 5) {//扫描准备
+                    tbSopInfoService.sopDeviceInOutSave(map, 4);
                     FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                     processLimitedTime = this.getProcessLimitedTime(flowTaskResult, SystemConstant.SCAN_START_TIME);
                     execField = SystemConstant.SCAN_START_TIME;
@@ -718,6 +730,7 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
                     processLimitedTime = this.getProcessLimitedTime(flowTaskResult, SystemConstant.ENV_DEPLOYMENT_TIME);
                     execField = SystemConstant.ENV_DEPLOYMENT_TIME;
                 } else if (tfFlowApprove.getSetup().intValue() == 6) {//扫描准备
+                    tbSopInfoService.sopDeviceInOutSave(map, 5);
                     FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                     processLimitedTime = this.getProcessLimitedTime(flowTaskResult, SystemConstant.SCAN_START_TIME);
                     execField = SystemConstant.SCAN_START_TIME;
@@ -757,6 +770,54 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
                     tsJobRemindService.saveJobRemind(tsJobRemindList);
                 }
             }
+        } else if (tfFlowApprove.getStatus() == FlowStatusEnum.FINISH) {
+            if (tfCustomFlow.getType() == TFCustomTypeEnum.OFFICE_SOP_FLOW) {//教务处sop
+                tbSopInfoService.sopDeviceInOutSave(map, 10);
+            } else if (tfCustomFlow.getType() == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {//研究生sop
+                tbSopInfoService.sopDeviceInOutSave(map, 11);
+            }
+        }
+    }
+
+    /**
+     * sop保存设备信息
+     *
+     * @param map
+     * @param setup
+     * @throws InterruptedException
+     */
+    @Override
+    @Transactional
+    public void sopDeviceInOutSave(Map<String, Object> map, Integer setup) throws InterruptedException {
+        TFCustomFlowEntity tfCustomFlowEntity = (TFCustomFlowEntity) map.get(SystemConstant.FLOW_ENTITY);
+        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());
+
+        FlowTaskResult flowTaskResultDeviceTable = this.getFormProperties(tfCustomFlowEntity, setup);
+        if (Objects.nonNull(flowTaskResultDeviceTable)) {
+            CrmProjectResult crmProjectResult = (CrmProjectResult) map.get(SystemConstant.CRM_INFO);
+            List<FlowFormWidgetResult> flowFormWidgetResultList = flowTaskResultDeviceTable.getFormProperty();
+            List<DeviceInOutForm> deviceInOutFormList = new ArrayList<>();
+            InOutTypeEnum type = null;
+            Long deviceInOutTime = null;
+            for (FlowFormWidgetResult f : flowFormWidgetResultList) {
+                if (f.getFormId().contains(SystemConstant.DEVICE_OUT_TIME) || f.getFormId().contains(SystemConstant.DEVICE_IN_TIME)) {
+                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
+                    String value = jsonObject.getString(SystemConstant.VALUE);
+                    deviceInOutTime = Long.parseLong(value);
+                    type = f.getFormId().contains(SystemConstant.DEVICE_OUT_TIME) ? InOutTypeEnum.OUT : InOutTypeEnum.IN;
+                } else if (f.getFormId().contains(SystemConstant.DEVICE_OUT_TABLE) || f.getFormId().contains(SystemConstant.DEVICE_IN_TABLE)) {
+                    if (Objects.isNull(type)) {
+                        type = f.getFormId().contains(SystemConstant.DEVICE_OUT_TABLE) ? InOutTypeEnum.OUT : InOutTypeEnum.IN;
+                    }
+                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
+                    JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
+                    for (int i = 0; i < jsonArray.size(); i++) {
+                        deviceInOutFormList.add(GsonUtil.fromJson(GsonUtil.toJson(jsonArray.getJSONObject(i)), DeviceInOutForm.class));
+                    }
+                }
+            }
+            tbDeviceInOutService.deviceInOutSubmit(new DeviceInOutSubmitParam(crmProjectResult.getServiceUnitId(),
+                    tfCustomFlowEntity.getCrmNo(), tfCustomFlowEntity.getCode(), deviceInOutTime, type, deviceInOutFormList));
         }
     }
 
@@ -767,7 +828,7 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
      * @return
      */
     @Override
-    public FlowResult sopEdit(Long id) {
+    public FlowResult sopEdit(Long id) throws InterruptedException {
         Optional.ofNullable(id).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("sopId不能为空"));
         TBSopInfo tbSopInfo = this.getById(id);
         Optional.ofNullable(tbSopInfo).orElseThrow(() -> ExceptionResultEnum.SOP_INFO_NO_DATA.exception());
@@ -778,10 +839,6 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
         TFFlowApprove tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda().eq(TFFlowApprove::getFlowId, tfCustomFlowEntity.getFlowId()));
         Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_NO_DATA.exception());
 
-//        if (tfFlowApprove.getStatus() == FlowStatusEnum.FINISH || tfFlowApprove.getStatus() == FlowStatusEnum.END) {
-//            throw ExceptionResultEnum.ERROR.exception("已结束的流程不允许修改");
-//        }
-
         FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
         FlowResult flowResultNew = new FlowResult();
         BeanUtils.copyProperties(flowResult, flowResultNew);
@@ -819,7 +876,7 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
      */
     @Override
     @Transactional
-    public Boolean sopSave(SopSaveParam sopSaveParam) {
+    public Boolean sopSave(SopSaveParam sopSaveParam) throws InterruptedException {
         TBSopInfo tbSopInfo = this.getById(sopSaveParam.getId());
         Optional.ofNullable(tbSopInfo).orElseThrow(() -> ExceptionResultEnum.SOP_INFO_NO_DATA.exception());
 
@@ -829,14 +886,30 @@ public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo
         TFFlowApprove tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda().eq(TFFlowApprove::getFlowId, tfCustomFlowEntity.getFlowId()));
         Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_NO_DATA.exception());
 
-        if (tfFlowApprove.getStatus() == FlowStatusEnum.FINISH || tfFlowApprove.getStatus() == FlowStatusEnum.END) {
-            throw ExceptionResultEnum.ERROR.exception("已结束的流程不允许修改");
-        }
+//        if (tfFlowApprove.getStatus() == FlowStatusEnum.FINISH || tfFlowApprove.getStatus() == FlowStatusEnum.END) {
+//            throw ExceptionResultEnum.ERROR.exception("已结束的流程不允许修改");
+//        }
 
         TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
         Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());
 
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+        if (tfFlowApprove.getStatus() != FlowStatusEnum.FINISH && tfFlowApprove.getStatus() != FlowStatusEnum.END) {
+            Map<String, Object> map = new HashMap<>();
+            CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(tfCustomFlowEntity.getCode(), tfCustomFlowEntity.getCrmNo());
+            Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());
+
+            TFFlowLog tfFlowLog = tfFlowLogService.getOne(new QueryWrapper<TFFlowLog>().lambda().eq(TFFlowLog::getFlowId, tfCustomFlowEntity.getFlowId()).last(" order by create_time limit 1 "));
+            Optional.ofNullable(tfFlowLog).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_LOG_NO_DATA.exception());
+
+            map.put(SystemConstant.FLOW_CUSTOM, tfCustomFlow);
+            map.put(SystemConstant.FLOW_ENTITY, tfCustomFlowEntity);
+            map.put(SystemConstant.FLOW_APPROVE, tfFlowApprove);
+            map.put(SystemConstant.FLOW_APPROVE_LOG, tfFlowLog);
+            map.put(SystemConstant.CRM_INFO, crmProjectResult);
+            tbSopInfoService.saveJobRemind(map);
+        }
+
         FlowResult flowResultParam = JSONObject.parseObject(sopSaveParam.getFormProperties(), FlowResult.class);
         LinkedHashMap<String, FlowTaskResult> setupParamMap = flowResultParam.getSetupMap();
         for (Map.Entry<String, FlowTaskResult> entry : setupParamMap.entrySet()) {

+ 42 - 1
sop-business/src/main/java/com/qmth/sop/business/sync/FxxkApiUtils.java

@@ -5,8 +5,10 @@ import com.alibaba.fastjson.JSONObject;
 import com.qmth.sop.business.service.SysConfigService;
 import com.qmth.sop.business.sync.been.FxxkAppAuthInfo;
 import com.qmth.sop.business.sync.been.FxxkAppAuthResult;
+import com.qmth.sop.business.sync.been.FxxkCrm;
 import com.qmth.sop.common.contant.SystemConstant;
 import com.qmth.sop.common.enums.ExceptionResultEnum;
+import com.qmth.sop.common.enums.ProductTypeEnum;
 import com.qmth.sop.common.util.HttpUtil;
 import com.qmth.sop.common.util.JacksonUtil;
 import org.apache.commons.lang3.StringUtils;
@@ -99,7 +101,7 @@ public class FxxkApiUtils {
     /**
      * 查询自定义对象列表
      */
-    public void findCustomList() {
+    public List<FxxkCrm> findCustomList() {
         String currentOpenUserId = sysConfigService.findByConfigKey(SystemConstant.FXXK_CURRENT_OPEN_USER_ID).getConfigValue();
         String postUrl = sysConfigService.findByConfigKey(SystemConstant.FXXK_CUSTOM_QUERY_URL).getConfigValue();
         try {
@@ -132,6 +134,45 @@ public class FxxkApiUtils {
             if (errorCode != 0) {
                 throw ExceptionResultEnum.ERROR.exception("获取自定义对象列表失败 : " + errorMessage);
             }
+            JSONObject data = jsonObject.getJSONObject("data");
+            JSONArray dataList = data.getJSONArray("dataList");
+
+            List<FxxkCrm> fxxkCrmList = new ArrayList<>();
+            for (int i = 0; i < dataList.size(); i++) {
+                JSONObject cell = dataList.getJSONObject(i);
+                String crmName = cell.getString("display_name");
+                String crmNo = cell.getString("name");
+                Long beginTime = cell.getLong("createTime");
+
+                JSONObject ownerR = cell.getJSONObject("owner__r.nAME");
+                String managerName = ownerR.getString("name");
+
+                String customType = cell.getString("field_spOcm__c");
+                String customName = cell.getString("field_6TD92__c__r");
+                String customCounty = cell.getString("field_O0l25__c__r");
+                String customProvince = cell.getString("field_Nc2M6__c__r");
+                String customCity = cell.getString("field_270tB__c__r");
+                String customAddress = cell.getString("field_KmXg2__c");
+
+                Long examStartTime = cell.getLong("field_Fl84j__c");
+                Long examEndTime = cell.getLong("field_Gcsmt__c");
+
+                FxxkCrm fxxkCrm = new FxxkCrm();
+                fxxkCrm.setCrmName(crmName);
+                fxxkCrm.setCrmNo(crmNo);
+                fxxkCrm.setBeginTime(beginTime);
+                fxxkCrm.setManagerName(managerName);
+                fxxkCrm.setCustomType(ProductTypeEnum.CLOUD_MARK);
+                fxxkCrm.setCustomName(customName);
+                fxxkCrm.setCustomCounty(customCounty);
+                fxxkCrm.setCustomProvince(customProvince);
+                fxxkCrm.setCustomCity(customCity);
+                fxxkCrm.setCustomAddress(customAddress);
+                fxxkCrm.setExamStartTime(examStartTime);
+                fxxkCrm.setExamEndTime(examEndTime);
+                fxxkCrmList.add(fxxkCrm);
+            }
+            return fxxkCrmList;
         } catch (Exception e) {
             throw ExceptionResultEnum.ERROR.exception(e.getMessage());
         }

+ 137 - 0
sop-business/src/main/java/com/qmth/sop/business/sync/been/FxxkCrm.java

@@ -0,0 +1,137 @@
+package com.qmth.sop.business.sync.been;
+
+import com.qmth.sop.common.enums.ProductTypeEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description: 纷享销客派单信息
+ * @Author: CaoZixuan
+ * @Date: 2023-10-12
+ */
+public class FxxkCrm {
+    @ApiModelProperty("派单编号")
+    private String crmNo;
+
+    @ApiModelProperty("派单名称")
+    private String crmName;
+
+    @ApiModelProperty("派单开始时间")
+    private Long beginTime;
+
+    @ApiModelProperty("客户经理")
+    private String managerName;
+
+    @ApiModelProperty("客户类型")
+    private ProductTypeEnum customType;
+    @ApiModelProperty("客户名称")
+    private String customName;
+    @ApiModelProperty("国家")
+    private String customCounty;
+    @ApiModelProperty("省份")
+    private String customProvince;
+    @ApiModelProperty("城市")
+    private String customCity;
+    @ApiModelProperty("详细地址")
+    private String customAddress;
+
+    @ApiModelProperty("考试开始时间")
+    private Long examStartTime;
+    @ApiModelProperty("考试结束时间")
+    private Long examEndTime;
+
+    public String getCrmNo() {
+        return crmNo;
+    }
+
+    public void setCrmNo(String crmNo) {
+        this.crmNo = crmNo;
+    }
+
+    public String getCrmName() {
+        return crmName;
+    }
+
+    public void setCrmName(String crmName) {
+        this.crmName = crmName;
+    }
+
+    public Long getBeginTime() {
+        return beginTime;
+    }
+
+    public void setBeginTime(Long beginTime) {
+        this.beginTime = beginTime;
+    }
+
+    public String getManagerName() {
+        return managerName;
+    }
+
+    public void setManagerName(String managerName) {
+        this.managerName = managerName;
+    }
+
+    public ProductTypeEnum getCustomType() {
+        return customType;
+    }
+
+    public void setCustomType(ProductTypeEnum customType) {
+        this.customType = customType;
+    }
+
+    public String getCustomName() {
+        return customName;
+    }
+
+    public void setCustomName(String customName) {
+        this.customName = customName;
+    }
+
+    public String getCustomCounty() {
+        return customCounty;
+    }
+
+    public void setCustomCounty(String customCounty) {
+        this.customCounty = customCounty;
+    }
+
+    public String getCustomProvince() {
+        return customProvince;
+    }
+
+    public void setCustomProvince(String customProvince) {
+        this.customProvince = customProvince;
+    }
+
+    public String getCustomCity() {
+        return customCity;
+    }
+
+    public void setCustomCity(String customCity) {
+        this.customCity = customCity;
+    }
+
+    public String getCustomAddress() {
+        return customAddress;
+    }
+
+    public void setCustomAddress(String customAddress) {
+        this.customAddress = customAddress;
+    }
+
+    public Long getExamStartTime() {
+        return examStartTime;
+    }
+
+    public void setExamStartTime(Long examStartTime) {
+        this.examStartTime = examStartTime;
+    }
+
+    public Long getExamEndTime() {
+        return examEndTime;
+    }
+
+    public void setExamEndTime(Long examEndTime) {
+        this.examEndTime = examEndTime;
+    }
+}

+ 7 - 1
sop-business/src/main/resources/db/log/caozixuan_update_log.sql

@@ -340,4 +340,10 @@ INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort,
 INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort, create_id) VALUES ('44', 'fxxk.api.name.crm.detail', '纷享销客项目派单明细apiName', 'object_bs553__c', '1', '1', '1');
 INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort, create_id) VALUES ('45', 'fxxk.app.auth.url', '纷享销客应用级授权接口', 'https://open.fxiaoke.com/cgi/corpAccessToken/get/V2', '1', '1', '1');
 INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort, create_id) VALUES ('46', 'fxxk.user.by.mobile.url', '纷享销客根据手机号查询员工接口', 'https://open.fxiaoke.com/cgi/user/getByMobile', '1', '1', '1');
-INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort, create_id) VALUES ('47', 'fxxk.custom.query.url', '纷享销客查询自定义对象接口', 'https://openfxiaokecom/cgi/crm/custom/v2/data/query', '1', '1', '1');
+INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort, create_id) VALUES ('47', 'fxxk.custom.query.url', '纷享销客查询自定义对象接口', 'https://openfxiaokecom/cgi/crm/custom/v2/data/query', '1', '1', '1');
+
+-- 2023-10-12
+ALTER TABLE t_b_device_in_out
+    ADD COLUMN address_arr VARCHAR(100) NULL COMMENT '发往地(回显)' AFTER address;
+ALTER TABLE sys_device
+    ADD COLUMN location_arr VARCHAR(100) NULL COMMENT '当前所在地(回显)' AFTER location;

+ 65 - 0
sop-business/src/main/resources/mapper/DeviceMonitorMapper.xml

@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qmth.sop.business.mapper.DeviceMonitorMapper">
+    <select id="count" resultType="java.util.Map">
+        SELECT count(d.id) TOTAL,
+        sum(case when d.bound='OUT' then 1 else 0 end) ISOUT,
+        sum(case when d.bound='IN' and d.`status`!='BREAK_DOWN' then 1 else 0 end) ISIN,
+        sum(case when d.`status`='BREAK_DOWN' then 1 else 0 end) BREAK_DOWN
+        from sys_device d
+        <where>
+            <if test="supplierId != null and supplierId != ''">
+                and d.supplier_id = #{supplierId}
+            </if>
+            <if test="model != null and model != ''">
+                and d.model = #{model}
+            </if>
+        </where>
+    </select>
+
+
+    <select id="countByModel" resultType="java.util.Map">
+        SELECT
+        d.model MODEL,
+        count( d.id ) TOTAL,
+        sum( CASE WHEN d.bound = 'OUT' THEN 1 ELSE 0 END ) ISOUT,
+        sum( CASE WHEN d.bound='IN' and d.`status`!='BREAK_DOWN' THEN 1 ELSE 0 END ) ISIN,
+        sum( CASE WHEN d.`status` = 'BREAK_DOWN' THEN 1 ELSE 0 END ) BREAK_DOWN
+        FROM
+        sys_device d
+        <where>
+            <if test="supplierId != null and supplierId != ''">
+                and d.supplier_id = #{supplierId}
+            </if>
+        </where>
+        group by d.model
+    </select>
+    <select id="countByServiceUnit" resultType="java.util.Map">
+        SELECT
+        sum( CASE WHEN s.`status` = 'PUBLISH' AND l.id IS NOT NULL THEN l.devices ELSE 0 END ) DEVICES,
+        sum( CASE WHEN d.bound = 'OUT' THEN 1 ELSE 0 END ) OUTS
+        FROM
+        t_b_service s
+        LEFT JOIN t_b_crm c ON c.service_id = s.id
+        LEFT JOIN sys_custom cu ON cu.id = c.custom_id
+        LEFT JOIN sys_level l ON l.id = cu.level_id
+
+        left join t_b_device_in_out io on io.service_id=s.id
+        left join sys_device d on d.device_code=io.device_no
+
+    </select>
+    <select id="countByServiceUnitDetail" resultType="java.util.Map">
+        SELECT
+        s.`name` NAME,sum( l.devices ) devices ,sum(case when d.bound='OUT' then 1 else 0 end ) OUTS
+        FROM
+        t_b_service s
+        LEFT JOIN t_b_crm c ON c.service_id = s.id
+        LEFT JOIN sys_custom cu ON cu.id = c.custom_id
+        LEFT JOIN sys_level l ON l.id = cu.level_id
+
+        left join t_b_device_in_out io on io.service_id=s.id
+        left join sys_device d on d.device_code=io.device_no
+
+        GROUP BY s.`name`
+    </select>
+</mapper>

+ 9 - 3
sop-business/src/main/resources/mapper/TBDeviceInOutMapper.xml

@@ -18,8 +18,10 @@
             su.real_name AS userName,
             IFNULL(tbdio.custom_name,'--') AS customName,
             tbdio.type AS inOutType,
-            tbdio.location AS location,
+            sd.location AS location,
+            sd.location_arr AS locationArrTemp,
             tbdio.address AS address,
+            tbdio.address_arr AS addressArrTemp,
             tbdio.serial_no AS serialNo,
             tbdio.base_photo_path AS basePhotoPath,
             ss.id AS supplierId,
@@ -92,8 +94,10 @@
             su.real_name AS userName,
             IFNULL(tbdio.custom_name,'--') AS customName,
             tbdio.type AS inOutType,
-            tbdio.location AS location,
+            sd.location AS location,
+            sd.location_arr AS locationArrTemp,
             tbdio.address AS address,
+            tbdio.address_arr AS addressArrTemp,
             tbdio.serial_no AS serialNo,
             tbdio.base_photo_path AS basePhotoPath,
             ss.id AS supplierId,
@@ -159,7 +163,8 @@
             sd.status AS deviceStatus,
             sd.scan_count AS scanCount,
             sd.device_code AS deviceNo,
-            sd.location
+            sd.location,
+            sd.location_arr AS locationArrTemp
         FROM
             sys_device sd
                 LEFT JOIN
@@ -188,6 +193,7 @@
             sd.scan_count AS scanCount,
             sd.device_code AS deviceNo,
             sd.location,
+            sd.location_arr AS locationArrTemp,
             ss.name AS address
         FROM
             sys_device sd

+ 5 - 0
sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java

@@ -145,6 +145,11 @@ public class SystemConstant {
     public static final String MARK_END_TIME = "mark_end_time";//评卷结束时间
     public static final String SERVICE_FINISH_PLAN_DATE = "service_finish_plan_date";//现场服务完成撤场计划时间
 
+    public static final String DEVICE_OUT_TIME = "device_out_time";//设备出库时间
+    public static final String DEVICE_OUT_TABLE = "device_out_table";//设备出库
+    public static final String DEVICE_IN_TIME = "device_in_time";//设备入库时间
+    public static final String DEVICE_IN_TABLE = "device_in_table";//设备入库
+
     /**
      * 研究生SOP处理时限字段
      */