opt:越南富佳接口优化

This commit is contained in:
2025-11-21 11:07:14 +08:00
parent 51347d2d0e
commit c33b088a89
8 changed files with 1039 additions and 0 deletions

View File

@@ -32,6 +32,21 @@ public class EXTConstant {
*/
public final static String SEND_TASK_ACS_API = "api/wms/task";
/**
* 下发ACS获取车辆运行状态
*/
public final static String GET_CAR_STATUS_ACS_API = "api/wms/getCarStatus";
/**
* 下发ACS暂停
*/
public final static String SUSPEND_ACS_API = "api/wms/suspend";
/**
* 下发ACS暂停
*/
public final static String START_ACS_API = "api/wms/start";
/**
* ERP获取物料详情请求地址
*/

View File

@@ -22,4 +22,26 @@ public interface WmsToAcsService {
* @return AcsResponse
*/
AcsResponse renotifyAcs(List<AcsTaskDto> list);
/**
* 获取车辆运行状态
* @return AcsResponse
*/
AcsResponse getCarStatus();
/**
* 暂停
* @param carNo 车辆号
* @return AcsResponse
*/
AcsResponse suspend(String carNo);
/**
* 暂停
* @param carNo 车辆号
* @return AcsResponse
*/
AcsResponse start(String carNo);
}

View File

@@ -26,4 +26,19 @@ public class WmsToAcsServiceImpl implements WmsToAcsService {
public AcsResponse renotifyAcs(List<AcsTaskDto> list) {
return AcsUtil.notifyAcs(EXTConstant.SEND_TASK_ACS_API, list);
}
@Override
public AcsResponse getCarStatus() {
return AcsUtil.getCarStatus(EXTConstant.GET_CAR_STATUS_ACS_API);
}
@Override
public AcsResponse suspend(String carNo) {
return AcsUtil.suspendAndStart(EXTConstant.SUSPEND_ACS_API,carNo);
}
@Override
public AcsResponse start(String carNo) {
return AcsUtil.suspendAndStart(EXTConstant.START_ACS_API,carNo);
}
}

View File

@@ -70,4 +70,99 @@ public class AcsUtil {
return resultAcs;
}
/**
* 获取车辆运行状态
* @param api acs地址
* @return AcsResponse
*/
public static <T> AcsResponse getCarStatus(String api) {
log.info("下发ACS获取车辆运行状态-------------------");
// 返回参数
AcsResponse resultAcs;
// 系统参数类
SysParamServiceImpl sysParamService = SpringContextHolder.getBean(SysParamServiceImpl.class);
//判断是否连接ACS系统
Param isConnectAcs = sysParamService.findByCode(SysParamConstant.IS_CONNECT_ACS);
if (ObjectUtil.isEmpty(isConnectAcs)) {
return AcsResponse.requestError("系统参数表中:" + SysParamConstant.IS_CONNECT_ACS + "不存在");
}
if (isConnectAcs.getValue().equals(IOSConstant.IS_DELETE_NO)) {
return AcsResponse.requestOkMessage("下发成功未连接ACS系统!");
}
//ACS地址
Param acsUrlParam = sysParamService.findByCode(SysParamConstant.ACS_URL);
if (ObjectUtil.isEmpty(acsUrlParam)) {
return AcsResponse.requestError("系统参数表中:" + SysParamConstant.ACS_URL + "不存在");
}
String url = acsUrlParam.getValue() + api;
try {
String resultMsg = HttpRequest.post(url)
.body("{}")
.execute().body();
// 格式转换
JSONObject result = JSONObject.parseObject(resultMsg);
resultAcs = JSONObject.toJavaObject(result, AcsResponse.class);
log.info("下下发ACS获取车辆运行状态的输出参数为-------------------" + resultMsg);
} catch (Exception e) {
//网络不通
String msg = e.getMessage();
log.error("连接失败:{}", msg);
return AcsResponse.requestError("网络不通,操作失败!");
}
return resultAcs;
}
/**
* 获取车辆运行状态
* @param api acs地址
* @return AcsResponse
*/
public static <T> AcsResponse suspendAndStart(String api,String carNo) {
JSONObject jsonObject = new JSONObject() ;
jsonObject.put("carNo",carNo);
log.info("下发ACS车辆启听-------------------");
// 返回参数
AcsResponse resultAcs;
// 系统参数类
SysParamServiceImpl sysParamService = SpringContextHolder.getBean(SysParamServiceImpl.class);
//判断是否连接ACS系统
Param isConnectAcs = sysParamService.findByCode(SysParamConstant.IS_CONNECT_ACS);
if (ObjectUtil.isEmpty(isConnectAcs)) {
return AcsResponse.requestError("系统参数表中:" + SysParamConstant.IS_CONNECT_ACS + "不存在");
}
if (isConnectAcs.getValue().equals(IOSConstant.IS_DELETE_NO)) {
return AcsResponse.requestOkMessage("下发成功未连接ACS系统!");
}
//ACS地址
Param acsUrlParam = sysParamService.findByCode(SysParamConstant.ACS_URL);
if (ObjectUtil.isEmpty(acsUrlParam)) {
return AcsResponse.requestError("系统参数表中:" + SysParamConstant.ACS_URL + "不存在");
}
String url = acsUrlParam.getValue() + api;
try {
String resultMsg = HttpRequest.post(url)
.body(JSONObject.toJSONString(jsonObject))
.execute().body();
// 格式转换
JSONObject result = JSONObject.parseObject(resultMsg);
resultAcs = JSONObject.toJavaObject(result, AcsResponse.class);
log.info("下发ACS车辆启听的输出参数为-------------------" + resultMsg);
} catch (Exception e) {
//网络不通
String msg = e.getMessage();
log.error("连接失败:{}", msg);
return AcsResponse.requestError("网络不通,操作失败!");
}
return resultAcs;
}
}

