已添加15个文件
已修改30个文件
1183 ■■■■ 文件已修改
src/main/java/com/ruoyi/CodeGenerator.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/IApproveNodeService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/IApproveProcessService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/SupplierManage.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/TokenService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductBomController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/SalesLedgerProductTemplateController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerProductImportDto.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerTemplateMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/SalesLedgerProductTemplateMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/PurchaseLedgerTemplateService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/SalesLedgerProductTemplateService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java 224 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/SalesLedgerProductTemplateServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/PurchaseLedgerTemplateMapper.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/SalesLedgerProductTemplateMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/采购台账导入模板.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/销售台账导入模板.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/CodeGenerator.java
@@ -19,11 +19,11 @@
// æ¼”示例子,执行 main æ–¹æ³•控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
    public static String database_url = "jdbc:mysql://1.15.17.182:9999/product-inventory-management-new";
    public static String database_url = "jdbc:mysql://localhost:3306/product-inventory-management-new";
    public static String database_username = "root";
    public static String database_password= "xd@123456..";
    public static String database_password= "123456";
    public static String author = "芯导软件(江苏)有限公司";
    public static String model = "stock"; // æ¨¡å—
    public static String model = "purchase"; // æ¨¡å—
    public static String setParent = "com.ruoyi."+ model; // åŒ…路径
    public static String tablePrefix = ""; // è®¾ç½®è¿‡æ»¤è¡¨å‰ç¼€
    public static void main(String[] args) {
src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java
@@ -115,8 +115,8 @@
    @DeleteMapping("/deleteIds")
    @ApiOperation(value = "删除审批")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteIds(@RequestBody Long[] ids) {
        if (ids == null || ids.length == 0) {
    public AjaxResult deleteIds(@RequestBody List<Long> ids) {
        if (ids == null || ids.size() == 0) {
            return AjaxResult.warn("参数不能为空");
        }
        approveProcessService.delApprove(ids);
src/main/java/com/ruoyi/approve/service/IApproveNodeService.java
@@ -17,5 +17,5 @@
    void updateApproveNode(ApproveNode approveNode) throws IOException;
    void delApproveNodeByApproveId(Long id);
    void delApproveNodeByApproveId(String id);
}
src/main/java/com/ruoyi/approve/service/IApproveProcessService.java
@@ -27,7 +27,7 @@
    IPage<ApproveProcess> listAll(Page page, ApproveProcess approveProcess);
    void delApprove(Long[] ids);
    void delApprove(List<Long> ids);
    void updateByApproveId(ApproveGetAndUpdateVo approveGetAndUpdateVo) throws IOException;
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -19,6 +19,8 @@
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.service.ISysNoticeService;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.sales.mapper.CommonFileMapper;
import com.ruoyi.sales.mapper.SalesQuotationMapper;
import com.ruoyi.sales.mapper.SalesQuotationProductMapper;
@@ -61,10 +63,16 @@
    private DeviceRepairMapper deviceRepairMapper;
    @Autowired
    private PurchaseLedgerMapper purchaseLedgerMapper;
    @Autowired
    private SalesQuotationMapper salesQuotationMapper;
    @Autowired
    private ShippingInfoMapper shippingInfoMapper;
    @Autowired
    private CommonFileServiceImpl commonFileService;
@@ -168,6 +176,26 @@
            }
            deviceRepairMapper.updateById(deviceRepair);
        }
        //采购审核
        if(approveProcess.getApproveType().equals(5)){
            PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
                    .eq(PurchaseLedger::getPurchaseContractNumber, approveProcess.getApproveReason())
                    .last("limit 1"));
            if(purchaseLedger != null) {
                if (status.equals(2)) {
                    // åŒæ„
                    purchaseLedger.setApprovalStatus(3);
                } else if (status.equals(3)) {
                    // æ‹’绝
                    purchaseLedger.setApprovalStatus(4);
                } else if (status.equals(1)) {
                    // å®¡æ ¸ä¸­
                    purchaseLedger.setApprovalStatus(2);
                }
                purchaseLedgerMapper.updateById(purchaseLedger);
            }
        }
        // é”€å”®æŠ¥ä»·çŠ¶æ€ä¿®æ”¹
        if(approveProcess.getApproveType().equals(6)){
            SalesQuotation salesQuote = salesQuotationMapper.selectOne(new LambdaQueryWrapper<SalesQuotation>()
@@ -237,11 +265,17 @@
    }
    @Override
    public void delApproveNodeByApproveId(Long id) {
    public void delApproveNodeByApproveId(String id) {
        List<ApproveNode> approveNodes = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
                .eq(ApproveNode::getApproveProcessId, id));
        UpdateWrapper<ApproveNode> queryWrapper = new UpdateWrapper<>();
        queryWrapper.lambda().set(ApproveNode::getDeleteFlag, 1)
                .eq(ApproveNode::getApproveProcessId, id);
        update(queryWrapper);
        // åˆ é™¤é™„ä»¶
        for (ApproveNode approveNode : approveNodes) {
            commonFileService.deleteByBusinessId(approveNode.getId(), FileNameType.ApproveNode.getValue());
        }
    }
    //审批类型获取(与前端页面对应)
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -27,6 +27,7 @@
import com.ruoyi.project.system.service.ISysNoticeService;
import com.ruoyi.sales.mapper.CommonFileMapper;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
@@ -64,6 +65,7 @@
    private final ApproveProcessMapper approveProcessMapper;
    private final TempFileServiceImpl tempFileService;
    private final CommonFileMapper commonFileMapper;
    private final CommonFileServiceImpl commonFileService;
    private final ISysNoticeService sysNoticeService;
    @Override
@@ -153,19 +155,58 @@
        return approveProcessIPage;
    }
    @Override
    public void delApprove(Long[] ids) {
        ApproveProcess approveProcess;
    public void delByIds(List<Long> ids) {
        for (Long approveId : ids) {
            //  é€»è¾‘删除审批流程
            update(new UpdateWrapper<ApproveProcess>()
                    .lambda()
                    .set(ApproveProcess::getApproveDelete, 1)
                    .eq(ApproveProcess::getApproveId, approveId));
                    .eq(ApproveProcess::getId, approveId));
            // åˆ é™¤å¯¹åº”的附件
            commonFileService.deleteByBusinessId(approveId, FileNameType.ApproveProcess.getValue());
            ApproveProcess approveProcess = approveProcessMapper.selectById(approveId);
            //  åˆ é™¤å®¡æ‰¹èŠ‚ç‚¹
            approveNodeService.delApproveNodeByApproveId(approveId);
            approveNodeService.delApproveNodeByApproveId(approveProcess.getApproveId());
            //  åªæŸ¥æœ€æ–°ä¸€æ¡å®¡æ‰¹æµç¨‹
            ApproveProcess latestProcess = approveProcessMapper.selectOne(
                    new LambdaQueryWrapper<ApproveProcess>()
                            .eq(ApproveProcess::getApproveId, approveId)
                            .orderByDesc(ApproveProcess::getCreateTime)
                            .last("LIMIT 1"));
            if (latestProcess == null) {
                continue;
            }
            //  åˆ é™¤å¯¹åº”的消息通知
            sysNoticeService.remove(new LambdaQueryWrapper<SysNotice>()
                    .eq(SysNotice::getNoticeTitle, approveProcessType(latestProcess.getApproveType()))
                    .eq(SysNotice::getSenderId, latestProcess.getApproveUser())
                    .apply("CAST(notice_content AS CHAR) LIKE CONCAT('%', {0}, '%')", latestProcess.getApproveId()));
        }
    }
    @Override
    public void delApprove(List<Long> ids) {
        for (Long approveId : ids) {
            ApproveProcess approveProcess = approveProcessMapper.selectOne(new LambdaQueryWrapper<ApproveProcess>()
                    .eq(ApproveProcess::getApproveId, approveId)
                    .eq(ApproveProcess::getApproveDelete, 0)
                    .last("LIMIT 1"));
            //  é€»è¾‘删除审批流程
            update(new UpdateWrapper<ApproveProcess>()
                    .lambda()
                    .set(ApproveProcess::getApproveDelete, 1)
                    .eq(ApproveProcess::getApproveId, approveId));
            // åˆ é™¤å¯¹åº”的附件
            commonFileService.deleteByBusinessId(approveProcess.getId(), FileNameType.ApproveProcess.getValue());
            //  åˆ é™¤å®¡æ‰¹èŠ‚ç‚¹
            approveNodeService.delApproveNodeByApproveId(approveId.toString());
            //  åªæŸ¥æœ€æ–°ä¸€æ¡å®¡æ‰¹æµç¨‹
            ApproveProcess latestProcess = approveProcessMapper.selectOne(
src/main/java/com/ruoyi/basic/pojo/SupplierManage.java
@@ -14,7 +14,7 @@
public class SupplierManage {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private Long id;
    @ApiModelProperty(value = "供应商名称")
    @Excel(name = "供应商名称")
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -27,13 +27,13 @@
    private String maintenancePlanTimeReq;
    @ApiModelProperty("计划保养日期")
    private LocalDateTime maintenancePlanTime;
    private String maintenancePlanTime;
    @ApiModelProperty("实际保养人")
    private String maintenanceActuallyName;
    @ApiModelProperty("实际保养日期")
    private LocalDateTime maintenanceActuallyTime;
    private String maintenanceActuallyTime;
    @ApiModelProperty("实际保养日期")
    private String maintenanceActuallyTimeReq;
src/main/java/com/ruoyi/framework/security/service/TokenService.java
@@ -160,6 +160,7 @@
        loginUser.setLoginTime(System.currentTimeMillis());
        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
        loginUser.setDeptIds(getDeptIdsByUserId(loginUser.getUserId()));
        loginUser.setCurrentDeptId(loginUser.getDeptIds()[0]);
        // æ ¹æ®uuid将loginUser缓存
        String userKey = getTokenKey(loginUser.getToken());
        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
@@ -64,6 +64,9 @@
    public IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
        LambdaQueryWrapper<InspectionTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(InspectionTask::getCreateTime);
        if (StringUtils.isNotBlank(inspectionTaskDto.getTaskName())) {
            queryWrapper.like(InspectionTask::getTaskName, inspectionTaskDto.getTaskName());
        }
        IPage<InspectionTask> entityPage = inspectionTaskMapper.selectPage(page, queryWrapper);
        //  æ— æ•°æ®æå‰è¿”回
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.inspectiontask.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -47,7 +48,12 @@
    @Override
    public IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask) {
        // 1. å…ˆåˆ†é¡µæŸ¥è¯¢å®šæ—¶ä»»åŠ¡æ•°æ®
        IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, null);
        // æž„建查询条件
        LambdaQueryWrapper<TimingTask> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(timingTask.getTaskName())) {
            queryWrapper.like(TimingTask::getTaskName, timingTask.getTaskName());
        }
        IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, queryWrapper);
        // 2. å¦‚果没有数据,直接返回空分页
        if (taskPage.getRecords().isEmpty()) {
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java
@@ -8,6 +8,7 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerRecordService;
import io.jsonwebtoken.lang.Collections;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -16,6 +17,7 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
 * @author :yys
@@ -50,6 +52,14 @@
        return AjaxResult.error();
    }
    @DeleteMapping("/delete")
    @ApiOperation("计量器具台账记录-删除")
    @Log(title = "计量器具台账记录-删除", businessType = BusinessType.DELETE)
    public AjaxResult delete(@RequestBody List<Long> ids) {
        if(Collections.isEmpty(ids)) return AjaxResult.error("请选择要删除的数据");
        return AjaxResult.success(measuringInstrumentLedgerRecordService.removeBatchByIds(ids));
    }
    /**
     * å¯¼å‡ºè®¡é‡å™¨å…·å°è´¦
     */
src/main/java/com/ruoyi/production/controller/ProductBomController.java
@@ -3,9 +3,11 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.production.dto.BomImportDto;
import com.ruoyi.production.dto.ProductBomDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductBom;
@@ -19,6 +21,7 @@
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -100,6 +103,7 @@
    @PostMapping("uploadBom")
    @PreAuthorize("@ss.hasPermi('product:bom:import')")
    @Log(title = "根据Excel导入BOM", businessType = BusinessType.IMPORT)
    @ApiOperation("根据Excel导入BOM")
    public AjaxResult uploadBom(@RequestParam("file") MultipartFile file) {
@@ -107,9 +111,18 @@
    }
    @PostMapping("exportBom")
    @Log(title = "导出BOM文件", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('product:bom:export')")
    @ApiOperation("导出BOM文件")
    @Log(title = "导出BOM文件", businessType = BusinessType.EXPORT)
    public void exportBom(HttpServletResponse response, @RequestParam Integer bomId) {
        productBomService.exportBom(response, bomId);
    }
    @GetMapping("/downloadTemplate")
    @Log(title = "下载BOM导入模板", businessType = BusinessType.EXPORT)
    @ApiOperation("下载BOM导入模板")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<BomImportDto> excelUtil = new ExcelUtil<>(BomImportDto.class);
        excelUtil.importTemplateExcel(response, "BOM导入模板");
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -14,10 +14,7 @@
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.controller.ProductWorkOrderController;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.dto.ProductionProductMainDto;
import com.ruoyi.production.mapper.*;
@@ -44,10 +41,8 @@
@Transactional(rollbackFor = Exception.class)
public class ProductionProductMainServiceImpl extends ServiceImpl<ProductionProductMainMapper, ProductionProductMain> implements ProductionProductMainService {
    private final ProcurementRecordOutMapper procurementRecordOutMapper;
    private ProductionProductMainMapper productionProductMainMapper;
    private ProductWorkOrderController productWorkOrderController;
    private ProductWorkOrderMapper productWorkOrderMapper;
@@ -56,7 +51,6 @@
    private ProductionProductOutputMapper productionProductOutputMapper;
    private ProcessRouteItemMapper processRouteItemMapper;
    private ProductModelMapper productModelMapper;
@@ -69,7 +63,6 @@
    private QualityTestStandardParamMapper qualityTestStandardParamMapper;
    private QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
    private QualityTestStandardMapper qualityTestStandardMapper;
    private QualityInspectParamMapper qualityInspectParamMapper;
@@ -163,21 +156,8 @@
            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
            productionProductInput.setProductMainId(productionProductMain.getId());
            productionProductInputMapper.insert(productionProductInput);
            //对应的库存出库
            DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyyMMdd");
            LocalDate now = LocalDate.now();
            ProcurementRecordOut procurementRecordOut1 = procurementRecordOutMapper.selectCode(dateFormat.format(now));
            Long aLong = procurementRecordOut1 == null ? 1L : Long.valueOf(procurementRecordOut1.getCode().split("LS" + dateFormat.format(now))[1]);
            ProcurementRecordOut.ProcurementRecordOutBuilder procurementRecordOut = ProcurementRecordOut.builder()
                    .procurementRecordStorageId(0)
                    .code("LS" + dateFormat.format(now) + String.format("%03d", aLong + 1))
                    .salesLedgerProductId(productionProductMain.getId())//关联报工产出
                    .inboundBatches(aLong.equals(0L) ? "第1批次" : "第" + (aLong + 1) + "批次")
                    .inboundNum(productionProductInput.getQuantity())
                    .type(4)
                    .createBy(user.getNickName())
                    .productModelId(productModel1.getId());
            procurementRecordOutMapper.insert(procurementRecordOut.build());
            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
        }
        /*新增报工产出表*/
        ProductionProductOutput productionProductOutput = new ProductionProductOutput();
@@ -311,13 +291,13 @@
        // åˆ é™¤äº§å‡ºè®°å½•
        productionProductOutputMapper.delete(new LambdaQueryWrapper<ProductionProductOutput>()
                .eq(ProductionProductOutput::getProductMainId, productionProductMain.getId()));
        /*删除投入*/
        procurementRecordOutMapper.delete(new LambdaQueryWrapper<ProcurementRecordOut>()
                .eq(ProcurementRecordOut::getSalesLedgerProductId, productionProductMain.getId()));
        //删除入库
        productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
                .eq(ProductionProductInput::getProductMainId, productionProductMain.getId()));
        //删除报废的入库记录
        stockUtils.deleteStockRecord(productionProductMain.getId(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
        //删除投入对应的出库记录
        stockUtils.deleteStockRecord(productionProductMain.getId(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
        // åˆ é™¤ä¸»è¡¨
        productionProductMainMapper.deleteById(productionProductMain.getId());
        return true;
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
@@ -11,19 +11,30 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.mapper.PurchaseLedgerTemplateMapper;
import com.ruoyi.purchase.mapper.SalesLedgerProductTemplateMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
import com.ruoyi.purchase.service.IPurchaseLedgerService;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.sales.service.ISalesLedgerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -37,12 +48,68 @@
@RestController
@RequestMapping("/purchase/ledger")
@AllArgsConstructor
@Api(tags = "111")
@Api(tags = "采购台账")
@Slf4j
public class PurchaseLedgerController extends BaseController {
    private IPurchaseLedgerService purchaseLedgerService;
    private ISalesLedgerService salesLedgerService;
    private ISalesLedgerProductService salesLedgerProductService;
    private PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
    private SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
    /**
     * å¯¼å…¥é‡‡è´­å°è´¦
     */
    @Log(title = "导入采购台账", businessType = BusinessType.INSERT)
    @PostMapping("/import")
    @ApiOperation("导入采购台账")
    public AjaxResult importData(@RequestParam("file")
                                 @ApiParam(value = "Excel文件", required = true)
                                         MultipartFile file) {
        return purchaseLedgerService.importData(file);
    }
    @ApiOperation("导出采购台账模板")
    @PostMapping("/exportTemplate")
    public void exportTemplate(HttpServletResponse response) {
        // 1. æ¨¡æ¿æ–‡ä»¶åœ¨resources/static下的路径
        String templatePath = "static/采购台账导入模板.xlsx";
        // 2. èŽ·å–æ¨¡æ¿æ–‡ä»¶çš„è¾“å…¥æµ
        try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(templatePath)) {
            if (inputStream == null) {
                throw new FileNotFoundException("模板文件不存在:" + templatePath);
            }
            // 3. è®¾ç½®å“åº”头,触发浏览器下载
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("采购台账导入模板.xlsx", "utf-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            // 4. å°†æ¨¡æ¿æ–‡ä»¶å†™å…¥å“åº”输出流
            try (OutputStream outputStream = response.getOutputStream()) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, len);
                }
                outputStream.flush();
            }
        } catch (IOException e) {
            log.error("导出销售台账模板失败", e);
            // è‹¥æ¨¡æ¿æ–‡ä»¶è¯»å–失败,返回错误提示
            try {
                response.getWriter().write("模板导出失败:" + e.getMessage());
            } catch (IOException ex) {
                log.error("响应输出错误", ex);
            }
        }
    }
    /**
     * æŸ¥è¯¢é‡‡è´­å°è´¦åˆ—表
@@ -84,34 +151,24 @@
     */
    @Log(title = "采购台账", businessType = BusinessType.INSERT)
    @PostMapping("/addOrEditPurchase")
    public AjaxResult addOrEditPurchase(@RequestBody PurchaseLedgerDto purchaseLedgerDto) throws IOException {
    public AjaxResult addOrEditPurchase(@RequestBody PurchaseLedgerDto purchaseLedgerDto) throws Exception {
        return toAjax(purchaseLedgerService.addOrEditPurchase(purchaseLedgerDto));
    }
    /**
     * æ–°å¢žé‡‡è´­æ¨¡æ¿
     */
    @PostMapping("/addPurchaseTemplate")
    public AjaxResult addPurchaseTemplate(@RequestBody PurchaseLedgerDto purchaseLedgerDto) throws IOException {
        return toAjax(purchaseLedgerService.addPurchaseTemplate(purchaseLedgerDto));
    }
    /**
     * æŸ¥è¯¢é‡‡è´­æ¨¡æ¿
     */
    @ApiOperation("/2222")
    @ApiOperation("/查询采购模板")
    @GetMapping("/getPurchaseTemplateList")
    public AjaxResult getPurchaseTemplateList() {
        PurchaseLedgerDto purchaseLedgerDto = new PurchaseLedgerDto();
        purchaseLedgerDto.setApprovalStatus(3);
        IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = purchaseLedgerService.selectPurchaseLedgerListPage(new Page(1, -1), purchaseLedgerDto);
        List<PurchaseLedgerDto> purchaseLedgers = purchaseLedgerDtoIPage.getRecords();
        List<PurchaseLedgerTemplate>  purchaseLedgers = purchaseLedgerTemplateMapper.selectList(null);
        purchaseLedgers.forEach(purchaseLedgerDto1 -> {
            LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedgerDto1.getId())
                    .eq(SalesLedgerProduct::getType, 2);
            List<SalesLedgerProduct> list = salesLedgerProductService.list(queryWrapper);
            LambdaQueryWrapper<SalesLedgerProductTemplate> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SalesLedgerProductTemplate::getSalesLedgerId, purchaseLedgerDto1.getId())
                    .eq(SalesLedgerProductTemplate::getType, 2);
            List<SalesLedgerProductTemplate> list = salesLedgerProductTemplateMapper.selectList(queryWrapper);
            if (!list.isEmpty()) {
                purchaseLedgerDto1.setProductData(list);
                purchaseLedgerDto1.setProductList(list);
            }
        });
        return AjaxResult.success(purchaseLedgers);
@@ -194,27 +251,7 @@
     */
    @GetMapping("/listPage")
    public AjaxResult listPage(Page page, PurchaseLedgerDto purchaseLedger) {
        IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = Optional.ofNullable(
                purchaseLedgerService.selectPurchaseLedgerListPage(page, purchaseLedger)
        ).orElse(new Page<>());
        // å¤„理null
        Optional.ofNullable(purchaseLedgerDtoIPage.getRecords())
                .filter(CollectionUtils::isNotEmpty)
                .ifPresent(records -> {
                    // è¿‡æ»¤approvalStatus=3的记录
                    records.removeIf(dto -> dto != null && dto.getApprovalStatus() == 3);
                    // ä¿®æ­£æœªæ”¶ä»˜æ¬¾é‡‘额
                    records.forEach(dto -> {
                        if (dto == null) return;
                        BigDecimal unReceiptAmt = Optional.ofNullable(dto.getUnReceiptPaymentAmount()).orElse(BigDecimal.ZERO);
                        if (unReceiptAmt.compareTo(BigDecimal.ZERO) == 0) {
                            dto.setUnReceiptPaymentAmount(Optional.ofNullable(dto.getContractAmount()).orElse(BigDecimal.ZERO));
                        }
                    });
                });
        return AjaxResult.success(purchaseLedgerDtoIPage);
        return AjaxResult.success(purchaseLedgerService.selectPurchaseLedgerListPage(page, purchaseLedger));
    }
    @ApiOperation("生成采购序列号")
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
package com.ruoyi.purchase.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.mapper.PurchaseLedgerTemplateMapper;
import com.ruoyi.purchase.mapper.SalesLedgerProductTemplateMapper;
import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
import com.ruoyi.purchase.service.PurchaseLedgerTemplateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
/**
 * <p>
 * é‡‡è´­å°è´¦æ¨¡æ¿ å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:21:44
 */
@RestController
@RequestMapping("/purchaseLedgerTemplate")
@Api(tags = "采购台账模板")
public class PurchaseLedgerTemplateController {
    @Autowired
    private PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
    @Autowired
    private SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
    @PostMapping("/add")
    @Log(title = "添加采购台账模板", businessType = BusinessType.INSERT)
    @ApiOperation(value = "添加采购台账模板")
    public AjaxResult add(@RequestBody PurchaseLedgerDto purchaseLedgerDto) {
        // é‡‡è´­æ¨¡æ¿
        if(StringUtils.isNotEmpty(purchaseLedgerDto.getTemplateName())){
            // æ¨¡æ¿åç§°ä¸èƒ½é‡å¤ï¼Œæœ‰é‡å¤å°±ä¸éœ€è¦æ–°å¢žäº†
            PurchaseLedgerTemplate purchaseLedgerTemplate = purchaseLedgerTemplateMapper
                    .selectOne(new LambdaQueryWrapper<PurchaseLedgerTemplate>()
                            .eq(PurchaseLedgerTemplate::getTemplateName, purchaseLedgerDto.getTemplateName())
                            .last("limit 1"));
            if(purchaseLedgerTemplate == null){
                purchaseLedgerTemplate = new PurchaseLedgerTemplate();
                BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedgerTemplate);
                purchaseLedgerTemplate.setTemplateName(purchaseLedgerDto.getTemplateName());
                purchaseLedgerTemplateMapper.insert(purchaseLedgerTemplate);
                // äº§å“æ¨¡æ¿æ–°å¢ž
                PurchaseLedgerTemplate finalPurchaseLedgerTemplate = purchaseLedgerTemplate;
                purchaseLedgerDto.getProductData().forEach(product -> {
                    SalesLedgerProductTemplate salesLedgerProductTemplate = new SalesLedgerProductTemplate();
                    BeanUtils.copyProperties(product, salesLedgerProductTemplate);
                    salesLedgerProductTemplate.setSalesLedgerId(finalPurchaseLedgerTemplate.getId());
                    salesLedgerProductTemplate.setType(2);
                    salesLedgerProductTemplateMapper.insert(salesLedgerProductTemplate);
                });
            }
        }
        return AjaxResult.success();
    }
    @DeleteMapping("/delete")
    @Log(title = "采购台账模板", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除采购台账模板")
    public AjaxResult delete(@RequestBody List<Long> id) {
        if(CollectionUtils.isEmpty(id)) return AjaxResult.error("请选择要删除的采购台账模板");
        int result = purchaseLedgerTemplateMapper.deleteBatchIds(id);
        salesLedgerProductTemplateMapper.delete(new LambdaQueryWrapper<SalesLedgerProductTemplate>()
                .in(SalesLedgerProductTemplate::getSalesLedgerId, id));
        return AjaxResult.success(result);
    }
    @PostMapping("/update")
    @Log(title = "修改采购台账模板", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "修改采购台账模板")
    public AjaxResult update(@RequestBody PurchaseLedgerDto purchaseLedgerDto) {
        // æ¨¡æ¿åç§°ä¸èƒ½é‡å¤ï¼Œæœ‰é‡å¤å°±ä¸éœ€è¦æ–°å¢žäº†
        PurchaseLedgerTemplate purchaseLedgerTemplate = purchaseLedgerTemplateMapper
                .selectOne(new LambdaQueryWrapper<PurchaseLedgerTemplate>()
                        .eq(PurchaseLedgerTemplate::getTemplateName, purchaseLedgerDto.getTemplateName())
                        .last("limit 1"));
        if(purchaseLedgerTemplate != null){
            BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedgerTemplate);
            purchaseLedgerTemplate.setTemplateName(purchaseLedgerDto.getTemplateName());
            purchaseLedgerTemplateMapper.updateById(purchaseLedgerTemplate);
            // äº§å“æ¨¡æ¿åˆ é™¤
            salesLedgerProductTemplateMapper.delete(new LambdaQueryWrapper<SalesLedgerProductTemplate>()
                    .in(SalesLedgerProductTemplate::getSalesLedgerId, purchaseLedgerTemplate.getId()));
            // äº§å“æ¨¡æ¿æ–°å¢ž
            purchaseLedgerDto.getProductData().forEach(product -> {
                SalesLedgerProductTemplate salesLedgerProductTemplate = new SalesLedgerProductTemplate();
                BeanUtils.copyProperties(product, salesLedgerProductTemplate);
                salesLedgerProductTemplate.setSalesLedgerId(purchaseLedgerTemplate.getId());
                salesLedgerProductTemplateMapper.insert(salesLedgerProductTemplate);
            });
        }
        return AjaxResult.success();
    }
}
src/main/java/com/ruoyi/purchase/controller/SalesLedgerProductTemplateController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.purchase.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * äº§å“ä¿¡æ¯æ¨¡æ¿ å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:22:23
 */
@RestController
@RequestMapping("/salesLedgerProductTemplate")
public class SalesLedgerProductTemplateController {
}
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
@@ -15,6 +15,12 @@
@Data
public class PurchaseLedgerDto {
    /**
     * å®¡æ‰¹äººid列表
     */
    @ApiModelProperty(value = "审批人id列表")
    private String approveUserIds;
    private String entryDateStart;
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
package com.ruoyi.purchase.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * @author :yys
 * @date : 2026/1/26 16:01
 */
@Data
public class PurchaseLedgerImportDto extends PurchaseLedgerProductImportDto{
    @Excel(name = "采购单号")
    private String purchaseContractNumber;
    @Excel(name = "销售单号")
    private String salesContractNo;
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "录入日期", width = 30, dateFormat = "yyyy-MM-dd")
    private Date entryDate;
    @Excel(name = "供应商名称")
    private String supplierName;
    @Excel(name = "项目名称")
    private String projectName;
    /**
     * å½•入人姓名
     */
    @Excel(name = "录入人")
    private String recorderName;
    @Excel(name = "备注")
    private String remarks;
    @ApiModelProperty(value = "签订日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "签订日期", width = 30, dateFormat = "yyyy-MM-dd")
    private Date executionDate;
    @ApiModelProperty(value = "付款方式")
    @Excel(name = "付款方式")
    private String paymentMethod;
    @ApiModelProperty(value = "审核人(多个用,隔开)")
    @Excel(name = "审核人(多个用,隔开)")
    private String approveUserIds;
}
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerProductImportDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
package com.ruoyi.purchase.dto;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.dto.SalesLedgerProductImportDto;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author :yys
 * @date : 2026/1/26 16:03
 */
@Data
public class PurchaseLedgerProductImportDto{
    @Excel(name = "采购单号")
    private String purchaseContractNumber;
    /**
     * é¢„警数量
     */
    @Excel(name = "库存预警数量")
    private BigDecimal warnNum;
    @Excel(name = "销售单号")
    private String salesContractNo;
    /**
     * äº§å“å¤§ç±»
     */
    @Excel(name = "产品大类")
    private String productCategory;
    /**
     * è§„格型号
     */
    @Excel(name = "规格型号")
    private String specificationModel;
    /**
     * å•位
     */
    @Excel(name = "单位")
    private String unit;
    /**
     * æ•°é‡
     */
    @Excel(name = "数量")
    private BigDecimal quantity;
    /**
     * ç¨Žçއ
     */
    @Excel(name = "税率")
    private BigDecimal taxRate;
    /**
     * å«ç¨Žå•ä»·
     */
    @Excel(name = "含税单价")
    private BigDecimal taxInclusiveUnitPrice;
    /**
     * å«ç¨Žæ€»ä»·
     */
    @Excel(name = "含税总价")
    private BigDecimal taxInclusiveTotalPrice;
    /**
     * å‘票类型
     */
    @Excel(name = "发票类型")
    private String invoiceType;
    /**
     * æ˜¯å¦è´¨æ£€
     */
    @Excel(name = "是否质检", readConverterExp = "0=否,1=是")
    private Integer isChecked;
}
src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerTemplateMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.purchase.mapper;
import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * é‡‡è´­å°è´¦æ¨¡æ¿ Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:21:44
 */
@Mapper
public interface PurchaseLedgerTemplateMapper extends BaseMapper<PurchaseLedgerTemplate> {
}
src/main/java/com/ruoyi/purchase/mapper/SalesLedgerProductTemplateMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.purchase.mapper;
import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * äº§å“ä¿¡æ¯æ¨¡æ¿ Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:22:23
 */
@Mapper
public interface SalesLedgerProductTemplateMapper extends BaseMapper<SalesLedgerProductTemplate> {
}
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
@@ -150,12 +150,12 @@
    @ApiModelProperty(value = "付款方式")
    private String paymentMethod;
    @ApiModelProperty("审批状态")
    @ApiModelProperty("审批状态  1-待审核,2-审批中,3-审批通过,4-审批失败,5表示是模板")
    private Integer approvalStatus;
    @ApiModelProperty(value = "模板名称")
    private String templateName;
    @ApiModelProperty(value = "审批人id")
    private Integer approverId;
    private String approveUserIds;
}
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
package com.ruoyi.purchase.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * <p>
 * é‡‡è´­å°è´¦æ¨¡æ¿
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:21:44
 */
@Getter
@Setter
@TableName("purchase_ledger_template")
@ApiModel(value = "PurchaseLedgerTemplate对象", description = "采购台账模板")
public class PurchaseLedgerTemplate implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("自增主键ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("采购合同号")
    private String purchaseContractNumber;
    @ApiModelProperty("供应商名称id")
    private Long supplierId;
    @ApiModelProperty("供应商名称")
    private String supplierName;
    @ApiModelProperty("录入人id")
    private Integer recorderId;
    @ApiModelProperty("录入人姓名")
    private String recorderName;
    @ApiModelProperty("销售合同号")
    private String salesContractNo;
    @ApiModelProperty("项目名称")
    private String projectName;
    @ApiModelProperty("录入日期")
    private Date entryDate;
    @ApiModelProperty("备注")
    private String remarks;
    @ApiModelProperty("记录创建时间")
    private Date createdAt;
    @ApiModelProperty("记录最后更新时间")
    private Date updatedAt;
    @ApiModelProperty("关联销售台账主表主键")
    private Integer salesLedgerId;
    @ApiModelProperty("合同金额")
    private BigDecimal contractAmount;
    @ApiModelProperty("业务员")
    private String businessPerson;
    @ApiModelProperty("业务员id")
    private Integer businessPersonId;
    @ApiModelProperty("录入人电话")
    private String phoneNumber;
    private String paymentMethod;
    private Date executionDate;
    @ApiModelProperty("模板名称")
    private String templateName;
    @TableField(exist = false)
    private List<SalesLedgerProductTemplate> productList;
}
src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.ruoyi.purchase.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * <p>
 * äº§å“ä¿¡æ¯æ¨¡æ¿
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:22:23
 */
@Getter
@Setter
@TableName("sales_ledger_product_template")
@ApiModel(value = "SalesLedgerProductTemplate对象", description = "产品信息模板")
public class SalesLedgerProductTemplate implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("产品信息主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("关联台账主表主键")
    private Integer salesLedgerId;
    @ApiModelProperty("产品大类")
    private String productCategory;
    @ApiModelProperty("规格型号")
    private String specificationModel;
    @ApiModelProperty("单位")
    private String unit;
    @ApiModelProperty("数量")
    private BigDecimal quantity;
    @ApiModelProperty("最低库存")
    private BigDecimal minStock;
    @ApiModelProperty("税率")
    private BigDecimal taxRate;
    @ApiModelProperty("含税单价")
    private BigDecimal taxInclusiveUnitPrice;
    @ApiModelProperty("含税总价")
    private BigDecimal taxInclusiveTotalPrice;
    @ApiModelProperty("不含税总价")
    private BigDecimal taxExclusiveTotalPrice;
    @ApiModelProperty("发票类型")
    private String invoiceType;
    @ApiModelProperty("1.销售台账,2.采购台账")
    private Integer type;
    @ApiModelProperty("产品id")
    private Integer productId;
    @ApiModelProperty("型号id")
    private Integer productModelId;
    private String register;
    private LocalDateTime registerDate;
    private BigDecimal warnNum;
    @ApiModelProperty("是否推送质检")
    private Boolean isChecked;
}
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
@@ -3,9 +3,11 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
@@ -20,7 +22,7 @@
    List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger);
    int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws IOException;
    int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws Exception;
    int deletePurchaseLedgerByIds(Long[] ids);
@@ -40,5 +42,5 @@
    String getPurchaseNo();
    int addPurchaseTemplate(PurchaseLedgerDto purchaseLedgerDto) throws IOException;
    AjaxResult importData(MultipartFile file);
}
src/main/java/com/ruoyi/purchase/service/PurchaseLedgerTemplateService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.purchase.service;
import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * é‡‡è´­å°è´¦æ¨¡æ¿ æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:21:44
 */
public interface PurchaseLedgerTemplateService extends IService<PurchaseLedgerTemplate> {
}
src/main/java/com/ruoyi/purchase/service/SalesLedgerProductTemplateService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.purchase.service;
import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * äº§å“ä¿¡æ¯æ¨¡æ¿ æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:22:23
 */
public interface SalesLedgerProductTemplateService extends IService<SalesLedgerProductTemplate> {
}
src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java
@@ -344,7 +344,6 @@
        List<Long> supplierIds = suppliers.stream()
                .map(SupplierManage::getId) // å…ˆèŽ·å–Integer类型的ID
                .filter(Objects::nonNull)    // è¿‡æ»¤æŽ‰å¯èƒ½çš„null值
                .map(Integer::longValue)    // å°†Integer转换为Long
                .collect(Collectors.toList());
        // èŽ·å–å½“æœˆçš„å¼€å§‹å’Œç»“æŸæ—¥æœŸ
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.purchase.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -10,9 +11,13 @@
import com.ruoyi.account.pojo.AccountIncome;
import com.ruoyi.account.service.AccountExpenseService;
import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
import com.ruoyi.approve.vo.ApproveProcessVO;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.mapper.SupplierManageMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.pojo.SupplierManage;
@@ -21,7 +26,9 @@
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
@@ -29,17 +36,15 @@
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
import com.ruoyi.purchase.mapper.ProductRecordMapper;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
import com.ruoyi.purchase.pojo.PaymentRegistration;
import com.ruoyi.purchase.pojo.ProductRecord;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.purchase.pojo.TicketRegistration;
import com.ruoyi.purchase.dto.PurchaseLedgerImportDto;
import com.ruoyi.purchase.dto.PurchaseLedgerProductImportDto;
import com.ruoyi.purchase.mapper.*;
import com.ruoyi.purchase.pojo.*;
import com.ruoyi.purchase.service.IPurchaseLedgerService;
import com.ruoyi.quality.mapper.*;
import com.ruoyi.quality.pojo.*;
import com.ruoyi.sales.dto.SalesLedgerImportDto;
import com.ruoyi.sales.dto.SalesLedgerProductImportDto;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
@@ -53,9 +58,12 @@
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -96,6 +104,8 @@
    private final ProductModelMapper productModelMapper;
    private final SysUserMapper sysUserMapper;
    private final TicketRegistrationMapper ticketRegistrationMapper;
    private final ProductRecordMapper productRecordMapper;
@@ -111,7 +121,13 @@
    private final QualityTestStandardMapper qualityTestStandardMapper;
    private final QualityInspectParamMapper qualityInspectParamMapper;
    private final ApproveProcessServiceImpl approveProcessService;
    private final ProcurementRecordMapper procurementRecordStorageMapper;
    private final PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
    private final SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
@@ -123,52 +139,10 @@
        }
        return purchaseLedgerMapper.selectList(queryWrapper);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addPurchaseTemplate(PurchaseLedgerDto purchaseLedgerDto)throws IOException {
        //录入人
        SysUser sysUser = userMapper.selectUserById(purchaseLedgerDto.getRecorderId());
        SupplierManage supplierManage = supplierManageMapper.selectById(purchaseLedgerDto.getSupplierId());
        PurchaseLedger purchaseLedger = new PurchaseLedger();
//        BeanUtils.copyProperties(purchaseLedger,purchaseLedgerDto);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(ObjectUtils.isNotEmpty(loginUser) && null != loginUser.getTenantId()) {
            purchaseLedger.setTenantId(loginUser.getTenantId());
        }
        purchaseLedger.setPaymentMethod(purchaseLedgerDto.getPaymentMethod());
        purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId());
        purchaseLedger.setSupplierId(purchaseLedgerDto.getSupplierId());
        purchaseLedger.setTemplateName(purchaseLedgerDto.getTemplateName());
//        purchaseLedger.setSalesLedgerPId(purchaseLedgerDto.getSalesLedgerId());
        purchaseLedger.setApprovalStatus(3);
        purchaseLedger.setSupplierName(supplierManage.getSupplierName());
        purchaseLedger.setRecorderName(sysUser.getNickName());
        purchaseLedger.setPhoneNumber(sysUser.getPhonenumber());
        purchaseLedger.setPurchaseContractNumber(UUID.randomUUID().toString().replaceAll("-", ""));
        purchaseLedger.setEntryDate(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()));
        int insert = purchaseLedgerMapper.insert(purchaseLedger);
        LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PurchaseLedger::getSupplierName, purchaseLedger.getSupplierName())
                .eq(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber())
                .eq(PurchaseLedger::getApprovalStatus,3);
        PurchaseLedger purchaseLedger1 = purchaseLedgerMapper.selectOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(purchaseLedgerDto.getProductData())) {
            // 4. å¤„理子表数据
            List<SalesLedgerProduct> salesLedgerProductList = purchaseLedgerDto.getProductData();
            salesLedgerProductList.forEach(salesLedgerProduct -> {
                salesLedgerProduct.setSalesLedgerId(purchaseLedger1.getId());
                salesLedgerProduct.setType(2);
            });
            salesLedgerProductList.forEach(salesLedgerProductMapper::insert);
        }
        return insert;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws IOException {
    public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws Exception {
        SalesLedger salesLedger = salesLedgerMapper.selectById(purchaseLedgerDto.getSalesLedgerId());
        //录入人
@@ -193,8 +167,19 @@
        if (purchaseLedger.getId() == null) {
            purchaseLedgerMapper.insert(purchaseLedger);
        } else {
            // åˆ é™¤é‡‡è´­å®¡æ ¸ï¼Œé‡æ–°æäº¤
            ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
                    .eq(ApproveProcess::getApproveType, 5)
                    .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber())
                    .eq(ApproveProcess::getApproveDelete, 0)
                    .last("limit 1"));
            if (one != null) {
                approveProcessService.delByIds(Collections.singletonList(one.getId()));
            }
            purchaseLedgerMapper.updateById(purchaseLedger);
        }
        // 6.采购审核新增
        addApproveByPurchase(loginUser, purchaseLedger);
        // 4. å¤„理子表数据
        List<SalesLedgerProduct> productList = purchaseLedgerDto.getProductData();
