diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.java index 930b0a6..cb2168b 100644 --- a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.java +++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.java @@ -80,4 +80,10 @@ public interface MdPbStoragevehicleextMapper extends BaseMapper queryAvailableInv(@Param("params") Map whereJson); + + /** + * 根据物料分组(大屏)、按照可用数量排序 + * @return List + */ + List getBigScreenIvt(); } diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.xml b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.xml index d3ea289..6d7a80c 100644 --- a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.xml +++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/mapper/MdPbStoragevehicleextMapper.xml @@ -266,4 +266,19 @@ ORDER BY ext.insert_time + + diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/controller/BigScreenController.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/controller/BigScreenController.java new file mode 100644 index 0000000..aaa4f26 --- /dev/null +++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/controller/BigScreenController.java @@ -0,0 +1,40 @@ +package org.nl.wms.pda.bigscreen_management.controller; + + +import cn.dev33.satoken.annotation.SaIgnore; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.common.logging.annotation.Log; +import org.nl.wms.pda.bigscreen_management.service.BigScreenService; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 大屏显示 控制层 + *

+ * + * @author Liuxy + * @since 2025-06-24 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/bigScreen") +@Slf4j +public class BigScreenController { + + @Autowired + private BigScreenService bigScreenService; + + @PostMapping("/getData") + @Log("大屏数据") + @SaIgnore + public ResponseEntity getData() { + return new ResponseEntity<>(bigScreenService.getData(), HttpStatus.OK); + } + +} diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/service/BigScreenService.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/service/BigScreenService.java new file mode 100644 index 0000000..1843a48 --- /dev/null +++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/service/BigScreenService.java @@ -0,0 +1,21 @@ +package org.nl.wms.pda.bigscreen_management.service; + +import org.nl.wms.pda.util.PdaResponse; + +/** + *

+ * 大屏显示 服务类 + *

+ * + * @author Liuxy + * @since 2025-06-24 + */ +public interface BigScreenService { + + /** + * 获取大屏数据 + * + * @return PdaResponse + */ + PdaResponse getData(); +} diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/service/impl/BigScreenServiceImpl.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/service/impl/BigScreenServiceImpl.java new file mode 100644 index 0000000..c3606e9 --- /dev/null +++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/pda/bigscreen_management/service/impl/BigScreenServiceImpl.java @@ -0,0 +1,392 @@ +package org.nl.wms.pda.bigscreen_management.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.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.nl.system.service.dict.dao.Dict; +import org.nl.system.service.dict.dao.mapper.SysDictMapper; +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.MdPbStoragevehicleextMapper; +import org.nl.wms.pda.bigscreen_management.service.BigScreenService; +import org.nl.wms.pda.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_management.enums.IOSConstant; +import org.nl.wms.warehouse_management.enums.IOSEnum; +import org.nl.wms.warehouse_management.service.IOutBillService; +import org.nl.wms.warehouse_management.service.dao.IOStorInv; +import org.nl.wms.warehouse_management.service.dao.IOStorInvDis; +import org.nl.wms.warehouse_management.service.dao.mapper.IOStorInvDisMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 大屏显示 实现类 + *

