Commit be99b262 authored by chicheng's avatar chicheng

进度报表添加

parent 26c94cac
...@@ -87,6 +87,16 @@ public class BaseController { ...@@ -87,6 +87,16 @@ public class BaseController {
return rspData; return rspData;
} }
/**
* 响应请求分页数据(显式传入总条数,用于 Service 内重新组装列表导致 PageHelper 总条数丢失的场景)
*/
protected static <T> TableDataInfo<T> getDataTable(final List<T> list, final long total) {
final TableDataInfo<T> rspData = new TableDataInfo<>(list, total);
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
return rspData;
}
/** /**
* 返回成功 * 返回成功
*/ */
......
...@@ -5,7 +5,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; ...@@ -5,7 +5,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkorder; import com.ximai.mes.pro.domain.proWorkOrder.ProWorkorder;
import com.ximai.mes.pro.domain.task.ProTask; import com.ximai.mes.pro.domain.task.ProTask;
import com.ximai.mes.pro.domain.vo.*; import com.ximai.mes.pro.domain.vo.*;
import com.ximai.mes.report.request.ProgressReportRequest;
import com.ximai.mes.report.request.WorkOrderProgressRequest; import com.ximai.mes.report.request.WorkOrderProgressRequest;
import com.ximai.mes.report.response.ProgressReportProcessQtyDto;
import com.ximai.mes.report.response.ProgressReportRowDto;
import com.ximai.mes.report.response.WorkOrderProgressListResponse; import com.ximai.mes.report.response.WorkOrderProgressListResponse;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;
...@@ -154,4 +157,14 @@ public interface ProWorkorderMapper extends BaseMapper<ProWorkorder> { ...@@ -154,4 +157,14 @@ public interface ProWorkorderMapper extends BaseMapper<ProWorkorder> {
void rollBACKschedule(@Param("workorderCode")String workorderCode, @Param("quantity")BigDecimal quantity, @Param("username")String username); void rollBACKschedule(@Param("workorderCode")String workorderCode, @Param("quantity")BigDecimal quantity, @Param("username")String username);
List<WorkOrderProgressListResponse> getWorkOrderProgressServiceList(WorkOrderProgressRequest workOrderProgressRequest); List<WorkOrderProgressListResponse> getWorkOrderProgressServiceList(WorkOrderProgressRequest workOrderProgressRequest);
/**
* 进度报表:主表列表(按工单,排产时间降序)
*/
List<ProgressReportRowDto> getProgressReportList(ProgressReportRequest request);
/**
* 进度报表:各工单各工序完工数量(按 workorder_id 关联)
*/
List<ProgressReportProcessQtyDto> getProgressReportProcessQuantities(@Param("workorderIds") List<Long> workorderIds);
} }
...@@ -9,12 +9,12 @@ import com.ximai.common.enums.BusinessType; ...@@ -9,12 +9,12 @@ import com.ximai.common.enums.BusinessType;
import com.ximai.common.utils.data.StringUtils; import com.ximai.common.utils.data.StringUtils;
import com.ximai.common.utils.poi.ExcelUtil; import com.ximai.common.utils.poi.ExcelUtil;
import com.ximai.mes.report.request.FeedbackRequest; import com.ximai.mes.report.request.FeedbackRequest;
import com.ximai.mes.report.request.ProgressReportRequest;
import com.ximai.mes.report.response.*; import com.ximai.mes.report.response.*;
import com.ximai.mes.report.service.FeedbackService; import com.ximai.mes.report.service.FeedbackService;
import com.ximai.system.service.ISysDictDataService; import com.ximai.system.service.ISysDictDataService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -38,6 +38,31 @@ public class FeedbackController extends BaseController { ...@@ -38,6 +38,31 @@ public class FeedbackController extends BaseController {
/** /**
* 新增生产报工记录 * 新增生产报工记录
*/ */
/**
* 进度报表:工序名称列表(动态表头)
*/
@ApiOperation("进度报表:工序名称列表")
@PreAuthorize("@ss.hasPermi('mes:pro:feedback:get')")
@Log(title = "进度报表:工序名称", businessType = BusinessType.QUERY)
@GetMapping("/progressReport/processNames")
public AjaxResult getProgressReportProcessNames() {
return AjaxResult.success(feedbackService.getProgressReportProcessNames());
}
/**
* 进度报表:列表(筛选:排产时间、订单单号、订单序号、产品编号、产品名称、在制进度小于、需求时间小于)
* 表格:排产时间、订单单号(工单时间降序)、产线名称、生产工单、订单序号、工单类型、产品编号、产品名称、工序1~N(动态)、计划数量、在制进度%、需求时间
*/
@ApiOperation("进度报表:列表")
@PreAuthorize("@ss.hasPermi('mes:pro:feedback:get')")
@Log(title = "进度报表", businessType = BusinessType.QUERY)
@GetMapping("/progressReport/list")
public TableDataInfo<ProgressReportResponse> getProgressReportList(ProgressReportRequest request) {
startPage();
ProgressReportListResult result = feedbackService.getProgressReportList(request);
return getDataTable(result.getList(), result.getTotal());
}
@ApiOperation("生产报工记录:明细界面") @ApiOperation("生产报工记录:明细界面")
@PreAuthorize("@ss.hasPermi('mes:pro:feedback:get')") @PreAuthorize("@ss.hasPermi('mes:pro:feedback:get')")
@Log(title = "生产报工记录", businessType = BusinessType.QUERY) @Log(title = "生产报工记录", businessType = BusinessType.QUERY)
......
package com.ximai.mes.report.service; package com.ximai.mes.report.service;
import com.ximai.mes.report.request.FeedbackRequest; import com.ximai.mes.report.request.FeedbackRequest;
import com.ximai.mes.report.request.ProgressReportRequest;
import com.ximai.mes.report.response.*; import com.ximai.mes.report.response.*;
import java.util.List; import java.util.List;
public interface FeedbackService { public interface FeedbackService {
/** 进度报表:工序列表(按工序名动态表头) */
List<String> getProgressReportProcessNames();
/** 进度报表:列表数据(含总条数,供分页展示) */
ProgressReportListResult getProgressReportList(ProgressReportRequest request);
List<FeedbackResponse> getList(FeedbackRequest feedbackRequest); List<FeedbackResponse> getList(FeedbackRequest feedbackRequest);
List<FeedbackResponseExportByList> export(FeedbackRequest feedbackRequest); List<FeedbackResponseExportByList> export(FeedbackRequest feedbackRequest);
......
package com.ximai.mes.report.service.impl; package com.ximai.mes.report.service.impl;
import com.ximai.mes.pro.domain.ProFeedback; import com.ximai.mes.pro.domain.ProProcess;
import com.ximai.mes.pro.mapper.ProFeedbackMapper; import com.ximai.mes.pro.mapper.ProFeedbackMapper;
import com.ximai.mes.pro.mapper.ProProcessMapper;
import com.ximai.mes.pro.mapper.proWorkOrder.ProWorkorderMapper;
import com.ximai.mes.report.request.FeedbackRequest; import com.ximai.mes.report.request.FeedbackRequest;
import com.ximai.mes.report.request.ProgressReportRequest;
import com.ximai.mes.report.response.*; import com.ximai.mes.report.response.*;
import com.ximai.mes.report.service.FeedbackService; import com.ximai.mes.report.service.FeedbackService;
import org.checkerframework.checker.units.qual.A; import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Service @Service
public class FeedbackServiceImp implements FeedbackService { public class FeedbackServiceImp implements FeedbackService {
@Autowired @Autowired
ProFeedbackMapper proFeedbackMapper; ProFeedbackMapper proFeedbackMapper;
@Autowired
ProWorkorderMapper proWorkorderMapper;
@Autowired
ProProcessMapper proProcessMapper;
@Override
public List<String> getProgressReportProcessNames() {
// 进度报表表头:使用全部工序(不限制启用),保证与工序完工数据能对应
ProProcess query = new ProProcess();
List<ProProcess> list = proProcessMapper.selectProProcessList(query);
if (list == null) return Collections.emptyList();
return list.stream()
.sorted(Comparator.comparing(ProProcess::getProcessId, Comparator.nullsLast(Long::compareTo)))
.map(ProProcess::getProcessName)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
@Override
public ProgressReportListResult getProgressReportList(ProgressReportRequest request) {
List<ProgressReportRowDto> rows = proWorkorderMapper.getProgressReportList(request);
long total = new PageInfo<>(rows).getTotal();
if (rows == null || rows.isEmpty()) {
return new ProgressReportListResult(Collections.emptyList(), total);
}
List<Long> workorderIds = rows.stream()
.map(ProgressReportRowDto::getWorkorderId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
Map<Long, Map<String, BigDecimal>> workorderProcessMap = new HashMap<>();
if (!workorderIds.isEmpty()) {
List<ProgressReportProcessQtyDto> processQtys = proWorkorderMapper.getProgressReportProcessQuantities(workorderIds);
for (ProgressReportProcessQtyDto dto : processQtys) {
if (dto.getWorkorderId() == null) {
continue;
}
workorderProcessMap
.computeIfAbsent(dto.getWorkorderId(), k -> new LinkedHashMap<>())
.put(dto.getProcessName(), dto.getQuantityProduced() != null ? dto.getQuantityProduced() : BigDecimal.ZERO);
}
}
// 仅保留本次查询实际用到的工序列(按工序ID顺序过滤)
List<String> allProcessNames = getProgressReportProcessNames();
Set<String> usedProcessNames = workorderProcessMap.values().stream()
.flatMap(m -> m.entrySet().stream())
.filter(e -> e.getValue() != null) // 有数据的工序
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
List<String> processNames = allProcessNames.stream()
.filter(usedProcessNames::contains)
.collect(Collectors.toList());
List<ProgressReportResponse> result = new ArrayList<>();
for (ProgressReportRowDto row : rows) {
BigDecimal progressPercent = row.getProgressPercent() != null ? row.getProgressPercent() : BigDecimal.ZERO;
ProgressReportResponse resp = new ProgressReportResponse();
resp.setScheduleTime(row.getScheduleTime());
resp.setOrderCode(row.getOrderCode());
resp.setLineName(row.getLineName());
resp.setWorkorderCode(row.getWorkorderCode());
resp.setOrderSerial(row.getOrderSerial());
resp.setWorkorderType(row.getWorkorderType());
resp.setProductCode(row.getProductCode());
resp.setProductName(row.getProductName());
resp.setPlanQuantity(row.getPlanQuantity());
resp.setProgressPercent(progressPercent);
resp.setRequestDate(row.getRequestDate());
Map<String, BigDecimal> rowProcess = workorderProcessMap.getOrDefault(row.getWorkorderId(), new LinkedHashMap<>());
for (String pname : processNames) {
// 只响应该工单实际有数据的工序;没有记录则不放入 processQuantities
BigDecimal val = rowProcess.get(pname);
if (val != null) {
resp.getProcessQuantities().put(pname, val);
}
}
result.add(resp);
}
return new ProgressReportListResult(result, total);
}
@Override @Override
public List<FeedbackResponse> getList(FeedbackRequest feedbackRequest) { public List<FeedbackResponse> getList(FeedbackRequest feedbackRequest) {
return proFeedbackMapper.getList(feedbackRequest); return proFeedbackMapper.getList(feedbackRequest);
......
...@@ -370,6 +370,100 @@ ...@@ -370,6 +370,100 @@
item.line_name item.line_name
</select> </select>
<!-- 进度报表:主表列表,按工单排产时间降序。工序数/报工和用 JOIN 聚合表一次算出,避免每行相关子查询 -->
<select id="getProgressReportList" resultType="com.ximai.mes.report.response.ProgressReportRowDto">
SELECT
pw.workorder_id,
pw.arrange_code,
st.schedule_time,
pw.order_code,
item.line_name,
pw.workorder_code,
pw.order_serial,
pw.workorder_type,
pw.product_code,
pw.product_name,
pw.quantity AS plan_quantity,
SUM(CASE WHEN task.is_last_process = 1 THEN fe.quantity_qualify + fe.quantity_unqualify ELSE 0 END) AS quantity_produced,
pw.request_date,
IFNULL(pc.cnt, 0) AS process_count,
IFNULL(sq.sum_qty, 0) AS sum_process_qty,
CASE WHEN IFNULL(pc.cnt, 0) = 0 OR pw.quantity * IFNULL(pc.cnt, 0) = 0 THEN 0
ELSE ROUND(IFNULL(sq.sum_qty, 0) * 100.0 / (pw.quantity * pc.cnt), 2)
END AS progress_percent
FROM pro_workorder pw
LEFT JOIN (
SELECT tw.workorder_id, MIN(ptw.schedule_start_date) AS schedule_time
FROM pro_task_workorder tw
INNER JOIN pro_task t ON tw.task_id = t.task_id
INNER JOIN pro_task_workunit ptw ON t.task_id = ptw.task_id
GROUP BY tw.workorder_id
) st ON st.workorder_id = pw.workorder_id
LEFT JOIN (
SELECT tw.workorder_id, COUNT(DISTINCT t.process_id) AS cnt
FROM pro_task_workorder tw INNER JOIN pro_task t ON tw.task_id = t.task_id
GROUP BY tw.workorder_id
) pc ON pc.workorder_id = pw.workorder_id
LEFT JOIN (
SELECT tw.workorder_id, IFNULL(SUM(ptw.quantity_produced), 0) AS sum_qty
FROM pro_task_workunit ptw INNER JOIN pro_task t ON ptw.task_id = t.task_id INNER JOIN pro_task_workorder tw ON t.task_id = tw.task_id
GROUP BY tw.workorder_id
) sq ON sq.workorder_id = pw.workorder_id
LEFT JOIN pro_feedback fe ON fe.workorder_id = pw.workorder_id
LEFT JOIN pro_task task ON task.task_id = fe.task_id
LEFT JOIN md_item item ON item.item_id = pw.product_id
<where>
<if test="scheduleStartDate != null">
AND st.schedule_time &gt;= #{scheduleStartDate}
</if>
<if test="scheduleEndDate != null">
AND st.schedule_time &lt;= #{scheduleEndDate}
</if>
<if test="orderCode != null and orderCode != ''">
AND pw.order_code LIKE concat('%', #{orderCode}, '%')
</if>
<if test="orderSerial != null and orderSerial != ''">
AND pw.order_serial LIKE concat('%', #{orderSerial}, '%')
</if>
<if test="productCode != null and productCode != ''">
AND pw.product_code LIKE concat('%', #{productCode}, '%')
</if>
<if test="productName != null and productName != ''">
AND pw.product_name LIKE concat('%', #{productName}, '%')
</if>
<if test="requestDateBefore != null">
AND pw.request_date &lt; #{requestDateBefore}
</if>
</where>
GROUP BY pw.workorder_id, pw.arrange_code, st.schedule_time, pw.order_code, item.line_name, pw.workorder_code, pw.order_serial,
pw.workorder_type, pw.product_code, pw.product_name, pw.quantity, pw.request_date, pc.cnt, sq.sum_qty
<if test="progressLessThan != null">
HAVING progress_percent &lt; #{progressLessThan}
</if>
ORDER BY st.schedule_time DESC
</select>
<!-- 进度报表:各工单各工序完工数量(来自 pro_task_workunit 按工序汇总) -->
<select id="getProgressReportProcessQuantities" resultType="com.ximai.mes.report.response.ProgressReportProcessQtyDto">
SELECT
tw.workorder_id,
p.process_name,
IFNULL(SUM(ptw.quantity_produced), 0) AS quantity_produced
FROM pro_task_workunit ptw
INNER JOIN pro_task t ON ptw.task_id = t.task_id
INNER JOIN pro_task_workorder tw ON t.task_id = tw.task_id
INNER JOIN pro_process p ON t.process_id = p.process_id
<where>
<if test="workorderIds != null and workorderIds.size() > 0">
AND tw.workorder_id IN
<foreach collection="workorderIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</where>
GROUP BY tw.workorder_id, p.process_id, p.process_name
</select>
<insert id="insertProWorkorder" parameterType="ProWorkorder" useGeneratedKeys="true" keyProperty="workorderId"> <insert id="insertProWorkorder" parameterType="ProWorkorder" useGeneratedKeys="true" keyProperty="workorderId">
insert into pro_workorder insert into pro_workorder
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment