diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/WorkHourReportVo.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/WorkHourReportVo.java new file mode 100644 index 00000000..18952535 --- /dev/null +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/WorkHourReportVo.java @@ -0,0 +1,90 @@ +package org.dromara.mes.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 报工工时数据报表VO + * + * @author Yinq + * @date 2025-01-17 + */ +@Data +@ExcelIgnoreUnannotated +public class WorkHourReportVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 派工单 + */ + @ExcelProperty(value = "派工单") + private String dispatchCode; + + /** + * 班组 + */ + @ExcelProperty(value = "班组") + private String teamName; + + /** + * 工位 + */ + @ExcelProperty(value = "工位") + private String stationName; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 工序名称 + */ + @ExcelProperty(value = "工序名称") + private String processName; + + /** + * 报工数量 + */ + @ExcelProperty(value = "报工数量") + private BigDecimal completeAmount; + + /** + * 标准工时(h) + */ + @ExcelProperty(value = "标准工时(h)") + private BigDecimal standardWorkHour; + + /** + * 报工工时(h) + */ + @ExcelProperty(value = "报工工时(h)") + private BigDecimal reportWorkHour; + + /** + * 生产效率 + */ + @ExcelProperty(value = "生产效率") + private BigDecimal productionEfficiency; + + /** + * 派工单状态 + */ + @ExcelProperty(value = "派工单状态") + private String planStatus; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsReportController.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsReportController.java new file mode 100644 index 00000000..fe68601e --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsReportController.java @@ -0,0 +1,187 @@ +package org.dromara.wms.controller; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.web.core.BaseController; +import org.dromara.wms.domain.vo.*; +import org.dromara.wms.service.IWmsReportService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * WMS报表管理 + * 前端访问路由地址为:/wms/report + * + * @author hwmom + * @date 2025-01-20 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/report") +public class WmsReportController extends BaseController { + + private final IWmsReportService wmsReportService; + + /** + * 查询退库原因分析报表 + */ + //@SaCheckPermission("wms:report:returnReason") + @GetMapping("/returnReasonAnalysis") + public R> getReturnReasonAnalysis( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId) { + List list = wmsReportService.getReturnReasonAnalysis(tenantId, materialCategoryId); + return R.ok(list); + } + + /** + * 导出退库原因分析报表 + */ + //@SaCheckPermission("wms:report:returnReason") + @Log(title = "退库原因分析报表", businessType = BusinessType.EXPORT) + @PostMapping("/returnReasonAnalysis/export") + public void exportReturnReasonAnalysis( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId, + HttpServletResponse response) { + List list = wmsReportService.getReturnReasonAnalysis(tenantId, materialCategoryId); + ExcelUtil.exportExcel(list, "退库原因分析报表", WmsReturnReasonAnalysisVo.class, response); + } + + /** + * 查询库存变动趋势分析报表 + */ + //@SaCheckPermission("wms:report:inventoryTrend") + @GetMapping("/inventoryTrendAnalysis") + public R> getInventoryTrendAnalysis( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId) { + List list = wmsReportService.getInventoryTrendAnalysis(tenantId, materialCategoryId); + return R.ok(list); + } + + /** + * 导出库存变动趋势分析报表 + */ + //@SaCheckPermission("wms:report:inventoryTrend") + @Log(title = "库存变动趋势分析报表", businessType = BusinessType.EXPORT) + @PostMapping("/inventoryTrendAnalysis/export") + public void exportInventoryTrendAnalysis( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId, + HttpServletResponse response) { + List list = wmsReportService.getInventoryTrendAnalysis(tenantId, materialCategoryId); + ExcelUtil.exportExcel(list, "库存变动趋势分析报表", WmsInventoryTrendAnalysisVo.class, response); + } + + /** + * 查询安全库存预警报表 + */ + //@SaCheckPermission("wms:report:safetyStock") + @GetMapping("/safetyStockAlert") + public R> getSafetyStockAlert( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId) { + List list = wmsReportService.getSafetyStockAlert(tenantId, materialCategoryId); + return R.ok(list); + } + + /** + * 导出安全库存预警报表 + */ + //@SaCheckPermission("wms:report:safetyStock") + @Log(title = "安全库存预警报表", businessType = BusinessType.EXPORT) + @PostMapping("/safetyStockAlert/export") + public void exportSafetyStockAlert( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId, + HttpServletResponse response) { + List list = wmsReportService.getSafetyStockAlert(tenantId, materialCategoryId); + ExcelUtil.exportExcel(list, "安全库存预警报表", WmsSafetyStockAlertVo.class, response); + } + + /** + * 查询呆滞料库存报表 + */ + //@SaCheckPermission("wms:report:stagnantInventory") + @GetMapping("/stagnantInventory") + public R> getStagnantInventory( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId) { + List list = wmsReportService.getStagnantInventory(tenantId, materialCategoryId); + return R.ok(list); + } + + /** + * 导出呆滞料库存报表 + */ + //@SaCheckPermission("wms:report:stagnantInventory") + @Log(title = "呆滞料库存报表", businessType = BusinessType.EXPORT) + @PostMapping("/stagnantInventory/export") + public void exportStagnantInventory( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId, + HttpServletResponse response) { + List list = wmsReportService.getStagnantInventory(tenantId, materialCategoryId); + ExcelUtil.exportExcel(list, "呆滞料库存报表", WmsStagnantInventoryVo.class, response); + } + + /** + * 查询库存差异报表 + */ + //@SaCheckPermission("wms:report:inventoryDifference") + @GetMapping("/inventoryDifference") + public R> getInventoryDifference( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId) { + List list = wmsReportService.getInventoryDifference(tenantId, materialCategoryId); + return R.ok(list); + } + + /** + * 导出库存差异报表 + */ + //@SaCheckPermission("wms:report:inventoryDifference") + @Log(title = "库存差异报表", businessType = BusinessType.EXPORT) + @PostMapping("/inventoryDifference/export") + public void exportInventoryDifference( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId, + HttpServletResponse response) { + List list = wmsReportService.getInventoryDifference(tenantId, materialCategoryId); + ExcelUtil.exportExcel(list, "库存差异报表", WmsInventoryDifferenceVo.class, response); + } + + /** + * 查询库存周转报表 + */ + //@SaCheckPermission("wms:report:inventoryTurnover") + @GetMapping("/inventoryTurnover") + public R> getInventoryTurnover( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId) { + List list = wmsReportService.getInventoryTurnover(tenantId, materialCategoryId); + return R.ok(list); + } + + /** + * 导出库存周转报表 + */ + //@SaCheckPermission("wms:report:inventoryTurnover") + @Log(title = "库存周转报表", businessType = BusinessType.EXPORT) + @PostMapping("/inventoryTurnover/export") + public void exportInventoryTurnover( + @RequestParam(required = false) String tenantId, + @RequestParam(required = false) Long materialCategoryId, + HttpServletResponse response) { + List list = wmsReportService.getInventoryTurnover(tenantId, materialCategoryId); + ExcelUtil.exportExcel(list, "库存周转报表", WmsInventoryTurnoverVo.class, response); + } +} diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryDifferenceVo.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryDifferenceVo.java new file mode 100644 index 00000000..6a1f31d4 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryDifferenceVo.java @@ -0,0 +1,126 @@ +package org.dromara.wms.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 库存差异报表视图对象 wms_inventory_difference + * + * @author hwmom + * @date 2025-01-20 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsInventoryDifferenceVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 盘点单号 + */ + @ExcelProperty(value = "盘点单号") + private String checkCode; + + /** + * 盘点类型 + */ + @ExcelProperty(value = "盘点类型") + private String checkType; + + /** + * 仓库ID + */ + @ExcelProperty(value = "仓库ID") + private Long warehouseId; + + /** + * 仓库名称 + */ + @ExcelProperty(value = "仓库名称") + private String warehouseName; + + /** + * 物料ID + */ + @ExcelProperty(value = "物料ID") + private Long materialId; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 物料大类 + */ + @ExcelProperty(value = "物料大类") + private String materialCategoryName; + + /** + * 账面数量 + */ + @ExcelProperty(value = "账面数量") + private BigDecimal bookInventoryQty; + + /** + * 实际盘点数量 + */ + @ExcelProperty(value = "实际盘点数量") + private BigDecimal actualInventoryQty; + + /** + * 差异量 + */ + @ExcelProperty(value = "差异量") + private BigDecimal differenceQty; + + /** + * 差异类型 + */ + @ExcelProperty(value = "差异类型") + private String differenceType; + + /** + * 差异率 + */ + @ExcelProperty(value = "差异率(%)") + private BigDecimal differenceRate; + + /** + * 差异等级 + */ + @ExcelProperty(value = "差异等级") + private String differenceLevel; + + /** + * 盘点时间 + */ + @ExcelProperty(value = "盘点时间") + private Date checkTime; + + /** + * 盘点人员 + */ + @ExcelProperty(value = "盘点人员") + private String checkBy; +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryTrendAnalysisVo.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryTrendAnalysisVo.java new file mode 100644 index 00000000..2c86d083 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryTrendAnalysisVo.java @@ -0,0 +1,95 @@ +package org.dromara.wms.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 库存变动趋势分析报表视图对象 wms_inventory_trend_analysis + * + * @author hwmom + * @date 2025-01-20 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsInventoryTrendAnalysisVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 物料ID + */ + @ExcelProperty(value = "物料ID") + private Long materialId; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 物料大类 + */ + @ExcelProperty(value = "物料大类") + private String materialCategoryName; + + /** + * 统计月份 + */ + @ExcelProperty(value = "统计月份") + private String statisticsMonth; + + /** + * 统计周 + */ + @ExcelProperty(value = "统计周") + private Integer statisticsWeek; + + /** + * 当前库存数量 + */ + @ExcelProperty(value = "当前库存数量") + private BigDecimal currentInventoryQty; + + /** + * 本周入库数量 + */ + @ExcelProperty(value = "本周入库数量") + private BigDecimal weekInstockQty; + + /** + * 本周出库数量 + */ + @ExcelProperty(value = "本周出库数量") + private BigDecimal weekOutstockQty; + + /** + * 上周结存数量 + */ + @ExcelProperty(value = "上周结存数量") + private BigDecimal lastWeekInventoryQty; + + /** + * 关键节点标注 + */ + @ExcelProperty(value = "关键节点标注") + private String keyNodeMark; +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryTurnoverVo.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryTurnoverVo.java new file mode 100644 index 00000000..32003e04 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsInventoryTurnoverVo.java @@ -0,0 +1,95 @@ +package org.dromara.wms.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 库存周转报表视图对象 wms_inventory_turnover + * + * @author hwmom + * @date 2025-01-20 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsInventoryTurnoverVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 物料ID + */ + @ExcelProperty(value = "物料ID") + private Long materialId; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 物料大类 + */ + @ExcelProperty(value = "物料大类") + private String materialCategoryName; + + /** + * 统计月份 + */ + @ExcelProperty(value = "统计月份") + private String statisticsMonth; + + /** + * 月初库存数量 + */ + @ExcelProperty(value = "月初库存数量") + private BigDecimal beginInventoryQty; + + /** + * 月末库存数量 + */ + @ExcelProperty(value = "月末库存数量") + private BigDecimal endInventoryQty; + + /** + * 月出库数量 + */ + @ExcelProperty(value = "月出库数量") + private BigDecimal monthOutstockQty; + + /** + * 库存周转率 + */ + @ExcelProperty(value = "库存周转率(%)") + private BigDecimal inventoryTurnoverRate; + + /** + * 简化周转率 + */ + @ExcelProperty(value = "简化周转率(%)") + private BigDecimal simpleTurnoverRate; + + /** + * 周转评价 + */ + @ExcelProperty(value = "周转评价") + private String turnoverEvaluation; +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsReturnReasonAnalysisVo.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsReturnReasonAnalysisVo.java new file mode 100644 index 00000000..d49fb8d8 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsReturnReasonAnalysisVo.java @@ -0,0 +1,77 @@ +package org.dromara.wms.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 退库原因分析报表视图对象 wms_return_reason_analysis + * + * @author hwmom + * @date 2025-01-20 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsReturnReasonAnalysisVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 退库原因分类 + */ + @ExcelProperty(value = "退库原因分类") + private String returnReasonCategory; + + /** + * 退库单数 + */ + @ExcelProperty(value = "退库单数") + private Long returnOrderCount; + + /** + * 退库总数量 + */ + @ExcelProperty(value = "退库总数量") + private BigDecimal totalReturnAmount; + + /** + * 退库单数占比 + */ + @ExcelProperty(value = "退库单数占比(%)") + private BigDecimal orderCountRatio; + + /** + * 退库数量占比 + */ + @ExcelProperty(value = "退库数量占比(%)") + private BigDecimal amountRatio; + + /** + * 主要物料名称 + */ + @ExcelProperty(value = "主要物料名称") + private String materialName; + + /** + * 物料大类 + */ + @ExcelProperty(value = "物料大类") + private String materialCategoryName; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + private String materialCode; +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsSafetyStockAlertVo.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsSafetyStockAlertVo.java new file mode 100644 index 00000000..cb0fc67b --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsSafetyStockAlertVo.java @@ -0,0 +1,96 @@ +package org.dromara.wms.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 安全库存预警报表视图对象 wms_safety_stock_alert + * + * @author hwmom + * @date 2025-01-20 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsSafetyStockAlertVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 物料ID + */ + @ExcelProperty(value = "物料ID") + private Long materialId; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 物料大类 + */ + @ExcelProperty(value = "物料大类") + private String materialCategoryName; + + /** + * 当前库存数量 + */ + @ExcelProperty(value = "当前库存数量") + private BigDecimal currentInventoryQty; + + /** + * 安全库存值 + */ + @ExcelProperty(value = "安全库存值") + private BigDecimal safeStockAmount; + + /** + * 最小库存值 + */ + @ExcelProperty(value = "最小库存值") + private BigDecimal minStockAmount; + + /** + * 最大库存值 + */ + @ExcelProperty(value = "最大库存值") + private BigDecimal maxStockAmount; + + /** + * 预警状态 + */ + @ExcelProperty(value = "预警状态") + private String alertStatus; + + /** + * 差异量 + */ + @ExcelProperty(value = "差异量") + private BigDecimal differenceAmount; + + /** + * 最后更新时间 + */ + @ExcelProperty(value = "最后更新时间") + private Date lastUpdateTime; +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsStagnantInventoryVo.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsStagnantInventoryVo.java new file mode 100644 index 00000000..f2cb1704 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/vo/WmsStagnantInventoryVo.java @@ -0,0 +1,102 @@ +package org.dromara.wms.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 呆滞料库存报表视图对象 wms_stagnant_inventory + * + * @author hwmom + * @date 2025-01-20 + */ +@Data +@ExcelIgnoreUnannotated +public class WmsStagnantInventoryVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户编号 + */ + @ExcelProperty(value = "租户编号") + private String tenantId; + + /** + * 物料ID + */ + @ExcelProperty(value = "物料ID") + private Long materialId; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 物料大类 + */ + @ExcelProperty(value = "物料大类") + private String materialCategoryName; + + /** + * 呆滞库存数量 + */ + @ExcelProperty(value = "呆滞库存数量") + private BigDecimal stagnantInventoryQty; + + /** + * 计量单位 + */ + @ExcelProperty(value = "计量单位") + private String materialUnit; + + /** + * 最后出库时间 + */ + @ExcelProperty(value = "最后出库时间") + private String lastOutstockTime; + + /** + * 呆滞天数 + */ + @ExcelProperty(value = "呆滞天数") + private Integer stagnantDays; + + /** + * 呆滞原因 + */ + @ExcelProperty(value = "呆滞原因") + private String stagnantReason; + + /** + * 物料规格 + */ + @ExcelProperty(value = "物料规格") + private String materialSpec; + + /** + * 所在仓库 + */ + @ExcelProperty(value = "所在仓库") + private String warehouseName; + + /** + * 最后活动时间 + */ + @ExcelProperty(value = "最后活动时间") + private String lastActivityTime; +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/mapper/WmsReportMapper.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/mapper/WmsReportMapper.java new file mode 100644 index 00000000..282d3db6 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/mapper/WmsReportMapper.java @@ -0,0 +1,341 @@ +package org.dromara.wms.mapper; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.dromara.wms.domain.vo.*; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * WMS报表Mapper接口 + * + * @author hwmom + * @date 2025-01-20 + */ +@Repository +@Mapper +public interface WmsReportMapper { + + /** + * 查询退库原因分析报表 + */ + @Select("SELECT " + + " ro.tenant_id AS tenantId, " + + " CASE " + + " WHEN ro.return_reason LIKE '%质量%' OR ro.return_reason LIKE '%不合格%' THEN '质量问题' " + + " WHEN ro.return_reason LIKE '%订单%' OR ro.return_reason LIKE '%变更%' THEN '订单变更' " + + " WHEN ro.return_reason LIKE '%损坏%' OR ro.return_reason LIKE '%破损%' THEN '物料损坏' " + + " WHEN ro.return_reason LIKE '%过期%' OR ro.return_reason LIKE '%超期%' THEN '过期物料' " + + " ELSE '其他原因' " + + " END AS returnReasonCategory, " + + " COUNT(*) AS returnOrderCount, " + + " SUM(ro.return_amount) AS totalReturnAmount, " + + " CAST(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM wms_return_order WHERE tenant_id = ro.tenant_id AND order_status = '1') AS DECIMAL(10,2)) AS orderCountRatio, " + + " CAST(SUM(ro.return_amount) * 100.0 / (SELECT SUM(return_amount) FROM wms_return_order WHERE tenant_id = ro.tenant_id AND order_status = '1') AS DECIMAL(10,2)) AS amountRatio, " + + " mi.material_name AS materialName, " + + " mc.material_category_name AS materialCategoryName, " + + " mi.material_code AS materialCode " + + "FROM wms_return_order ro " + + "INNER JOIN base_material_info_copy1 mi ON ro.material_id = mi.material_id " + + "INNER JOIN base_material_category mc ON mi.material_category_id = mc.material_category_id " + + "WHERE ro.order_status = '1' " + + " AND (#{tenantId} IS NULL OR ro.tenant_id = #{tenantId}) " + + " AND (#{materialCategoryId} IS NULL OR mc.material_category_id = #{materialCategoryId}) " + + "GROUP BY ro.tenant_id, " + + " CASE " + + " WHEN ro.return_reason LIKE '%质量%' OR ro.return_reason LIKE '%不合格%' THEN '质量问题' " + + " WHEN ro.return_reason LIKE '%订单%' OR ro.return_reason LIKE '%变更%' THEN '订单变更' " + + " WHEN ro.return_reason LIKE '%损坏%' OR ro.return_reason LIKE '%破损%' THEN '物料损坏' " + + " WHEN ro.return_reason LIKE '%过期%' OR ro.return_reason LIKE '%超期%' THEN '过期物料' " + + " ELSE '其他原因' " + + " END, " + + " mi.material_name, " + + " mc.material_category_name, " + + " mi.material_code " + + "ORDER BY ro.tenant_id, totalReturnAmount DESC") + List selectReturnReasonAnalysis(@Param("tenantId") String tenantId, + @Param("materialCategoryId") Long materialCategoryId); + + /** + * 查询库存变动趋势分析报表 + */ + @Select("SELECT " + + " inv.tenant_id AS tenantId, " + + " inv.material_id AS materialId, " + + " mi.material_code AS materialCode, " + + " mi.material_name AS materialName, " + + " mc.material_category_name AS materialCategoryName, " + + " CONVERT(VARCHAR(7), GETDATE(), 126) AS statisticsMonth, " + + " DATEPART(WEEK, GETDATE()) AS statisticsWeek, " + + " SUM(inv.inventory_qty) AS currentInventoryQty, " + + " ISNULL(instock_data.weekInstockQty, 0) AS weekInstockQty, " + + " ISNULL(outstock_data.weekOutstockQty, 0) AS weekOutstockQty, " + + " (SUM(inv.inventory_qty) + ISNULL(outstock_data.weekOutstockQty, 0) - ISNULL(instock_data.weekInstockQty, 0)) AS lastWeekInventoryQty, " + + " CASE " + + " WHEN ISNULL(instock_data.weekInstockQty, 0) > 1000 THEN '大额入库' " + + " WHEN ISNULL(outstock_data.weekOutstockQty, 0) > 1000 THEN '大额出库' " + + " ELSE '正常变动' " + + " END AS keyNodeMark " + + "FROM wms_inventory inv " + + "INNER JOIN base_material_info_copy1 mi ON inv.material_id = mi.material_id " + + "INNER JOIN base_material_category mc ON mi.material_category_id = mc.material_category_id " + + "LEFT JOIN ( " + + " SELECT material_id, tenant_id, SUM(instock_qty) AS weekInstockQty " + + " FROM wms_instock_record " + + " WHERE create_time >= DATEADD(DAY, -7, GETDATE()) " + + " GROUP BY material_id, tenant_id " + + ") instock_data ON inv.material_id = instock_data.material_id AND inv.tenant_id = instock_data.tenant_id " + + "LEFT JOIN ( " + + " SELECT material_id, tenant_id, SUM(outstock_qty) AS weekOutstockQty " + + " FROM wms_outstock_record " + + " WHERE create_time >= DATEADD(DAY, -7, GETDATE()) " + + " GROUP BY material_id, tenant_id " + + ") outstock_data ON inv.material_id = outstock_data.material_id AND inv.tenant_id = outstock_data.tenant_id " + + "WHERE inv.inventory_status = '1' " + + " AND (#{tenantId} IS NULL OR inv.tenant_id = #{tenantId}) " + + " AND (#{materialCategoryId} IS NULL OR mc.material_category_id = #{materialCategoryId}) " + + "GROUP BY inv.tenant_id, inv.material_id, mi.material_code, mi.material_name, mc.material_category_name, " + + " instock_data.weekInstockQty, outstock_data.weekOutstockQty " + + "ORDER BY inv.tenant_id, currentInventoryQty DESC") + List selectInventoryTrendAnalysis(@Param("tenantId") String tenantId, + @Param("materialCategoryId") Long materialCategoryId); + + /** + * 查询安全库存预警报表 + */ + @Select("SELECT " + + " inv.tenant_id AS tenantId, " + + " inv.material_id AS materialId, " + + " mi.material_code AS materialCode, " + + " mi.material_name AS materialName, " + + " mc.material_category_name AS materialCategoryName, " + + " SUM(inv.inventory_qty) AS currentInventoryQty, " + + " mi.safe_stock_amount AS safeStockAmount, " + + " mi.min_stock_amount AS minStockAmount, " + + " mi.max_stock_amount AS maxStockAmount, " + + " CASE " + + " WHEN SUM(inv.inventory_qty) < mi.min_stock_amount THEN '短缺预警' " + + " WHEN SUM(inv.inventory_qty) > mi.max_stock_amount THEN '积压预警' " + + " WHEN SUM(inv.inventory_qty) < mi.safe_stock_amount THEN '低于安全库存' " + + " ELSE '正常' " + + " END AS alertStatus, " + + " CASE " + + " WHEN SUM(inv.inventory_qty) < mi.min_stock_amount THEN mi.min_stock_amount - SUM(inv.inventory_qty) " + + " WHEN SUM(inv.inventory_qty) > mi.max_stock_amount THEN SUM(inv.inventory_qty) - mi.max_stock_amount " + + " WHEN SUM(inv.inventory_qty) < mi.safe_stock_amount THEN mi.safe_stock_amount - SUM(inv.inventory_qty) " + + " ELSE 0 " + + " END AS differenceAmount, " + + " inv.update_time AS lastUpdateTime " + + "FROM wms_inventory inv " + + "INNER JOIN base_material_info_copy1 mi ON inv.material_id = mi.material_id " + + "INNER JOIN base_material_category mc ON mi.material_category_id = mc.material_category_id " + + "WHERE inv.inventory_status = '1' " + + " AND mi.active_flag = '1' " + + " AND (mi.safe_stock_amount IS NOT NULL OR mi.min_stock_amount IS NOT NULL OR mi.max_stock_amount IS NOT NULL) " + + " AND (#{tenantId} IS NULL OR inv.tenant_id = #{tenantId}) " + + " AND (#{materialCategoryId} IS NULL OR mc.material_category_id = #{materialCategoryId}) " + + "GROUP BY inv.tenant_id, inv.material_id, mi.material_code, mi.material_name, mc.material_category_name, " + + " mi.safe_stock_amount, mi.min_stock_amount, mi.max_stock_amount, inv.update_time " + + "HAVING SUM(inv.inventory_qty) < mi.safe_stock_amount " + + " OR SUM(inv.inventory_qty) < mi.min_stock_amount " + + " OR SUM(inv.inventory_qty) > mi.max_stock_amount " + + "ORDER BY inv.tenant_id, alertStatus, differenceAmount DESC") + List selectSafetyStockAlert(@Param("tenantId") String tenantId, + @Param("materialCategoryId") Long materialCategoryId); + + /** + * 查询呆滞料库存报表 + */ + @Select("SELECT " + + " inv.tenant_id AS tenantId, " + + " inv.material_id AS materialId, " + + " mi.material_code AS materialCode, " + + " mi.material_name AS materialName, " + + " mc.material_category_name AS materialCategoryName, " + + " SUM(inv.inventory_qty) AS stagnantInventoryQty, " + + " mi.material_unit AS materialUnit, " + + " CASE " + + " WHEN last_out.lastOutstockTime IS NULL THEN '从未出库' " + + " ELSE CONVERT(VARCHAR(19), last_out.lastOutstockTime, 120) " + + " END AS lastOutstockTime, " + + " CASE " + + " WHEN last_out.lastOutstockTime IS NULL THEN DATEDIFF(DAY, first_in.firstInstockTime, GETDATE()) " + + " ELSE DATEDIFF(DAY, last_out.lastOutstockTime, GETDATE()) " + + " END AS stagnantDays, " + + " CASE " + + " WHEN last_out.lastOutstockTime IS NULL THEN '从未出库' " + + " WHEN DATEDIFF(DAY, last_out.lastOutstockTime, GETDATE()) > 180 THEN '超过6个月未出库' " + + " ELSE '正常' " + + " END AS stagnantReason, " + + " mi.material_spec AS materialSpec, " + + " w.warehouse_name AS warehouseName, " + + " CASE " + + " WHEN last_out.lastOutstockTime IS NULL THEN CONVERT(VARCHAR(19), first_in.firstInstockTime, 120) " + + " ELSE CONVERT(VARCHAR(19), last_out.lastOutstockTime, 120) " + + " END AS lastActivityTime " + + "FROM wms_inventory inv " + + "INNER JOIN base_material_info_copy1 mi ON inv.material_id = mi.material_id " + + "INNER JOIN base_material_category mc ON mi.material_category_id = mc.material_category_id " + + "INNER JOIN wms_base_warehouse w ON inv.warehouse_id = w.warehouse_id " + + "LEFT JOIN ( " + + " SELECT " + + " material_id, " + + " tenant_id, " + + " MIN(create_time) AS firstInstockTime " + + " FROM wms_instock_record " + + " WHERE create_time IS NOT NULL " + + " GROUP BY material_id, tenant_id " + + ") first_in ON inv.material_id = first_in.material_id AND inv.tenant_id = first_in.tenant_id " + + "LEFT JOIN ( " + + " SELECT " + + " material_id, " + + " tenant_id, " + + " MAX(create_time) AS lastOutstockTime " + + " FROM wms_outstock_record " + + " WHERE create_time IS NOT NULL " + + " GROUP BY material_id, tenant_id " + + ") last_out ON inv.material_id = last_out.material_id AND inv.tenant_id = last_out.tenant_id " + + "WHERE inv.inventory_status = '1' " + + " AND inv.inventory_qty > 0 " + + " AND mi.active_flag = '1' " + + " AND mi.del_flag = '0' " + + " AND ( " + + " last_out.lastOutstockTime IS NULL " + + " OR DATEDIFF(DAY, last_out.lastOutstockTime, GETDATE()) >= 180 " + + " ) " + + " AND (#{tenantId} IS NULL OR inv.tenant_id = #{tenantId}) " + + " AND (#{materialCategoryId} IS NULL OR mc.material_category_id = #{materialCategoryId}) " + + "GROUP BY " + + " inv.tenant_id, " + + " inv.material_id, " + + " mi.material_code, " + + " mi.material_name, " + + " mc.material_category_name, " + + " mi.material_unit, " + + " last_out.lastOutstockTime, " + + " mi.material_spec, " + + " w.warehouse_name, " + + " first_in.firstInstockTime " + + "ORDER BY inv.tenant_id, stagnantDays DESC, stagnantInventoryQty DESC") + List selectStagnantInventory(@Param("tenantId") String tenantId, + @Param("materialCategoryId") Long materialCategoryId); + + /** + * 查询库存差异报表 + */ + @Select("SELECT " + + " ic.tenant_id AS tenantId, " + + " ic.check_code AS checkCode, " + + " CASE ic.check_type " + + " WHEN '0' THEN '抽检' " + + " WHEN '1' THEN '盘点' " + + " WHEN '2' THEN '库位/货架盘点' " + + " ELSE '未知' " + + " END AS checkType, " + + " ic.plan_warehouse_id AS warehouseId, " + + " w.warehouse_name AS warehouseName, " + + " icr.material_id AS materialId, " + + " mi.material_code AS materialCode, " + + " mi.material_name AS materialName, " + + " mc.material_category_name AS materialCategoryName, " + + " icr.inventory_qty AS bookInventoryQty, " + + " icr.check_qty AS actualInventoryQty, " + + " (icr.check_qty - icr.inventory_qty) AS differenceQty, " + + " CASE " + + " WHEN ABS(icr.check_qty - icr.inventory_qty) = 0 THEN '无差异' " + + " WHEN (icr.check_qty - icr.inventory_qty) > 0 THEN '盘盈' " + + " ELSE '盘亏' " + + " END AS differenceType, " + + " CASE " + + " WHEN icr.inventory_qty > 0 THEN " + + " ABS((icr.check_qty - icr.inventory_qty) / icr.inventory_qty * 100) " + + " ELSE 0 " + + " END AS differenceRate, " + + " CASE " + + " WHEN ABS(icr.check_qty - icr.inventory_qty) > 10 THEN '重大差异' " + + " WHEN ABS(icr.check_qty - icr.inventory_qty) > 5 THEN '一般差异' " + + " WHEN ABS(icr.check_qty - icr.inventory_qty) > 0 THEN '轻微差异' " + + " ELSE '无差异' " + + " END AS differenceLevel, " + + " ic.create_time AS checkTime, " + + " ic.create_by AS checkBy " + + "FROM wms_inventory_check ic " + + "INNER JOIN wms_base_warehouse w ON ic.plan_warehouse_id = w.warehouse_id " + + "INNER JOIN wms_inventory_check_record icr ON icr.check_code = ic.check_code AND icr.tenant_id = ic.tenant_id " + + "INNER JOIN base_material_info_copy1 mi ON icr.material_id = mi.material_id " + + "INNER JOIN base_material_category mc ON mi.material_category_id = mc.material_category_id " + + "WHERE ic.check_status = '3' " + + " AND (#{tenantId} IS NULL OR ic.tenant_id = #{tenantId}) " + + " AND (#{materialCategoryId} IS NULL OR mc.material_category_id = #{materialCategoryId}) " + + "ORDER BY ic.tenant_id, ic.check_code, differenceRate DESC") + List selectInventoryDifference(@Param("tenantId") String tenantId, + @Param("materialCategoryId") Long materialCategoryId); + + /** + * 查询库存周转报表 + */ + @Select("SELECT " + + " base_data.tenantId, " + + " base_data.materialId, " + + " base_data.materialCode, " + + " base_data.materialName, " + + " base_data.materialCategoryName, " + + " base_data.statisticsMonth, " + + " base_data.beginInventoryQty, " + + " base_data.endInventoryQty, " + + " base_data.monthOutstockQty, " + + " CASE " + + " WHEN (base_data.beginInventoryQty + base_data.endInventoryQty) > 0 THEN " + + " CAST(base_data.monthOutstockQty * 2.0 / (base_data.beginInventoryQty + base_data.endInventoryQty) * 100 AS DECIMAL(10,2)) " + + " ELSE 0 " + + " END AS inventoryTurnoverRate, " + + " CASE " + + " WHEN base_data.endInventoryQty > 0 THEN " + + " CAST(base_data.monthOutstockQty / base_data.endInventoryQty * 100 AS DECIMAL(10,2)) " + + " ELSE 0 " + + " END AS simpleTurnoverRate, " + + " CASE " + + " WHEN base_data.monthOutstockQty = 0 THEN '无流动' " + + " WHEN CAST(base_data.monthOutstockQty * 2.0 / (base_data.beginInventoryQty + base_data.endInventoryQty) * 100 AS DECIMAL(10,2)) >= 100 THEN '快速周转' " + + " WHEN CAST(base_data.monthOutstockQty * 2.0 / (base_data.beginInventoryQty + base_data.endInventoryQty) * 100 AS DECIMAL(10,2)) >= 50 THEN '正常周转' " + + " ELSE '缓慢周转' " + + " END AS turnoverEvaluation " + + "FROM ( " + + " SELECT " + + " inv.tenant_id AS tenantId, " + + " inv.material_id AS materialId, " + + " mi.material_code AS materialCode, " + + " mi.material_name AS materialName, " + + " mc.material_category_name AS materialCategoryName, " + + " CONVERT(VARCHAR(7), GETDATE(), 126) AS statisticsMonth, " + + " SUM(inv.inventory_qty) AS endInventoryQty, " + + " SUM(inv.inventory_qty) + ISNULL(month_out.monthOutstockQty, 0) - ISNULL(month_in.monthInstockQty, 0) AS beginInventoryQty, " + + " ISNULL(month_out.monthOutstockQty, 0) AS monthOutstockQty " + + " FROM wms_inventory inv " + + " INNER JOIN base_material_info_copy1 mi ON inv.material_id = mi.material_id " + + " INNER JOIN base_material_category mc ON mi.material_category_id = mc.material_category_id " + + " LEFT JOIN ( " + + " SELECT material_id, tenant_id, SUM(outstock_qty) AS monthOutstockQty " + + " FROM wms_outstock_record " + + " WHERE create_time >= DATEADD(MONTH, -1, GETDATE()) " + + " GROUP BY material_id, tenant_id " + + " ) month_out ON inv.material_id = month_out.material_id AND inv.tenant_id = month_out.tenant_id " + + " LEFT JOIN ( " + + " SELECT material_id, tenant_id, SUM(instock_qty) AS monthInstockQty " + + " FROM wms_instock_record " + + " WHERE create_time >= DATEADD(MONTH, -1, GETDATE()) " + + " GROUP BY material_id, tenant_id " + + " ) month_in ON inv.material_id = month_in.material_id AND inv.tenant_id = month_in.tenant_id " + + " WHERE inv.inventory_status = '1' " + + " AND (#{tenantId} IS NULL OR inv.tenant_id = #{tenantId}) " + + " AND (#{materialCategoryId} IS NULL OR mc.material_category_id = #{materialCategoryId}) " + + " GROUP BY inv.tenant_id, inv.material_id, mi.material_code, mi.material_name, mc.material_category_name, " + + " month_out.monthOutstockQty, month_in.monthInstockQty " + + ") base_data " + + "WHERE base_data.beginInventoryQty > 0 OR base_data.endInventoryQty > 0 OR base_data.monthOutstockQty > 0 " + + "ORDER BY base_data.tenantId, inventoryTurnoverRate DESC") + List selectInventoryTurnover(@Param("tenantId") String tenantId, + @Param("materialCategoryId") Long materialCategoryId); +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsReportService.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsReportService.java new file mode 100644 index 00000000..eed39970 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsReportService.java @@ -0,0 +1,68 @@ +package org.dromara.wms.service; + +import org.dromara.wms.domain.vo.*; + +import java.util.List; + +/** + * WMS报表Service接口 + * + * @author hwmom + * @date 2025-01-20 + */ +public interface IWmsReportService { + + /** + * 查询退库原因分析报表 + * + * @param tenantId 租户编号 + * @param materialCategoryId 物料大类ID + * @return 退库原因分析报表列表 + */ + List getReturnReasonAnalysis(String tenantId, Long materialCategoryId); + + /** + * 查询库存变动趋势分析报表 + * + * @param tenantId 租户编号 + * @param materialCategoryId 物料大类ID + * @return 库存变动趋势分析报表列表 + */ + List getInventoryTrendAnalysis(String tenantId, Long materialCategoryId); + + /** + * 查询安全库存预警报表 + * + * @param tenantId 租户编号 + * @param materialCategoryId 物料大类ID + * @return 安全库存预警报表列表 + */ + List getSafetyStockAlert(String tenantId, Long materialCategoryId); + + /** + * 查询呆滞料库存报表 + * + * @param tenantId 租户编号 + * @param materialCategoryId 物料大类ID + * @return 呆滞料库存报表列表 + */ + List getStagnantInventory(String tenantId, Long materialCategoryId); + + /** + * 查询库存差异报表 + * + * @param tenantId 租户编号 + * @param materialCategoryId 物料大类ID + * @return 库存差异报表列表 + */ + List getInventoryDifference(String tenantId, Long materialCategoryId); + + /** + * 查询库存周转报表 + * + * @param tenantId 租户编号 + * @param materialCategoryId 物料大类ID + * @return 库存周转报表列表 + */ + List getInventoryTurnover(String tenantId, Long materialCategoryId); +} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsReportServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsReportServiceImpl.java new file mode 100644 index 00000000..906ece3b --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsReportServiceImpl.java @@ -0,0 +1,70 @@ +package org.dromara.wms.service.impl; + +import lombok.RequiredArgsConstructor; +import org.dromara.wms.domain.vo.*; +import org.dromara.wms.mapper.WmsReportMapper; +import org.dromara.wms.service.IWmsReportService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * WMS报表Service业务层处理 + * + * @author hwmom + * @date 2025-01-20 + */ +@RequiredArgsConstructor +@Service +public class WmsReportServiceImpl implements IWmsReportService { + + private final WmsReportMapper wmsReportMapper; + + /** + * 查询退库原因分析报表 + */ + @Override + public List getReturnReasonAnalysis(String tenantId, Long materialCategoryId) { + return wmsReportMapper.selectReturnReasonAnalysis(tenantId, materialCategoryId); + } + + /** + * 查询库存变动趋势分析报表 + */ + @Override + public List getInventoryTrendAnalysis(String tenantId, Long materialCategoryId) { + return wmsReportMapper.selectInventoryTrendAnalysis(tenantId, materialCategoryId); + } + + /** + * 查询安全库存预警报表 + */ + @Override + public List getSafetyStockAlert(String tenantId, Long materialCategoryId) { + return wmsReportMapper.selectSafetyStockAlert(tenantId, materialCategoryId); + } + + /** + * 查询呆滞料库存报表 + */ + @Override + public List getStagnantInventory(String tenantId, Long materialCategoryId) { + return wmsReportMapper.selectStagnantInventory(tenantId, materialCategoryId); + } + + /** + * 查询库存差异报表 + */ + @Override + public List getInventoryDifference(String tenantId, Long materialCategoryId) { + return wmsReportMapper.selectInventoryDifference(tenantId, materialCategoryId); + } + + /** + * 查询库存周转报表 + */ + @Override + public List getInventoryTurnover(String tenantId, Long materialCategoryId) { + return wmsReportMapper.selectInventoryTurnover(tenantId, materialCategoryId); + } +} \ No newline at end of file