@@ -214,7 +199,6 @@
        if (purchaseLedgerDto.getTempFileIds() != null && !purchaseLedgerDto.getTempFileIds().isEmpty()) {
            migrateTempFilesToFormal(purchaseLedger.getId(), purchaseLedgerDto.getTempFileIds());
        }
        return 1;
    }
@@ -461,7 +445,20 @@
            qualityStandardLambdaQueryWrapper.in(QualityInspectParam::getInspectId, inspectIds);
            qualityInspectParamMapper.delete(qualityStandardLambdaQueryWrapper);
        }
        // åˆ é™¤é‡‡è´­å®¡æ‰¹è®°å½•
        for (Long id : ids) {
            PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
            if(purchaseLedger != null){
                ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
                        .eq(ApproveProcess::getApproveType, 5)
                        .eq(ApproveProcess::getApproveDelete, 0)
                        .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber())
                        .last("limit 1"));
                if (one != null) {
                    approveProcessService.delByIds(Collections.singletonList(one.getId()));
                }
            }
        }
        //批量删除原材料检验数据
        qualityInspectMapper.delete(materialInspectLambdaQueryWrapper);
        // æ‰¹é‡åˆ é™¤é‡‡è´­å°è´¦
@@ -619,6 +616,125 @@
        return purchaseNo + String.format("%03d", sequence);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importData(MultipartFile file) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        try {
            InputStream inputStream = file.getInputStream();
            ExcelUtil<PurchaseLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(PurchaseLedgerImportDto.class);
            Map<String, List<PurchaseLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("采购台账数据", "采购产品数据"), inputStream, 0);
            if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("采购表格为空!");
            // ä¸šåŠ¡å±‚åˆå¹¶
            List<PurchaseLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("采购台账数据");
            if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("采购台账数据为空!");
            List<PurchaseLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("采购产品数据");
            if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("采购产品数据为空!");
            // ä¾›åº”商数据
            List<SupplierManage> customers = supplierManageMapper.selectList(new LambdaQueryWrapper<SupplierManage>().in(SupplierManage::getSupplierName,
                    salesLedgerImportDtoList.stream().map(PurchaseLedgerImportDto::getSupplierName).collect(Collectors.toList())));
            List<Map<String,Object>> list = productModelMapper.getProductAndModelList();
            // å½•入人数据
            List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName,
                    salesLedgerImportDtoList.stream().map(PurchaseLedgerImportDto::getRecorderName).collect(Collectors.toList())));
            for (PurchaseLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) {
                PurchaseLedger salesLedger = new PurchaseLedger();
                BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
                // é€šè¿‡ä¾›åº”商名称查询ID
                salesLedger.setSupplierId(customers.stream()
                        .filter(customer -> customer.getSupplierName().equals(salesLedger.getSupplierName()))
                        .findFirst()
                        .map(SupplierManage::getId)
                        .orElse(null));
                Long aLong = sysUsers.stream()
                        .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getRecorderName()))
                        .findFirst()
                        .map(SysUser::getUserId)
                        .orElse(null);
                if (aLong == null)
                    throw new RuntimeException("录入人:" + salesLedger.getRecorderName() + ",无对应用户!");
                salesLedger.setRecorderId(aLong);
                // é‡‡è´­äº§å“æ•°æ®ç»‘定,通过采购单号获取对应采购产品数据
                List<PurchaseLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream()
                        .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getPurchaseContractNumber().equals(salesLedger.getPurchaseContractNumber()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
                    throw new RuntimeException("采购单号:" + salesLedgerImportDto.getPurchaseContractNumber() + ",无对应产品数据!");
                salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
                        .map(PurchaseLedgerProductImportDto::getTaxInclusiveTotalPrice)
                        .reduce(BigDecimal.ZERO,BigDecimal::add));
                // é€šè¿‡é”€å”®å•号绑定销售
                SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
                        .eq(SalesLedger::getSalesContractNo, salesLedger.getSalesContractNo())
                        .last("LIMIT 1"));
                if(salesLedger1 != null){
                    salesLedger.setSalesLedgerId(salesLedger1.getId());
                }
                // é‡‡è´­å®¡æ ¸
                // é€šè¿‡æ˜µç§°èŽ·å–ç”¨æˆ·ID
                String[] split = salesLedger.getApproveUserIds().split(",");
                List<Long> ids = new ArrayList<>();
                for (int i = 0; i < split.length; i++) {
                    SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, split[i])
                            .last("LIMIT 1"));
                    if (sysUser != null) {
                        ids.add(sysUser.getUserId());
                    }
                }
                // å°†é›†åˆè½¬ä¸ºå­—符串,隔开
                String collect = ids.stream().map(Object::toString).collect(Collectors.joining(","));
                salesLedger.setApproveUserIds(collect);
                purchaseLedgerMapper.insert(salesLedger);
                for (PurchaseLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
                    SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
                    BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
                    salesLedgerProduct.setSalesLedgerId(salesLedger.getId());
                    salesLedgerProduct.setType(2);
                    // è®¡ç®—不含税总价
                    salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
                    salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
                    salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
                    list.stream()
                            .filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel()))
                            .findFirst()
                            .ifPresent(map -> {
                                salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
                                salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
                            });
                    salesLedgerProduct.setRegister(loginUser.getNickName());
                    salesLedgerProduct.setRegisterDate(LocalDateTime.now());
                    salesLedgerProduct.setApproveStatus(0);
                    salesLedgerProduct.setPendingTicketsTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
                    // æ˜¯å¦è´¨æ£€åˆ¤æ–­
                    salesLedgerProduct.setIsChecked(salesLedgerProductImportDto.getIsChecked() == 1);
                    if(salesLedgerProductImportDto.getIsChecked() == 1){
                        addQualityInspect(salesLedger, salesLedgerProduct);
                    }
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                }
                // é‡‡è´­å®¡æ ¸
                addApproveByPurchase(loginUser,salesLedger);
            }
            return AjaxResult.success("导入成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success("导入失败");
    }
    public void addApproveByPurchase(LoginUser loginUser,PurchaseLedger purchaseLedger) throws Exception {
        ApproveProcessVO approveProcessVO = new ApproveProcessVO();
        approveProcessVO.setApproveType(5);
        approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
        approveProcessVO.setApproveReason(purchaseLedger.getPurchaseContractNumber());
        approveProcessVO.setApproveUserIds(purchaseLedger.getApproveUserIds());
        approveProcessVO.setApproveUser(loginUser.getUserId());
        approveProcessVO.setApproveTime(LocalDate.now().toString());
        approveProcessService.addApprove(approveProcessVO);
    }
    /**
     * ä¸‹åˆ’线命名转驼峰命名
     */
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.ruoyi.purchase.service.impl;
import com.ruoyi.purchase.mapper.SalesLedgerProductTemplateMapper;
import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
import com.ruoyi.purchase.mapper.PurchaseLedgerTemplateMapper;
import com.ruoyi.purchase.service.PurchaseLedgerTemplateService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * <p>
 * é‡‡è´­å°è´¦æ¨¡æ¿ æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:21:44
 */