+ * + * @author Liuxy + * @since 2025-06-24 + */ +@Service +public class BigScreenServiceImpl implements BigScreenService { + + /** + * 仓位服务 + */ + @Autowired + private IStructattrService iStructattrService; + + /** + * 载具扩展属性mapper服务 + */ + @Autowired + private MdPbStoragevehicleextMapper mdPbStoragevehicleextMapper; + + /** + * 出入库服务 + */ + @Autowired + private IOutBillService iOutBillService; + + /** + * 分配明细mapper服务 + */ + @Autowired + private IOStorInvDisMapper ioStorInvDisMapper; + + /** + * 任务服务 + */ + @Autowired + private ISchBaseTaskService iSchBaseTaskService; + + /** + * 字典服务 + */ + @Autowired + private SysDictMapper sysDictMapper; + + @Override + public PdaResponse getData() { + JSONObject result = new JSONObject(); + //1.【货位使用】数据 + result.put("pointUse", pointUse()); + //2.【实时库存分析】数据 + result.put("ivtAnalyse", ivtAnalyse()); + //3.【出入库趋势】数据 + result.put("inAndOutTrend", inAndOutTrend()); + //4.【今日出入库】数据 + result.put("toDayInAndOut", toDayInAndOut()); + //5.【今日出入库】数据 + result.put("realTask", realTask()); + //6.【未完成单据】数据 + result.put("unIos", unIos()); + return PdaResponse.requestParamOk(result); + } + + /** + * 货位使用 + * + * @return JSONObject { + * total_qty: 总货位数 + * use_qty: 已用货位 + * emp_qty: 空余货位 + * use_percentage: 百分比(使用货位百分比) + * } + */ + private JSONObject pointUse() { + // 返回数据 + JSONObject result = new JSONObject(); + // 查询所有未删除且启用仓位 + List attrList = iStructattrService.list( + new QueryWrapper().lambda() + .eq(Structattr::getIs_used, IOSConstant.IS_DELETE_YES) + .eq(Structattr::getIs_delete, IOSConstant.IS_DELETE_NO) + ); + // 总货位数 + result.put("total_qty", attrList.size()); + // 已用货位数 + long use_qty = attrList.stream() + .filter(row -> ObjectUtil.isNotEmpty(row.getStoragevehicle_code())) + .count(); + result.put("use_qty", use_qty); + // 空余货位 + result.put("emp_qty", attrList.size() - use_qty); + // 使用货位百分比 + double use_percentage = NumberUtil.mul(NumberUtil.div(use_qty, attrList.size()), 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() { + // 返回数据 + JSONObject result = new JSONObject(); + // 查询所有库存 + List ivtList = mdPbStoragevehicleextMapper.getBigScreenIvt(); + // 总数 + double total_qty = ivtList.stream() + .map(row -> row.getDoubleValue("canuse_qty")) + .reduce(Double::sum).orElse(0.0); + result.put("total_qty", NumberUtil.round(total_qty, 2)); + + // 查询排名前五的物料库存 + List topFiveList; + List otherList = null; + if (ivtList.size() < 5) { + topFiveList = ivtList; + } else { + topFiveList = ivtList.subList(0, 5); + otherList = ivtList.subList(5, ivtList.size()); + } + // 组织数据(物料前五) + for (JSONObject json : topFiveList) { + // 库存数量 + json.put("ivt_qty", NumberUtil.round(json.getDoubleValue("canuse_qty"), 2)); + // 百分比 + double percentage = NumberUtil.mul(NumberUtil.div(json.getDoubleValue("canuse_qty"), total_qty), 100); + json.put("percentage", NumberUtil.round(percentage, 2)); + } + + // 计算其他物料 + if (ObjectUtil.isNotEmpty(otherList)) { + JSONObject jsonOther = new JSONObject(); + jsonOther.put("material_name", "其他"); + double ivt_qty = otherList.stream() + .map(row -> row.getDoubleValue("canuse_qty")) + .reduce(Double::sum).orElse(0.0); + jsonOther.put("ivt_qty", NumberUtil.round(ivt_qty, 2)); + // 百分比 + double percentage = NumberUtil.mul(NumberUtil.div(ivt_qty, total_qty), 100); + jsonOther.put("percentage", NumberUtil.round(percentage, 2)); + topFiveList.add(jsonOther); + } + + result.put("data", topFiveList); + return result; + } + + /** + * 出入库趋势 + * + * @return JSONObject { + * in: [{date:日期,qty:数量}] + * out: [{date:日期,qty:数量}] + * } + */ + private JSONObject inAndOutTrend() { + // 获取七天天数集合 + DateTime dateTime = DateUtil.offsetDay(DateUtil.parseDate(DateUtil.today()), -6); + List 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 allIosList = iOutBillService.list( + new QueryWrapper().lambda() + .in(IOStorInv::getBiz_date, dateList) + .eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO) + .eq(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成")) + ); + + // 查询入库单据 + List inIosList = allIosList.stream() + .filter(row -> row.getIo_type().equals(IOSEnum.IO_TYPE.code("入库"))) + .collect(Collectors.toList()); + // 查询出库单据 + List outIosList = allIosList.stream() + .filter(row -> row.getIo_type().equals(IOSEnum.IO_TYPE.code("出库"))) + .collect(Collectors.toList()); + // 组织数据 + List inList = new ArrayList<>(); + List 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() { + // 查询今天出入库单据 + List inList = iOutBillService.list( + new QueryWrapper().lambda() + .eq(IOStorInv::getBiz_date, DateUtil.today()) + .eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO) + .eq(IOStorInv::getIo_type, IOSEnum.IO_TYPE.code("入库")) + .eq(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成")) + ); + // 查询今天出库单据 + List outList = iOutBillService.list( + new QueryWrapper().lambda() + .eq(IOStorInv::getBiz_date, DateUtil.today()) + .eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO) + .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 inDisList = new ArrayList<>(); + if (ObjectUtil.isNotEmpty(inList)) { + inDisList = ioStorInvDisMapper.selectList( + new QueryWrapper().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 outDisList = new ArrayList<>(); + if (ObjectUtil.isNotEmpty(outList)) { + outDisList = ioStorInvDisMapper.selectList( + new QueryWrapper().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 { + * 任务实体列 + * } + */ + private List realTask() { + List list = iSchBaseTaskService.list( + new QueryWrapper().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{ + * 出入库实体类 + * } + */ + private List unIos() { + List dicts = sysDictMapper.selectList( + new QueryWrapper().lambda() + .in(Dict::getCode, "ST_INV_IN_TYPE", "ST_INV_OUT_TYPE") + ); + + List list = iOutBillService.list( + new QueryWrapper().lambda() + .eq(IOStorInv::getIs_delete, IOSConstant.IS_DELETE_NO) + .ne(IOStorInv::getBill_status, IOSEnum.BILL_STATUS.code("完成")) + ); + list.stream().forEach(item -> { + item.setIo_type(item.getIo_type().equals(IOSEnum.IO_TYPE.code("入库")) ? IOSConstant.IOS_IO_TYPE_IN : IOSConstant.IOS_IO_TYPE_OUT); + 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("分配完"); + } + Dict dict = dicts.stream() + .filter(row -> row.getValue().equals(item.getBill_type())) + .findFirst().orElse(null); + item.setBill_type(dict.getLabel()); + }); + return list; + } +} diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSConstant.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSConstant.java index ac0ff53..664fcd4 100644 --- a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSConstant.java +++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSConstant.java @@ -17,6 +17,15 @@ public class IOSConstant { */ public final static String IS_DELETE_YES = "1"; + /** + * 出入库 入库 + */ + public final static String IOS_IO_TYPE_IN = "入库"; + /** + * 出入库 出库 + */ + public final static String IOS_IO_TYPE_OUT = "出库"; + /** * 创建方式 */