工序计划展示,作业人员推送
This commit is contained in:
parent
4c39bbab96
commit
e5aab8b9a7
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ mvnw.cmd
|
|||||||
maven-wrapper.properties
|
maven-wrapper.properties
|
||||||
**/logs/
|
**/logs/
|
||||||
|
|
||||||
|
/logs/
|
||||||
|
|||||||
@ -0,0 +1,71 @@
|
|||||||
|
package com.ruoyi.system.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import com.ruoyi.system.domain.bo.EquipmentInfoBo;
|
||||||
|
import com.ruoyi.system.domain.vo.EquipmentInfoVo;
|
||||||
|
import com.ruoyi.system.service.IEquipmentInfoService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/equipment")
|
||||||
|
public class EquipmentInfoController extends BaseController {
|
||||||
|
|
||||||
|
private final IEquipmentInfoService equipmentInfoService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<EquipmentInfoVo> list(EquipmentInfoBo bo, PageQuery pageQuery) {
|
||||||
|
return equipmentInfoService.queryPageList(bo, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/options")
|
||||||
|
public R<List<EquipmentInfoVo>> options(@RequestParam(required = false) String workCenterName,
|
||||||
|
@RequestParam(required = false) String keyword) {
|
||||||
|
return R.ok(equipmentInfoService.queryOptions(workCenterName, keyword));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public R<EquipmentInfoVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
|
||||||
|
return R.ok(equipmentInfoService.queryById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatSubmit
|
||||||
|
@PostMapping
|
||||||
|
public R<Void> add(@Validated(AddGroup.class) @RequestBody EquipmentInfoBo bo) {
|
||||||
|
return toAjax(equipmentInfoService.insertByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatSubmit
|
||||||
|
@PutMapping
|
||||||
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody EquipmentInfoBo bo) {
|
||||||
|
return toAjax(equipmentInfoService.updateByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
|
||||||
|
return toAjax(equipmentInfoService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
package com.ruoyi.system.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchOverviewRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchProcessDefectRankRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderBarRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderProgressRespDto;
|
||||||
|
import com.ruoyi.system.service.IWorkbenchService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台(看板)数据接口。
|
||||||
|
* <p>
|
||||||
|
* 说明:
|
||||||
|
* <ul>
|
||||||
|
* <li>时间参数格式:yyyy-MM-dd HH:mm:ss</li>
|
||||||
|
* <li>workCenterName:按工作中心过滤(来自工序计划明细的 work_center_name)</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/system/workbench")
|
||||||
|
public class WorkbenchController {
|
||||||
|
|
||||||
|
private final IWorkbenchService workbenchService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顶部概览卡片(一次返回 4 张卡,保证口径一致)。
|
||||||
|
*
|
||||||
|
* <p>rangeType 仅在未传 startTime/endTime 时生效。</p>
|
||||||
|
*
|
||||||
|
* @param rangeType 时间范围类型:day|week|month|year(默认 month)
|
||||||
|
* @param startTime 自定义开始时间(可选,格式 yyyy-MM-dd HH:mm:ss)
|
||||||
|
* @param endTime 自定义结束时间(可选,格式 yyyy-MM-dd HH:mm:ss)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
@GetMapping("/overview")
|
||||||
|
public R<WorkbenchOverviewRespDto> overview(@RequestParam(required = false) String rangeType,
|
||||||
|
@RequestParam(required = false) String startTime,
|
||||||
|
@RequestParam(required = false) String endTime,
|
||||||
|
@RequestParam(required = false) String workCenterName) {
|
||||||
|
return R.ok(workbenchService.overview(rangeType, startTime, endTime, workCenterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工单数量柱状图。
|
||||||
|
*
|
||||||
|
* <p>当未传 startTime/endTime 时,默认统计当年 1~12 月。</p>
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间(可选,格式 yyyy-MM-dd HH:mm:ss)
|
||||||
|
* @param endTime 统计结束时间(可选,格式 yyyy-MM-dd HH:mm:ss)
|
||||||
|
* @param groupBy 分组粒度:month|day(默认 month)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
@GetMapping("/workOrderBar")
|
||||||
|
public R<WorkbenchWorkOrderBarRespDto> workOrderBar(@RequestParam(required = false) String startTime,
|
||||||
|
@RequestParam(required = false) String endTime,
|
||||||
|
@RequestParam(required = false) String groupBy,
|
||||||
|
@RequestParam(required = false) String workCenterName) {
|
||||||
|
return R.ok(workbenchService.workOrderBar(startTime, endTime, groupBy, workCenterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工单实时进度。
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间(可选,格式 yyyy-MM-dd HH:mm:ss;不传则按默认 month 范围)
|
||||||
|
* @param endTime 统计结束时间(可选,格式 yyyy-MM-dd HH:mm:ss;不传则按默认 month 范围)
|
||||||
|
* @param topN 返回条数(默认 5)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
@GetMapping("/workOrderProgress")
|
||||||
|
public R<WorkbenchWorkOrderProgressRespDto> workOrderProgress(@RequestParam(required = false) String startTime,
|
||||||
|
@RequestParam(required = false) String endTime,
|
||||||
|
@RequestParam(required = false) Integer topN,
|
||||||
|
@RequestParam(required = false) String workCenterName) {
|
||||||
|
return R.ok(workbenchService.workOrderProgress(startTime, endTime, topN, workCenterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工序不良率 TopN 排名。
|
||||||
|
*
|
||||||
|
* <p>不良率 = 不良数 / (合格数 + 不良数)。</p>
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间(可选,格式 yyyy-MM-dd HH:mm:ss;不传则按默认 month 范围)
|
||||||
|
* @param endTime 统计结束时间(可选,格式 yyyy-MM-dd HH:mm:ss;不传则按默认 month 范围)
|
||||||
|
* @param topN 返回条数(默认 10)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
@GetMapping("/processDefectRank")
|
||||||
|
public R<WorkbenchProcessDefectRankRespDto> processDefectRank(@RequestParam(required = false) String startTime,
|
||||||
|
@RequestParam(required = false) String endTime,
|
||||||
|
@RequestParam(required = false) Integer topN,
|
||||||
|
@RequestParam(required = false) String workCenterName) {
|
||||||
|
return R.ok(workbenchService.processDefectRank(startTime, endTime, topN, workCenterName));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.ruoyi.system.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("equipment_info")
|
||||||
|
public class EquipmentInfo extends BaseEntity {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String equipmentName;
|
||||||
|
|
||||||
|
private String equipmentCode;
|
||||||
|
|
||||||
|
private String operator;
|
||||||
|
|
||||||
|
private String workCenterName;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.ruoyi.system.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class EquipmentInfoBo extends BaseEntity {
|
||||||
|
|
||||||
|
@NotNull(message = "id不能为空", groups = {EditGroup.class})
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank(message = "设备名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||||
|
private String equipmentName;
|
||||||
|
|
||||||
|
@NotBlank(message = "设备编号不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||||
|
private String equipmentCode;
|
||||||
|
|
||||||
|
@NotBlank(message = "作业人员不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||||
|
private String operator;
|
||||||
|
|
||||||
|
@NotBlank(message = "所属工段不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||||
|
private String workCenterName;
|
||||||
|
}
|
||||||
|
|
||||||
@ -81,5 +81,7 @@ public class SfcOperationPlanningMainBo extends BaseEntity {
|
|||||||
@NotNull(message = "计划结束时间不能为空", groups = { AddGroup.class, EditGroup.class })
|
@NotNull(message = "计划结束时间不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
private Date planFinishTime;
|
private Date planFinishTime;
|
||||||
|
|
||||||
|
private String workCenterName;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchOverviewAggDto {
|
||||||
|
/**
|
||||||
|
* 工单数(工序计划主表记录数)。
|
||||||
|
*/
|
||||||
|
private Long workOrderCount;
|
||||||
|
/**
|
||||||
|
* 完工工单数(当前实现口径见 WorkbenchMapper.selectOverviewAgg 的说明)。
|
||||||
|
*/
|
||||||
|
private Long finishedWorkOrderCount;
|
||||||
|
/**
|
||||||
|
* 在制品数量(当前实现口径:计划数 - 完工数,小于 0 按 0 计)。
|
||||||
|
*/
|
||||||
|
private BigDecimal wipCount;
|
||||||
|
/**
|
||||||
|
* 不良品数(不良数量汇总)。
|
||||||
|
*/
|
||||||
|
private BigDecimal ngCount;
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchOverviewRespDto {
|
||||||
|
/**
|
||||||
|
* 数据统计时点(服务端当前时间)。
|
||||||
|
*/
|
||||||
|
private String asOf;
|
||||||
|
/**
|
||||||
|
* 4 张卡片(固定顺序:完工工单数/生产工单数/在制品/不良品数)。
|
||||||
|
*/
|
||||||
|
private List<Card> cards;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Card {
|
||||||
|
/**
|
||||||
|
* 唯一标识(前端用于识别卡片):finishedWorkOrderCount/workOrderCount/wipCount/ngCount。
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
/**
|
||||||
|
* 卡片标题。
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 主数值(整数)。
|
||||||
|
*/
|
||||||
|
private Long value;
|
||||||
|
/**
|
||||||
|
* 环比增长率: (本期-上期)/上期。
|
||||||
|
* <p>例如 0.68 表示 +68%。</p>
|
||||||
|
*/
|
||||||
|
private BigDecimal mom;
|
||||||
|
/**
|
||||||
|
* 同比增长率: (本期-去年同期)/去年同期。
|
||||||
|
* <p>例如 -0.05 表示 -5%。</p>
|
||||||
|
*/
|
||||||
|
private BigDecimal yoy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchProcessDefectRankRespDto {
|
||||||
|
/**
|
||||||
|
* 排名列表。
|
||||||
|
*/
|
||||||
|
private List<Item> items;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Item {
|
||||||
|
/**
|
||||||
|
* 名次(从 1 开始)。
|
||||||
|
*/
|
||||||
|
private Integer rank;
|
||||||
|
/**
|
||||||
|
* 工序/作业名称。
|
||||||
|
*/
|
||||||
|
private String processName;
|
||||||
|
/**
|
||||||
|
* 不良率:不良数 / (合格数 + 不良数)。
|
||||||
|
* <p>例如 0.40 表示 40%。</p>
|
||||||
|
*/
|
||||||
|
private BigDecimal defectRate;
|
||||||
|
/**
|
||||||
|
* 不良数量。
|
||||||
|
*/
|
||||||
|
private Long defectQty;
|
||||||
|
/**
|
||||||
|
* 送检数量(合格数 + 不良数)。
|
||||||
|
*/
|
||||||
|
private Long inspectedQty;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchProcessDefectRankRowDto {
|
||||||
|
/**
|
||||||
|
* 工序/作业名称(来自明细 process_name)。
|
||||||
|
*/
|
||||||
|
private String processName;
|
||||||
|
/**
|
||||||
|
* 不良数量(unqualified_qty 汇总)。
|
||||||
|
*/
|
||||||
|
private BigDecimal defectQty;
|
||||||
|
/**
|
||||||
|
* 送检数量(qualified_qty + unqualified_qty 汇总)。
|
||||||
|
*/
|
||||||
|
private BigDecimal inspectedQty;
|
||||||
|
/**
|
||||||
|
* 不良率(defectQty / inspectedQty)。
|
||||||
|
*/
|
||||||
|
private BigDecimal defectRate;
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchWorkOrderBarPointDto {
|
||||||
|
/**
|
||||||
|
* 分组桶标识:
|
||||||
|
* <ul>
|
||||||
|
* <li>groupBy=day:yyyy-MM-dd</li>
|
||||||
|
* <li>groupBy=month:数字月份(1~12)</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
private String bucket;
|
||||||
|
/**
|
||||||
|
* 分组内工单数(count distinct 主表 id)。
|
||||||
|
*/
|
||||||
|
private Long cnt;
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchWorkOrderBarRespDto {
|
||||||
|
/**
|
||||||
|
* X 轴分组名称:
|
||||||
|
* <ul>
|
||||||
|
* <li>groupBy=month:固定为 1月~12月</li>
|
||||||
|
* <li>groupBy=day:为 yyyy-MM-dd</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
private List<String> xAxis;
|
||||||
|
/**
|
||||||
|
* 系列数据(当前只有 1 个系列:工单数)。
|
||||||
|
*/
|
||||||
|
private List<Series> series;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Series {
|
||||||
|
/**
|
||||||
|
* 系列名称(例如:工单数)。
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 与 xAxis 一一对应的数据点。
|
||||||
|
*/
|
||||||
|
private List<Long> data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchWorkOrderProgressRespDto {
|
||||||
|
private List<Item> items;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Item {
|
||||||
|
private String workOrderNo;
|
||||||
|
private String status;
|
||||||
|
private Long progress;
|
||||||
|
private Long totalQty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.ruoyi.system.domain.dto.workbench;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkbenchWorkOrderProgressRowDto {
|
||||||
|
private String workOrderNo;
|
||||||
|
private String status;
|
||||||
|
private BigDecimal progress;
|
||||||
|
private BigDecimal totalQty;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.ruoyi.system.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class EquipmentInfoVo {
|
||||||
|
|
||||||
|
@ExcelProperty("id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ExcelProperty("设备名称")
|
||||||
|
private String equipmentName;
|
||||||
|
|
||||||
|
@ExcelProperty("设备编号")
|
||||||
|
private String equipmentCode;
|
||||||
|
|
||||||
|
@ExcelProperty("作业人员")
|
||||||
|
private String operator;
|
||||||
|
|
||||||
|
@ExcelProperty("所属工段")
|
||||||
|
private String workCenterName;
|
||||||
|
|
||||||
|
@ExcelProperty("创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.ruoyi.system.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
||||||
|
import com.ruoyi.system.domain.EquipmentInfo;
|
||||||
|
import com.ruoyi.system.domain.vo.EquipmentInfoVo;
|
||||||
|
|
||||||
|
public interface EquipmentInfoMapper extends BaseMapperPlus<EquipmentInfoMapper, EquipmentInfo, EquipmentInfoVo> {
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
package com.ruoyi.system.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchOverviewAggDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchProcessDefectRankRowDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderBarPointDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderProgressRowDto;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台(看板)统计查询。
|
||||||
|
*
|
||||||
|
* <p>这里的查询只负责“按口径聚合出结果”,不做时间范围推导、补点、环比/同比等计算。</p>
|
||||||
|
*/
|
||||||
|
public interface WorkbenchMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 概览卡片所需的聚合汇总。
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>workOrderCount:工单数(主表记录数)</li>
|
||||||
|
* <li>finishedWorkOrderCount:完工工单数(当前实现口径:取每个工单“最大工序号”的状态=4 认为完工)</li>
|
||||||
|
* <li>wipCount:在制品(当前实现口径:计划数 - 完工数,小于 0 按 0 计)</li>
|
||||||
|
* <li>ngCount:不良品数(明细不良数汇总)</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间
|
||||||
|
* @param endTime 统计结束时间
|
||||||
|
* @param workCenterName 工作中心过滤(可为空)
|
||||||
|
*/
|
||||||
|
WorkbenchOverviewAggDto selectOverviewAgg(@Param("startTime") Date startTime,
|
||||||
|
@Param("endTime") Date endTime,
|
||||||
|
@Param("workCenterName") String workCenterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工单数量柱状图的分组统计点。
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间
|
||||||
|
* @param endTime 统计结束时间
|
||||||
|
* @param groupBy day|month
|
||||||
|
* @param workCenterName 工作中心过滤(可为空)
|
||||||
|
*/
|
||||||
|
List<WorkbenchWorkOrderBarPointDto> selectWorkOrderBar(@Param("startTime") Date startTime,
|
||||||
|
@Param("endTime") Date endTime,
|
||||||
|
@Param("groupBy") String groupBy,
|
||||||
|
@Param("workCenterName") String workCenterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工单实时进度列表。
|
||||||
|
*
|
||||||
|
* <p>进度=合格数汇总/计划数汇总*100。</p>
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间
|
||||||
|
* @param endTime 统计结束时间
|
||||||
|
* @param topN 返回条数
|
||||||
|
* @param workCenterName 工作中心过滤(可为空)
|
||||||
|
*/
|
||||||
|
List<WorkbenchWorkOrderProgressRowDto> selectWorkOrderProgress(@Param("startTime") Date startTime,
|
||||||
|
@Param("endTime") Date endTime,
|
||||||
|
@Param("topN") Integer topN,
|
||||||
|
@Param("workCenterName") String workCenterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工序不良率 TopN。
|
||||||
|
*
|
||||||
|
* <p>defectRate = defectQty / inspectedQty,inspectedQty = okQty + ngQty。</p>
|
||||||
|
*
|
||||||
|
* @param startTime 统计开始时间
|
||||||
|
* @param endTime 统计结束时间
|
||||||
|
* @param topN 返回条数
|
||||||
|
* @param workCenterName 工作中心过滤(可为空)
|
||||||
|
*/
|
||||||
|
List<WorkbenchProcessDefectRankRowDto> selectProcessDefectRank(@Param("startTime") Date startTime,
|
||||||
|
@Param("endTime") Date endTime,
|
||||||
|
@Param("topN") Integer topN,
|
||||||
|
@Param("workCenterName") String workCenterName);
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.system.domain.bo.EquipmentInfoBo;
|
||||||
|
import com.ruoyi.system.domain.vo.EquipmentInfoVo;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IEquipmentInfoService {
|
||||||
|
|
||||||
|
EquipmentInfoVo queryById(Long id);
|
||||||
|
|
||||||
|
TableDataInfo<EquipmentInfoVo> queryPageList(EquipmentInfoBo bo, PageQuery pageQuery);
|
||||||
|
|
||||||
|
List<EquipmentInfoVo> queryList(EquipmentInfoBo bo);
|
||||||
|
|
||||||
|
List<EquipmentInfoVo> queryOptions(String workCenterName, String keyword);
|
||||||
|
|
||||||
|
Boolean insertByBo(EquipmentInfoBo bo);
|
||||||
|
|
||||||
|
Boolean updateByBo(EquipmentInfoBo bo);
|
||||||
|
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchOverviewRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderProgressRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchProcessDefectRankRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderBarRespDto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作台(看板)统计服务。
|
||||||
|
* <p>
|
||||||
|
* 统一约定:时间字符串入参格式为 yyyy-MM-dd HH:mm:ss。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface IWorkbenchService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顶部 4 张概览卡片。
|
||||||
|
*
|
||||||
|
* <p>mom/yoy 为“增长率”,不是百分数:例如 0.68 表示 +68%。</p>
|
||||||
|
*
|
||||||
|
* @param rangeType day|week|month|year(默认 month,仅在未传 startTime/endTime 时生效)
|
||||||
|
* @param startTime 自定义开始时间(可选)
|
||||||
|
* @param endTime 自定义结束时间(可选)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
WorkbenchOverviewRespDto overview(String rangeType, String startTime, String endTime, String workCenterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工单数量柱状图。
|
||||||
|
*
|
||||||
|
* @param startTime 开始时间(可选,不传则默认当年 1~12 月)
|
||||||
|
* @param endTime 结束时间(可选,不传则默认当年 1~12 月)
|
||||||
|
* @param groupBy month|day(默认 month)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
WorkbenchWorkOrderBarRespDto workOrderBar(String startTime, String endTime, String groupBy, String workCenterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工单实时进度列表。
|
||||||
|
*
|
||||||
|
* @param startTime 开始时间(可选,不传则默认 month 范围)
|
||||||
|
* @param endTime 结束时间(可选,不传则默认 month 范围)
|
||||||
|
* @param topN 返回条数(默认 5)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
WorkbenchWorkOrderProgressRespDto workOrderProgress(String startTime, String endTime, Integer topN, String workCenterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工序不良率 TopN。
|
||||||
|
*
|
||||||
|
* @param startTime 开始时间(可选,不传则默认 month 范围)
|
||||||
|
* @param endTime 结束时间(可选,不传则默认 month 范围)
|
||||||
|
* @param topN TopN(默认 10)
|
||||||
|
* @param workCenterName 工作中心名称(可选)
|
||||||
|
*/
|
||||||
|
WorkbenchProcessDefectRankRespDto processDefectRank(String startTime, String endTime, Integer topN, String workCenterName);
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.domain.EquipmentInfo;
|
||||||
|
import com.ruoyi.system.domain.bo.EquipmentInfoBo;
|
||||||
|
import com.ruoyi.system.domain.vo.EquipmentInfoVo;
|
||||||
|
import com.ruoyi.system.mapper.EquipmentInfoMapper;
|
||||||
|
import com.ruoyi.system.service.IEquipmentInfoService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EquipmentInfoServiceImpl implements IEquipmentInfoService {
|
||||||
|
|
||||||
|
private final EquipmentInfoMapper baseMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EquipmentInfoVo queryById(Long id) {
|
||||||
|
return baseMapper.selectVoById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<EquipmentInfoVo> queryPageList(EquipmentInfoBo bo, PageQuery pageQuery) {
|
||||||
|
LambdaQueryWrapper<EquipmentInfo> lqw = buildQueryWrapper(bo);
|
||||||
|
Page<EquipmentInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||||
|
return TableDataInfo.build(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EquipmentInfoVo> queryList(EquipmentInfoBo bo) {
|
||||||
|
LambdaQueryWrapper<EquipmentInfo> lqw = buildQueryWrapper(bo);
|
||||||
|
return baseMapper.selectVoList(lqw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EquipmentInfoVo> queryOptions(String workCenterName, String keyword) {
|
||||||
|
LambdaQueryWrapper<EquipmentInfo> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(StringUtils.isNotBlank(workCenterName), EquipmentInfo::getWorkCenterName, workCenterName);
|
||||||
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
|
String kw = keyword.trim();
|
||||||
|
lqw.and(w -> w.like(EquipmentInfo::getEquipmentName, kw).or().like(EquipmentInfo::getEquipmentCode, kw));
|
||||||
|
}
|
||||||
|
lqw.orderByAsc(EquipmentInfo::getWorkCenterName)
|
||||||
|
.orderByAsc(EquipmentInfo::getEquipmentName)
|
||||||
|
.orderByAsc(EquipmentInfo::getEquipmentCode);
|
||||||
|
return baseMapper.selectVoList(lqw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<EquipmentInfo> buildQueryWrapper(EquipmentInfoBo bo) {
|
||||||
|
Map<String, Object> params = bo.getParams();
|
||||||
|
LambdaQueryWrapper<EquipmentInfo> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getEquipmentCode()), EquipmentInfo::getEquipmentCode, bo.getEquipmentCode());
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getEquipmentName()), EquipmentInfo::getEquipmentName, bo.getEquipmentName());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getOperator()), EquipmentInfo::getOperator, bo.getOperator());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getWorkCenterName()), EquipmentInfo::getWorkCenterName, bo.getWorkCenterName());
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean insertByBo(EquipmentInfoBo bo) {
|
||||||
|
EquipmentInfo add = BeanUtil.toBean(bo, EquipmentInfo.class);
|
||||||
|
return baseMapper.insert(add) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean updateByBo(EquipmentInfoBo bo) {
|
||||||
|
EquipmentInfo update = BeanUtil.toBean(bo, EquipmentInfo.class);
|
||||||
|
return baseMapper.updateById(update) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -2,15 +2,14 @@ package com.ruoyi.system.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.core.domain.PageQuery;
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.ruoyi.common.helper.LoginHelper;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import lombok.var;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.ruoyi.system.domain.bo.SfcOperationPlanningMainBo;
|
import com.ruoyi.system.domain.bo.SfcOperationPlanningMainBo;
|
||||||
@ -384,38 +383,12 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TableDataInfo<OperationPlanResultDTO> queryCascadePageList(SfcOperationPlanningMainBo bo, PageQuery pageQuery) {
|
public TableDataInfo<OperationPlanResultDTO> queryCascadePageList(SfcOperationPlanningMainBo bo, PageQuery pageQuery) {
|
||||||
// 1. 获取当前登录用户信息与工段
|
// 1. 构建主表查询条件
|
||||||
boolean isAdmin = false;
|
|
||||||
String currentUserWorkCenter = "";
|
|
||||||
try {
|
|
||||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
|
||||||
if (loginUser != null && loginUser.getDeptName() != null) {
|
|
||||||
isAdmin = com.ruoyi.common.helper.LoginHelper.isAdmin();
|
|
||||||
if (loginUser.getDeptName() != null) {
|
|
||||||
currentUserWorkCenter = loginUser.getDeptName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("获取当前登录用户失败,可能未登录或在定时任务中执行");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 构建主表查询条件
|
|
||||||
LambdaQueryWrapper<SfcOperationPlanningMain> lqw = buildQueryWrapper(bo);
|
LambdaQueryWrapper<SfcOperationPlanningMain> lqw = buildQueryWrapper(bo);
|
||||||
// 过滤生产令号包含“暂停”的记录
|
// 过滤生产令号包含“暂停”的记录
|
||||||
lqw.notLike(SfcOperationPlanningMain::getHbytSclh, "暂停");
|
lqw.notLike(SfcOperationPlanningMain::getHbytSclh, "暂停");
|
||||||
|
|
||||||
// 3. 如果不是管理员,且有所属工段,且部门名称是指定的具体工段之一,则只查询明细表中包含该工段的订单主表 ID
|
// 2. 分页查询主表数据
|
||||||
boolean isSpecificWorkCenter = false;
|
|
||||||
if (!isAdmin && StringUtils.isNotBlank(currentUserWorkCenter)) {
|
|
||||||
List<String> targetWorkCenters = java.util.Arrays.asList("机一工段", "装二工段", "装一工段", "铆焊工段", "机二工段", "委外中心");
|
|
||||||
if (targetWorkCenters.contains(currentUserWorkCenter)) {
|
|
||||||
isSpecificWorkCenter = true;
|
|
||||||
lqw.inSql(SfcOperationPlanningMain::getId,
|
|
||||||
"SELECT main_id FROM sfc_operation_planning_detail WHERE work_center_name = '" + currentUserWorkCenter + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 分页查询主表数据
|
|
||||||
Page<SfcOperationPlanningMain> page = baseMapper.selectPage(pageQuery.build(), lqw);
|
Page<SfcOperationPlanningMain> page = baseMapper.selectPage(pageQuery.build(), lqw);
|
||||||
List<SfcOperationPlanningMain> mainList = page.getRecords();
|
List<SfcOperationPlanningMain> mainList = page.getRecords();
|
||||||
|
|
||||||
@ -423,19 +396,22 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin
|
|||||||
return TableDataInfo.build(new ArrayList<>());
|
return TableDataInfo.build(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 提取当前页所有主表的 ID
|
// 3. 提取当前页所有主表的 ID
|
||||||
List<Long> mainIds = mainList.stream().map(SfcOperationPlanningMain::getId).collect(Collectors.toList());
|
List<Long> mainIds = mainList.stream().map(SfcOperationPlanningMain::getId).collect(Collectors.toList());
|
||||||
|
|
||||||
// 6. 根据主表 ID 批量查询子表数据,并按工序号升序排序 (这里查询所有的明细用于计算外层的总进度)
|
// 4. 根据主表 ID 批量查询子表数据,并按工序号升序排序 (这里查询所有的明细用于计算外层的总进度)
|
||||||
List<SfcOperationPlanningDetail> detailList = detailMapper.selectList(Wrappers.<SfcOperationPlanningDetail>lambdaQuery()
|
var detailQuery = Wrappers.<SfcOperationPlanningDetail>lambdaQuery()
|
||||||
.in(SfcOperationPlanningDetail::getMainId, mainIds)
|
.in(SfcOperationPlanningDetail::getMainId, mainIds);
|
||||||
.orderByAsc(SfcOperationPlanningDetail::getOperNumber));
|
if (StringUtils.isNotBlank(bo.getWorkCenterName())) {
|
||||||
|
detailQuery.eq(SfcOperationPlanningDetail::getWorkCenterName, bo.getWorkCenterName().trim());
|
||||||
|
}
|
||||||
|
List<SfcOperationPlanningDetail> detailList = detailMapper.selectList(detailQuery.orderByAsc(SfcOperationPlanningDetail::getOperNumber));
|
||||||
|
|
||||||
// 7. 按主表 ID 对子表数据进行分组
|
// 5. 按主表 ID 对子表数据进行分组
|
||||||
Map<Long, List<SfcOperationPlanningDetail>> detailMap = detailList.stream()
|
Map<Long, List<SfcOperationPlanningDetail>> detailMap = detailList.stream()
|
||||||
.collect(Collectors.groupingBy(SfcOperationPlanningDetail::getMainId));
|
.collect(Collectors.groupingBy(SfcOperationPlanningDetail::getMainId));
|
||||||
|
|
||||||
// 8. 组装返回给前端的层级结构
|
// 6. 组装返回给前端的层级结构
|
||||||
List<OperationPlanResultDTO> resultList = new ArrayList<>();
|
List<OperationPlanResultDTO> resultList = new ArrayList<>();
|
||||||
for (SfcOperationPlanningMain main : mainList) {
|
for (SfcOperationPlanningMain main : mainList) {
|
||||||
OperationPlanResultDTO resultDTO = new OperationPlanResultDTO();
|
OperationPlanResultDTO resultDTO = new OperationPlanResultDTO();
|
||||||
@ -472,13 +448,7 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建明细列表,并在构建时进行权限过滤(只有指定的几个工段用户才只能看到自己的数据,其他非管理员都能看所有)
|
|
||||||
for (SfcOperationPlanningDetail detail : relatedDetails) {
|
for (SfcOperationPlanningDetail detail : relatedDetails) {
|
||||||
// 权限过滤:如果当前用户属于这几个特定的工段,则只显示自己工段的明细
|
|
||||||
if (isSpecificWorkCenter && !currentUserWorkCenter.equals(detail.getWorkCenterName())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessDetailDTO detailDTO = new ProcessDetailDTO();
|
ProcessDetailDTO detailDTO = new ProcessDetailDTO();
|
||||||
detailDTO.setOperNo(detail.getOperNumber() != null ? detail.getOperNumber().intValue() : null);
|
detailDTO.setOperNo(detail.getOperNumber() != null ? detail.getOperNumber().intValue() : null);
|
||||||
detailDTO.setProcessName(detail.getProcessName());
|
detailDTO.setProcessName(detail.getProcessName());
|
||||||
@ -593,8 +563,23 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin
|
|||||||
lqw.eq(StringUtils.isNotBlank(bo.getProductCode()), SfcOperationPlanningMain::getProductCode, bo.getProductCode());
|
lqw.eq(StringUtils.isNotBlank(bo.getProductCode()), SfcOperationPlanningMain::getProductCode, bo.getProductCode());
|
||||||
lqw.like(StringUtils.isNotBlank(bo.getProductName()), SfcOperationPlanningMain::getProductName, bo.getProductName());
|
lqw.like(StringUtils.isNotBlank(bo.getProductName()), SfcOperationPlanningMain::getProductName, bo.getProductName());
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getProSpecification()), SfcOperationPlanningMain::getProSpecification, bo.getProSpecification());
|
lqw.eq(StringUtils.isNotBlank(bo.getProSpecification()), SfcOperationPlanningMain::getProSpecification, bo.getProSpecification());
|
||||||
lqw.eq(bo.getPlanStartTime() != null, SfcOperationPlanningMain::getPlanStartTime, bo.getPlanStartTime());
|
lqw.ge(bo.getPlanStartTime() != null, SfcOperationPlanningMain::getPlanStartTime, bo.getPlanStartTime());
|
||||||
lqw.eq(bo.getPlanFinishTime() != null, SfcOperationPlanningMain::getPlanFinishTime, bo.getPlanFinishTime());
|
lqw.le(bo.getPlanFinishTime() != null, SfcOperationPlanningMain::getPlanFinishTime, bo.getPlanFinishTime());
|
||||||
|
if (StringUtils.isNotBlank(bo.getWorkCenterName())) {
|
||||||
|
String workCenterName = bo.getWorkCenterName().trim();
|
||||||
|
List<Long> filteredMainIds = detailMapper.selectList(Wrappers.<SfcOperationPlanningDetail>lambdaQuery()
|
||||||
|
.select(SfcOperationPlanningDetail::getMainId)
|
||||||
|
.eq(SfcOperationPlanningDetail::getWorkCenterName, workCenterName))
|
||||||
|
.stream()
|
||||||
|
.map(SfcOperationPlanningDetail::getMainId)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (filteredMainIds.isEmpty()) {
|
||||||
|
lqw.eq(SfcOperationPlanningMain::getId, -1L);
|
||||||
|
} else {
|
||||||
|
lqw.in(SfcOperationPlanningMain::getId, filteredMainIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
return lqw;
|
return lqw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,285 @@
|
|||||||
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateField;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchOverviewAggDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchOverviewRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchProcessDefectRankRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchProcessDefectRankRowDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderBarPointDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderBarRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderProgressRespDto;
|
||||||
|
import com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderProgressRowDto;
|
||||||
|
import com.ruoyi.system.mapper.WorkbenchMapper;
|
||||||
|
import com.ruoyi.system.service.IWorkbenchService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WorkbenchServiceImpl implements IWorkbenchService {
|
||||||
|
|
||||||
|
private final WorkbenchMapper workbenchMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkbenchOverviewRespDto overview(String rangeType, String startTime, String endTime, String workCenterName) {
|
||||||
|
Date asOf = new Date();
|
||||||
|
TimeRange current = resolveRange(rangeType, startTime, endTime, asOf);
|
||||||
|
TimeRange prev = previousRange(current);
|
||||||
|
TimeRange yoy = yearOverYearRange(current);
|
||||||
|
|
||||||
|
WorkbenchOverviewAggDto curAgg = defaultAgg(workbenchMapper.selectOverviewAgg(current.startTime, current.endTime, trimToNull(workCenterName)));
|
||||||
|
WorkbenchOverviewAggDto prevAgg = defaultAgg(workbenchMapper.selectOverviewAgg(prev.startTime, prev.endTime, trimToNull(workCenterName)));
|
||||||
|
WorkbenchOverviewAggDto yoyAgg = defaultAgg(workbenchMapper.selectOverviewAgg(yoy.startTime, yoy.endTime, trimToNull(workCenterName)));
|
||||||
|
|
||||||
|
WorkbenchOverviewRespDto resp = new WorkbenchOverviewRespDto();
|
||||||
|
resp.setAsOf(DateUtil.formatDateTime(asOf));
|
||||||
|
|
||||||
|
List<WorkbenchOverviewRespDto.Card> cards = new ArrayList<>();
|
||||||
|
cards.add(buildCard("finishedWorkOrderCount", "完工工单数",
|
||||||
|
nvl(curAgg.getFinishedWorkOrderCount()), nvl(prevAgg.getFinishedWorkOrderCount()), nvl(yoyAgg.getFinishedWorkOrderCount())));
|
||||||
|
cards.add(buildCard("workOrderCount", "生产工单数",
|
||||||
|
nvl(curAgg.getWorkOrderCount()), nvl(prevAgg.getWorkOrderCount()), nvl(yoyAgg.getWorkOrderCount())));
|
||||||
|
cards.add(buildCard("wipCount", "在制品",
|
||||||
|
toLong(curAgg.getWipCount()), toLong(prevAgg.getWipCount()), toLong(yoyAgg.getWipCount())));
|
||||||
|
cards.add(buildCard("ngCount", "不良品数",
|
||||||
|
toLong(curAgg.getNgCount()), toLong(prevAgg.getNgCount()), toLong(yoyAgg.getNgCount())));
|
||||||
|
resp.setCards(cards);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkbenchWorkOrderBarRespDto workOrderBar(String startTime, String endTime, String groupBy, String workCenterName) {
|
||||||
|
Date asOf = new Date();
|
||||||
|
TimeRange range = resolveBarRange(startTime, endTime, asOf);
|
||||||
|
String gb = normalizeGroupBy(groupBy);
|
||||||
|
|
||||||
|
List<WorkbenchWorkOrderBarPointDto> points = workbenchMapper.selectWorkOrderBar(range.startTime, range.endTime, gb, trimToNull(workCenterName));
|
||||||
|
Map<String, Long> bucketToCnt = new HashMap<>();
|
||||||
|
if (points != null) {
|
||||||
|
for (WorkbenchWorkOrderBarPointDto p : points) {
|
||||||
|
if (p != null && StringUtils.isNotBlank(p.getBucket())) {
|
||||||
|
bucketToCnt.put(p.getBucket(), nvl(p.getCnt()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkbenchWorkOrderBarRespDto resp = new WorkbenchWorkOrderBarRespDto();
|
||||||
|
WorkbenchWorkOrderBarRespDto.Series series = new WorkbenchWorkOrderBarRespDto.Series();
|
||||||
|
series.setName("工单数");
|
||||||
|
|
||||||
|
if ("day".equals(gb)) {
|
||||||
|
List<String> xAxis = new ArrayList<>();
|
||||||
|
List<Long> data = new ArrayList<>();
|
||||||
|
|
||||||
|
Date cursor = DateUtil.beginOfDay(range.startTime);
|
||||||
|
Date endDay = DateUtil.beginOfDay(range.endTime);
|
||||||
|
while (!cursor.after(endDay)) {
|
||||||
|
String bucket = DateUtil.format(cursor, "yyyy-MM-dd");
|
||||||
|
xAxis.add(bucket);
|
||||||
|
data.add(bucketToCnt.getOrDefault(bucket, 0L));
|
||||||
|
cursor = DateUtil.offsetDay(cursor, 1);
|
||||||
|
}
|
||||||
|
resp.setXAxis(xAxis);
|
||||||
|
series.setData(data);
|
||||||
|
} else {
|
||||||
|
List<String> xAxis = new ArrayList<>();
|
||||||
|
List<Long> data = new ArrayList<>();
|
||||||
|
for (int m = 1; m <= 12; m++) {
|
||||||
|
xAxis.add(m + "月");
|
||||||
|
data.add(bucketToCnt.getOrDefault(String.valueOf(m), 0L));
|
||||||
|
}
|
||||||
|
resp.setXAxis(xAxis);
|
||||||
|
series.setData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WorkbenchWorkOrderBarRespDto.Series> seriesList = new ArrayList<>();
|
||||||
|
seriesList.add(series);
|
||||||
|
resp.setSeries(seriesList);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkbenchWorkOrderProgressRespDto workOrderProgress(String startTime, String endTime, Integer topN, String workCenterName) {
|
||||||
|
Date asOf = new Date();
|
||||||
|
TimeRange range = resolveRange("month", startTime, endTime, asOf);
|
||||||
|
int limit = (topN == null || topN <= 0) ? 5 : topN;
|
||||||
|
|
||||||
|
List<WorkbenchWorkOrderProgressRowDto> rows = workbenchMapper.selectWorkOrderProgress(range.startTime, range.endTime, limit, trimToNull(workCenterName));
|
||||||
|
List<WorkbenchWorkOrderProgressRespDto.Item> items = new ArrayList<>();
|
||||||
|
if (rows != null) {
|
||||||
|
for (WorkbenchWorkOrderProgressRowDto r : rows) {
|
||||||
|
WorkbenchWorkOrderProgressRespDto.Item item = new WorkbenchWorkOrderProgressRespDto.Item();
|
||||||
|
item.setWorkOrderNo(r.getWorkOrderNo());
|
||||||
|
item.setStatus(r.getStatus());
|
||||||
|
item.setProgress(toLong(r.getProgress()));
|
||||||
|
item.setTotalQty(toLong(r.getTotalQty()));
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkbenchWorkOrderProgressRespDto resp = new WorkbenchWorkOrderProgressRespDto();
|
||||||
|
resp.setItems(items);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkbenchProcessDefectRankRespDto processDefectRank(String startTime, String endTime, Integer topN, String workCenterName) {
|
||||||
|
Date asOf = new Date();
|
||||||
|
TimeRange range = resolveRange("month", startTime, endTime, asOf);
|
||||||
|
int limit = (topN == null || topN <= 0) ? 10 : topN;
|
||||||
|
|
||||||
|
List<WorkbenchProcessDefectRankRowDto> rows = workbenchMapper.selectProcessDefectRank(range.startTime, range.endTime, limit, trimToNull(workCenterName));
|
||||||
|
List<WorkbenchProcessDefectRankRespDto.Item> items = new ArrayList<>();
|
||||||
|
if (rows != null) {
|
||||||
|
int rank = 1;
|
||||||
|
for (WorkbenchProcessDefectRankRowDto r : rows) {
|
||||||
|
WorkbenchProcessDefectRankRespDto.Item item = new WorkbenchProcessDefectRankRespDto.Item();
|
||||||
|
item.setRank(rank++);
|
||||||
|
item.setProcessName(r.getProcessName());
|
||||||
|
item.setDefectRate(scale(r.getDefectRate(), 4));
|
||||||
|
item.setDefectQty(toLong(r.getDefectQty()));
|
||||||
|
item.setInspectedQty(toLong(r.getInspectedQty()));
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkbenchProcessDefectRankRespDto resp = new WorkbenchProcessDefectRankRespDto();
|
||||||
|
resp.setItems(items);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkbenchOverviewRespDto.Card buildCard(String key, String title, long cur, long prev, long yoy) {
|
||||||
|
WorkbenchOverviewRespDto.Card card = new WorkbenchOverviewRespDto.Card();
|
||||||
|
card.setKey(key);
|
||||||
|
card.setTitle(title);
|
||||||
|
card.setValue(cur);
|
||||||
|
card.setMom(calcRate(cur, prev));
|
||||||
|
card.setYoy(calcRate(cur, yoy));
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal calcRate(long current, long base) {
|
||||||
|
if (base == 0L) {
|
||||||
|
return current == 0L ? BigDecimal.ZERO : BigDecimal.ONE;
|
||||||
|
}
|
||||||
|
return BigDecimal.valueOf(current)
|
||||||
|
.subtract(BigDecimal.valueOf(base))
|
||||||
|
.divide(BigDecimal.valueOf(base), 4, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal scale(BigDecimal val, int scale) {
|
||||||
|
if (val == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return val.setScale(scale, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkbenchOverviewAggDto defaultAgg(WorkbenchOverviewAggDto agg) {
|
||||||
|
if (agg != null) {
|
||||||
|
if (agg.getWorkOrderCount() == null) agg.setWorkOrderCount(0L);
|
||||||
|
if (agg.getFinishedWorkOrderCount() == null) agg.setFinishedWorkOrderCount(0L);
|
||||||
|
if (agg.getWipCount() == null) agg.setWipCount(BigDecimal.ZERO);
|
||||||
|
if (agg.getNgCount() == null) agg.setNgCount(BigDecimal.ZERO);
|
||||||
|
return agg;
|
||||||
|
}
|
||||||
|
WorkbenchOverviewAggDto a = new WorkbenchOverviewAggDto();
|
||||||
|
a.setWorkOrderCount(0L);
|
||||||
|
a.setFinishedWorkOrderCount(0L);
|
||||||
|
a.setWipCount(BigDecimal.ZERO);
|
||||||
|
a.setNgCount(BigDecimal.ZERO);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long nvl(Long v) {
|
||||||
|
return v == null ? 0L : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long toLong(BigDecimal v) {
|
||||||
|
return v == null ? 0L : v.setScale(0, RoundingMode.HALF_UP).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String s) {
|
||||||
|
if (StringUtils.isBlank(s)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String t = s.trim();
|
||||||
|
return t.isEmpty() ? null : t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeGroupBy(String groupBy) {
|
||||||
|
if ("day".equalsIgnoreCase(groupBy)) {
|
||||||
|
return "day";
|
||||||
|
}
|
||||||
|
return "month";
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimeRange resolveBarRange(String startTime, String endTime, Date asOf) {
|
||||||
|
if (StringUtils.isBlank(startTime) || StringUtils.isBlank(endTime)) {
|
||||||
|
Date start = DateUtil.beginOfYear(asOf);
|
||||||
|
Date end = DateUtil.endOfYear(asOf);
|
||||||
|
return new TimeRange(start, end);
|
||||||
|
}
|
||||||
|
return new TimeRange(parseDateTime(startTime), parseDateTime(endTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimeRange resolveRange(String rangeType, String startTime, String endTime, Date asOf) {
|
||||||
|
if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
|
||||||
|
return new TimeRange(parseDateTime(startTime), parseDateTime(endTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
String rt = StringUtils.defaultIfBlank(rangeType, "month").toLowerCase();
|
||||||
|
Date start;
|
||||||
|
if ("day".equals(rt)) {
|
||||||
|
start = DateUtil.beginOfDay(asOf);
|
||||||
|
} else if ("week".equals(rt)) {
|
||||||
|
start = DateUtil.beginOfWeek(asOf);
|
||||||
|
} else if ("year".equals(rt)) {
|
||||||
|
start = DateUtil.beginOfYear(asOf);
|
||||||
|
} else {
|
||||||
|
start = DateUtil.beginOfMonth(asOf);
|
||||||
|
}
|
||||||
|
return new TimeRange(start, asOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date parseDateTime(String s) {
|
||||||
|
return DateUtil.parse(s.trim(), "yyyy-MM-dd HH:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimeRange previousRange(TimeRange current) {
|
||||||
|
long durationMs = current.endTime.getTime() - current.startTime.getTime();
|
||||||
|
Date prevEnd = new Date(current.startTime.getTime() - 1);
|
||||||
|
Date prevStart = new Date(prevEnd.getTime() - durationMs);
|
||||||
|
return new TimeRange(prevStart, prevEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimeRange yearOverYearRange(TimeRange current) {
|
||||||
|
Date start = DateUtil.offset(current.startTime, DateField.YEAR, -1);
|
||||||
|
Date end = DateUtil.offset(current.endTime, DateField.YEAR, -1);
|
||||||
|
return new TimeRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TimeRange {
|
||||||
|
private final Date startTime;
|
||||||
|
private final Date endTime;
|
||||||
|
|
||||||
|
private TimeRange(Date startTime, Date endTime) {
|
||||||
|
if (startTime != null && endTime != null && startTime.after(endTime)) {
|
||||||
|
this.startTime = endTime;
|
||||||
|
this.endTime = startTime;
|
||||||
|
} else {
|
||||||
|
this.startTime = startTime;
|
||||||
|
this.endTime = endTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.system.mapper.EquipmentInfoMapper">
|
||||||
|
|
||||||
|
<resultMap type="com.ruoyi.system.domain.EquipmentInfo" id="EquipmentInfoResult">
|
||||||
|
<result property="id" column="id"/>
|
||||||
|
<result property="equipmentName" column="equipment_name"/>
|
||||||
|
<result property="equipmentCode" column="equipment_code"/>
|
||||||
|
<result property="operator" column="operator"/>
|
||||||
|
<result property="workCenterName" column="work_center_name"/>
|
||||||
|
<result property="createTime" column="create_time"/>
|
||||||
|
<result property="updateTime" column="update_time"/>
|
||||||
|
<result property="createBy" column="create_by"/>
|
||||||
|
<result property="updateBy" column="update_by"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|
||||||
@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.system.mapper.WorkbenchMapper">
|
||||||
|
|
||||||
|
<select id="selectOverviewAgg" resultType="com.ruoyi.system.domain.dto.workbench.WorkbenchOverviewAggDto">
|
||||||
|
SELECT
|
||||||
|
COALESCE(COUNT(t.main_id), 0) AS workOrderCount,
|
||||||
|
COALESCE(SUM(t.finished_flag), 0) AS finishedWorkOrderCount,
|
||||||
|
COALESCE(SUM(CASE WHEN (t.plan_qty - t.finish_qty) > 0 THEN (t.plan_qty - t.finish_qty) ELSE 0 END), 0) AS wipCount,
|
||||||
|
COALESCE(SUM(t.ng_qty), 0) AS ngCount
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
a.main_id,
|
||||||
|
a.plan_qty,
|
||||||
|
a.ng_qty,
|
||||||
|
CASE WHEN COALESCE(d2.oper_status, '') = '4' THEN 1 ELSE 0 END AS finished_flag,
|
||||||
|
COALESCE(SUM(COALESCE(d2.qualified_qty, 0)), 0) AS finish_qty
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
d.main_id,
|
||||||
|
MAX(d.oper_number) AS max_oper,
|
||||||
|
MAX(COALESCE(d.oper_qty, 0)) AS plan_qty,
|
||||||
|
SUM(COALESCE(d.unqualified_qty, 0)) AS ng_qty
|
||||||
|
FROM sfc_operation_planning_detail d
|
||||||
|
INNER JOIN sfc_operation_planning_main m ON m.id = d.main_id
|
||||||
|
WHERE m.plan_start_time <![CDATA[>=]]> #{startTime}
|
||||||
|
AND m.plan_start_time <![CDATA[<=]]> #{endTime}
|
||||||
|
<if test="workCenterName != null and workCenterName != ''">
|
||||||
|
AND d.work_center_name = #{workCenterName}
|
||||||
|
</if>
|
||||||
|
GROUP BY d.main_id
|
||||||
|
) a
|
||||||
|
LEFT JOIN sfc_operation_planning_detail d2
|
||||||
|
ON d2.main_id = a.main_id
|
||||||
|
AND d2.oper_number = a.max_oper
|
||||||
|
GROUP BY a.main_id, a.plan_qty, a.ng_qty, finished_flag
|
||||||
|
) t
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectWorkOrderBar" resultType="com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderBarPointDto">
|
||||||
|
SELECT
|
||||||
|
<choose>
|
||||||
|
<when test="groupBy == 'day'">
|
||||||
|
DATE_FORMAT(m.plan_start_time, '%Y-%m-%d')
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
DATE_FORMAT(m.plan_start_time, '%c')
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
AS bucket,
|
||||||
|
COUNT(DISTINCT m.id) AS cnt
|
||||||
|
FROM sfc_operation_planning_main m
|
||||||
|
LEFT JOIN sfc_operation_planning_detail d ON d.main_id = m.id
|
||||||
|
WHERE m.plan_start_time <![CDATA[>=]]> #{startTime}
|
||||||
|
AND m.plan_start_time <![CDATA[<=]]> #{endTime}
|
||||||
|
<if test="workCenterName != null and workCenterName != ''">
|
||||||
|
AND d.work_center_name = #{workCenterName}
|
||||||
|
</if>
|
||||||
|
GROUP BY bucket
|
||||||
|
ORDER BY
|
||||||
|
<choose>
|
||||||
|
<when test="groupBy == 'day'">
|
||||||
|
bucket
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
CAST(bucket AS UNSIGNED)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectWorkOrderProgress" resultType="com.ruoyi.system.domain.dto.workbench.WorkbenchWorkOrderProgressRowDto">
|
||||||
|
SELECT
|
||||||
|
m.mo_number AS workOrderNo,
|
||||||
|
CASE
|
||||||
|
WHEN SUM(CASE WHEN COALESCE(d.oper_status, '') = '4' THEN 1 ELSE 0 END) = COUNT(1) THEN '已完工'
|
||||||
|
WHEN SUM(COALESCE(d.trans_in_qty, 0)) > 0
|
||||||
|
OR SUM(COALESCE(d.qualified_qty, 0) + COALESCE(d.unqualified_qty, 0)) > 0
|
||||||
|
OR SUM(CASE WHEN COALESCE(d.oper_status, '') = '3' THEN 1 ELSE 0 END) > 0
|
||||||
|
THEN '已开工'
|
||||||
|
ELSE '未开工'
|
||||||
|
END AS status,
|
||||||
|
CASE
|
||||||
|
WHEN SUM(COALESCE(d.oper_qty, 0)) = 0 THEN 0
|
||||||
|
ELSE ROUND(SUM(COALESCE(d.qualified_qty, 0)) / SUM(COALESCE(d.oper_qty, 0)) * 100, 0)
|
||||||
|
END AS progress,
|
||||||
|
COALESCE(MAX(COALESCE(d.oper_qty, 0)), 0) AS totalQty
|
||||||
|
FROM sfc_operation_planning_main m
|
||||||
|
INNER JOIN sfc_operation_planning_detail d ON d.main_id = m.id
|
||||||
|
WHERE m.plan_start_time <![CDATA[>=]]> #{startTime}
|
||||||
|
AND m.plan_start_time <![CDATA[<=]]> #{endTime}
|
||||||
|
<if test="workCenterName != null and workCenterName != ''">
|
||||||
|
AND d.work_center_name = #{workCenterName}
|
||||||
|
</if>
|
||||||
|
GROUP BY m.mo_number
|
||||||
|
ORDER BY m.plan_start_time DESC, progress DESC
|
||||||
|
LIMIT #{topN}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectProcessDefectRank" resultType="com.ruoyi.system.domain.dto.workbench.WorkbenchProcessDefectRankRowDto">
|
||||||
|
SELECT
|
||||||
|
d.process_name AS processName,
|
||||||
|
COALESCE(SUM(COALESCE(d.unqualified_qty, 0)), 0) AS defectQty,
|
||||||
|
COALESCE(SUM(COALESCE(d.qualified_qty, 0) + COALESCE(d.unqualified_qty, 0)), 0) AS inspectedQty,
|
||||||
|
CASE
|
||||||
|
WHEN SUM(COALESCE(d.qualified_qty, 0) + COALESCE(d.unqualified_qty, 0)) = 0 THEN 0
|
||||||
|
ELSE SUM(COALESCE(d.unqualified_qty, 0)) / SUM(COALESCE(d.qualified_qty, 0) + COALESCE(d.unqualified_qty, 0))
|
||||||
|
END AS defectRate
|
||||||
|
FROM sfc_operation_planning_detail d
|
||||||
|
INNER JOIN sfc_operation_planning_main m ON m.id = d.main_id
|
||||||
|
WHERE m.plan_start_time <![CDATA[>=]]> #{startTime}
|
||||||
|
AND m.plan_start_time <![CDATA[<=]]> #{endTime}
|
||||||
|
<if test="workCenterName != null and workCenterName != ''">
|
||||||
|
AND d.work_center_name = #{workCenterName}
|
||||||
|
</if>
|
||||||
|
GROUP BY d.process_name
|
||||||
|
ORDER BY defectRate DESC, defectQty DESC
|
||||||
|
LIMIT #{topN}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Loading…
Reference in New Issue
Block a user