feat(report): 新增小时产量统计功能

- 在IProdReportService接口中新增hourlyOutputByHour方法定义
- 在ProdReportController中新增hourlyOutputByHour接口
- 在ProdReportMapper中新增hourlyOutputByHour方法及XML映射
- 实现小时产量统计逻辑,支持按扫描时间分桶统计
- 支持根据processId动态获取计划表名和明细表名
- 提供产量、合格数、不合格数的统计字段
- 在XML中完善查询条件过滤和数据聚合逻辑
-修复部分SQL注释格式问题- 调整部分代码空行格式
master
zangch@mesnac.com 3 months ago
parent 6343b7036b
commit d4cc4f4758

@ -229,4 +229,5 @@ public class ProdPlanInfoController extends BaseController {
public void exportMonitor(ProdPlanInfoBo bo, HttpServletResponse response) {
prodPlanInfoService.exportMonitor(bo, response);
}
}

@ -123,6 +123,7 @@ public class ProdReportController extends BaseController {
return R.ok(vos);
}
/**
*
*/
@ -174,11 +175,21 @@ public class ProdReportController extends BaseController {
public void wipTrackingReportExport(@RequestParam(required = false) Map hashMap, HttpServletResponse response) {
// 获取报表数据
List<WipTrackingReportVo> list = prodReportService.wipTrackingReportList(hashMap);
// 转换为导出专用VO
List<WipTrackingReportExportVo> exportList = prodReportService.convertToExportVo(list);
// 使用EasyExcel导出保持与页面相同的样式和数据
ExcelUtil.exportExcel(exportList, "在制品跟踪报表", WipTrackingReportExportVo.class, response);
}
/**
*
*/
@GetMapping("/hourlyOutputByHour")
public R<List<HashMap<String, Object>>> hourlyOutputByHour(@RequestParam(required = false) Map hashMap) {
List<HashMap<String, Object>> vos = prodReportService.hourlyOutputByHour(hashMap);
return R.ok(vos);
}
}

@ -131,4 +131,9 @@ public interface ProdReportMapper {
*/
List<ProcessProgressVo> getOrdersProcessProgressBatch(@Param("productOrderIds") List<Long> productOrderIds,
@Param("planTableName") String planTableName);
// 新增:小时产量统计(按结束时间小时分桶)
List<HashMap<String, Object>> hourlyOutputByHour(@Param("map") Map hashMap,
@Param("detailTableName") String detailTableName,
@Param("planTableName") String planTableName);
}

@ -129,4 +129,11 @@ public interface IProdReportService {
*/
List<WipTrackingReportExportVo> convertToExportVo(List<WipTrackingReportVo> reportList);
/**
*
* @param hashMap beginDate/endDateprocessIdmachineIdshiftIdclassTeamIdmaterialName
* @return productionDatehourSlotproductionQuantityqualifiedQuantityunqualifiedQuantity
*/
List<HashMap<String, Object>> hourlyOutputByHour(Map hashMap);
}

@ -84,6 +84,7 @@ public class ProdProductPlanDetailServiceImpl implements IProdProductPlanDetailS
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ProdProductPlanDetail> lqw = JoinWrappers.lambda(ProdProductPlanDetail.class)
.selectAll(ProdProductPlanDetail.class)
// //工装连表查询名称
// .select(BaseToolingInfo::getToolingName)
// .leftJoin(BaseToolingInfo.class, BaseToolingInfo::getToolingId, ProdProductPlanDetail::getToolingId)
@ -99,7 +100,6 @@ public class ProdProductPlanDetailServiceImpl implements IProdProductPlanDetailS
/* .select(ProdShiftChange::)
.leftJoin(ProdShiftChange.class, ProdShiftChange::getShiftChangeId, ProdProductPlanDetail::getShiftChangeId)*/
.eq(bo.getPlanDetailId() != null, ProdProductPlanDetail::getPlanDetailId, bo.getPlanDetailId())
.eq(StringUtils.isNotBlank(bo.getPlanDetailCode()), ProdProductPlanDetail::getPlanDetailCode, bo.getPlanDetailCode())
.eq(bo.getPlanId() != null, ProdProductPlanDetail::getPlanId, bo.getPlanId())