@Service
public class PurchaseLedgerTemplateServiceImpl extends ServiceImpl<PurchaseLedgerTemplateMapper, PurchaseLedgerTemplate> implements PurchaseLedgerTemplateService {
    @Autowired
    private PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
    @Autowired
    private SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
}
src/main/java/com/ruoyi/purchase/service/impl/SalesLedgerProductTemplateServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.ruoyi.purchase.service.impl;
import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
import com.ruoyi.purchase.mapper.SalesLedgerProductTemplateMapper;
import com.ruoyi.purchase.service.SalesLedgerProductTemplateService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 * äº§å“ä¿¡æ¯æ¨¡æ¿ æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-26 11:22:23
 */
@Service
public class SalesLedgerProductTemplateServiceImpl extends ServiceImpl<SalesLedgerProductTemplateMapper, SalesLedgerProductTemplate> implements SalesLedgerProductTemplateService {
}
src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -82,7 +82,7 @@
        // å‘货审批
        ApproveProcessVO approveProcessVO = new ApproveProcessVO();
        approveProcessVO.setApproveType(7);
        approveProcessVO.setApproveDeptId(loginUser.getTenantId());
        approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
        approveProcessVO.setApproveReason(req.getType() + ":" +sh);
        approveProcessVO.setApproveUserIds(req.getApproveUserIds());
        approveProcessVO.setApproveUser(loginUser.getUserId());
