From 0989ec1e6b465141f99ed67e40fa2a0b928dce94 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期三, 29 四月 2026 16:54:51 +0800
Subject: [PATCH] feat(production): 新增生产核算和生产工单功能模块 - 添加生产核算控制器、服务接口及实现类 - 实现生产核算分页查询和工人生产工资信息查询功能 - 添加生产工单控制器、服务接口及实现类 - 实现生产工单的增删改查和状态统计功能 - 集成工单流转卡下载和二维码生成功能 - 添加工单相关的数据传输对象和值对象 - 实现工单与用户关联的分配功能 - 完善工单附件图片处理和展示功能
---
src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java | 69 +++
src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java | 29 +
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java | 181 +++++++++
src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java | 18
src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java | 5
src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java | 42 +-
src/main/java/com/ruoyi/production/controller/ProductionAccountController.java | 29 +
src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java | 4
src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java | 284 ++++++++++++++++
src/main/resources/mapper/production/ProductionOperationTaskMapper.xml | 24 +
src/main/java/com/ruoyi/production/service/ProductionAccountService.java | 7
src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java | 24 +
src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java | 56 +++
src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java | 2
src/main/resources/mapper/production/ProductionProductMainMapper.xml | 50 ++
src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java | 5
src/main/resources/mapper/production/ProductionAccountMapper.xml | 68 ++++
src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java | 1
src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java | 5
src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java | 63 +++
src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java | 3
src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java | 6
22 files changed, 899 insertions(+), 76 deletions(-)
diff --git a/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java b/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java
index d79f911..79ae5d4 100644
--- a/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java
+++ b/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java
@@ -1,16 +1,10 @@
package com.ruoyi.basic.controller;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.dto.StorageAttachmentDTO;
-import com.ruoyi.basic.dto.StorageBlobDTO;
-import com.ruoyi.basic.dto.SupplierManageDto;
-import com.ruoyi.basic.enums.ApplicationTypeEnum;
-import com.ruoyi.basic.enums.RecordTypeEnum;
-import com.ruoyi.basic.pojo.StorageAttachment;
import com.ruoyi.basic.service.StorageAttachmentService;
-import com.ruoyi.common.constant.StorageAttachmentConstants;
-import com.ruoyi.common.enums.StorageAttachmentRecordType;
import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
@@ -18,26 +12,31 @@
@RestController
@AllArgsConstructor
- @RequestMapping("/basic/storage_attachment")
+@Tag(name = "閫氱敤涓婁紶")
+@RequestMapping("/storageAttachment")
public class StorageAttachmentController {
private StorageAttachmentService storageAttachmentService;
/**
* 鍒嗛〉鏌ヨ閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+ *
* @param storageAttachmentDTO 鍏宠仈璁板綍淇℃伅
* @return 鍒嗛〉缁撴灉
*/
@GetMapping("/list")
+ @Operation(summary = "鍒嗛〉鏌ヨ閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�")
public R list(StorageAttachmentDTO storageAttachmentDTO) {
return R.ok(storageAttachmentService.list(storageAttachmentDTO));
}
/**
* 鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+ *
* @param ids 鏂囦欢id鍒楄〃
* @return 鍒犻櫎缁撴灉
*/
@DeleteMapping("/delete")
+ @Operation(summary = "鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�")
public R batchDelete(@RequestBody List<Long> ids) {
return R.ok(storageAttachmentService.batchDeleteStorageAttachment(ids));
}
@@ -46,6 +45,7 @@
* 淇濆瓨閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
*/
@PostMapping("/add")
+ @Operation(summary = "淇濆瓨閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�")
public R add(@RequestBody StorageAttachmentDTO storageAttachmentDTO) {
storageAttachmentService.saveStorageAttachment(storageAttachmentDTO);
return R.ok();
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java
new file mode 100644
index 0000000..91b97ef
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java
@@ -0,0 +1,63 @@
+package com.ruoyi.production.bean.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.production.pojo.ProductionAccount;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "ProductionAccountDto", description = "production account query dto")
+public class ProductionAccountDto extends ProductionAccount {
+
+ @Schema(description = "sales contract no")
+ private String salesContractNo;
+
+ @Schema(description = "customer contract no")
+ private String customerContractNo;
+
+ @Schema(description = "project name")
+ private String projectName;
+
+ @Schema(description = "customer name")
+ private String customerName;
+
+ @Schema(description = "product category")
+ private String productCategory;
+
+ @Schema(description = "specification model")
+ private String specificationModel;
+
+ @Schema(description = "scheduling user id")
+ private Long schedulingUserId;
+
+ @Schema(description = "scheduling user name")
+ private String schedulingUserName;
+
+ @Schema(description = "process")
+ private String process;
+
+ @Schema(description = "date type(day/month)")
+ private String dateType;
+
+ @Schema(description = "day query date")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate entryDate;
+
+ @Schema(description = "date range")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate[] dateRange;
+
+ @Schema(description = "start date")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate entryDateStart;
+
+ @Schema(description = "end date")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate entryDateEnd;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
index d2653c6..4326c95 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
@@ -1,10 +1,34 @@
package com.ruoyi.production.bean.dto;
import com.ruoyi.production.pojo.ProductionOperationTask;
+import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
@EqualsAndHashCode(callSuper = true)
@Data
public class ProductionOperationTaskDto extends ProductionOperationTask {
+
+ @Schema(description = "宸ュ簭鍚嶇О")
+ private String processName;
+
+ @Schema(description = "鐢熶骇璁㈠崟鍙�")
+ private String productOrderNpsNo;
+
+ @Schema(description = "浜у搧鍚嶇О")
+ private String productName;
+
+ @Schema(description = "瑙勬牸鍨嬪彿")
+ private String model;
+
+ @Schema(description = "鍗曚綅")
+ private String unit;
+
+ @Schema(description = "鎶ュ簾鏁伴噺")
+ private BigDecimal scrapQty;
+
+ @Schema(description = "瀹屾垚杩涘害")
+ private BigDecimal completionStatus;
}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
index 1721e81..9fc8d86 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
@@ -12,57 +12,63 @@
@EqualsAndHashCode(callSuper = true)
@Data
-@Schema(name = "ProductionProductMainDto", description = "鐢熶骇鎶ュ伐鏌ヨ瀵硅薄")
+@Schema(name = "ProductionProductMainDto", description = "production report query dto")
public class ProductionProductMainDto extends ProductionProductMain {
- @Schema(description = "浜у搧宸ヨ壓璺嚎鏄庣粏ID")
+ @Schema(description = "product process route item id")
private Long productProcessRouteItemId;
- @Schema(description = "鐢熶骇鎶ュ伐琛╥d")
+ @Schema(description = "production report id")
private Long productMainId;
- @Schema(description = "绉熸埛ID")
+ @Schema(description = "tenant id")
private Long tenantId;
- @Schema(description = "宸ュ崟缂栧彿")
+ @Schema(description = "work order no")
private String workOrderNo;
- @Schema(description = "宸ュ崟鐘舵��")
+ @Schema(description = "work order status")
private String workOrderStatus;
- @Schema(description = "鏄电О")
+ @Schema(description = "nick name")
private String nickName;
- @Schema(description = "鏁伴噺")
+ @Schema(description = "quantity")
private BigDecimal quantity;
- @Schema(description = "鎶ュ簾鏁伴噺")
+ @Schema(description = "scrap quantity")
private BigDecimal scrapQty;
- @Schema(description = "浜у搧鍚嶇О")
+ @Schema(description = "product name")
private String productName;
- @Schema(description = "浜у搧鍨嬪彿鍚嶇О")
+ @Schema(description = "product model name")
private String productModelName;
- @Schema(description = "鍗曚綅")
+ @Schema(description = "unit")
private String unit;
- @Schema(description = "閿�鍞悎鍚岀紪鍙�")
+ @Schema(description = "sales contract no")
private String salesContractNo;
- @Schema(description = "鎺掍骇鏃ユ湡")
+ @Schema(description = "scheduling date")
private LocalDate schedulingDate;
- @Schema(description = "鎺掍骇浜哄憳鍚嶇О")
+ @Schema(description = "scheduling user name")
private String schedulingUserName;
- @Schema(description = "瀹㈡埛鍚嶇О")
+ @Schema(description = "customer name")
private String customerName;
- @Schema(description = "宸ュ簭")
+ @Schema(description = "process")
private String process;
- @Schema(description = "宸ュ簭鍙傛暟鍒楄〃")
+ @Schema(description = "salary quota")
+ private BigDecimal workHours;
+
+ @Schema(description = "wages")
+ private BigDecimal wages;
+
+ @Schema(description = "operation param list")
private List<ProductionOrderRoutingOperationParam> productionOperationParamList;
}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java
new file mode 100644
index 0000000..47cb059
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java
@@ -0,0 +1,56 @@
+package com.ruoyi.production.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "ProductionAccountVo", description = "鐢熶骇鏍哥畻鍒嗛〉杩斿洖瀵硅薄")
+public class ProductionAccountVo {
+
+ @Schema(description = "瀹㈡埛鍚堝悓鍙�")
+ private String customerContractNo;
+
+ @Schema(description = "椤圭洰鍚嶇О")
+ private String projectName;
+
+ @Schema(description = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @Schema(description = "浜у搧澶х被")
+ private String productCategory;
+
+ @Schema(description = "瑙勬牸鍨嬪彿")
+ private String specificationModel;
+
+ @Schema(description = "鍗曚綅")
+ private String unit;
+
+ @Schema(description = "鐢熶骇浜篒D")
+ private Long schedulingUserId;
+
+ @Schema(description = "鐢熶骇浜哄悕绉�")
+ private String schedulingUserName;
+
+ @Schema(description = "宸ヨ祫")
+ private BigDecimal wages;
+
+ @Schema(description = "鐢熶骇鏁伴噺")
+ private BigDecimal finishedNum;
+
+ @Schema(description = "宸ユ椂瀹氶")
+ private BigDecimal workHours;
+
+ @Schema(description = "宸ュ簭")
+ private String process;
+
+ @Schema(description = "鐢熶骇鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate schedulingDate;
+
+ @Schema(description = "鐢熶骇鏈堜唤(yyyy-MM)")
+ private String schedulingMonth;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
index 0b56788..df444bd 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
@@ -26,9 +26,12 @@
@Schema(description = "宸ュ簭鍚嶇О")
private String operationName;
- @Schema(description = "宸ュ崟绫诲瀷 姝e父 /杩斿伐杩斾慨")
+ @Schema(description = "宸ュ崟绫诲瀷 姝e父/杩斿伐杩斾慨")
private String workOrderType;
@Schema(description = "瀹屾垚杩涘害")
private BigDecimal completionStatus;
+
+ @Schema(description = "鎶ュ伐浜哄憳鍚嶇О锛屽涓娇鐢ㄩ�楀彿鍒嗛殧")
+ private String userNames;
}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java b/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java
index 9c34f2a..d87996f 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java
@@ -1,5 +1,16 @@
package com.ruoyi.production.controller;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
+import com.ruoyi.production.service.ProductionAccountService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -7,12 +18,24 @@
* <p>
* 鐢熶骇鏍哥畻琛� 鍓嶇鎺у埗鍣�
* </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
*/
@RestController
@RequestMapping("/productionAccount")
+@RequiredArgsConstructor
+@Tag(name = "鐢熶骇鏍哥畻")
public class ProductionAccountController {
+ private final ProductionAccountService productionAccountService;
+
+ @GetMapping("/listPage")
+ @Operation(summary = "鐢熶骇鏍哥畻鍒嗛〉鏌ヨ")
+ public R<IPage<ProductionAccountVo>> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto) {
+ return R.ok(productionAccountService.listPage(page, dto));
+ }
+
+ @GetMapping("/listProductionDetails")
+ @Operation(summary ="鏌ヨ宸ヤ汉鐢熶骇宸ヨ祫淇℃伅")
+ public R<IPage<ProductionProductMainDto>> listProductionDetails(ProductionAccountDto productionAccountDto, Page page) {
+ return R.ok(productionAccountService.listProductionDetails(productionAccountDto,page));
+ }
}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
index e2c23ab..af6184a 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
@@ -6,18 +6,11 @@
import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
import com.ruoyi.production.pojo.ProductionOperationTask;
import com.ruoyi.production.service.ProductionOperationTaskService;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
-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.RestController;
+import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -71,4 +64,20 @@
return R.ok(productionOperationTaskService.updateProductWorkOrder(dto));
}
+ @Operation(summary = "鎸囨淳鎶ュ伐浜�")
+ @PostMapping("/assign")
+ public R<Boolean> assign(@RequestBody ProductionOperationTaskDto dto) {
+ return R.ok(productionOperationTaskService.assign(dto));
+ }
+
+ /**
+ * 宸ュ崟娴佽浆鍗′笅杞�
+ * @param response
+ * @param dto
+ */
+ @PostMapping("/down")
+ public void down(HttpServletResponse response, @RequestBody ProductionOperationTaskDto dto) {
+ productionOperationTaskService.down(response, dto);
+ }
+
}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java
index e1ae36b..2cdc8d0 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java
@@ -1,7 +1,11 @@
package com.ruoyi.production.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
import com.ruoyi.production.bean.dto.UserAccountDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
import com.ruoyi.production.pojo.ProductionAccount;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -19,6 +23,8 @@
*/
@Mapper
public interface ProductionAccountMapper extends BaseMapper<ProductionAccount> {
+ IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, @Param("c") ProductionAccountDto dto);
+
UserAccountDto selectUserAccount(@Param("userId") Long userId, @Param("date") String date);
List<Map<String, Object>> selectDailyWagesStats(@Param("startDate") String startDate, @Param("endDate") String endDate);
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
index e23b611..4349537 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
@@ -40,4 +40,5 @@
@Param("userId") Long userId,
@Param("processIds") List<Long> processIds);
+ ProductionOperationTaskDto getProductWorkOrderFlowCard(@Param("id") Long id);
}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
index c637caf..01b9912 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
@@ -3,8 +3,8 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
import com.ruoyi.production.bean.dto.ProductionProductMainDto;
-import com.ruoyi.production.bean.dto.SalesLedgerProductionAccountingDto;
import com.ruoyi.production.pojo.ProductionOrder;
import com.ruoyi.production.pojo.ProductionProductMain;
import org.apache.ibatis.annotations.Mapper;
@@ -30,7 +30,7 @@
*/
ProductionOrder getOrderByMainId(@Param("productMainId") Long productMainId);
- IPage<ProductionProductMainDto> listProductionDetails(@Param("ew") SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page);
+ IPage<ProductionProductMainDto> listProductionDetails(@Param("c") ProductionAccountDto productionAccountDto, Page page);
ArrayList<Long> listMain(List<Long> idList);
}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
index 752a839..04de53d 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
@@ -90,4 +90,7 @@
@Schema(description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭ID")
private Long productionOrderRoutingOperationId;
+
+ @Schema(description = "鐢熶骇鎶ュ伐琛↖D")
+ private Long productionProductMainId;
}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionAccountService.java b/src/main/java/com/ruoyi/production/service/ProductionAccountService.java
index 6c5ee53..a02c3a4 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionAccountService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionAccountService.java
@@ -1,5 +1,10 @@
package com.ruoyi.production.service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.production.pojo.ProductionAccount;
@@ -12,5 +17,7 @@
* @since 2026-04-21 03:55:52
*/
public interface ProductionAccountService extends IService<ProductionAccount> {
+ IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto);
+ IPage<ProductionProductMainDto> listProductionDetails(ProductionAccountDto productionAccountDto, Page page);
}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
index 4ff1e16..2735cc3 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
@@ -6,6 +6,7 @@
import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
import com.ruoyi.production.pojo.ProductionOperationTask;
+import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@@ -23,4 +24,8 @@
boolean removeProductionOperationTask(List<Long> ids);
int updateProductWorkOrder(ProductionOperationTaskDto dto);
+
+ boolean assign(ProductionOperationTaskDto dto);
+
+ void down(HttpServletResponse response, ProductionOperationTaskDto dto);
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java
index e8e3126..9c1843c 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java
@@ -1,20 +1,73 @@
package com.ruoyi.production.service.impl;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
import com.ruoyi.production.mapper.ProductionAccountMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
import com.ruoyi.production.pojo.ProductionAccount;
import com.ruoyi.production.service.ProductionAccountService;
+import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
-/**
- * <p>
- * 鐢熶骇鏍哥畻琛� 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
+import java.time.LocalDate;
+
@Service
+@RequiredArgsConstructor
public class ProductionAccountServiceImpl extends ServiceImpl<ProductionAccountMapper, ProductionAccount> implements ProductionAccountService {
+
+ private final ProductionProductMainMapper productionProductMainMapper;
+
+ @Override
+ public IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto) {
+ ProductionAccountDto queryDto = normalizeDateQuery(dto);
+ return baseMapper.listPage(page, queryDto);
+ }
+
+ @Override
+ public IPage<ProductionProductMainDto> listProductionDetails(ProductionAccountDto dto, Page page) {
+ return productionProductMainMapper.listProductionDetails(normalizeDateQuery(dto), page);
+ }
+
+ private ProductionAccountDto normalizeDateQuery(ProductionAccountDto dto) {
+ if (dto == null) {
+ return new ProductionAccountDto();
+ }
+ LocalDate[] dateRange = dto.getDateRange();
+ if ((dto.getEntryDateStart() == null || dto.getEntryDateEnd() == null)
+ && dateRange != null
+ && dateRange.length > 0) {
+ if (dto.getEntryDateStart() == null) {
+ dto.setEntryDateStart(dateRange[0]);
+ }
+ if (dto.getEntryDateEnd() == null) {
+ dto.setEntryDateEnd(dateRange.length > 1 ? dateRange[1] : dateRange[0]);
+ }
+ }
+
+ String dateType = dto.getDateType();
+ if ("day".equalsIgnoreCase(dateType)) {
+ if (dto.getEntryDate() == null && dateRange != null && dateRange.length > 0) {
+ dto.setEntryDate(dateRange[0]);
+ }
+ if (dto.getEntryDate() == null) {
+ dto.setEntryDate(dto.getEntryDateStart());
+ }
+ dto.setEntryDateStart(null);
+ dto.setEntryDateEnd(null);
+ } else if ("month".equalsIgnoreCase(dateType)) {
+ if ((dto.getEntryDateStart() == null || dto.getEntryDateEnd() == null) && dto.getEntryDate() != null) {
+ LocalDate monthDate = dto.getEntryDate();
+ dto.setEntryDateStart(monthDate.withDayOfMonth(1));
+ dto.setEntryDateEnd(monthDate.withDayOfMonth(monthDate.lengthOfMonth()));
+ }
+ dto.setEntryDate(null);
+ }
+ return dto;
+ }
+
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
index 8553869..e202ec2 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -1,42 +1,82 @@
package com.ruoyi.production.service.impl;
import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.deepoove.poi.XWPFTemplate;
+import com.deepoove.poi.data.PictureRenderData;
+import com.deepoove.poi.data.PictureType;
+import com.deepoove.poi.data.Pictures;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.common.config.FileProperties;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MatrixToImageWriter;
+import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
import com.ruoyi.production.pojo.ProductionOperationTask;
import com.ruoyi.production.service.ProductionOperationTaskService;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
-import java.util.List;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ProductionOperationTaskServiceImpl extends ServiceImpl<ProductionOperationTaskMapper, ProductionOperationTask> implements ProductionOperationTaskService {
+ private final SysUserMapper sysUserMapper;
+ private final FileUtil fileUtil;
+
+ private final FileProperties fileProperties;
+
+ @Value("${file.temp-dir}")
+ private String tempDir;
@Override
public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) {
Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
- return baseMapper.pageProductionOperationTask(voPage, dto);
+ IPage<ProductionOperationTaskVo> result = baseMapper.pageProductionOperationTask(voPage, dto);
+ fillUserNames(result.getRecords());
+ return result;
}
@Override
public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto) {
- return BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class);
+ List<ProductionOperationTaskVo> result = BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class);
+ fillUserNames(result);
+ return result;
}
@Override
public ProductionOperationTaskVo getProductionOperationTaskInfo(Long id) {
ProductionOperationTask item = this.getById(id);
- return item == null ? null : BeanUtil.copyProperties(item, ProductionOperationTaskVo.class);
+ if (item == null) {
+ return null;
+ }
+ ProductionOperationTaskVo vo = BeanUtil.copyProperties(item, ProductionOperationTaskVo.class);
+ fillUserNames(Collections.singletonList(vo));
+ return vo;
}
@Override
@@ -47,6 +87,27 @@
@Override
public boolean removeProductionOperationTask(List<Long> ids) {
return ids != null && !ids.isEmpty() && this.removeByIds(ids);
+ }
+
+ @Override
+ public int updateProductWorkOrder(ProductionOperationTaskDto dto) {
+ return baseMapper.updateById(dto);
+ }
+
+ @Override
+ public boolean assign(ProductionOperationTaskDto dto) {
+ if (dto == null || dto.getId() == null) {
+ throw new ServiceException("宸ュ崟ID涓嶈兘涓虹┖");
+ }
+
+ ProductionOperationTask update = new ProductionOperationTask();
+ update.setId(dto.getId());
+ update.setUserIds(dto.getUserIds());
+ int rows = baseMapper.updateById(update);
+ if (rows <= 0) {
+ throw new ServiceException("宸ュ崟涓嶅瓨鍦ㄦ垨宸插垹闄�");
+ }
+ return true;
}
private LambdaQueryWrapper<ProductionOperationTask> buildQueryWrapper(ProductionOperationTaskDto dto) {
@@ -62,8 +123,219 @@
.orderByDesc(ProductionOperationTask::getId);
}
+ private void fillUserNames(List<ProductionOperationTaskVo> voList) {
+ if (voList == null || voList.isEmpty()) {
+ return;
+ }
+ Set<Long> userIdSet = new LinkedHashSet<>();
+ for (ProductionOperationTaskVo vo : voList) {
+ if (vo == null) {
+ continue;
+ }
+ userIdSet.addAll(parseUserIdList(vo.getUserIds(), false));
+ }
+ if (userIdSet.isEmpty()) {
+ return;
+ }
+ List<SysUser> userList = sysUserMapper.selectUsersByIds(new ArrayList<>(userIdSet));
+ if (userList == null || userList.isEmpty()) {
+ return;
+ }
+ Map<Long, String> userNameById = userList.stream()
+ .filter(item -> item.getUserId() != null)
+ .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (left, right) -> left));
+
+ for (ProductionOperationTaskVo vo : voList) {
+ if (vo == null) {
+ continue;
+ }
+ List<Long> userIds = parseUserIdList(vo.getUserIds(), false);
+ if (userIds.isEmpty()) {
+ vo.setUserNames(null);
+ continue;
+ }
+ String userNames = userIds.stream()
+ .map(userNameById::get)
+ .filter(StringUtils::isNotBlank)
+ .collect(Collectors.joining(","));
+ vo.setUserNames(userNames);
+ }
+ }
+
+ private List<Long> parseUserIdList(String userIds, boolean strict) {
+ if (StringUtils.isBlank(userIds)) {
+ if (strict) {
+ throw new ServiceException("userIds鏍煎紡涓嶆纭紝蹇呴』涓篔SON鏁板瓧鏁扮粍");
+ }
+ return new ArrayList<>();
+ }
+
+ String text = userIds.trim();
+ try {
+ List<Long> parsed = JSON.parseArray(text, Long.class);
+ LinkedHashSet<Long> idSet = parsed == null ? new LinkedHashSet<>() : parsed.stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ if (strict && idSet.isEmpty()) {
+ throw new ServiceException("userIds鏍煎紡涓嶆纭紝蹇呴』涓篔SON鏁板瓧鏁扮粍");
+ }
+ return new ArrayList<>(idSet);
+ } catch (Exception e) {
+ if (strict) {
+ throw new ServiceException("userIds鏍煎紡涓嶆纭紝蹇呴』涓篔SON鏁板瓧鏁扮粍");
+ }
+ return new ArrayList<>();
+ }
+ }
+
@Override
- public int updateProductWorkOrder(ProductionOperationTaskDto dto) {
- return baseMapper.updateById(dto);
+ public void down(HttpServletResponse response, ProductionOperationTaskDto dto) {
+ if (dto == null || dto.getId() == null) {
+ throw new ServiceException("宸ュ崟ID涓嶈兘涓虹┖");
+ }
+
+ ProductionOperationTaskDto taskDto = baseMapper.getProductWorkOrderFlowCard(dto.getId());
+ if (taskDto == null) {
+ throw new ServiceException("宸ュ崟涓嶅瓨鍦紝ID=" + dto.getId());
+ }
+ String codePath;
+ try {
+ codePath = new MatrixToImageWriter().code(taskDto.getId().toString(), tempDir);
+ } catch (Exception e) {
+ throw new ServiceException("鐢熸垚浜岀淮鐮佸け璐�");
+ }
+
+ List<Map<String, Object>> images = buildTaskAttachmentImages(taskDto.getId());
+ Map<String, Object> renderData = new HashMap<>();
+ renderData.put("process", taskDto.getProcessName());
+ renderData.put("workOrderNo", taskDto.getWorkOrderNo());
+ renderData.put("productOrderNpsNo", taskDto.getProductOrderNpsNo());
+ renderData.put("productName", taskDto.getProductName());
+ renderData.put("planQuantity", taskDto.getPlanQuantity());
+ renderData.put("model", taskDto.getModel());
+ renderData.put("completeQuantity", taskDto.getCompleteQuantity());
+ renderData.put("scrapQty", taskDto.getScrapQty());
+ renderData.put("planStartTime", taskDto.getPlanStartTime());
+ renderData.put("planEndTime", taskDto.getPlanEndTime());
+ renderData.put("actualStartTime", taskDto.getActualStartTime());
+ renderData.put("actualEndTime", taskDto.getActualEndTime());
+ renderData.put("twoCode", Pictures.ofLocal(codePath).create());
+ renderData.put("images", images.isEmpty() ? null : images);
+
+ try (InputStream inputStream = this.getClass().getResourceAsStream("/static/work-order-template.docx")) {
+ if (inputStream == null) {
+ throw new ServiceException("娴佽浆鍗℃ā鏉夸笉瀛樺湪");
+ }
+ XWPFTemplate template = XWPFTemplate.compile(inputStream).render(renderData);
+ response.setContentType("application/msword");
+ String fileName = URLEncoder.encode("娴佽浆鍗�", "UTF-8");
+ response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+ response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
+ try (OutputStream os = response.getOutputStream()) {
+ template.write(os);
+ os.flush();
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("瀵煎嚭澶辫触");
+ }
+ }
+
+ private List<Map<String, Object>> buildTaskAttachmentImages(Long taskId) {
+ List<Map<String, Object>> images = new ArrayList<>();
+ StorageAttachmentDTO storageAttachmentDTO = new StorageAttachmentDTO();
+ storageAttachmentDTO.setRecordType(RecordTypeEnum.PRODUCTION_OPERATION_TASK.getType());
+ storageAttachmentDTO.setRecordId(taskId);
+ List<StorageBlobVO> taskWorkOrderFiles =
+ fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(storageAttachmentDTO);
+ if (CollectionUtils.isEmpty(taskWorkOrderFiles)) {
+ return images;
+ }
+ for (StorageBlobVO blobVO : taskWorkOrderFiles) {
+ if (blobVO == null) {
+ continue;
+ }
+ PictureType pictureType = resolvePictureType(blobVO);
+ if (pictureType == null) {
+ continue;
+ }
+ File imageFile = resolveImageFile(blobVO);
+ if (imageFile == null || !imageFile.exists() || !imageFile.isFile()) {
+ continue;
+ }
+ try (InputStream imageInputStream = new FileInputStream(imageFile)) {
+ Map<String, Object> image = new HashMap<>();
+ PictureRenderData pictureRenderData = Pictures.ofStream(imageInputStream, pictureType)
+ .sizeInCm(17, 20)
+ .create();
+ image.put("url", pictureRenderData);
+ images.add(image);
+ } catch (Exception ignored) {
+ // 鍗曚釜闄勪欢瑙f瀽澶辫触鏃惰烦杩囷紝閬垮厤褰卞搷鏁翠釜娴佽浆鍗″鍑�
+ }
+ }
+ return images;
+ }
+
+ private File resolveImageFile(StorageBlobVO blobVO) {
+ if (blobVO == null || StringUtils.isBlank(blobVO.getUidFilename())) {
+ return null;
+ }
+ if (StringUtils.isBlank(blobVO.getPath())) {
+ return new File(fileProperties.getPath(), blobVO.getUidFilename());
+ }
+ return new File(new File(fileProperties.getPath(), blobVO.getPath()), blobVO.getUidFilename());
+ }
+
+ private PictureType resolvePictureType(StorageBlobVO blobVO) {
+ if (blobVO == null) {
+ return null;
+ }
+ PictureType type = parsePictureTypeByFileName(blobVO.getOriginalFilename());
+ if (type != null) {
+ return type;
+ }
+ type = parsePictureTypeByFileName(blobVO.getUidFilename());
+ if (type != null) {
+ return type;
+ }
+ return parsePictureTypeByContentType(blobVO.getContentType());
+ }
+
+ private PictureType parsePictureTypeByFileName(String fileName) {
+ if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
+ return null;
+ }
+ try {
+ return PictureType.suggestFileType(fileName);
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ private PictureType parsePictureTypeByContentType(String contentType) {
+ if (StringUtils.isBlank(contentType)) {
+ return null;
+ }
+ String normalized = contentType.trim().toLowerCase(Locale.ROOT);
+ switch (normalized) {
+ case "image/jpeg":
+ case "image/jpg":
+ case "image/pjpeg":
+ return PictureType.JPEG;
+ case "image/png":
+ return PictureType.PNG;
+ case "image/gif":
+ return PictureType.GIF;
+ case "image/bmp":
+ case "image/x-ms-bmp":
+ return PictureType.BMP;
+ case "image/tiff":
+ case "image/tif":
+ return PictureType.TIFF;
+ case "image/svg+xml":
+ return PictureType.SVG;
+ default:
+ return null;
+ }
}
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java
index 59094be..a99b194 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java
@@ -75,6 +75,10 @@
ProductionOrderRoutingOperationParam query = dto == null ? new ProductionOrderRoutingOperationParam() : dto;
return Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
.eq(query.getId() != null, ProductionOrderRoutingOperationParam::getId, query.getId())
+ .eq(query.getProductionProductMainId() != null,
+ ProductionOrderRoutingOperationParam::getProductionProductMainId, query.getProductionProductMainId())
+ .isNull(query.getProductionProductMainId() == null,
+ ProductionOrderRoutingOperationParam::getProductionProductMainId)
.eq(query.getProductionOrderId() != null, ProductionOrderRoutingOperationParam::getProductionOrderId, query.getProductionOrderId())
.eq(query.getProductionOrderRoutingOperationId() != null, ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, query.getProductionOrderRoutingOperationId())
.eq(query.getTechnologyOperationId() != null,
@@ -148,6 +152,7 @@
private void checkDuplicate(ProductionOrderRoutingOperationParam item) {
boolean duplicate = productionOrderRoutingOperationParamMapper.selectCount(
Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+ .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId)
.eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, item.getProductionOrderRoutingOperationId())
.eq(item.getTechnologyRoutingOperationParamId() != null,
ProductionOrderRoutingOperationParam::getTechnologyRoutingOperationParamId, item.getTechnologyRoutingOperationParamId())
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index abbc525..9b967c4 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -40,10 +40,14 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
@Service
@@ -75,7 +79,9 @@
@Override
public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) {
- return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
+ IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
+ fillOperationParamList(result.getRecords());
+ return result;
}
@Override
@@ -85,9 +91,119 @@
@Override
public ProductionProductMainDto getProductionProductMainInfo(Long id) {
- return productionProductMainMapper.listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{
+ return listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{
setId(id);
}}).getRecords().stream().findFirst().orElse(null);
+ }
+
+ private void fillOperationParamList(List<ProductionProductMainDto> recordList) {
+ if (recordList == null || recordList.isEmpty()) {
+ return;
+ }
+ Set<Long> mainIdSet = recordList.stream()
+ .map(ProductionProductMainDto::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ if (mainIdSet.isEmpty()) {
+ recordList.forEach(item -> item.setProductionOperationParamList(Collections.emptyList()));
+ return;
+ }
+
+ List<ProductionOrderRoutingOperationParam> paramList = productionOrderRoutingOperationParamMapper.selectList(
+ Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+ .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, mainIdSet)
+ .orderByAsc(ProductionOrderRoutingOperationParam::getId));
+ Map<Long, List<ProductionOrderRoutingOperationParam>> paramGroupMap = new HashMap<>();
+ for (ProductionOrderRoutingOperationParam param : paramList) {
+ if (param == null || param.getProductionProductMainId() == null) {
+ continue;
+ }
+ paramGroupMap.computeIfAbsent(param.getProductionProductMainId(), key -> new ArrayList<>()).add(param);
+ }
+
+ Set<Long> missingMainIdSet = new LinkedHashSet<>();
+ for (ProductionProductMainDto item : recordList) {
+ Long mainId = item.getId();
+ if (mainId == null) {
+ item.setProductionOperationParamList(Collections.emptyList());
+ continue;
+ }
+ List<ProductionOrderRoutingOperationParam> params = paramGroupMap.get(mainId);
+ if (params != null && !params.isEmpty()) {
+ item.setProductionOperationParamList(params);
+ continue;
+ }
+ missingMainIdSet.add(mainId);
+ }
+ if (missingMainIdSet.isEmpty()) {
+ return;
+ }
+
+ // 鍏煎鍘嗗彶鏁版嵁锛氭棫鎶ュ伐璁板綍娌℃湁鎸夋姤宸D钀藉弬鏁板揩鐓ф椂锛屽洖閫�灞曠ず宸ュ簭妯℃澘鍙傛暟銆�
+ List<ProductionProductMain> mainList = productionProductMainMapper.selectBatchIds(missingMainIdSet);
+ Map<Long, Long> mainIdToTaskIdMap = mainList.stream()
+ .filter(Objects::nonNull)
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(ProductionProductMain::getId,
+ ProductionProductMain::getProductionOperationTaskId, (left, right) -> left));
+ Set<Long> taskIdSet = mainIdToTaskIdMap.values().stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ if (taskIdSet.isEmpty()) {
+ for (ProductionProductMainDto item : recordList) {
+ if (item.getId() != null && missingMainIdSet.contains(item.getId())) {
+ item.setProductionOperationParamList(Collections.emptyList());
+ }
+ }
+ return;
+ }
+
+ List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList(
+ Wrappers.<ProductionOperationTask>lambdaQuery()
+ .in(ProductionOperationTask::getId, taskIdSet));
+ Map<Long, Long> taskIdToRoutingOperationIdMap = taskList.stream()
+ .filter(Objects::nonNull)
+ .filter(item -> item.getId() != null)
+ .collect(Collectors.toMap(ProductionOperationTask::getId,
+ ProductionOperationTask::getProductionOrderRoutingOperationId, (left, right) -> left));
+ Set<Long> routingOperationIdSet = taskIdToRoutingOperationIdMap.values().stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ if (routingOperationIdSet.isEmpty()) {
+ for (ProductionProductMainDto item : recordList) {
+ if (item.getId() != null && missingMainIdSet.contains(item.getId())) {
+ item.setProductionOperationParamList(Collections.emptyList());
+ }
+ }
+ return;
+ }
+
+ List<ProductionOrderRoutingOperationParam> fallbackParamList = productionOrderRoutingOperationParamMapper.selectList(
+ Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+ .in(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, routingOperationIdSet)
+ .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId)
+ .orderByAsc(ProductionOrderRoutingOperationParam::getId));
+ Map<Long, List<ProductionOrderRoutingOperationParam>> fallbackGroupMap = new HashMap<>();
+ for (ProductionOrderRoutingOperationParam param : fallbackParamList) {
+ if (param == null || param.getProductionOrderRoutingOperationId() == null) {
+ continue;
+ }
+ fallbackGroupMap.computeIfAbsent(param.getProductionOrderRoutingOperationId(), key -> new ArrayList<>()).add(param);
+ }
+
+ for (ProductionProductMainDto item : recordList) {
+ Long mainId = item.getId();
+ if (mainId == null || !missingMainIdSet.contains(mainId)) {
+ continue;
+ }
+ Long taskId = mainIdToTaskIdMap.get(mainId);
+ Long routingOperationId = taskId == null ? null : taskIdToRoutingOperationIdMap.get(taskId);
+ if (routingOperationId == null) {
+ item.setProductionOperationParamList(Collections.emptyList());
+ continue;
+ }
+ item.setProductionOperationParamList(fallbackGroupMap.getOrDefault(routingOperationId, Collections.emptyList()));
+ }
}
@Override
@@ -132,7 +248,6 @@
if (productionOrder == null) {
throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
}
- syncOperationParamInputValue(dto, routingOperation.getId());
TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId());
TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null
: technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId());
@@ -149,11 +264,16 @@
productionProductMain.setProductionOperationTaskId(taskId);
productionProductMain.setStatus(0);
productionProductMainMapper.insert(productionProductMain);
+ syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId());
List<ProductStructureDto> productStructureDtos = resolveInputStructures(
productionOrder.getId(), routingOperation, productModel.getId());
+ // 濡傛灉娌℃湁bom瀛愯妭鐐逛簡锛岄偅涔堟姇鍏ュ氨鏄粬鏈韩
if (productStructureDtos.isEmpty()) {
- throw new ServiceException("鏈壘鍒板綋鍓嶅伐搴忓搴旂殑BOM鎶曞叆鑺傜偣");
+ ProductStructureDto fallbackInput = new ProductStructureDto();
+ fallbackInput.setProductModelId(productModel.getId());
+ fallbackInput.setUnitQuantity(BigDecimal.ONE);
+ productStructureDtos.add(fallbackInput);
}
for (ProductStructureDto item : productStructureDtos) {
// 褰撳墠瀹炵幇鎸夊伐搴忔垚鍝佺洿鎺ヤ綔涓烘姇鍏ワ紝鍚庣画鑻ユ帴鍏ラ鏂欒褰曞彲鍦ㄨ繖閲屾浛鎹㈡潵婧愩��
@@ -199,7 +319,7 @@
qualityInspect.setProductModelId(productModel.getId());
qualityInspectMapper.insert(qualityInspect);
List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
- if (qualityTestStandard.size() > 0) {
+ if (!qualityTestStandard.isEmpty()) {
qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
qualityInspectMapper.updateById(qualityInspect);
qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
@@ -270,20 +390,33 @@
return true;
}
- private void syncOperationParamInputValue(ProductionProductMainDto dto, Long productionOrderRoutingOperationId) {
- if (dto == null || productionOrderRoutingOperationId == null) {
+ private void syncOperationParamInputValue(ProductionProductMainDto dto,
+ Long productionOrderRoutingOperationId,
+ Long productionProductMainId) {
+ if (dto == null || productionOrderRoutingOperationId == null || productionProductMainId == null) {
return;
}
List<ProductionOrderRoutingOperationParam> paramList = dto.getProductionOperationParamList();
if (paramList == null || paramList.isEmpty()) {
return;
}
+ Set<Long> sourceParamIdSet = paramList.stream()
+ .filter(Objects::nonNull)
+ .map(ProductionOrderRoutingOperationParam::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ if (sourceParamIdSet.isEmpty()) {
+ return;
+ }
+
List<ProductionOrderRoutingOperationParam> dbParamList = productionOrderRoutingOperationParamMapper.selectList(
Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+ .in(ProductionOrderRoutingOperationParam::getId, sourceParamIdSet)
.eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, productionOrderRoutingOperationId));
if (dbParamList == null || dbParamList.isEmpty()) {
return;
}
+
Map<Long, ProductionOrderRoutingOperationParam> dbParamMap = dbParamList.stream()
.filter(item -> item != null && item.getId() != null)
.collect(Collectors.toMap(ProductionOrderRoutingOperationParam::getId, item -> item, (left, right) -> left));
@@ -295,14 +428,31 @@
if (dbParam == null) {
throw new ServiceException("宸ュ簭鍙傛暟涓嶅瓨鍦ㄦ垨涓嶅睘浜庡綋鍓嶅伐鍗曞伐搴忥紝ID=" + param.getId());
}
- if (Objects.equals(dbParam.getInputValue(), param.getInputValue())) {
- continue;
- }
- ProductionOrderRoutingOperationParam updateParam = new ProductionOrderRoutingOperationParam();
- updateParam.setId(dbParam.getId());
- updateParam.setInputValue(param.getInputValue());
- productionOrderRoutingOperationParamMapper.updateById(updateParam);
+ productionOrderRoutingOperationParamMapper.insert(buildReportParamSnapshot(dbParam, param.getInputValue(), productionProductMainId));
}
+ }
+
+ private ProductionOrderRoutingOperationParam buildReportParamSnapshot(ProductionOrderRoutingOperationParam source,
+ String inputValue,
+ Long productionProductMainId) {
+ ProductionOrderRoutingOperationParam target = new ProductionOrderRoutingOperationParam();
+ target.setProductionOrderId(source.getProductionOrderId());
+ target.setTechnologyRoutingOperationParamId(source.getTechnologyRoutingOperationParamId());
+ target.setParamCode(source.getParamCode());
+ target.setParamName(source.getParamName());
+ target.setParamType(source.getParamType());
+ target.setParamFormat(source.getParamFormat());
+ target.setUnit(source.getUnit());
+ target.setIsRequired(source.getIsRequired());
+ target.setRemark(source.getRemark());
+ target.setParamId(source.getParamId());
+ target.setTechnologyOperationId(source.getTechnologyOperationId());
+ target.setTechnologyOperationParamId(source.getTechnologyOperationParamId());
+ target.setStandardValue(source.getStandardValue());
+ target.setInputValue(inputValue);
+ target.setProductionOrderRoutingOperationId(source.getProductionOrderRoutingOperationId());
+ target.setProductionProductMainId(productionProductMainId);
+ return target;
}
private List<ProductStructureDto> resolveInputStructures(Long productionOrderId,
@@ -431,6 +581,9 @@
.eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId()));
productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
.eq(ProductionProductInput::getProductionProductMainId, productionProductMain.getId()));
+ productionOrderRoutingOperationParamMapper.delete(
+ Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+ .eq(ProductionOrderRoutingOperationParam::getProductionProductMainId, productionProductMain.getId()));
stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode());
stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
index a5c8fcc..3130951 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
@@ -122,7 +122,7 @@
throw new ServiceException("bom浜у搧缁撴瀯涓虹┖锛�");
}
- // 鍚屼竴涓� BOM 涓彲鑳介噸澶嶅紩鐢ㄧ浉鍚屽伐搴忥紝杩欓噷鎸夐娆″嚭鐜伴『搴忓幓閲嶃��
+ // 鍚屼竴涓� BOM 涓彲鑳介噸澶嶅紩鐢ㄧ浉鍚屽伐搴忥紝鎸夌収涓婁竴灞傜殑鐖惰妭鐐圭殑浜у搧鏄惁鐩稿悓鍜屽伐搴忔槸鍚︾浉鍚�
Map<Long, TechnologyBomStructure> structureById = new HashMap<>();
for (TechnologyBomStructure bomStructure : bomStructures) {
if (bomStructure != null && bomStructure.getId() != null) {
diff --git a/src/main/resources/mapper/production/ProductionAccountMapper.xml b/src/main/resources/mapper/production/ProductionAccountMapper.xml
index 8b669e9..f213a5f 100644
--- a/src/main/resources/mapper/production/ProductionAccountMapper.xml
+++ b/src/main/resources/mapper/production/ProductionAccountMapper.xml
@@ -21,6 +21,74 @@
<result column="dept_id" property="deptId" />
</resultMap>
+ <select id="listPage" resultType="com.ruoyi.production.bean.vo.ProductionAccountVo">
+ select
+ group_concat(distinct p_parent.product_name order by p_parent.product_name separator ',') as productCategory,
+ group_concat(distinct pm.model order by pm.model separator ',') as specificationModel,
+ group_concat(distinct pm.unit order by pm.unit separator ',') as unit,
+ pa.scheduling_user_id as schedulingUserId,
+ pa.scheduling_user_name as schedulingUserName,
+ cast(sum(
+ ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) *
+ case
+ when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$'
+ then cast(substring_index(pm.model, '*', -1) as decimal(18,4))
+ else 1
+ end
+ ) as decimal(18,4)) as wages,
+ cast(sum(ifnull(pa.finished_num, 0)) as decimal(18,4)) as finishedNum,
+ cast(sum(ifnull(pa.work_hours, 0)) as decimal(18,4)) as workHours,
+ group_concat(distinct pa.technology_operation_name order by pa.technology_operation_name separator ',') as process,
+ case
+ when count(distinct date(pa.scheduling_date)) = 1 then min(date(pa.scheduling_date))
+ else null
+ end as schedulingDate,
+ case
+ when count(distinct date_format(pa.scheduling_date, '%Y-%m')) = 1 then min(date_format(pa.scheduling_date, '%Y-%m'))
+ else null
+ end as schedulingMonth
+ from production_account pa
+ left join production_product_main ppm on ppm.id = pa.production_product_main_id
+ left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+ left join production_order po on pot.production_order_id = po.id
+ left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+ left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+ left join product p on pm.product_id = p.id
+ left join product p_parent on p_parent.id = p.parent_id
+ <where>
+ <if test="c != null">
+ <if test="c.productCategory != null and c.productCategory != ''">
+ and p_parent.product_name like concat('%', #{c.productCategory}, '%')
+ </if>
+ <if test="c.specificationModel != null and c.specificationModel != ''">
+ and pm.model like concat('%', #{c.specificationModel}, '%')
+ </if>
+ <if test="c.schedulingUserId != null">
+ and pa.scheduling_user_id = #{c.schedulingUserId}
+ </if>
+ <if test="c.schedulingUserName != null and c.schedulingUserName != ''">
+ and pa.scheduling_user_name like concat('%', #{c.schedulingUserName}, '%')
+ </if>
+ <if test="c.process != null and c.process != ''">
+ and pa.technology_operation_name like concat('%', #{c.process}, '%')
+ </if>
+ <if test="c.entryDate != null">
+ and date(pa.scheduling_date) = #{c.entryDate}
+ </if>
+ <if test="c.entryDateStart != null">
+ and date(pa.scheduling_date) >= #{c.entryDateStart}
+ </if>
+ <if test="c.entryDateEnd != null">
+ and date(pa.scheduling_date) <= #{c.entryDateEnd}
+ </if>
+ </if>
+ </where>
+ group by pa.scheduling_user_id,
+ pa.scheduling_user_name
+ order by wages desc,
+ pa.scheduling_user_id asc
+ </select>
+
<select id="selectUserAccount" resultType="com.ruoyi.production.bean.dto.UserAccountDto">
select ifnull(sum(finished_num), 0) as accountBalance,
ifnull(sum(work_hours), 0) as account
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index ebafa7a..31bf61b 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -120,4 +120,28 @@
group by poro.technology_operation_id, poro.operation_name
</select>
+ <select id="getProductWorkOrderFlowCard" resultType="com.ruoyi.production.bean.dto.ProductionOperationTaskDto">
+ SELECT pot.*,
+ poro.operation_name AS processName,
+ pm.model AS model,
+ pm.unit AS unit,
+ p.product_name AS productName,
+ po.nps_no AS productOrderNpsNo,
+ ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus,
+ IFNULL(scrapStat.scrapQty, 0) AS scrapQty
+ FROM production_operation_task pot
+ LEFT JOIN production_order po ON pot.production_order_id = po.id
+ LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id
+ LEFT JOIN product_model pm ON pm.id = ifnull(poro.product_model_id, po.product_model_id)
+ LEFT JOIN product p ON p.id = pm.product_id
+ LEFT JOIN (
+ SELECT ppm.production_operation_task_id AS taskId,
+ SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty
+ FROM production_product_main ppm
+ LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id
+ GROUP BY ppm.production_operation_task_id
+ ) scrapStat ON scrapStat.taskId = pot.id
+ WHERE pot.id = #{id}
+ </select>
+
</mapper>
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index 8dd4613..5a78a5b 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -95,17 +95,59 @@
p.product_name as productName,
pm.model as productModelName,
pm.unit,
- poro.operation_name as process,
+ pa.technology_operation_name as process,
ifnull(ppo.quantity, 0) as quantity,
- ifnull(ppo.scrap_qty, 0) as scrapQty
- from production_product_main ppm
+ ifnull(ppo.scrap_qty, 0) as scrapQty,
+ date(pa.scheduling_date) as schedulingDate,
+ pa.scheduling_user_name as schedulingUserName,
+ cast(ifnull(pa.work_hours, 0) as decimal(18,4)) as workHours,
+ cast(
+ ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) *
+ case
+ when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$'
+ then cast(substring_index(pm.model, '*', -1) as decimal(18,4))
+ else 1
+ end
+ as decimal(18,4)
+ ) as wages
+ from production_account pa
+ left join production_product_main ppm on ppm.id = pa.production_product_main_id
left join production_operation_task pot on ppm.production_operation_task_id = pot.id
left join production_order po on pot.production_order_id = po.id
left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
left join product p on pm.product_id = p.id
+ left join product p_parent on p_parent.id = p.parent_id
left join production_product_output ppo on ppo.production_product_main_id = ppm.id
- order by ppm.create_time desc
+ <where>
+ <if test="c != null">
+ <if test="c.productCategory != null and c.productCategory != ''">
+ and p_parent.product_name like concat('%', #{c.productCategory}, '%')
+ </if>
+ <if test="c.specificationModel != null and c.specificationModel != ''">
+ and pm.model like concat('%', #{c.specificationModel}, '%')
+ </if>
+ <if test="c.schedulingUserId != null">
+ and pa.scheduling_user_id = #{c.schedulingUserId}
+ </if>
+ <if test="c.schedulingUserName != null and c.schedulingUserName != ''">
+ and pa.scheduling_user_name like concat('%', #{c.schedulingUserName}, '%')
+ </if>
+ <if test="c.process != null and c.process != ''">
+ and pa.technology_operation_name like concat('%', #{c.process}, '%')
+ </if>
+ <if test="c.entryDate != null">
+ and date(pa.scheduling_date) = #{c.entryDate}
+ </if>
+ <if test="c.entryDateStart != null">
+ and date(pa.scheduling_date) >= #{c.entryDateStart}
+ </if>
+ <if test="c.entryDateEnd != null">
+ and date(pa.scheduling_date) <= #{c.entryDateEnd}
+ </if>
+ </if>
+ </where>
+ order by pa.scheduling_date desc, pa.id desc
</select>
<select id="listMain" resultType="java.lang.Long">
--
Gitblit v1.9.3