@ -553,4 +553,18 @@ public class ProdReportServiceImpl implements IProdReportService {
return processIds;
}
/**
*
* @param hashMap
*/
@Override
public List<HashMap<String, Object>> hourlyOutputByHour(Map hashMap) {
Long processId = Long.parseLong(String.valueOf(hashMap.get("processId")));
String detailTable = getPlanDetailTableNameByProcessId(processId);
String planTable = getPlanInfoTableNameByProcessId(processId);
return prodReportMapper.hourlyOutputByHour(hashMap, detailTable, planTable);
}
}

@ -217,8 +217,8 @@
FORMAT(ppd.create_time, 'yyyy-MM-dd') BETWEEN #{map.beginDate} AND #{map.endDate}
</if>
<!-- <if test="map.processId != null and map.processId != ''">
<!-- AND ppi.process_id = #{map.processId}
<!-- </if>-->
AND ppi.process_id = #{map.processId}
</if>-->
<if test="map.machineId != null and map.machineId != ''">
AND ppi.release_id = #{map.machineId}
</if>
@ -321,7 +321,7 @@
),
ProcessStats AS (
-- 统计每个订单的工序进度信息仅统计已过滤的订单范围UNION ALL 提升性能)
SELECT
SELECT
ap.product_order_id,
ap.tenant_id,
COUNT(*) AS totalProcessCount,
@ -336,7 +336,7 @@
SUM(CASE WHEN ap.plan_status = '2' THEN ISNULL(ap.plan_amount - ap.complete_amount, 0) * ap.process_order ELSE 0 END) AS wipWeightedSum
FROM (
-- 半制品工序prod_plan_info_2
SELECT
SELECT
p2.product_order_id,
p2.tenant_id,
p2.process_id,
@ -349,11 +349,11 @@
LEFT JOIN prod_base_process_info pr2 ON pr2.process_id = p2.process_id
INNER JOIN Orders ord ON ord.product_order_id = p2.product_order_id AND ord.tenant_id = p2.tenant_id
WHERE p2.product_order_id IS NOT NULL
UNION ALL
-- 成型工序prod_plan_info_3
SELECT
SELECT
p3.product_order_id,
p3.tenant_id,
p3.process_id,
@ -366,11 +366,11 @@
LEFT JOIN prod_base_process_info pr3 ON pr3.process_id = p3.process_id
INNER JOIN Orders ord ON ord.product_order_id = p3.product_order_id AND ord.tenant_id = p3.tenant_id
WHERE p3.product_order_id IS NOT NULL
UNION ALL
-- 硫化工序prod_plan_info_4
SELECT
SELECT
p4.product_order_id,
p4.tenant_id,
p4.process_id,
@ -406,18 +406,18 @@
-- 整体进度计算:已完成数量占比 + 在制品进度占比
CONCAT(
CAST(
CASE
CASE
WHEN o.plan_amount > 0 AND ps.totalProcessCount > 0
THEN (
-- 已完成数量占比
(CAST(ISNULL(o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) * 100 +
-- 在制品进度占比:(在制数量/计划总数量) * (当前工序位置/总工序数)
(CAST(ISNULL(o.plan_amount - o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) *
(CAST(ISNULL(o.plan_amount - o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) *
(CAST(ISNULL(ps.maxCompletedOrder, 0) + 1 AS DECIMAL(18,6)) / CAST(ps.totalProcessCount AS DECIMAL(18,6))) * 100
)
WHEN o.plan_amount > 0
THEN (CAST(ISNULL(o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) * 100
ELSE 0
ELSE 0
END
AS DECIMAL(10,2)), '%'
) AS overallProgress,
@ -431,18 +431,18 @@
CAST(ISNULL(ps.wipWeightedSum, 0) AS DECIMAL(18,2)) AS wipWeightedSum,
-- 数值型整体进度
CAST(
CASE
CASE
WHEN o.plan_amount > 0 AND ps.totalProcessCount > 0
THEN (
-- 已完成数量占比
(CAST(ISNULL(o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) * 100 +
-- 在制品进度占比
(CAST(ISNULL(o.plan_amount - o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) *
(CAST(ISNULL(o.plan_amount - o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) *
(CAST(ISNULL(ps.maxCompletedOrder, 0) + 1 AS DECIMAL(18,6)) / CAST(ps.totalProcessCount AS DECIMAL(18,6))) * 100
)
WHEN o.plan_amount > 0
THEN (CAST(ISNULL(o.complete_amount,0) AS DECIMAL(18,6)) / CAST(o.plan_amount AS DECIMAL(18,6))) * 100
ELSE 0
ELSE 0
END
AS DECIMAL(10,2)) AS overallProgressNum
FROM prod_order_info o
@ -547,4 +547,44 @@
</select>
<!-- 小时产量统计按扫描时间小时分桶来源于生产产出扫描表不依赖QC质检表 -->
<select id="hourlyOutputByHour" resultType="java.util.HashMap">
SELECT
CONVERT(DATE, t.create_time) AS productionDate,
RIGHT('00' + CAST(DATEPART(HOUR, t.create_time) AS VARCHAR(2)), 2) + ':00' AS hourSlot,
CAST(COUNT(1) AS DECIMAL(18,4)) AS productionQuantity,
CAST(SUM(CASE WHEN (UPPER(t.scan_result) IN ('OK','PASS') OR t.scan_result IN (N'通过')) THEN 1 ELSE 0 END) AS DECIMAL(18,4)) AS qualifiedQuantity,
CAST(SUM(CASE WHEN t.scan_result IS NULL THEN 0 WHEN (UPPER(t.scan_result) IN ('OK','PASS') OR t.scan_result IN (N'通过')) THEN 0 ELSE 1 END) AS DECIMAL(18,4)) AS unqualifiedQuantity
FROM prod_output_scan_info t
LEFT JOIN ${planTableName} ppi
ON ppi.process_id = t.process_id
AND ppi.release_id = t.machine_id
AND t.create_time &gt;= COALESCE(ppi.real_begin_time, ppi.plan_begin_time)
AND t.create_time &lt; COALESCE(ppi.real_end_time, ppi.plan_end_time, DATEADD(day, 1, COALESCE(ppi.real_begin_time, ppi.plan_begin_time)))
LEFT JOIN base_material_info bmi ON bmi.material_id = t.materiel_id
<where>
<if test="map.beginDate != null and map.beginDate != '' and map.endDate != null and map.endDate != ''">
AND t.create_time &gt;= CAST(#{map.beginDate} AS DATETIME)
AND t.create_time &lt; DATEADD(day, 1, CAST(#{map.endDate} AS DATETIME))
</if>
<if test="map.processId != null and map.processId != ''">
AND t.process_id = #{map.processId}
</if>
<if test="map.machineId != null and map.machineId != ''">
AND t.machine_id = #{map.machineId}
</if>
<if test="map.shiftId != null and map.shiftId != ''">
AND ppi.shift_id = #{map.shiftId}
</if>
<if test="map.classTeamId != null and map.classTeamId != ''">
AND ppi.class_team_id = #{map.classTeamId}
</if>
<if test="map.materialName != null and map.materialName != ''">
AND bmi.material_name LIKE CONCAT('%', #{map.materialName}, '%')
</if>
</where>
GROUP BY CONVERT(DATE, t.create_time), DATEPART(HOUR, t.create_time)
ORDER BY productionDate, DATEPART(HOUR, t.create_time)
</select>
</mapper>

Loading…
Cancel
Save