View File

@@ -0,0 +1,74 @@
package org.nl.wms.pda_manage.bigscreen_manage.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log;
import org.nl.wms.pda_manage.bigscreen_manage.service.PdaBigScreenService;
import org.nl.wms.pda_manage.util.PdaResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;
/**
* 大屏功能
*
* @author zhengxuming
* @since 2025-06-06
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/pda/bigscreen")
@Slf4j
@SaIgnore
public class BigscreenController {
@Autowired
private PdaBigScreenService pdaBigScreenService;
@PostMapping("/getData")
@Log("大屏数据")
@SaIgnore
public ResponseEntity<PdaResponse> getData() {
PdaResponse data = pdaBigScreenService.getData();
return new ResponseEntity<>(data, HttpStatus.OK);
}
@PostMapping("/getAgvStatusByCode")
@Log("根据AGV编号获取设备状态")
@SaIgnore
public ResponseEntity<PdaResponse> getAgvStatusByCode(@RequestBody JSONObject whereJson) {
PdaResponse data = pdaBigScreenService.getAgvStatusByCode(whereJson);
return new ResponseEntity<>(data, HttpStatus.OK);
}
// @PostMapping("/suspend")
// @Log("暂停")
// public ResponseEntity<Object> suspend(@RequestBody JSONObject whereJson) {
// assertNotBlankJson(whereJson, "请求参数不能为空", "vehicle_code", "material_id","qty");
// return new ResponseEntity<>(pdaIosInService.groupPlate(whereJson),HttpStatus.OK);
// }
// @PostMapping("/start")
// @Log("启动")
// public ResponseEntity<Object> start(@RequestBody JSONObject whereJson) {
// assertNotBlankJson(whereJson, "请求参数不能为空", "vehicle_code", "material_id","qty");
// return new ResponseEntity<>(pdaIosInService.groupPlate(whereJson),HttpStatus.OK);
// }
// @PostMapping("/charge")
// @Log("去充电")
// public ResponseEntity<Object> charge(@RequestBody JSONObject whereJson) {
// assertNotBlankJson(whereJson, "请求参数不能为空", "vehicle_code", "material_id","qty");
// return new ResponseEntity<>(pdaIosInService.groupPlate(whereJson),HttpStatus.OK);
// }
}

View File

@@ -0,0 +1,45 @@
package org.nl.wms.pda_manage.bigscreen_manage.service;
import com.alibaba.fastjson.JSONObject;
import org.nl.wms.pda_manage.util.PdaResponse;
/**
* <p>
* 大屏显示 服务类
* </p>
*
* @author Liuxy
* @since 2025-06-24
*/
public interface PdaBigScreenService {
/**
* 获取大屏数据
*根据配置的仓库
* @return PdaResponse
*/
PdaResponse getData();
/**
* 获取大屏数据
*根据配置的仓库
* @return PdaResponse
*/
PdaResponse getAgvStatusByCode(JSONObject whereJson);
JSONObject getDashboardData(String storCode);
/**
* 获取报表数据
* @return 报表数据JSON对象包含统计数据和历史数据
*/
JSONObject getReportData();
/**
* 获取按周对比数据
* @return 按周对比数据JSON对象
*/
JSONObject getWeeklyData();
}

View File

@@ -0,0 +1,11 @@
package org.nl.wms.pda_manage.bigscreen_manage.service.dto;
import lombok.Data;
@Data
public class IvtAnalyse {
private String stor_code;
private String material_id;
private String material_name;
private Integer sum_qty;
}

View File