@@ -106,6 +106,7 @@
        }
        byId.setExpressNumber(req.getExpressNumber());
        byId.setExpressCompany(req.getExpressCompany());
        byId.setStatus("已发货");
        byId.setShippingCarNumber(req.getShippingCarNumber());
        boolean update = shippingInfoService.updateById(req);
        // è¿ç§»æ–‡ä»¶
src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
@@ -43,9 +43,6 @@
    @Excel(name = "签订日期", width = 30, dateFormat = "yyyy-MM-dd")
    private Date executionDate;
    @Excel(name = "合同金额")
    private BigDecimal contractAmount;
    @ApiModelProperty(value = "付款方式")
    @Excel(name = "付款方式")
    private String paymentMethod;
src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java
@@ -37,7 +37,7 @@
    @ApiModelProperty(value = "销售报价产品表id")
    private Long salesLedgerProductId;
    @ApiModelProperty(value = "状态")
    @ApiModelProperty(value = "状态 å¾…审核 å®¡æ ¸ä¸­ ï¼Œå®¡æ ¸æ‹’绝 å®¡æ ¸é€šè¿‡")
    @Excel(name = "状态")
    private String status;
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -391,13 +391,18 @@
                if (aLong == null)
                    throw new RuntimeException("录入人:" + salesLedger.getEntryPerson() + ",无对应用户!");
                salesLedger.setEntryPerson(aLong.toString());
                salesLedgerMapper.insert(salesLedger);
                // é”€å”®äº§å“æ•°æ®ç»‘定,通过销售单号获取对应销售产品数据
                List<SalesLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream()
                        .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getSalesContractNo().equals(salesLedger.getSalesContractNo()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
                    throw new RuntimeException("销售单号:" + salesLedgerImportDto.getSalesContractNo() + ",无对应产品数据!");
                salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
                        .map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice)
                        .reduce(BigDecimal.ZERO,BigDecimal::add));
                salesLedgerMapper.insert(salesLedger);
                for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
                    SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
                    BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
