buhuazhen
2026-04-22 255d39d428e5867306a8c379f8cef4f20920da03
feat(production): 新增开始报工功能及生产时间字段

- 在ProductWorkOrder实体中添加开始报工和结束报工的LocalDateTime字段
- 实现ProductOrderService的startProduction方法,设置工单开始生产时间
- 增加ProductOrderController的开始报工接口
- 在addProductMain方法中改为使用工单的开始生产时间和当前时间设置生产主记录时间
- 更新产品工单中结束报工时间,生产订单中开始和结束时间统一使用获取的当前时间
- 修正销售合同号校验断言逻辑,防止合同号重复
已修改6个文件
57 ■■■■ 文件已修改
src/main/java/com/ruoyi/production/controller/ProductOrderController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductOrderService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -75,4 +75,10 @@
    public R delete(@PathVariable("ids") Long[] ids) {
        return R.ok(productOrderService.delete(ids));
    }
    @ApiOperation("开始报工")
    @PostMapping("/startProduction/{id}")
    public R startProduction(@PathVariable("id") Long id) {
        return R.ok(productOrderService.startProduction(id));
    }
}
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java
@@ -129,4 +129,15 @@
    @TableField(fill = FieldFill.INSERT)
    private Long deptId;
    // 开始报工
    @TableField(value = "start_product_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime startProductTime;
    // 结束报工
    @TableField(value = "end_product_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime endProductTime;
}
src/main/java/com/ruoyi/production/service/ProductOrderService.java
@@ -8,6 +8,7 @@
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.pojo.ProductWorkOrder;
import java.util.List;
@@ -25,4 +26,10 @@
    Boolean addProductOrder(ProductOrder productOrder);
    Boolean delete(Long[] id);
    /**
     * 开始报工
     * @param id
     */
    ProductWorkOrder startProduction(Long id);
}
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.production.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -23,6 +24,7 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
@@ -157,6 +159,22 @@
        return true;
    }
    @Override
    public ProductWorkOrder startProduction(Long id) {
        LocalDateTime now = LocalDateTime.now();
        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(id);
        productWorkOrder.setStartProductTime(now);
        Assert.notNull(productWorkOrder, "工单不存在");
        ProductWorkOrder needUpdate = new ProductWorkOrder();
        needUpdate.setId(id);
        needUpdate.setStartProductTime(now);
        productWorkOrderMapper.updateById(needUpdate);
        return productWorkOrder;
    }
    //获取当前生产订单号
    public String getMaxOrderNoByDate(String datePrefix) {
        QueryWrapper<ProductOrder> queryWrapper = new QueryWrapper<>();
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -101,6 +101,9 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addProductMain(ProductionProductMainDto dto) {
        LocalDateTime now = LocalDateTime.now();
        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
        SysUser user = userMapper.selectUserById(dto.getUserId());
        ProductionProductMain productionProductMain = new ProductionProductMain();
        //当前工艺路线对应的工序详情
@@ -159,8 +162,8 @@
        productionProductMain.setAuditUserId(dto.getAuditUserId());
        productionProductMain.setAuditUserName(dto.getAuditUserName());
        productionProductMain.setStatus(0);
        productionProductMain.setStartTime(dto.getStartTime());
        productionProductMain.setEndTime(dto.getEndTime());
        productionProductMain.setStartTime(productWorkOrder.getStartProductTime());
        productionProductMain.setEndTime(now);
        productionProductMain.setDeviceId(productProcess.getDeviceId());
        productionProductMain.setDeviceName(productProcess.getDeviceName());
        productionProductMainMapper.insert(productionProductMain);
@@ -197,7 +200,6 @@
        if (productQty.compareTo(BigDecimal.ZERO) > 0) {
            List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
            /*更新工单和生产订单*/
            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
            productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty));
            if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
                productWorkOrder.setActualStartTime(LocalDate.now());//实际开始时间
@@ -205,17 +207,18 @@
            if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) {
                productWorkOrder.setActualEndTime(LocalDate.now());//实际结束时间
            }
            productWorkOrder.setEndProductTime(now);
            productWorkOrderMapper.updateById(productWorkOrder);
            //生产订单
            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
            if (ObjectUtils.isNull(productOrder.getStartTime())) {
                productOrder.setStartTime(LocalDateTime.now());//开始时间
                productOrder.setStartTime(now);//开始时间
            }
            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
                //如果是最后一道工序报工之后生产订单完成数量+
                productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty));
                if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) {
                    productOrder.setEndTime(LocalDateTime.now());//结束时间
                    productOrder.setEndTime(now);//结束时间
                }
            }
            productOrderMapper.updateById(productOrder);
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -681,7 +681,7 @@
                // 为空 自动生成
                String contractNo =StrUtil.isBlank(salesLedgerDto.getSalesContractNo())? generateSalesContractNoBy8Date():salesLedgerDto.getSalesContractNo();
                // 不能有重复数据的合同号
               Assert.isFalse(salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
               Assert.isTrue(salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
                        .eq(SalesLedger::getSalesContractNo, contractNo)
                        .last("limit 1")) == null, contractNo+"合同号已存在");
                salesLedger.setSalesContractNo(contractNo);