@@ -0,0 +1,762 @@
package org.nl.wms.pda_manage.bigscreen_manage.service.impl;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.nl.wms.basedata_manage.service.IStructattrService;
import org.nl.wms.basedata_manage.service.dao.Structattr;
import org.nl.wms.basedata_manage.service.dao.mapper.BsrealStorattrMapper;
import org.nl.wms.basedata_manage.service.dao.mapper.StructattrMapper;
import org.nl.wms.ext_manage.service.WmsToAcsService;
import org.nl.wms.pda_manage.bigscreen_manage.service.PdaBigScreenService;
import org.nl.wms.pda_manage.util.PdaResponse;
import org.nl.wms.sch_manage.enums.TaskStatus;
import org.nl.wms.sch_manage.service.ISchBaseTaskService;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.warehouse_manage.enums.IOSConstant;
import org.nl.wms.warehouse_manage.enums.IOSEnum;
import org.nl.wms.warehouse_manage.service.IOutBillService;
import org.nl.wms.warehouse_manage.service.dao.IOStorInv;
import org.nl.wms.warehouse_manage.service.dao.IOStorInvDis;
import org.nl.wms.warehouse_manage.service.dao.mapper.IOStorInvDisMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 大屏显示 实现类
* </p>
*
* @author Liuxy
* @since 2025-06-24
*/
@Service
public class PdaBigScreenServiceImpl implements PdaBigScreenService {
@Autowired
private IStructattrService iStructattrService;
@Resource
private IOutBillService iOutBillService;
@Resource
private BsrealStorattrMapper screenMapper;
@Resource
private IOStorInvDisMapper ioStorInvDisMapper;
@Autowired
private ISchBaseTaskService iSchBaseTaskService;
@Autowired
private StructattrMapper structattrMapper;
@Autowired
private WmsToAcsService wmsToAcsService;
@Override
public PdaResponse getData() {
// 1. 构建统计数据
JSONObject stats = new JSONObject();
JSONObject result = new JSONObject();
//1、查询任务
// 今日任务数
QueryWrapper<SchBaseTask> todayTaskWrapper = new QueryWrapper<>();
todayTaskWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status, TaskStatus.FINISHED.getCode())
.ge(SchBaseTask::getCreate_time, DateUtil.beginOfDay(DateUtil.date()))
.le(SchBaseTask::getCreate_time, DateUtil.endOfDay(DateUtil.date()));
int todayTasks = iSchBaseTaskService.count(todayTaskWrapper);
stats.put("todayTasks", todayTasks);
// 执行中任务数
QueryWrapper<SchBaseTask> executingTaskWrapper = new QueryWrapper<>();
executingTaskWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status, TaskStatus.EXECUTING.getCode());
int executingTasks = iSchBaseTaskService.count(executingTaskWrapper);
stats.put("executingTasks", executingTasks);
result.put("stats", stats);
//通过查询ACS系统获取
String agvStatus = wmsToAcsService.getCarStatus().getResponseDate();
result.put("agvStatus", JSONObject.parse(agvStatus));
return PdaResponse.requestParamOk(result);
}
@Override
public PdaResponse getAgvStatusByCode(JSONObject whereJson) {
String agvStatus = wmsToAcsService.getCarStatus().getResponseDate();
JSONObject jsonObject =getAgvStatusByNumber(agvStatus,whereJson.getInteger("device_code"));
return PdaResponse.requestParamOk(jsonObject);
}
/**
* 根据AGV编号从JSON字符串中查找并返回对应的JSONObject
*
* @param agvStatusJson 包含AGV状态的JSON字符串
* @param agvNumber 要查找的AGV编号 (例如 2)
* @return 找到的AGV状态JSONObject如果未找到则返回null
*/
public static JSONObject getAgvStatusByNumber(String agvStatusJson, int agvNumber) {
try {
// 1. 使用Fastjson将JSON字符串解析为JSONArray
JSONArray agvArray = JSON.parseArray(agvStatusJson);
// 2. 遍历JSONArray中的每个JSONObject
for (Object obj : agvArray) {
JSONObject agvObject = (JSONObject) obj;
// 3. 获取当前对象的device_code
String deviceCode = agvObject.getString("device_code");
// 增加null检查防止因缺少device_code字段而引发异常
if (deviceCode != null) {
try {
// 4. 将device_code字符串转换为整数并与目标编号比较
int currentDeviceCode = Integer.parseInt(deviceCode);
if (currentDeviceCode == agvNumber) {
// 5. 如果编号匹配则返回当前JSONObject
return agvObject;
}
} catch (NumberFormatException e) {
// 如果device_code的值无法转换为整数例如 "AGV2"
// 则打印一条警告信息并跳过这个对象
System.err.println("警告: device_code '" + deviceCode + "' 不是一个有效的数字,已跳过此条目。");
}
}
}
} catch (JSONException e) {
// 如果JSON格式不正确会抛出JSONException
e.printStackTrace();
System.err.println("解析AGV状态JSON字符串失败: " + e.getMessage());
}
// 如果遍历完所有元素都没有找到匹配的返回null
return null;
}
@Override
public JSONObject getDashboardData(String storCode) {
JSONObject item = new JSONObject();
//1.【库位总数】数据
item.put("overview", overview(storCode));
item.put("locations", locations(storCode));
return item;
}
/**
//
// * 货位使用
// *
// * @return JSONObject {
// * total_qty: 总货位数
// * use_qty: 已用货位
// * emp_qty: 空余货位
// * use_percentage: 百分比(使用货位百分比)
// * }
// */
private JSONObject overview(String storCode) {
return structattrMapper.overview(storCode);
}
private List<JSONObject> locations(String storCode) {
return structattrMapper.locations(storCode);
}
private JSONObject pointUse(String storCode) {
// 返回数据
JSONObject result = new JSONObject();
// 查询所有未删除且启用仓位
int emp_qty = iStructattrService.count(
new QueryWrapper<Structattr>().lambda()
.eq(Structattr::getIs_used, Boolean.TRUE)
.eq(Structattr::getStor_code, storCode)
.isNull(Structattr::getStoragevehicle_code));
int use_qty = iStructattrService.count(
new QueryWrapper<Structattr>().lambda()
.eq(Structattr::getIs_used, Boolean.TRUE)
.eq(Structattr::getStor_code, storCode)
.isNotNull(Structattr::getStoragevehicle_code));
int total_qty = iStructattrService.count(
new QueryWrapper<Structattr>().lambda()
.eq(Structattr::getIs_used, Boolean.TRUE)
.eq(Structattr::getStor_code, storCode));
// 总货位数
result.put("total_qty", total_qty);
// 已用货位数
result.put("use_qty", use_qty);
// 空余货位
result.put("emp_qty", emp_qty);
// 使用货位百分比
double use_percentage = NumberUtil.mul(NumberUtil.div(use_qty, total_qty==0?1:total_qty), 100);
result.put("use_percentage", NumberUtil.round(use_percentage, 2));
return result;
}
/**
* 实时库存分析
*
* @return JSONObject {
* total_qty: 总数
* data: [
* material_name: 物料名称
* ivt_qty: 库存数量
* percentage: 百分比
* ]
* }
*/
private JSONObject ivtAnalyse(String storCode) {
return null;
}
/**
* 出入库趋势
*
* @return JSONObject {
* in: [{date:日期qty:数量}]
* out: [{date:日期qty:数量}]
* }
*/
private JSONObject inAndOutTrend(String storCode) {
// 获取七天天数集合
DateTime dateTime = DateUtil.offsetDay(DateUtil.parseDate(DateUtil.today()), -6);
List<String> dateList = DateUtil.rangeToList(dateTime, DateUtil.parse(DateUtil.today()), DateField.DAY_OF_YEAR).stream()
.map(DateTime::toString)
.map(row -> row.substring(0, 10))
.collect(Collectors.toList());
// 查询七天内的出入库数据
List<IOStorInv> allIosList = iOutBillService.list(
new QueryWrapper<IOStorInv>().lambda()
.in(IOStorInv::getBiz_date, dateList)
.eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(IOStorInv::getStor_code, storCode)
.eq(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成"))
);
// 查询入库单据
List<IOStorInv> inIosList = allIosList.stream()
.filter(row -> row.getIo_type().equals(IOSEnum.IO_TYPE.code("入库")))
.collect(Collectors.toList());
// 查询出库单据
List<IOStorInv> outIosList = allIosList.stream()
.filter(row -> row.getIo_type().equals(IOSEnum.IO_TYPE.code("出库")))
.collect(Collectors.toList());
// 组织数据
List<JSONObject> inList = new ArrayList<>();
List<JSONObject> outList = new ArrayList<>();
for (String date : dateList) {
// 处理入库数量
JSONObject jsonIn = new JSONObject();
jsonIn.put("date", date);
double in_qty = inIosList.stream()
.filter(row -> row.getBiz_date().equals(date))
.map(row -> row.getTotal_qty().doubleValue())
.reduce(Double::sum).orElse(0.00);
jsonIn.put("qty", NumberUtil.round(in_qty, 2));
inList.add(jsonIn);
// 处理出库数据
JSONObject jsonOut = new JSONObject();
jsonOut.put("date", date);
double out_qty = outIosList.stream()
.filter(row -> row.getBiz_date().equals(date))
.map(row -> row.getTotal_qty().doubleValue())
.reduce(Double::sum).orElse(0.00);
jsonOut.put("qty", NumberUtil.round(out_qty, 2));
outList.add(jsonOut);
}
JSONObject result = new JSONObject();
result.put("in", inList);
result.put("out", outList);
return result;
}
/**
* 今日出入库
*
* @return JSONObject {
* in: {total_qty:总数量vehicle_qty:托盘数量}
* out: {total_qty:总数量vehicle_qty:托盘数量}
* }
*/
private JSONObject toDayInAndOut(String storCode) {
// 查询今天出入库单据
List<IOStorInv> inList = iOutBillService.list(
new QueryWrapper<IOStorInv>().lambda()
.eq(IOStorInv::getBiz_date, DateUtil.today())
.eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(IOStorInv::getStor_code, storCode)
.eq(IOStorInv::getIo_type, IOSEnum.IO_TYPE.code("入库"))
.eq(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成"))
);
// 查询今天出库单据
List<IOStorInv> outList = iOutBillService.list(
new QueryWrapper<IOStorInv>().lambda()
.eq(IOStorInv::getBiz_date, DateUtil.today())
.eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(IOStorInv::getStor_code, storCode)
.eq(IOStorInv::getIo_type, IOSEnum.IO_TYPE.code("出库"))
.eq(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成"))
);
// 入库
JSONObject jsonIn = new JSONObject();
// 总数量
double total_qty_in = inList.stream()
.map(row -> row.getTotal_qty().doubleValue())
.reduce(Double::sum).orElse(0.0);
jsonIn.put("total_qty", NumberUtil.round(total_qty_in, 2));
// 托盘数
List<IOStorInvDis> inDisList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(inList)) {
inDisList = ioStorInvDisMapper.selectList(
new QueryWrapper<IOStorInvDis>().lambda()
.in(IOStorInvDis::getIostorinv_id, inList.stream()
.map(IOStorInv::getIostorinv_id)
.collect(Collectors.toList())
)
);
}
jsonIn.put("vehicle_qty", inDisList.size());
// 出库
JSONObject jsonOut = new JSONObject();
// 总数量
double total_qty_out = outList.stream()
.map(row -> row.getTotal_qty().doubleValue())
.reduce(Double::sum).orElse(0.0);
jsonOut.put("total_qty", NumberUtil.round(total_qty_out, 2));
// 托盘数
List<IOStorInvDis> outDisList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(outList)) {
outDisList = ioStorInvDisMapper.selectList(
new QueryWrapper<IOStorInvDis>().lambda()
.in(IOStorInvDis::getIostorinv_id, outList.stream()
.map(IOStorInv::getIostorinv_id)
.collect(Collectors.toList())
)
);
}
jsonOut.put("vehicle_qty", outDisList.size());
JSONObject result = new JSONObject();
result.put("in", jsonIn);
result.put("out", jsonOut);
return result;
}
/**
* 实时任务
*
* @return List<SchBaseTask> {
* 任务实体列
* }
*/
private List<SchBaseTask> realTask(String storCode) {
List<SchBaseTask> list = iSchBaseTaskService.list(
new QueryWrapper<SchBaseTask>().lambda()
.in(SchBaseTask::getTask_status, TaskStatus.CREATE.getCode()
, TaskStatus.ISSUED.getCode(), TaskStatus.EXECUTING.getCode()
)
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
);
list.stream().forEach(item -> {
if (item.getTask_status().equals(TaskStatus.CREATE.getCode())) {
item.setTask_status(TaskStatus.CREATE.getName());
}
if (item.getTask_status().equals(TaskStatus.ISSUED.getCode())) {
item.setTask_status(TaskStatus.ISSUED.getName());
}
if (item.getTask_status().equals(TaskStatus.EXECUTING.getCode())) {
item.setTask_status(TaskStatus.EXECUTING.getName());
}
});
return list;
}
/**
* 未完成单据
*
* @return List<IOStorInv>{
* 出入库实体类
* }
*/
private List<IOStorInv> unIos(String storCode) {
List<IOStorInv> list = iOutBillService.list(
new QueryWrapper<IOStorInv>().lambda()
.eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(IOStorInv::getStor_code, storCode)
.ne(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成"))
);
list.stream().forEach(item -> {
item.setIo_type(item.getIo_type().equals(IOSEnum.IO_TYPE.code("入库"))?"入库":"出库");
if (item.getBill_status().equals(IOSEnum.BILL_STATUS.code("生成"))) {
item.setBill_status("生成");
}
if (item.getBill_status().equals(IOSEnum.BILL_STATUS.code("分配中"))) {
item.setBill_status("分配中");
}
if (item.getBill_status().equals(IOSEnum.BILL_STATUS.code("分配完"))) {
item.setBill_status("分配完");
}
item.setBill_type("dict.getLabel()");
});
return list;
}
@Override
public JSONObject getReportData() {
String storCode = "FJ"; // 默认为富佳仓库
JSONObject result = new JSONObject();
// 1. 构建统计数据
JSONObject stats = new JSONObject();
// 总任务数
QueryWrapper<SchBaseTask> taskWrapper = new QueryWrapper<>();
taskWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode())
;
stats.put("totalTasks", iSchBaseTaskService.count(taskWrapper));
// 今日任务数
QueryWrapper<SchBaseTask> todayTaskWrapper = new QueryWrapper<>();
todayTaskWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode())
.ge(SchBaseTask::getCreate_time, DateUtil.beginOfDay(DateUtil.date()))
.le(SchBaseTask::getCreate_time, DateUtil.endOfDay(DateUtil.date()));
int todayTasks = iSchBaseTaskService.count(todayTaskWrapper);
stats.put("todayTasks", todayTasks);
// 昨日任务数(计算日环比)
QueryWrapper<SchBaseTask> yesterdayTaskWrapper = new QueryWrapper<>();
yesterdayTaskWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode())
.ge(SchBaseTask::getCreate_time, DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -1)))
.le(SchBaseTask::getCreate_time, DateUtil.endOfDay(DateUtil.offsetDay(DateUtil.date(), -1)));
int yesterdayTasks = iSchBaseTaskService.count(yesterdayTaskWrapper);
double dayOnDay = yesterdayTasks > 0 ? ((double)(todayTasks - yesterdayTasks) / yesterdayTasks) * 100 : 0;
stats.put("dayOnDay", NumberUtil.round(dayOnDay, 1));
// 本月任务数
QueryWrapper<SchBaseTask> monthTaskWrapper = new QueryWrapper<>();
monthTaskWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode())
.ge(SchBaseTask::getCreate_time, DateUtil.beginOfMonth(DateUtil.date()))
.le(SchBaseTask::getCreate_time, DateUtil.endOfMonth(DateUtil.date()));
stats.put("monthTasks", iSchBaseTaskService.count(monthTaskWrapper));
// 月均任务数(简单计算:总任务数/12
// int totalTasks = iSchBaseTaskService.count(taskWrapper);
// stats.put("monthlyAvg", Math.round((double)totalTasks / 12));
// 库位数量
QueryWrapper<Structattr> structattrWrapper = new QueryWrapper<>();
structattrWrapper.lambda().eq(Structattr::getStor_code, storCode)
.eq(Structattr::getIs_used, Boolean.TRUE);
stats.put("locationCount", iStructattrService.count(structattrWrapper));
// 在库数量
int inventoryCount = iStructattrService.count(
new QueryWrapper<Structattr>().lambda()
.eq(Structattr::getStor_code, storCode)
.eq(Structattr::getIs_used, Boolean.TRUE)
.isNotNull(Structattr::getStoragevehicle_code));
stats.put("inventoryCount", inventoryCount);
// 入库数量
int inboundCount = iSchBaseTaskService.count(
new QueryWrapper<SchBaseTask>().lambda()
.eq(SchBaseTask::getConfig_code,"STInTask")
.eq(SchBaseTask::getIs_delete, Boolean.FALSE)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode()));
stats.put("inboundCount", inboundCount);
// 出库数量
int outboundCount = iSchBaseTaskService.count(
new QueryWrapper<SchBaseTask>().lambda()
.eq(SchBaseTask::getConfig_code,"STOutTask")
.eq(SchBaseTask::getIs_delete, Boolean.FALSE)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode()));
stats.put("outboundCount", outboundCount);
// 运转数量
int operationCount = iSchBaseTaskService.count(
new QueryWrapper<SchBaseTask>().lambda()
.eq(SchBaseTask::getConfig_code,"MoveTask")
.eq(SchBaseTask::getIs_delete, Boolean.FALSE)
.eq(SchBaseTask::getTask_status,TaskStatus.FINISHED.getCode()));
stats.put("operationCount", operationCount);
result.put("stats", stats);
// 2. 构建历史数据最近7天
List<JSONObject> historyList = new ArrayList<>();
DateTime dateTime = DateUtil.offsetDay(DateUtil.date(), -6);
List<String> dateList = DateUtil.rangeToList(dateTime, DateUtil.date(), DateField.DAY_OF_YEAR).stream()
.map(DateTime::toString)
.map(row -> row.substring(0, 10))
.collect(Collectors.toList());
for (String date : dateList) {
JSONObject item = new JSONObject();
item.put("date", date);
// 查询该日入库任务数
QueryWrapper<SchBaseTask> inWrapper = new QueryWrapper<>();
inWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STInTask")
.ge(SchBaseTask::getCreate_time, DateUtil.parse(date + " 00:00:00"))
.le(SchBaseTask::getCreate_time, DateUtil.parse(date + " 23:59:59"));
item.put("inbound", iSchBaseTaskService.count(inWrapper));
// 查询该日出库任务数
QueryWrapper<SchBaseTask> outWrapper = new QueryWrapper<>();
outWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STOutTask")
.ge(SchBaseTask::getCreate_time, DateUtil.parse(date + " 00:00:00"))
.le(SchBaseTask::getCreate_time, DateUtil.parse(date + " 23:59:59"));
item.put("outbound", iSchBaseTaskService.count(outWrapper));
// 其他搬运任务数
QueryWrapper<SchBaseTask> otherWrapper = new QueryWrapper<>();
otherWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.ne(SchBaseTask::getConfig_code, "STOutTask")
.ne(SchBaseTask::getConfig_code, "STInTask")
.ge(SchBaseTask::getCreate_time, DateUtil.parse(date + " 00:00:00"))
.le(SchBaseTask::getCreate_time, DateUtil.parse(date + " 23:59:59"));
item.put("other", iSchBaseTaskService.count(otherWrapper));
// 计算总数
int inbound = iSchBaseTaskService.count(inWrapper);
int outbound = iSchBaseTaskService.count(outWrapper);
int other = iSchBaseTaskService.count(otherWrapper);
item.put("total", inbound + outbound + other);
historyList.add(item);
}
result.put("historyList", historyList);
return result;
}
@Override
public JSONObject getWeeklyData() {
String storCode = "FJ"; // 默认为富佳仓库
JSONObject result = new JSONObject();
JSONObject data = new JSONObject(); // 创建data对象用于封装所有数据
// 获取当前时间和近3周的时间范围
DateTime now = DateUtil.date();
// 1. 计算周对比数据(本周和上周)
// 本周数据
DateTime weekStart = DateUtil.beginOfWeek(now, true); // 周一为起始
DateTime weekEnd = DateUtil.endOfWeek(now, true);
// 上周数据
DateTime lastWeekStart = DateUtil.beginOfWeek(DateUtil.offsetWeek(now, -1), true);
DateTime lastWeekEnd = DateUtil.endOfWeek(DateUtil.offsetWeek(now, -1), true);
// 本周任务统计
JSONObject currentWeek = new JSONObject();
QueryWrapper<SchBaseTask> currentWeekWrapper = new QueryWrapper<>();
currentWeekWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.ge(SchBaseTask::getCreate_time, weekStart)
.le(SchBaseTask::getCreate_time, weekEnd);
Integer totalTasks = iSchBaseTaskService.count(currentWeekWrapper);
currentWeek.put("totalTasks", totalTasks);
// 本周已完成任务数
QueryWrapper<SchBaseTask> currentWeekCompletedWrapper = new QueryWrapper<>();
currentWeekCompletedWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status, TaskStatus.FINISHED.getCode())
.ge(SchBaseTask::getCreate_time, weekStart)
.le(SchBaseTask::getCreate_time, weekEnd);
Integer completedTasks = iSchBaseTaskService.count(currentWeekCompletedWrapper);
currentWeek.put("completedTasks", completedTasks);
// 计算完成率
double completionRate = totalTasks > 0 ? (double) completedTasks / totalTasks * 100 : 0;
currentWeek.put("completionRate", NumberUtil.round(completionRate, 1));
// 本周入库任务数
QueryWrapper<SchBaseTask> currentWeekInWrapper = new QueryWrapper<>();
currentWeekInWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STInTask")
.ge(SchBaseTask::getCreate_time, weekStart)
.le(SchBaseTask::getCreate_time, weekEnd);
currentWeek.put("inboundTasks", iSchBaseTaskService.count(currentWeekInWrapper));
// 本周出库任务数
QueryWrapper<SchBaseTask> currentWeekOutWrapper = new QueryWrapper<>();
currentWeekOutWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STOutTask")
.ge(SchBaseTask::getCreate_time, weekStart)
.le(SchBaseTask::getCreate_time, weekEnd);
currentWeek.put("outboundTasks", iSchBaseTaskService.count(currentWeekOutWrapper));
// 上周任务统计
JSONObject lastWeek = new JSONObject();
QueryWrapper<SchBaseTask> lastWeekWrapper = new QueryWrapper<>();
lastWeekWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.ge(SchBaseTask::getCreate_time, lastWeekStart)
.le(SchBaseTask::getCreate_time, lastWeekEnd);
Integer lastTotalTasks = iSchBaseTaskService.count(lastWeekWrapper);
lastWeek.put("totalTasks", lastTotalTasks);
// 上周已完成任务数
QueryWrapper<SchBaseTask> lastWeekCompletedWrapper = new QueryWrapper<>();
lastWeekCompletedWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getTask_status, TaskStatus.FINISHED.getCode())
.ge(SchBaseTask::getCreate_time, lastWeekStart)
.le(SchBaseTask::getCreate_time, lastWeekEnd);
Integer lastCompletedTasks = iSchBaseTaskService.count(lastWeekCompletedWrapper);
lastWeek.put("completedTasks", lastCompletedTasks);
// 计算上周完成率
double lastCompletionRate = lastTotalTasks > 0 ? (double) lastCompletedTasks / lastTotalTasks * 100 : 0;
lastWeek.put("completionRate", NumberUtil.round(lastCompletionRate, 1));
// 上周入库任务数
QueryWrapper<SchBaseTask> lastWeekInWrapper = new QueryWrapper<>();
lastWeekInWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STInTask")
.ge(SchBaseTask::getCreate_time, lastWeekStart)
.le(SchBaseTask::getCreate_time, lastWeekEnd);
lastWeek.put("inboundTasks", iSchBaseTaskService.count(lastWeekInWrapper));
// 上周出库任务数
QueryWrapper<SchBaseTask> lastWeekOutWrapper = new QueryWrapper<>();
lastWeekOutWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STOutTask")
.ge(SchBaseTask::getCreate_time, lastWeekStart)
.le(SchBaseTask::getCreate_time, lastWeekEnd);
lastWeek.put("outboundTasks", iSchBaseTaskService.count(lastWeekOutWrapper));
// 计算周环比
double totalGrowthRate = lastTotalTasks > 0
? ((double)(totalTasks - lastTotalTasks) / lastTotalTasks) * 100 : 0;
double inboundGrowthRate = lastWeek.getInteger("inboundTasks") > 0
? ((double)(currentWeek.getInteger("inboundTasks") - lastWeek.getInteger("inboundTasks"))
/ lastWeek.getInteger("inboundTasks")) * 100 : 0;
double outboundGrowthRate = lastWeek.getInteger("outboundTasks") > 0
? ((double)(currentWeek.getInteger("outboundTasks") - lastWeek.getInteger("outboundTasks"))
/ lastWeek.getInteger("outboundTasks")) * 100 : 0;
JSONObject growthRates = new JSONObject();
growthRates.put("totalGrowthRate", NumberUtil.round(totalGrowthRate, 1));
growthRates.put("inboundGrowthRate", NumberUtil.round(inboundGrowthRate, 1));
growthRates.put("outboundGrowthRate", NumberUtil.round(outboundGrowthRate, 1));
growthRates.put("growthRate", NumberUtil.round(totalGrowthRate, 1)); // 为了兼容前端dashboard2.js中的直接使用
// 2. 计算近3周的数据用于图表
List<String> weeks = new ArrayList<>();
List<Integer> inboundData = new ArrayList<>();
List<Integer> outboundData = new ArrayList<>();
List<Integer> otherData = new ArrayList<>();
// 获取近3周的数据
for (int i = 2; i >= 0; i--) {
DateTime targetWeekStart = DateUtil.beginOfWeek(DateUtil.offsetWeek(now, -i), true);
DateTime targetWeekEnd = DateUtil.endOfWeek(DateUtil.offsetWeek(now, -i), true);
// 格式化周标签MM-DD-MM-DD格式
String weekLabel = targetWeekStart.toString("MM-dd") + "-" + targetWeekEnd.toString("MM-dd");
weeks.add(weekLabel);
// 该周入库任务数
QueryWrapper<SchBaseTask> weekInWrapper = new QueryWrapper<>();
weekInWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STInTask")
.ge(SchBaseTask::getCreate_time, targetWeekStart)
.le(SchBaseTask::getCreate_time, targetWeekEnd);
inboundData.add(iSchBaseTaskService.count(weekInWrapper));
// 该周出库任务数
QueryWrapper<SchBaseTask> weekOutWrapper = new QueryWrapper<>();
weekOutWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.eq(SchBaseTask::getConfig_code, "STOutTask")
.ge(SchBaseTask::getCreate_time, targetWeekStart)
.le(SchBaseTask::getCreate_time, targetWeekEnd);
outboundData.add(iSchBaseTaskService.count(weekOutWrapper));
// 该周其他任务数(非入库出库任务)
QueryWrapper<SchBaseTask> weekOtherWrapper = new QueryWrapper<>();
weekOtherWrapper.lambda()
.eq(SchBaseTask::getIs_delete, IOSConstant.IS_DELETE_NO)
.notIn(SchBaseTask::getConfig_code, Arrays.asList("STInTask", "STOutTask"))
.ge(SchBaseTask::getCreate_time, targetWeekStart)
.le(SchBaseTask::getCreate_time, targetWeekEnd);
otherData.add(iSchBaseTaskService.count(weekOtherWrapper));
}
// 构造符合前端要求的响应结构
JSONObject chartData = new JSONObject();
chartData.put("weeks", weeks);
chartData.put("inboundData", inboundData);
chartData.put("outboundData", outboundData);
chartData.put("otherData", otherData);
// 将所有数据放入data对象
data.put("thisWeek", currentWeek);
data.put("lastWeek", lastWeek);
data.put("growthRate", NumberUtil.round(totalGrowthRate, 1)); // 为了兼容前端dashboard2.js中的直接使用
data.put("growthRates", growthRates);
data.put("currentWeekDate", weekStart.toString("yyyy-MM-dd") + "" + weekEnd.toString("yyyy-MM-dd"));
data.put("lastWeekDate", lastWeekStart.toString("yyyy-MM-dd") + "" + lastWeekEnd.toString("yyyy-MM-dd"));
data.put("weeks", weeks);
data.put("inboundData", inboundData);
data.put("outboundData", outboundData);
data.put("otherData", otherData);
// 为了兼容两种前端使用方式将数据同时放在根级别和data对象中
result.put("success", true);
result.put("data", data);
result.put("thisWeek", currentWeek);
result.put("lastWeek", lastWeek);
result.put("growthRate", NumberUtil.round(totalGrowthRate, 1));
return result;
}
}