@@ -79,7 +79,7 @@
        // æŠ¥ä»·å®¡æ‰¹
        ApproveProcessVO approveProcessVO = new ApproveProcessVO();
        approveProcessVO.setApproveType(6);
        approveProcessVO.setApproveDeptId(loginUser.getTenantId());
        approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
        approveProcessVO.setApproveReason(quotationNo);
        approveProcessVO.setApproveUserIds(salesQuotationDto.getApproveUserIds());
        approveProcessVO.setApproveUser(loginUser.getUserId());
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
@@ -44,6 +44,10 @@
            <if test="deviceMaintenanceDto.maintenanceActuallyTimeReq != null">
                and dm.maintenance_actually_time like concat('%',#{deviceMaintenanceDto.maintenanceActuallyTimeReq},'%')
            </if>
            <if test="deviceMaintenanceDto.maintenanceActuallyTime != null">
                and dm.maintenance_actually_time >= str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, '%Y-%m-%d')
                and dm.maintenance_actually_time &lt; date_add(str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, '%Y-%m-%d'), interval 1 day)
            </if>
        </where>
    </select>
    <select id="detailById" resultType="com.ruoyi.device.dto.DeviceMaintenanceDto">
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml
@@ -40,10 +40,10 @@
            <if test="req.status != null">
                <choose>
                    <when test="req.status == 1">
                        AND next_date &gt;=  DATE_FORMAT(now(),'%Y-%m-%d')
                        AND most_date &gt;=  DATE_FORMAT(now(),'%Y-%m-%d')
                    </when>
                    <when test="req.status == 2">
                        AND next_date &lt;  DATE_FORMAT(now(),'%Y-%m-%d')
                        AND most_date &lt;  DATE_FORMAT(now(),'%Y-%m-%d')
                    </when>
                </choose>
            </if>
src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -21,10 +21,11 @@
        sum(tr.invoice_amount)as receipt_payment_amount,
        pl.contract_amount-sum(tr.invoice_amount) AS unReceipt_payment_amount,
        pl.entry_date,
        pl.execution_date,
        pl.recorder_id,
        pl.recorder_name,
        pl.template_name,
        pl.approver_id,
        pl.approve_user_ids,
        sm.is_white,
        pl.approval_status,
        pl.payment_method
src/main/resources/mapper/purchase/PurchaseLedgerTemplateMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
<?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.purchase.mapper.PurchaseLedgerTemplateMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.purchase.pojo.PurchaseLedgerTemplate">
        <id column="id" property="id" />
        <result column="purchase_contract_number" property="purchaseContractNumber" />
        <result column="supplier_id" property="supplierId" />
        <result column="supplier_name" property="supplierName" />
        <result column="recorder_id" property="recorderId" />
        <result column="recorder_name" property="recorderName" />
        <result column="sales_contract_no" property="salesContractNo" />
        <result column="project_name" property="projectName" />
        <result column="entry_date" property="entryDate" />
        <result column="remarks" property="remarks" />
        <result column="created_at" property="createdAt" />
        <result column="updated_at" property="updatedAt" />
        <result column="sales_ledger_id" property="salesLedgerId" />
        <result column="contract_amount" property="contractAmount" />
        <result column="business_person" property="businessPerson" />
        <result column="business_person_id" property="businessPersonId" />
        <result column="phone_number" property="phoneNumber" />
        <result column="payment_method" property="paymentMethod" />
        <result column="execution_date" property="executionDate" />
        <result column="template_name" property="templateName" />
    </resultMap>
</mapper>
src/main/resources/mapper/purchase/SalesLedgerProductTemplateMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
<?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.purchase.mapper.SalesLedgerProductTemplateMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.purchase.pojo.SalesLedgerProductTemplate">
        <id column="id" property="id" />
        <result column="sales_ledger_id" property="salesLedgerId" />
        <result column="product_category" property="productCategory" />
        <result column="specification_model" property="specificationModel" />
        <result column="unit" property="unit" />
        <result column="quantity" property="quantity" />
        <result column="min_stock" property="minStock" />
        <result column="tax_rate" property="taxRate" />
        <result column="tax_inclusive_unit_price" property="taxInclusiveUnitPrice" />
        <result column="tax_inclusive_total_price" property="taxInclusiveTotalPrice" />
        <result column="tax_exclusive_total_price" property="taxExclusiveTotalPrice" />
        <result column="invoice_type" property="invoiceType" />
        <result column="type" property="type" />
        <result column="product_id" property="productId" />
        <result column="product_model_id" property="productModelId" />
        <result column="register" property="register" />
        <result column="register_date" property="registerDate" />
        <result column="warn_num" property="warnNum" />
        <result column="is_checked" property="isChecked" />
    </resultMap>
</mapper>
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -9,7 +9,7 @@
        T1.*,
        t3.shipping_car_number,
        t3.shipping_date,
        t3.status as shippingStatus
        t3.status as shippingStatus,
        t3.shipping_date,
        CASE
        WHEN t2.qualitity > T1.quantity THEN 1
src/main/resources/static/²É¹ºÌ¨Õ˵¼ÈëÄ£°å.xlsx
Binary files differ
src/main/resources/static/ÏúÊŲ̂Õ˵¼ÈëÄ£°å.xlsx
Binary files differ