yaowanxin
4 天以前 a0914318549b357ef3c438d0c2a3714f58ea3487
Merge remote-tracking branch 'origin/dev_New' into dev_New
已添加37个文件
已修改49个文件
2850 ■■■■ 文件已修改
src/main/java/com/ruoyi/CodeGenerator.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/EnumController.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/SelectOptionDTO.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/utils/EnumUtils.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/BaseEnum.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/SalesLedgerType.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StockQualifiedRecordTypeEnum.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StockUnQualifiedRecordTypeEnum.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/UserStatus.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/EnumUtil.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/service/CustomerVisitsService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceRepairController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductBomController.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductStructureController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 167 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java 128 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/LossProductModelDto.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockInventoryController.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockUninventoryDto.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockInRecordMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockOutRecordMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInventory.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockUninventory.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockInRecordService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockInventoryService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockOutRecordService.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockUninventoryService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/StaffContactsPersonalMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/lavorissue/LavorIssueMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionProductMainMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityInspectMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInRecordMapper.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInventoryMapper.xml 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockOutRecordMapper.xml 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockUninventoryMapper.xml 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/CodeGenerator.java
@@ -19,11 +19,11 @@
// æ¼”示例子,执行 main æ–¹æ³•控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
    public static String database_url = "jdbc:mysql://127.0.0.1:3306/product-inventory-management-new";
    public static String database_url = "jdbc:mysql://1.15.17.182:9999/product-inventory-management-new";
    public static String database_username = "root";
    public static String database_password= "123456";
    public static String database_password= "xd@123456..";
    public static String author = "芯导软件(江苏)有限公司";
    public static String model = "account"; // æ¨¡å—
    public static String model = "stock"; // æ¨¡å—
    public static String setParent = "com.ruoyi."+ model; // åŒ…路径
    public static String tablePrefix = ""; // è®¾ç½®è¿‡æ»¤è¡¨å‰ç¼€
    public static void main(String[] args) {
src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java
@@ -22,7 +22,7 @@
    /**
     * çŸ¥è¯†ç±»åž‹
     */
    @Excel(name = "知识类型",readConverterExp = "contract=合同特批,approval=审批案例,solution=解决方案,experience=经验总结,guide=操作指南")
    @Excel(name = "知识类型")
    private String type;
    /**
     * é€‚用场景
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -67,7 +67,7 @@
        LambdaQueryWrapper<ApproveProcess> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveProcess::getApproveId, id);
        queryWrapper.eq(ApproveProcess::getApproveDelete, 0);
        queryWrapper.eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId());
//        queryWrapper.eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId());
        queryWrapper.last("limit 1");
        ApproveProcess one = approveProcessMapper.selectOne(queryWrapper);
        return one;
@@ -76,14 +76,12 @@
    @Override
    public void initApproveNodes(String approveUserIds,String approveID,Long tenantId) {
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        ApproveProcess approve = getApproveById(approveID);
        String[] names = approveUserIds.split(",");
        String approveId = approve.getApproveId();
        for (int i = 0; i < names.length; i++) {
            SysUser sysUser = sysUserMapper.selectUserById(Long.parseLong(names[i]));
            if (sysUser == null) continue;
            ApproveNode approveNode = new ApproveNode();
            approveNode.setApproveProcessId(approveId);
            approveNode.setApproveProcessId(approveID);
            approveNode.setApproveNodeOrder(i +1);
            approveNode.setApproveNodeUser(sysUser.getNickName());
            approveNode.setApproveNodeUserId(sysUser.getUserId());
@@ -104,14 +102,12 @@
        LambdaQueryWrapper<ApproveNode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveNode::getApproveProcessId, id);
        queryWrapper.eq(ApproveNode::getDeleteFlag, 0);
        queryWrapper.eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId());
        List<ApproveNode> list = list(queryWrapper);
        // æŒ‰ç…§ approveNodeOrder å­—段升序排序
        list.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder));
        LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, id)
                .eq(ApproveProcess::getApproveDelete, 0)
                .eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .last("limit 1");
        ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
        if(approveProcess != null && approveProcess.getApproveStatus() == 3){
@@ -137,7 +133,6 @@
        LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId())
                .eq(ApproveProcess::getApproveDelete, 0)
                .eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .last("limit 1");
        ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
        if(approveProcess == null) throw new RuntimeException("审批不存在");
@@ -145,7 +140,6 @@
        approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveNode.getApproveProcessId())
                .eq(ApproveNode::getApproveNodeOrder, approveNode.getApproveNodeOrder() + 1)
                .eq(ApproveNode::getDeleteFlag, 0)
                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .last("limit 1");
        ApproveNode approveNode1 = approveNodeMapper.selectOne(approveNodeLambdaQueryWrapper);
        approveProcess.setApproveStatus(status);
@@ -206,7 +200,6 @@
                    sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                            approveNode.getApproveProcessId()+"流程编号的审批需要您审核!!!!!",
                            Arrays.asList(Long.valueOf(id)),
                            approveNode.getTenantId(),
                            "/collaborativeApproval/approvalProcess?approveType="+approveProcess.getApproveType()+"&approveId="+approveNode.getApproveProcessId());
                }
                break;
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.ruoyi.approve.mapper.ApproveNodeMapper;
@@ -126,7 +127,6 @@
        sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcessVO.getApproveType()),
                approveID + "流程编号的审批需要您审核!!!!!",
                Arrays.asList(Long.valueOf(id)),
                approveProcessVO.getApproveDeptId(),
                "/collaborativeApproval/approvalProcess?approveType=" + approveProcessVO.getApproveType() + "&approveId=" + approveID);
    }
@@ -189,12 +189,9 @@
    @Override
    public ApproveProcess getApproveById(String id) {
        LambdaQueryWrapper<ApproveProcess> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveProcess::getApproveId, id);
        queryWrapper.eq(ApproveProcess::getApproveDelete, 0);
        queryWrapper.eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId());
        queryWrapper.last("limit 1");
        ApproveProcess one = getOne(queryWrapper);
        ApproveProcess one = approveProcessMapper.selectList(Wrappers.<ApproveProcess>lambdaQuery()
                .eq(ApproveProcess::getApproveId,id)
                .eq(ApproveProcess::getApproveDelete,0)).get(0);
        one.setCommonFileList(commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
                .eq(CommonFile::getCommonId, one.getId())
                .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue())));
@@ -232,7 +229,7 @@
        LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId())
                .eq(ApproveNode::getDeleteFlag, 0)
                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
//                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .orderByAsc(ApproveNode::getApproveNodeOrder);
        approveNodeMapper.delete(approveNodeLambdaQueryWrapper);
        approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approveProcess.getApproveId(), approveProcess.getTenantId());
@@ -241,7 +238,6 @@
        sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                approveProcess.getApproveId() + "流程编号的审批需要您审核!!!!!",
                Arrays.asList(Long.valueOf(id)),
                approveProcess.getApproveDeptId(),
                "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
    }
@@ -273,7 +269,7 @@
        LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approve.getApproveId())
                .eq(ApproveNode::getDeleteFlag, 0)
                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
//                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .orderByAsc(ApproveNode::getApproveNodeOrder);
        approveNodeMapper.delete(approveNodeLambdaQueryWrapper);
        approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approve.getApproveId(), approve.getTenantId());
@@ -300,7 +296,6 @@
        sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()),
                approve.getApproveId() + "流程编号的审批需要您审核!!!!!",
                Arrays.asList(Long.valueOf(id)),
                approve.getApproveDeptId(),
                "/collaborativeApproval/approvalProcess?approveType=" + approve.getApproveType() + "&approveId=" + approve.getApproveId());
    }
src/main/java/com/ruoyi/basic/controller/EnumController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package com.ruoyi.basic.controller;
import com.ruoyi.basic.utils.EnumUtils;
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
import com.ruoyi.framework.web.domain.R;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
@Api(tags = "枚举接口")
@RequestMapping("/basic/enum")
public class EnumController {
    //获取库存枚举
    @GetMapping("/stockRecordType")
    @Anonymous
    public R  getStockRecordTypeEnum(){
        List<Map<String, Object>> list = EnumUtil.toList(StockQualifiedRecordTypeEnum.class);
        return R.ok(list);
    }
    @GetMapping("/{className}")
    @Anonymous
    public R test(@PathVariable String className){
        return R.ok(EnumUtils.getOptions("com.ruoyi.common.enums." + className));
    }
}
src/main/java/com/ruoyi/basic/dto/SelectOptionDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.ruoyi.basic.dto;
import lombok.Data;
@Data
public class SelectOptionDTO<T> {
    private T value;
    private String label;
    public SelectOptionDTO(T code, String value) {
        this.value = code;
        this.label = value;
    }
}
src/main/java/com/ruoyi/basic/utils/EnumUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.ruoyi.basic.utils;
import com.ruoyi.basic.dto.SelectOptionDTO;
import com.ruoyi.common.enums.BaseEnum;
import java.util.ArrayList;
import java.util.List;
public class EnumUtils {
    public static List<SelectOptionDTO<?>> getOptions(String className) {
        try {
            Class<?> clazz = Class.forName(className);
            return getOptionsByClass(clazz);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    @SuppressWarnings("unchecked")
    private static List<SelectOptionDTO<?>> getOptionsByClass(Class<?> clazz) {
        if (!clazz.isEnum()) {
            throw new RuntimeException("不是枚举:" + clazz.getName());
        }
        if (!BaseEnum.class.isAssignableFrom(clazz)) {
            throw new RuntimeException("未实现 BaseEnum:" + clazz.getName());
        }
        return (List<SelectOptionDTO<?>>) getOptionsInternal((Class) clazz);
    }
    private static <T> List<SelectOptionDTO<T>> getOptionsInternal(
            Class<? extends BaseEnum<T>> clazz) {
        Enum<?>[] enums = (Enum<?>[]) clazz.getEnumConstants();
        List<SelectOptionDTO<T>> list = new ArrayList<>();
        for (Enum<?> e : enums) {
            BaseEnum<T> option = (BaseEnum<T>) e;
            list.add(new SelectOptionDTO<>(
                    option.getCode(),
                    option.getValue()
            ));
        }
        return list;
    }
}
src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java
@@ -5,6 +5,7 @@
import com.ruoyi.collaborativeApproval.dto.NoticeDTO;
import com.ruoyi.collaborativeApproval.pojo.Notice;
import com.ruoyi.collaborativeApproval.service.NoticeService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
@@ -16,6 +17,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.security.Security;
import java.util.List;
@RestController
@@ -42,7 +44,6 @@
            //正式发布通知所有人的消息通知
            sysNoticeService.simpleNoticeAll("通知公告",
                    noticeDTO.getTitle(),
                    noticeDTO.getTenantId(),
                    "/collaborativeApproval/noticeManagement?type="+noticeDTO.getType());
        }
        return AjaxResult.success(noticeService.save(noticeDTO));
@@ -57,7 +58,6 @@
            //正式发布通知所有人的消息通知
            sysNoticeService.simpleNoticeAll("通知公告",
                    notice.getTitle(),
                    notice.getTenantId(),
                    "/collaborativeApproval/noticeManagement?type="+notice.getType());
        }
        return AjaxResult.success(noticeService.updateById(noticeDTO));
src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java
@@ -34,7 +34,7 @@
     */
    @PostMapping("/add")
    public AjaxResult add(@RequestBody NoticeType noticeType) {
        return AjaxResult.success(noticeTypeService.save(noticeType));
        return AjaxResult.success(noticeTypeService.saveOrUpdate(noticeType));
    }
    /**
src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java
@@ -4,6 +4,7 @@
import com.ruoyi.approve.pojo.KnowledgeBase;
import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement;
import com.ruoyi.collaborativeApproval.service.SealApplicationManagementService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
@@ -45,7 +46,6 @@
                "申请编号:"+sealApplicationManagement.getApplicationNum()+"\n"
                +"申请标题:"+sealApplicationManagement.getTitle(),
                Arrays.asList(sealApplicationManagement.getApproveUserId()),
                sealApplicationManagement.getTenantId(),
                "/collaborativeApproval/sealManagement?applicationNum="+sealApplicationManagement.getApplicationNum());
        return AjaxResult.success();
    }
src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java
@@ -186,7 +186,6 @@
                                "会议时间:" + application.getStartTime() + "-" + application.getEndTime() + "\n" +
                                "发起人:" + application.getApplicant(),
                        userIds,
                        application.getTenantId(),
                        ""
                );
            }
src/main/java/com/ruoyi/common/enums/BaseEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.ruoyi.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
public interface BaseEnum<T> {
    @JsonValue
    T getCode();
    String getValue();
    /**
     * é€šç”¨é™æ€å·¥å…·æ–¹æ³•(可被所有枚举调用)
     */
    /**
     * é€šç”¨é™æ€å·¥å…·æ–¹æ³•:支持从 Integer æˆ– String ç±»åž‹çš„ Code è¿›è¡Œååºåˆ—化
     */
    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
    static <E extends Enum<E> & BaseEnum<?>> E fromCode(Class<E> enumClass, Object code) {
        if (code == null) {
            return null;
        }
        // ç›®æ ‡ Code çš„æ•´æ•°å€¼
        Integer targetCode = null;
        if (code instanceof Integer) {
            // 1. å¦‚果传入的是数字 (Integer)
            targetCode = (Integer) code;
        } else if (code instanceof String) {
            // 2. å¦‚果传入的是字符串 ("1")
            try {
                // å°è¯•将字符串转换为整数
                targetCode = Integer.valueOf((String) code);
            } catch (NumberFormatException e) {
                // å¦‚果字符串不是有效的数字(例如 "Unknown"),则 targetCode ä¿æŒä¸º null
                // æ‚¨ä¹Ÿå¯ä»¥åœ¨è¿™é‡Œè®°å½•日志或执行其他错误处理
                // System.err.println("无法将字符串 Code è½¬æ¢ä¸ºæ•°å­—: " + code);
                return null; // æˆ–者在找不到匹配的情况下返回 null
            }
        }
        // else if (code instanceof Long) { ... æ‚¨ä¹Ÿå¯ä»¥æ·»åР坹 Long ç±»åž‹çš„æ”¯æŒ }
        if (targetCode == null) {
            return null;
        }
        // ä½¿ç”¨èŽ·å–åˆ°çš„æ•´æ•°å€¼è¿›è¡ŒæŸ¥æ‰¾
        for (E e : enumClass.getEnumConstants()) {
            if (e.getCode().equals(targetCode)) {
                return e;
            }
        }
        return null;
    }
}
src/main/java/com/ruoyi/common/enums/SalesLedgerType.java
@@ -1,7 +1,7 @@
package com.ruoyi.common.enums;
public enum SalesLedgerType {
public enum SalesLedgerType implements BaseEnum<Integer>{
    SALES_LEDGER_TYPE_SALES_LEDGER(1, "销售台账"),
    SALES_LEDGER_TYPE_PURCHASE_LEDGER(2, "采购台账");
@@ -13,11 +13,11 @@
        this.label = label;
    }
    public Integer getValue() {
    public Integer getCode() {
        return value;
    }
    public String getLabel() {
    public String getValue() {
        return label;
    }
src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java
@@ -7,7 +7,7 @@
 *
 */
@AllArgsConstructor
public enum StaffLeaveReason {
public enum StaffLeaveReason implements BaseEnum<String> {
    StaffLeaveReasonSalary("salary","薪资待遇"),
    StaffLeaveReasonCareerDevelopment("career_development","职业发展"),
    StaffLeaveReasonWorkEnvironment("work_environment","工作环境"),
@@ -22,6 +22,10 @@
        return code;
    }
    public String getValue() {
        return info;
    }
    public String getInfo() {
        return info;
    }
src/main/java/com/ruoyi/common/enums/StockQualifiedRecordTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.common.enums;
import lombok.Getter;
@Getter
public enum StockQualifiedRecordTypeEnum implements BaseEnum<Integer> {
    CUSTOMIZATION_STOCK_IN(0, "合格自定义入库"),
    CUSTOMIZATION_STOCK_OUT(1, "合格自定义出库"),
    PRODUCTION_REPORT_STOCK_IN(2, "生产报工-入库"),
    PRODUCTION_REPORT_STOCK_OUT(3, "生产报工-出库"),
    DEFECTIVE_PASS(6, "不合格处理-让步放行"),
    PURCHASE_STOCK_IN(7, "采购-入库"),
    SALE_STOCK_OUT(8, "销售-出库"),
    QUALITYINSPECT_STOCK_IN(11, "质检-合格入库");
    private final Integer code;
    private final String value;
    StockQualifiedRecordTypeEnum(Integer code, String value) {
        this.code = code;
        this.value = value;
    }
}
src/main/java/com/ruoyi/common/enums/StockUnQualifiedRecordTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.ruoyi.common.enums;
import lombok.Getter;
@Getter
public enum StockUnQualifiedRecordTypeEnum implements BaseEnum<Integer> {
    PRODUCTION_SCRAP(4, "生产报工-报废"),
    DEFECTIVE_SCRAP(5, "不合格处理-报废"),
    CUSTOMIZATION_UNSTOCK_IN(9, "不合格自定义入库"),
    CUSTOMIZATION_UNSTOCK_OUT(10, "不合格自定义出库"),
    QUALITYINSPECT_UNSTOCK_IN(12, "质检-不合格入库");
    private final Integer code;
    private final String value;
    StockUnQualifiedRecordTypeEnum(Integer code, String value) {
        this.code = code;
        this.value = value;
    }
}
src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java
@@ -7,7 +7,7 @@
 *
 */
@AllArgsConstructor
public enum StorageAttachmentRecordType {
public enum StorageAttachmentRecordType implements BaseEnum<String> {
    // ä¾‹å­ å®žé™…开发请删除
    Template("Template","范例"),
    Archives("Archives","文档管理"),
@@ -23,6 +23,10 @@
        return code;
    }
    public String getValue() {
        return info;
    }
    public String getInfo() {
        return info;
    }
src/main/java/com/ruoyi/common/enums/UserStatus.java
@@ -5,7 +5,7 @@
 * 
 * @author ruoyi
 */
public enum UserStatus
public enum UserStatus implements BaseEnum<String>
{
    OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
@@ -23,8 +23,13 @@
        return code;
    }
    public String getValue() {
        return info;
    }
    public String getInfo()
    {
        return info;
    }
}
src/main/java/com/ruoyi/common/utils/EnumUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,106 @@
package com.ruoyi.common.utils;
import com.ruoyi.common.enums.BaseEnum;
import java.util.*;
import java.util.stream.Collectors;
/**
 * é€šç”¨æžšä¸¾å·¥å…·ç±»
 * é€‚用于所有实现 BaseEnum æŽ¥å£çš„æžšä¸¾
 *
 * @author Bu
 */
public class EnumUtil {
    /**
     * æ ¹æ® code èŽ·å–æžšä¸¾å®žä¾‹
     */
    public static <E extends Enum<E> & BaseEnum> E fromCode(Class<E> enumClass, int code) {
        for (E e : enumClass.getEnumConstants()) {
            if ((int)e.getCode() == code) {
                return e;
            }
        }
        throw new IllegalArgumentException("未知的 code: " + code + " å¯¹äºŽæžšä¸¾ " + enumClass.getSimpleName());
    }
    public static <E extends Enum<E> & BaseEnum> E fromCodeHasNull(Class<E> enumClass, int code) {
        for (E e : enumClass.getEnumConstants()) {
            if ((int)e.getCode() == code) {
                return e;
            }
        }
        return null;
    }
    public static <E extends Enum<E> & BaseEnum> E fromCodeHasDefault(Class<E> enumClass, int code,E defaultE) {
        for (E e : enumClass.getEnumConstants()) {
            if ((int)e.getCode() == code) {
                return e;
            }
        }
        return defaultE;
    }
    /**
     * æ ¹æ® value èŽ·å–æžšä¸¾å®žä¾‹
     */
    public static <E extends Enum<E> & BaseEnum> E fromValue(Class<E> enumClass, String value) {
        for (E e : enumClass.getEnumConstants()) {
            if (Objects.equals(e.getValue(), value)) {
                return e;
            }
        }
        throw new IllegalArgumentException("未知的 value: " + value + " å¯¹äºŽæžšä¸¾ " + enumClass.getSimpleName());
    }
    /**
     * èŽ·å–æ‰€æœ‰æžšä¸¾é¡¹åˆ—è¡¨
     */
    public static <E extends Enum<E> & BaseEnum> List<E> listAll(Class<E> enumClass) {
        return Arrays.asList(enumClass.getEnumConstants());
    }
    /**
     * è½¬ä¸º List<Map>(适合返回给前端)
     * æ ¼å¼: [{ "code": 1, "value": "绞线" }, ...]
     */
    public static <E extends Enum<E> & BaseEnum> List<Map<String, Object>> toList(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .map(e -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("key", e.getCode().toString());
                    map.put("value", e.getValue());
                    return map;
                })
                .collect(Collectors.toList());
    }
//    /**
//     * è½¬ä¸º Map<Integer, String>
//     * æ ¼å¼: { 1: "绞线", 0: "拉丝" }
//     */
//    public static <E extends Enum<E> & BaseEnum> Map<Integer, String> toMap(Class<E> enumClass) {
//        return Arrays.stream(enumClass.getEnumConstants())
//                .collect(Collectors.toMap((BaseEnum::getCode, BaseEnum::getValue));
//    }
//
//
//    public static void main(String[] args) {
//        // âœ… 1. æ ¹æ® code èŽ·å–æžšä¸¾
//        StockRecordTypeEnum status = EnumUtil.fromCode(StockRecordTypeEnum.class, 1);
//        System.out.println(status.getValue()); // ç»žçº¿
//
//        // âœ… 2. è½¬æˆ list (适合前端)
//        System.out.println(EnumUtil.toList(StockRecordTypeEnum.class));
//        // è¾“出: [{code=1, value=绞线}, {code=0, value=拉丝}]
//
//        // âœ… 3. è½¬æˆ map
//        System.out.println(EnumUtil.toMap(StockRecordTypeEnum.class));
//        // è¾“出: {1=绞线, 0=拉丝}
//    }
}
src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java
@@ -30,7 +30,7 @@
    @GetMapping("/listPage")
    @Log(title = "客户拜访-分页查询", businessType = BusinessType.OTHER)
    @ApiOperation("客户拜访-分页查询")
    public AjaxResult listPage(Page page, CustomerVisits customerVisits){
    public AjaxResult listPage(Page page, CustomerVisits customerVisits) {
        IPage<CustomerVisits> listPage = customerVisitsService.listPage(page, customerVisits);
        return AjaxResult.success(listPage);
    }
@@ -39,12 +39,37 @@
    @ApiOperation("客户拜访-添加")
    @PostMapping("/add")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@RequestBody CustomerVisits customerVisits){
    public AjaxResult add(@RequestBody CustomerVisits customerVisits) {
        boolean save = customerVisitsService.save(customerVisits);
        if (save){
        if (save) {
            return AjaxResult.success("添加成功");
        }
        return AjaxResult.error("添加失败");
    }
    @Log(title = "客户拜访-编辑", businessType = BusinessType.UPDATE)
    @ApiOperation("客户拜访-编辑")
    @PostMapping("update")
    public AjaxResult updateCustomerVisit(@RequestBody CustomerVisits customerVisits) {
        boolean updateResult = customerVisitsService.updateCustomerVisit(customerVisits);
        if (updateResult) {
            return AjaxResult.success("编辑成功");
        }
        return AjaxResult.error("编辑失败");
    }
    @Log(title = "客户拜访-删除", businessType = BusinessType.DELETE)
    @ApiOperation("客户拜访-删除")
    @DeleteMapping("{customerId}")
    public AjaxResult deleteCustomerVisit(@PathVariable Integer customerId) {
        if (customerId == null) {
            return AjaxResult.error("客户ID不能为空");
        }
        boolean deleteResult = customerVisitsService.removeById(customerId);
        if (deleteResult) {
            return AjaxResult.success("删除成功");
        }
        return AjaxResult.error("删除失败");
    }
}
src/main/java/com/ruoyi/customervisits/service/CustomerVisitsService.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.customervisits.pojo.CustomerVisits;
import com.ruoyi.framework.web.domain.AjaxResult;
/**
 * @author :yys
@@ -11,4 +12,7 @@
 */
public interface CustomerVisitsService extends IService<CustomerVisits> {
    IPage<CustomerVisits> listPage(Page page, CustomerVisits customerVisits);
    boolean updateCustomerVisit(CustomerVisits customerVisits);
}
src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java
@@ -11,6 +11,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
 * @author :yys
@@ -26,10 +27,27 @@
    @Override
    public IPage<CustomerVisits> listPage(Page page, CustomerVisits customerVisits) {
        LambdaQueryWrapper<CustomerVisits> customerVisitsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(customerVisits != null && !StringUtils.isEmpty(customerVisits.getCustomerName())){
        if (customerVisits != null && !StringUtils.isEmpty(customerVisits.getCustomerName())) {
            customerVisitsLambdaQueryWrapper.like(CustomerVisits::getCustomerName, customerVisits.getCustomerName());
        }
        Page page1 = customerVisitsMapper.selectPage(page, customerVisitsLambdaQueryWrapper);
        return page1;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCustomerVisit(CustomerVisits customerVisits) {
        if (customerVisits == null || customerVisits.getId() == null) {
            return false;
        }
        if (StringUtils.isEmpty(customerVisits.getCustomerName())
                || StringUtils.isEmpty(customerVisits.getPurposeVisit())
                || StringUtils.isEmpty(customerVisits.getVisitAddress())
                || StringUtils.isEmpty(customerVisits.getPurposeDate())) {
            return false;
        }
        return updateById(customerVisits);
    }
}
src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java
@@ -6,7 +6,7 @@
import com.ruoyi.device.service.DeviceDefectRecordService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -16,12 +16,12 @@
public class DeviceDefectRecordController {
    @Autowired
    private DeviceDefectRecordService deviceDefectRecordService;
    @ApiModelProperty("设备缺陷记录列表")
    @ApiOperation("设备缺陷记录列表")
    @GetMapping("/page")
    public AjaxResult page(Page page , DeviceDefectRecordDto deviceDefectRecordDto) {
        return AjaxResult.success(deviceDefectRecordService.listPage(page,deviceDefectRecordDto));
    }
    @ApiModelProperty("设备id查询设备缺陷记录列表")
    @ApiOperation("设备id查询设备缺陷记录列表")
    @GetMapping("/find/{deviceLedgerId}")
    public AjaxResult find(@PathVariable Long deviceLedgerId) {
        DeviceDefectRecordDto deviceDefectRecordDto = new DeviceDefectRecordDto();
@@ -30,17 +30,17 @@
    }
    @PostMapping("/add")
    @ApiModelProperty("添加设备缺陷记录")
    @ApiOperation("添加设备缺陷记录")
    public AjaxResult add(@RequestBody DeviceDefectRecord deviceDefectRecord) {
        return AjaxResult.success(deviceDefectRecordService.add(deviceDefectRecord));
    }
    @PostMapping("/update")
    @ApiModelProperty("修改设备缺陷记录")
    @ApiOperation("修改设备缺陷记录")
    public AjaxResult update(@RequestBody DeviceDefectRecord deviceDefectRecord) {
        return AjaxResult.success(deviceDefectRecordService.updateByDDR(deviceDefectRecord));
    }
    @DeleteMapping("/delete")
    @ApiModelProperty("删除设备缺陷记录")
    @ApiOperation("删除设备缺陷记录")
    public AjaxResult delete(@PathVariable Long id) {
        return AjaxResult.success(deviceDefectRecordService.removeById(id));
    }
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
@@ -12,7 +12,6 @@
import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -39,33 +38,33 @@
    @ApiModelProperty("设备台账列表")
    @ApiOperation("设备台账列表")
    @GetMapping("/page")
    public AjaxResult page(Page page , DeviceLedgerDto deviceLedger) {
        return AjaxResult.success(deviceLedgerService.queryPage(page,deviceLedger));
    }
    @PostMapping()
    @ApiModelProperty("添加设备台账")
    @ApiOperation("添加设备台账")
    public AjaxResult add(@RequestBody DeviceLedger deviceLedger) {
        return deviceLedgerService.saveDeviceLedger(deviceLedger);
    }
    @ApiModelProperty("根据id查询设备台账")
    @ApiOperation("根据id查询设备台账")
    @GetMapping("/{id}")
    public AjaxResult detail(@PathVariable Long id) {
        return AjaxResult.success(deviceLedgerService.getById(id));
    }
    @PutMapping ()
    @ApiModelProperty("修改设备台账")
    @ApiOperation("修改设备台账")
    public AjaxResult update(@RequestBody DeviceLedger deviceLedger) {
        return deviceLedgerService.updateDeviceLedger(deviceLedger);
    }
    @DeleteMapping("/{ids}")
    @ApiModelProperty("删除设备台账")
    @ApiOperation("删除设备台账")
    public AjaxResult delete(@PathVariable("ids") ArrayList<Long> ids) {
        boolean b = deviceLedgerService.removeBatchByIds(ids);
        if (!b) {
@@ -75,13 +74,13 @@
    }
    @PostMapping("export")
    @ApiModelProperty("导出设备台账")
    @ApiOperation("导出设备台账")
    public void export(HttpServletResponse response, Long[] ids) {
         deviceLedgerService.export(response, ids);
    }
    @PostMapping("import")
    @ApiModelProperty("导入设备台账")
    @ApiOperation("导入设备台账")
    public AjaxResult importData(MultipartFile file) throws IOException {
        Boolean b = deviceLedgerService.importData(file);
        if (b) {
@@ -92,7 +91,7 @@
    @GetMapping("getDeviceLedger")
    @ApiModelProperty("获取设备台账")
    @ApiOperation("获取设备台账")
    public AjaxResult getDeviceLedger( ) {
        return AjaxResult.success(deviceLedgerService.list(new QueryWrapper<DeviceLedger>().lambda()
                .select(DeviceLedger::getId, DeviceLedger::getDeviceName,DeviceLedger::getDeviceModel)));
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
@@ -9,7 +9,7 @@
import com.ruoyi.device.service.IDeviceMaintenanceService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -28,14 +28,14 @@
    @Autowired
    private IDeviceLedgerService deviceLedgerService;
    @ApiModelProperty("设备保养列表")
    @ApiOperation("设备保养列表")
    @GetMapping("/page")
    public AjaxResult page(Page page , DeviceMaintenanceDto deviceMaintenanceDto) {
        return AjaxResult.success(deviceMaintenanceService.queryPage(page,deviceMaintenanceDto));
    }
    @PostMapping()
    @ApiModelProperty("添加设备保养")
    @ApiOperation("添加设备保养")
    public AjaxResult add(@RequestBody DeviceMaintenance deviceMaintenance) {
        DeviceLedger byId = deviceLedgerService.getById(deviceMaintenance.getDeviceLedgerId());
        deviceMaintenance.setDeviceName(byId.getDeviceName());
@@ -43,14 +43,14 @@
        return deviceMaintenanceService.saveDeviceRepair(deviceMaintenance);
    }
    @ApiModelProperty("根据id查询设备保养")
    @ApiOperation("根据id查询设备保养")
    @GetMapping("/{id}")
    public AjaxResult detail(@PathVariable Long id) {
        return AjaxResult.success(deviceMaintenanceService.detailById(id));
    }
    @PutMapping ()
    @ApiModelProperty("修改设备保养")
    @ApiOperation("修改设备保养")
    public AjaxResult update(@RequestBody DeviceMaintenance deviceMaintenance) {
        DeviceLedger byId = deviceLedgerService.getById(deviceMaintenance.getDeviceLedgerId());
        deviceMaintenance.setDeviceName(byId.getDeviceName());
@@ -59,14 +59,14 @@
    }
    @PostMapping ("maintenance")
    @ApiModelProperty("修改设备保养")
    @ApiOperation("修改设备保养")
    public AjaxResult maintenance(@RequestBody DeviceMaintenance deviceMaintenance) {
        return deviceMaintenanceService.updateDeviceDeviceMaintenance(deviceMaintenance);
    }
    @DeleteMapping("/{ids}")
    @ApiModelProperty("删除设备保养")
    @ApiOperation("删除设备保养")
    public AjaxResult delete(@PathVariable("ids") Long[] ids) {
        boolean b = deviceMaintenanceService.removeBatchByIds(Arrays.asList(ids));
        if (!b) {
@@ -76,7 +76,7 @@
    }
    @PostMapping("export")
    @ApiModelProperty("导出设备保养")
    @ApiOperation("导出设备保养")
    public void export(HttpServletResponse response, Long[] ids) {
        deviceMaintenanceService.export(response, ids);
    }
src/main/java/com/ruoyi/device/controller/DeviceRepairController.java
@@ -8,7 +8,7 @@
import com.ruoyi.device.service.IDeviceRepairService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -26,19 +26,19 @@
    @Autowired
    private IDeviceLedgerService deviceLedgerService;
    @ApiModelProperty("设备报修列表")
    @ApiOperation("设备报修列表")
    @GetMapping("/page")
    public AjaxResult page(Page page , DeviceRepairDto deviceRepairDto) {
        return AjaxResult.success(deviceRepairService.queryPage(page,deviceRepairDto));
    }
    @PostMapping()
    @ApiModelProperty("添加设备报修")
    @ApiOperation("添加设备报修")
    public AjaxResult add( @RequestBody DeviceRepair deviceRepair) {
        return deviceRepairService.saveDeviceRepair(deviceRepair);
    }
    @ApiModelProperty("根据id查询设备报修")
    @ApiOperation("根据id查询设备报修")
    @GetMapping("/{id}")
    public AjaxResult detail(@PathVariable Long id) {
        DeviceRepairDto byId = deviceRepairService.detailById(id);
@@ -46,19 +46,19 @@
    }
    @PutMapping ()
    @ApiModelProperty("修改设备报修")
    @ApiOperation("修改设备报修")
    public AjaxResult update( @RequestBody DeviceRepair deviceRepair) {
        return deviceRepairService.updateDeviceRepair(deviceRepair);
    }
    @PostMapping ("repair")
    @ApiModelProperty("设备维修")
    @ApiOperation("设备维修")
    public AjaxResult repair( @RequestBody DeviceRepair deviceRepair) {
        return deviceRepairService.updateDeviceRepair(deviceRepair);
    }
    @DeleteMapping("/{ids}")
    @ApiModelProperty("删除设备报修")
    @ApiOperation("删除设备报修")
    public AjaxResult delete(@PathVariable("ids") Long[] ids) {
        boolean b = deviceRepairService.removeBatchByIds(Arrays.asList(ids));
        if (!b) {
@@ -68,7 +68,7 @@
    }
    @PostMapping("export")
    @ApiModelProperty("导出设备报修")
    @ApiOperation("导出设备报修")
    public void export(HttpServletResponse response, Long[] ids) {
        deviceRepairService.export(response, ids);
    }
src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -36,6 +36,31 @@
    @Autowired
    private HomeService homeService;
    /********************************************************基础类*****************************************************/
    @GetMapping("/todos")
    @Log(title = "待办事项", businessType = BusinessType.OTHER)
    @ApiOperation("待办事项")
    public AjaxResult todos(ApproveProcess req) throws ParseException {
        List<ApproveProcess> approveProcessList = homeService.todos();
        return AjaxResult.success(approveProcessList);
    }
    @GetMapping("/approveAndDeviceTodos")
    @ApiOperation("审批协同,设备报修待办事项")
    public AjaxResult approveAndDeviceTodos(){
        Map<String, Object> map = homeService.approveAndDeviceTodos();
        return AjaxResult.success(map);
    }
    @GetMapping("/noticesCount")
    @ApiOperation("未过期的公告数量")
    public AjaxResult noticesCount(){
        Long count = homeService.noticesCount();
        return AjaxResult.success(count);
    }
    /********************************************************营销采购类**************************************************/
    @GetMapping("/business")
    @Log(title = "销售-采购-库存数据", businessType = BusinessType.OTHER)
    @ApiOperation("销售-采购-库存数据")
@@ -53,43 +78,8 @@
        return AjaxResult.success(analysisCustomerContractAmounts);
    }
    @GetMapping("/qualityStatistics")
    @Log(title = "质量分析", businessType = BusinessType.OTHER)
    @ApiOperation("质量分析")
    public AjaxResult qualityStatistics(QualityStatisticsDto req) {
        QualityStatisticsDto qualityStatisticsDto = homeService.qualityStatistics();
        return AjaxResult.success(qualityStatisticsDto);
    }
    @GetMapping("/todos")
    @Log(title = "待办事项", businessType = BusinessType.OTHER)
    @ApiOperation("待办事项")
    public AjaxResult todos(ApproveProcess req) throws ParseException {
        List<ApproveProcess> approveProcessList = homeService.todos();
        return AjaxResult.success(approveProcessList);
    }
    @GetMapping("/statisticsReceivablePayable")
    @Log(title = "应收应付统计", businessType = BusinessType.OTHER)
    @ApiOperation("应收应付统计")
    public AjaxResult statisticsReceivablePayable(StatisticsReceivablePayableDto req, @RequestParam(value = "type", defaultValue = "1") Integer type ) {
        StatisticsReceivablePayableDto statisticsReceivablePayable = homeService.statisticsReceivablePayable(type);
        return AjaxResult.success(statisticsReceivablePayable);
    }
    @GetMapping("/approveAndDeviceTodos")
    @ApiOperation("审批协同,设备报修待办事项")
    public AjaxResult approveAndDeviceTodos(){
        Map<String, Object> map = homeService.approveAndDeviceTodos();
        return AjaxResult.success(map);
    }
    @GetMapping("/noticesCount")
    @ApiOperation("未过期的公告数量")
    public AjaxResult noticesCount(){
        Long count = homeService.noticesCount();
        return AjaxResult.success(count);
    }
    /********************************************************生产类*****************************************************/
    @GetMapping("/progressStatistics")
    @ApiOperation("各生产订单的完成进度统计")
    public AjaxResult progressStatistics(){
@@ -102,4 +92,38 @@
        ProductionTurnoverDto productionTurnoverDto = homeService.workInProcessTurnover();
        return AjaxResult.success(productionTurnoverDto);
    }
    /********************************************************质量类*****************************************************/
    @GetMapping("/qualityStatistics")
    @Log(title = "质量分析", businessType = BusinessType.OTHER)
    @ApiOperation("质量分析")
    public AjaxResult qualityStatistics(QualityStatisticsDto req) {
        QualityStatisticsDto qualityStatisticsDto = homeService.qualityStatistics();
        return AjaxResult.success(qualityStatisticsDto);
    }
    /********************************************************财务类*****************************************************/
    @GetMapping("/statisticsReceivablePayable")
    @Log(title = "应收应付统计", businessType = BusinessType.OTHER)
    @ApiOperation("应收应付统计")
    public AjaxResult statisticsReceivablePayable(StatisticsReceivablePayableDto req, @RequestParam(value = "type", defaultValue = "1") Integer type ) {
        StatisticsReceivablePayableDto statisticsReceivablePayable = homeService.statisticsReceivablePayable(type);
        return AjaxResult.success(statisticsReceivablePayable);
    }
    /********************************************************仓储类*****************************************************/
}
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -400,8 +400,8 @@
        LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveDelete, 0)
                .eq(ApproveProcess::getApproveUserCurrentId, loginUser.getUserId())
                .ne(ApproveProcess::getApproveStatus, 2)
                .eq(ApproveProcess::getTenantId, loginUser.getTenantId());
                .ne(ApproveProcess::getApproveStatus, 2);
//                .eq(ApproveProcess::getTenantId, loginUser.getTenantId());
        List<ApproveProcess> approveProcesses = approveProcessMapper.selectList(approveProcessLambdaQueryWrapper);
        if(CollectionUtils.isEmpty(approveProcesses)){
            approveProcesses = new ArrayList<>();
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -1,11 +1,21 @@
package com.ruoyi.procurementrecord.utils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.service.StockInRecordService;
import com.ruoyi.stock.service.StockInventoryService;
import com.ruoyi.stock.service.StockUninventoryService;
import com.ruoyi.stock.service.impl.StockInRecordServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -14,6 +24,9 @@
public class StockUtils {
    private final ProcurementRecordOutMapper procurementRecordOutMapper;
    private final ProcurementRecordMapper procurementRecordMapper;
    private final StockUninventoryService stockUninventoryService;
    private final StockInventoryService stockInventoryService;
    private final StockInRecordService stockInRecordService;
    // èŽ·å–å•†å“å…¥åº“æ•°é‡,出库数量,剩余库存
    public Map<String, BigDecimal> getStockQuantity(Long productModelId) {
@@ -29,4 +42,77 @@
        stockMap.put("stockQuantity", stockQuantity);
        return stockMap;
    }
    /**
     * ä¸åˆæ ¼å…¥åº“
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void addUnStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
        StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
        stockUninventoryDto.setRecordId(recordId);
        stockUninventoryDto.setRecordType(String.valueOf(recordType));
        stockUninventoryDto.setQualitity(quantity);
        stockUninventoryDto.setProductModelId(productModelId);
        stockUninventoryService.addStockUninventory(stockUninventoryDto);
    }
    /**
     * ä¸åˆæ ¼å‡ºåº“
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
        StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
        stockUninventoryDto.setRecordId(recordId);
        stockUninventoryDto.setRecordType(String.valueOf(recordType));
        stockUninventoryDto.setQualitity(quantity);
        stockUninventoryDto.setProductModelId(productModelId);
        stockUninventoryService.subtractStockUninventory(stockUninventoryDto);
    }
    /**
     * åˆæ ¼å…¥åº“
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void addStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        stockInventoryService.addstockInventory(stockInventoryDto);
    }
    /**
     * åˆæ ¼å‡ºåº“
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void substractStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        stockInventoryService.subtractStockInventory(stockInventoryDto);
    }
    //不合格库存删除
    public void deleteStockRecord(Long recordId, Integer recordType) {
        StockInRecord one = stockInRecordService.getOne(new QueryWrapper<StockInRecord>()
                .lambda().eq(StockInRecord::getRecordId, recordId)
                .eq(StockInRecord::getRecordType, recordType));
        stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
    }
}
src/main/java/com/ruoyi/production/controller/ProductBomController.java
@@ -8,14 +8,9 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.production.dto.ProductBomDto;
import com.ruoyi.production.dto.ProductProcessDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductBom;
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.pojo.ProductProcessRoute;
import com.ruoyi.production.service.ProcessRouteService;
import com.ruoyi.production.service.ProductBomService;
import com.ruoyi.production.service.ProductProcessRouteService;
import com.ruoyi.production.service.ProductProcessService;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +29,7 @@
 */
@RestController
@RequestMapping("/productBom")
@Api(tags = "BOM")
public class ProductBomController {
    @Autowired
@@ -44,6 +40,9 @@
    @Autowired
    private ProductProcessRouteService productProcessRouteService;
    @Autowired
    private ProductStructureService productStructureService;
    @GetMapping("/listPage")
    @Log(title = "BOM-分页查询", businessType = BusinessType.OTHER)
@@ -79,6 +78,8 @@
        if(CollectionUtils.isEmpty(ids)){
            return AjaxResult.error("请选择至少一条数据");
        }
        //删除bom子表
        productStructureService.remove(Wrappers.<ProductStructure>lambdaQuery().in(ProductStructure::getBomId,ids));
        return AjaxResult.success(productBomService.removeBatchByIds(ids));
    }
src/main/java/com/ruoyi/production/controller/ProductStructureController.java
@@ -26,13 +26,13 @@
    private ProductStructureService productStructureService;
    @ApiOperation("新增BOM")
    @ApiOperation("新增BOM子集")
    @PostMapping()
    public R addOrUpdate(@RequestBody ProductStructureDto productStructureDto){
        return R.ok(productStructureService.addProductStructureDto(productStructureDto));
    }
    @ApiOperation("BOM查看详情")
    @ApiOperation("BOM查看子集详情")
    @GetMapping("/listBybomId/{bomId}")
    public R listBybomId( @PathVariable("bomId") Long bomId){
        return R.ok(productStructureService.listBybomId(bomId));
src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -27,6 +27,10 @@
    @Excel(name = "报工数量")
    private BigDecimal quantity;
    @ApiModelProperty(value = "报废数量")
    @Excel(name = "报废数量")
    private BigDecimal scrapQty;
    //产品名称
    @Excel(name = "产品名称")
    private String productName;
src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.production.dto.ProductionProductMainDto;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.pojo.ProductionProductMain;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -19,4 +20,11 @@
     * æ ¹æ®å·¥å•ID批量删除生产主表数据
     */
    int deleteByWorkOrderIds(@Param("workOrderIds") List<Long> workOrderIds);
    /**
     * æ ¹æ®æŠ¥å·¥id查询生产订单
     * @param productMainId
     * @return
     */
    ProductOrder getOrderByMainId(@Param("productMainId") Long productMainId);
}
src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
@@ -20,7 +20,8 @@
    @ApiModelProperty(value = "产品id")
    private Long productModelId;
    @ApiModelProperty(value = "数量")
    //合格数量=报工数量-报废数量
    @ApiModelProperty(value = "报工数量")
    private BigDecimal quantity;
    @ApiModelProperty(value = "创建时间")
@@ -29,4 +30,7 @@
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty(value = "报废数量")
    private BigDecimal scrapQty;
}
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -2,8 +2,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -13,7 +11,8 @@
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.utils.SecurityUtils;
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;
@@ -28,19 +27,15 @@
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.quality.mapper.*;
import com.ruoyi.quality.pojo.*;
import io.swagger.models.auth.In;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.production.mapper.ProductionProductMainMapper;
import oshi.driver.mac.net.NetStat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -189,82 +184,92 @@
        productionProductOutput.setProductMainId(productionProductMain.getId());
        productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId());
        productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO);
        productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO);
        productionProductOutputMapper.insert(productionProductOutput);
        /*新增质检*/
        //对应的过程检或者出厂检
        List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
        int inspectType = 1;
        String process = productProcess.getName();//工序
        if (productProcessRouteItem.getDragSort()==productProcessRouteItems.size()){
            //最后一道工序生成出厂检
            inspectType = 2;
            process = null;
        }
        Product product = productMapper.selectById(productModel.getProductId());
        QualityInspect qualityInspect = new QualityInspect();
        qualityInspect.setProductId(product.getId());
        qualityInspect.setProductName(product.getProductName());
        qualityInspect.setModel(productModel.getModel());
        qualityInspect.setUnit(productModel.getUnit());
        qualityInspect.setQuantity(dto.getQuantity());
        qualityInspect.setProcess(productProcess.getName());
        qualityInspect.setInspectState(0);
        qualityInspect.setInspectType(inspectType);
        qualityInspect.setProductMainId(productionProductMain.getId());
        qualityInspect.setProductModelId(productModel.getId());
        qualityInspectMapper.insert(qualityInspect);
        List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType,process);
        if (qualityTestStandard.size()>0){
            qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
            qualityInspectMapper.updateById(qualityInspect);
            qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
                    .eq(QualityTestStandardParam::getTestStandardId,qualityTestStandard.get(0).getId()))//默认获取最新的
                    .forEach(qualityTestStandardParam -> {
                QualityInspectParam param = new QualityInspectParam();
                BeanUtils.copyProperties(qualityTestStandardParam, param);
                param.setId(null);
                param.setInspectId(qualityInspect.getId());
                qualityInspectParamMapper.insert(param);
            });
        }
        /*更新工单和生产订单*/
        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
        productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(dto.getQuantity()));
        if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())){
            productWorkOrder.setActualStartTime(LocalDate.now());//实际开始时间
        }
        if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0){
            productWorkOrder.setActualEndTime(LocalDate.now());//实际结束时间
        }
        productWorkOrderMapper.updateById(productWorkOrder);
        //生产订单
        ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
        if (ObjectUtils.isNull(productOrder.getStartTime())){
            productOrder.setStartTime(LocalDateTime.now());//开始时间
        }
        if (productProcessRouteItem.getDragSort()==productProcessRouteItems.size()){
            //如果是最后一道工序报工之后生产订单完成数量+
            productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(dto.getQuantity()));
            if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0){
                productOrder.setEndTime(LocalDateTime.now());//结束时间
        //合格数量=报工数量-报废数量
        BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty());
        //只有合格数量>0才能增加相应数据
        if (productQty.compareTo(BigDecimal.ZERO)>0) {
            /*新增质检*/
            //对应的过程检或者出厂检
            List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
            int inspectType = 1;
            String process = productProcess.getName();//工序
            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
                //最后一道工序生成出厂检
                inspectType = 2;
                process = null;
            }
            Product product = productMapper.selectById(productModel.getProductId());
            QualityInspect qualityInspect = new QualityInspect();
            qualityInspect.setProductId(product.getId());
            qualityInspect.setProductName(product.getProductName());
            qualityInspect.setModel(productModel.getModel());
            qualityInspect.setUnit(productModel.getUnit());
            qualityInspect.setQuantity(productQty);
            qualityInspect.setProcess(productProcess.getName());
            qualityInspect.setInspectState(0);
            qualityInspect.setInspectType(inspectType);
            qualityInspect.setProductMainId(productionProductMain.getId());
            qualityInspect.setProductModelId(productModel.getId());
            qualityInspectMapper.insert(qualityInspect);
            List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
            if (qualityTestStandard.size() > 0) {
                qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
                qualityInspectMapper.updateById(qualityInspect);
                qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
                        .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//默认获取最新的
                        .forEach(qualityTestStandardParam -> {
                            QualityInspectParam param = new QualityInspectParam();
                            BeanUtils.copyProperties(qualityTestStandardParam, param);
                            param.setId(null);
                            param.setInspectId(qualityInspect.getId());
                            qualityInspectParamMapper.insert(param);
                        });
            }
            /*更新工单和生产订单*/
            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
            productWorkOrder.setCompleteQuantity(productQty.add(dto.getQuantity()));
            if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
                productWorkOrder.setActualStartTime(LocalDate.now());//实际开始时间
            }
            if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) {
                productWorkOrder.setActualEndTime(LocalDate.now());//实际结束时间
            }
            productWorkOrderMapper.updateById(productWorkOrder);
            //生产订单
            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
            if (ObjectUtils.isNull(productOrder.getStartTime())) {
                productOrder.setStartTime(LocalDateTime.now());//开始时间
            }
            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
                //如果是最后一道工序报工之后生产订单完成数量+
                productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty));
                if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) {
                    productOrder.setEndTime(LocalDateTime.now());//结束时间
                }
            }
            productOrderMapper.updateById(productOrder);
            /*添加生产核算*/
            SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder()
                    .salesLedgerWorkId(productionProductMain.getId())
                    .salesLedgerSchedulingId(0L)
                    .salesLedgerId(productOrder.getSalesLedgerId())
                    .salesLedgerProductId(productOrder.getProductModelId())
                    .schedulingUserId(user.getUserId())
                    .schedulingUserName(user.getNickName())
                    .finishedNum(productQty)
                    .workHours(productProcess.getSalaryQuota())
                    .process(productProcess.getName())
                    .schedulingDate(LocalDate.now())
                    .tenantId(dto.getTenantId())
                    .build();
            salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting);
        }
        productOrderMapper.updateById(productOrder);
        /*添加生产核算*/
        SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder()
                .salesLedgerWorkId(productionProductMain.getId())
                .salesLedgerSchedulingId(0L)
                .salesLedgerId(productOrder.getSalesLedgerId())
                .salesLedgerProductId(productOrder.getProductModelId())
                .schedulingUserId(user.getUserId())
                .schedulingUserName(user.getNickName())
                .finishedNum(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO)
                .workHours(productProcess.getSalaryQuota())
                .process(productProcess.getName())
                .schedulingDate(LocalDate.now())
                .tenantId(dto.getTenantId())
                .build();
        salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting);
        //如果报废数量>0,需要进入报废的库存
        if (dto.getScrapQty().compareTo(BigDecimal.ZERO) > 0) {
            stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
        }
        return true;
    }
@@ -311,6 +316,8 @@
                .eq(ProcurementRecordOut::getSalesLedgerProductId, productionProductMain.getId()));
        productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
                .eq(ProductionProductInput::getProductMainId, productionProductMain.getId()));
        //删除报废的入库记录
        stockUtils.deleteStockRecord(productionProductMain.getId(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
        // åˆ é™¤ä¸»è¡¨
        productionProductMainMapper.deleteById(productionProductMain.getId());
        return true;
src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java
@@ -70,10 +70,9 @@
     * é€šè¿‡æŒ‡å®šäººå‘送提醒
     * @param title æ ‡é¢˜
     * @param message æ¶ˆæ¯
     * @param tenantId ç§Ÿæˆ·id
     * @param jumpPath è·³è½¬åœ°å€
     */
    void simpleNoticeByUser(final String title, final String message, final List<Long> consigneeId, final Long tenantId, final String jumpPath);
    void simpleNoticeByUser(final String title, final String message, final List<Long> consigneeId,  final String jumpPath);
    /**
     * é€šè¿‡æ‰€æœ‰äºº å‘送提醒
@@ -81,6 +80,6 @@
     * @param message æ¶ˆæ¯
     * @param jumpPath è·³è½¬åœ°å€
     */
    void simpleNoticeAll(final String title, final String message,final Long tenantId,final String jumpPath);
    void simpleNoticeAll(final String title, final String message,final String jumpPath);
}
src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -139,20 +139,20 @@
    }
    @Override
    public void simpleNoticeByUser(String title, String message,  List<Long> consigneeId, Long tenantId,
                                    String jumpPath) {
    public void simpleNoticeByUser(String title, String message,  List<Long> consigneeId, String jumpPath) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        Long tenantId = SecurityUtils.getLoginUser().getTenantId();
        List<SysNotice> sysNotices = consigneeId.stream().map(it -> convertSysNotice(title, message, it,tenantId, jumpPath, userId)).collect(Collectors.toList());
        sysNoticeService.saveBatch(sysNotices);
    }
    @Override
    public void simpleNoticeAll(String title, String message, Long rootDeptId, String jumpPath) {
    public void simpleNoticeAll(String title, String message,  String jumpPath) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        if (userId == null) {
            return;
        }
        Long rootDeptId = SecurityUtils.getLoginUser().getTenantId();
        //  æŸ¥æ‰€æœ‰å­éƒ¨é—¨
        List<SysDept> childrenDepts = deptMapper.selectChildrenDeptById(rootDeptId);
src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
@@ -30,7 +30,6 @@
import com.ruoyi.sales.mapper.CommonFileMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import lombok.RequiredArgsConstructor;
@@ -458,7 +457,7 @@
        BeanUtils.copyProperties(purchaseLedger, purchaseLedgerDto);
        SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
        salesLedgerProduct.setSalesLedgerId(id);
        salesLedgerProduct.setType(SalesLedgerType.SALES_LEDGER_TYPE_SALES_LEDGER.getValue());
        salesLedgerProduct.setType(SalesLedgerType.SALES_LEDGER_TYPE_SALES_LEDGER.getCode());
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct);
        purchaseLedgerDto.setProductData(salesLedgerProducts);
        List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -86,5 +86,15 @@
        qualityUnqualifiedService.qualityUnqualifiedExport(response, qualityUnqualified);
    }
    /**
     * ä¸åˆæ ¼ç®¡ç†å¤„理
     * @param qualityUnqualified
     * @return
     */
    @PostMapping("/deal")
    public AjaxResult deal(@RequestBody QualityUnqualified qualityUnqualified) {
        return AjaxResult.success(qualityUnqualifiedService.deal(qualityUnqualified));
    }
}
src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
@@ -133,5 +133,6 @@
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("关联检测id")
    private Long inspectId;
}
src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
@@ -14,4 +14,7 @@
    IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified);
    void qualityUnqualifiedExport(HttpServletResponse response, QualityUnqualified qualityUnqualified);
    int deal(QualityUnqualified qualityUnqualified);
}
src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -8,15 +8,11 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.procurementrecord.dto.Details;
import com.ruoyi.procurementrecord.dto.ProcurementAddDto;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
import com.ruoyi.procurementrecord.service.ProcurementRecordService;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.quality.dto.QualityInspectDto;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.mapper.QualityTestStandardMapper;
@@ -27,7 +23,6 @@
import com.ruoyi.quality.service.IQualityInspectParamService;
import com.ruoyi.quality.service.IQualityInspectService;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@@ -36,10 +31,7 @@
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
@@ -47,8 +39,9 @@
@AllArgsConstructor
@Service
@Transactional(rollbackFor = Exception.class)
public class QualityInspectServiceImpl extends ServiceImpl<QualityInspectMapper, QualityInspect>  implements IQualityInspectService {
public class QualityInspectServiceImpl extends ServiceImpl<QualityInspectMapper, QualityInspect> implements IQualityInspectService {
    private final StockUtils stockUtils;
    private QualityInspectMapper qualityInspectMapper;
    private IQualityInspectParamService qualityInspectParamService;
@@ -64,7 +57,7 @@
    @Override
    public int add(QualityInspectDto qualityInspectDto) {
        QualityInspect qualityInspect = new QualityInspect();
        BeanUtils.copyProperties(qualityInspectDto,qualityInspect);
        BeanUtils.copyProperties(qualityInspectDto, qualityInspect);
        qualityInspect.setInspectState(0);//默认未提交
        qualityInspectMapper.insert(qualityInspect);
        for (QualityInspectParam qualityInspectParam : qualityInspectDto.getQualityInspectParams()) {
@@ -79,7 +72,7 @@
        QualityInspect qualityInspect = qualityInspectMapper.selectById(id);
        List<QualityInspectParam> qualityInspectParams = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, id));
        QualityInspectDto qualityInspectDto = new QualityInspectDto();
        BeanUtils.copyProperties(qualityInspect,qualityInspectDto);
        BeanUtils.copyProperties(qualityInspect, qualityInspectDto);
        qualityInspectDto.setQualityInspectParams(qualityInspectParams);
        return qualityInspectDto;
    }
@@ -89,91 +82,18 @@
    public int submit(QualityInspect inspect) {
        QualityInspect qualityInspect = qualityInspectMapper.selectById(inspect.getId());
        /*判断不合格*/
        if (ObjectUtils.isNotNull(qualityInspect.getCheckResult()) && qualityInspect.getCheckResult().equals("不合格")){
        if (ObjectUtils.isNotNull(qualityInspect.getCheckResult()) && qualityInspect.getCheckResult().equals("不合格")) {
            QualityUnqualified qualityUnqualified = new QualityUnqualified();
            BeanUtils.copyProperties(qualityInspect,qualityUnqualified);
            BeanUtils.copyProperties(qualityInspect, qualityUnqualified);
            qualityUnqualified.setInspectState(0);//待处理
            List<QualityInspectParam> inspectParams = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, inspect.getId()));
            String text = inspectParams.stream().map(QualityInspectParam::getParameterItem).collect(Collectors.joining(","));
            qualityUnqualified.setDefectivePhenomena(text+"这些指标中存在不合格");//不合格现象
            qualityUnqualified.setDefectivePhenomena(text + "这些指标中存在不合格");//不合格现象
            qualityUnqualified.setInspectId(qualityInspect.getId());
            qualityUnqualifiedMapper.insert(qualityUnqualified);
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (qualityInspect.getInspectType() == 0) {
            if ("合格".equals(qualityInspect.getCheckResult())) {
                ProcurementAddDto procurementRecordOutAdd = new ProcurementAddDto();
                procurementRecordOutAdd.setType(1);
                procurementRecordOutAdd.setTypeName("采购原材料检验合格入库");
                procurementRecordOutAdd.setNickName(loginUser.getNickName());
                procurementRecordOutAdd.setPurchaseLedgerId(Math.toIntExact(qualityInspect.getPurchaseLedgerId()));
                if (qualityInspect.getPurchaseLedgerId() == null) {
                    throw new BaseException("请选择采购单");
                }
                SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(qualityInspect.getProductId());
                ArrayList<Details> detailss = new ArrayList<>();
                Details details = new Details();
                details.setId(Math.toIntExact(salesLedgerProduct.getId()));
                details.setInboundQuantity(qualityInspect.getQuantity());
                details.setWarnNum(salesLedgerProduct.getWarnNum());
                details.setUnitPrice(salesLedgerProduct.getTaxInclusiveUnitPrice());
                details.setTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice());
                details.setProductModelId(qualityInspect.getProductModelId());
                detailss.add( details);
                procurementRecordOutAdd.setDetails(detailss);
                procurementRecordOutAdd.setQualityInspectId(qualityInspect.getId());
                procurementRecordService.add(procurementRecordOutAdd);
            }
        }else if (qualityInspect.getInspectType() == 1) {
            //查询UnitPrice/TotalPrice
            ProcurementAddDto procurementRecordOutAdd = new ProcurementAddDto();
            procurementRecordOutAdd.setType(2);
            procurementRecordOutAdd.setTypeName("生产过程检验合格入库");
            procurementRecordOutAdd.setNickName(loginUser.getNickName());
            List<Details> details = new ArrayList<>();
            Details details1 = new Details();
            details1.setInboundQuantity(qualityInspect.getQuantity());
            details1.setProductModelId(qualityInspect.getProductModelId());
            procurementRecordOutAdd.setDetails(details);
            ProcurementRecordStorage.ProcurementRecordStorageBuilder procurementRecordBuilder = ProcurementRecordStorage.builder()
                    .salesLedgerProductId(0)
                    .inboundBatches( "生产半成品入库")
                    .inboundNum(details1.getInboundQuantity())
                    .type(2)
                    .warnNum(new BigDecimal(0))
                    .unitPrice(new BigDecimal(0))
                    .totalPrice(new BigDecimal(0))
                    .createTime(LocalDateTime.now())
                    .createUser(loginUser.getUserId())
                    .updateTime(LocalDateTime.now())
                    .updateUser(loginUser.getUserId())
                    .createBy(procurementRecordOutAdd.getNickName())
                    .productModelId(details1.getProductModelId())
                    .qualityInspectId(qualityInspect.getId());
            procurementRecordService.save(procurementRecordBuilder.build());
        }else if (qualityInspect.getInspectType() == 2) {
            //查询UnitPrice/TotalPrice
            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectSalesLedgerProductByMainId(qualityInspect.getProductMainId());
            ProcurementAddDto procurementRecordOutAdd = new ProcurementAddDto();
            procurementRecordOutAdd.setType(2);
            procurementRecordOutAdd.setTypeName("生产出厂检验合格入库");
            procurementRecordOutAdd.setNickName(loginUser.getNickName());
            List<Details> details = new ArrayList<>();
            Details details1 = new Details();
            details1.setInboundQuantity(qualityInspect.getQuantity());
            details1.setId(Math.toIntExact(salesLedgerProduct.getId()));
            details1.setUnitPrice(salesLedgerProduct.getTaxInclusiveUnitPrice());
            details1.setTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice());
            details1.setProductModelId(salesLedgerProduct.getProductModelId());
            details.add(details1);
            procurementRecordOutAdd.setDetails(details);
            procurementRecordOutAdd.setQualityInspectId(qualityInspect.getId());
            procurementRecordService.add(procurementRecordOutAdd);
        } else {
            //合格直接入库
            stockUtils.addStock(inspect.getProductModelId(), inspect.getQuantity(), StockQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), inspect.getId());
        }
        qualityInspect.setInspectState(1);//已提交
        return qualityInspectMapper.updateById(qualityInspect);
@@ -183,16 +103,16 @@
    @Override
    public void down(HttpServletResponse response, QualityInspect qualityInspect) {
        QualityInspect inspect = qualityInspectMapper.selectById(qualityInspect.getId());
        String inspectType="";
        switch (inspect.getInspectType()){
        String inspectType = "";
        switch (inspect.getInspectType()) {
            case 0:
                inspectType="原材料检验";
                inspectType = "原材料检验";
                break;
            case 1:
                inspectType="过程检验";
                inspectType = "过程检验";
                break;
            case 2:
                inspectType="出厂检验";
                inspectType = "出厂检验";
                break;
        }
        List<QualityInspectParam> paramList = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, inspect.getId()));
@@ -234,31 +154,31 @@
    @Override
    public int updateQualityInspect(QualityInspectDto qualityInspectDto) {
        if (ObjectUtils.isNotNull(qualityInspectDto.getQualityInspectParams())) {
            qualityInspectParamService.remove(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId,qualityInspectDto.getId()));
            qualityInspectParamService.remove(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, qualityInspectDto.getId()));
            for (QualityInspectParam qualityInspectParam : qualityInspectDto.getQualityInspectParams()) {
                qualityInspectParam.setInspectId(qualityInspectDto.getId());
            }
            qualityInspectParamService.saveBatch(qualityInspectDto.getQualityInspectParams());
        }
        QualityInspect qualityInspect = new QualityInspect();
        BeanUtils.copyProperties(qualityInspectDto,qualityInspect);
        BeanUtils.copyProperties(qualityInspectDto, qualityInspect);
        return qualityInspectMapper.updateById(qualityInspect);
    }
    @Override
    public IPage<QualityInspect> qualityInspectListPage(Page page, QualityInspect qualityInspect) {
        return qualityInspectMapper.qualityInspectListPage(page,qualityInspect);
        return qualityInspectMapper.qualityInspectListPage(page, qualityInspect);
    }
    @Override
    public void qualityInspectExport(HttpServletResponse response, QualityInspect qualityInspect) {
        List<QualityInspect> qualityInspects =qualityInspectMapper.qualityInspectExport(qualityInspect);
        List<QualityInspect> qualityInspects = qualityInspectMapper.qualityInspectExport(qualityInspect);
        ExcelUtil<QualityInspect> util = new ExcelUtil<QualityInspect>(QualityInspect.class);
        switch (qualityInspect.getInspectType()){
        switch (qualityInspect.getInspectType()) {
            case 0:
                util.exportExcel(response, qualityInspects, "原材料检验导出");
                break;
            case  1:
            case 1:
                util.exportExcel(response, qualityInspects, "过程检验导出");
                break;
            case 2:
src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -1,38 +1,146 @@
package com.ruoyi.quality.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
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.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
import com.ruoyi.production.mapper.ProductProcessRouteMapper;
import com.ruoyi.production.mapper.ProductWorkOrderMapper;
import com.ruoyi.production.mapper.ProductionProductMainMapper;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductOrderService;
import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.quality.pojo.QualityTestStandard;
import com.ruoyi.quality.pojo.QualityUnqualified;
import com.ruoyi.quality.service.IQualityInspectService;
import com.ruoyi.quality.service.IQualityUnqualifiedService;
import com.ruoyi.stock.service.StockUninventoryService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
@AllArgsConstructor
@Service
public class QualityUnqualifiedServiceImpl extends ServiceImpl<QualityUnqualifiedMapper, QualityUnqualified>  implements IQualityUnqualifiedService {
public class QualityUnqualifiedServiceImpl extends ServiceImpl<QualityUnqualifiedMapper, QualityUnqualified> implements IQualityUnqualifiedService {
    private final StockUtils stockUtils;
    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
    private IQualityInspectService qualityInspectService;
    private ProductOrderService productOrderService;
    private ProductionProductMainMapper productionProductMainMapper;
    private ProductProcessRouteMapper productProcessRouteMapper;
    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
    private ProductWorkOrderMapper productWorkOrderMapper;
    private StockUninventoryService stockUninventoryService;
    @Override
    public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
        return qualityUnqualifiedMapper.qualityUnqualifiedListPage(page,qualityUnqualified);
        return qualityUnqualifiedMapper.qualityUnqualifiedListPage(page, qualityUnqualified);
    }
    @Override
    public void qualityUnqualifiedExport(HttpServletResponse response, QualityUnqualified qualityUnqualified) {
        List<QualityUnqualified> qualityUnqualifieds =qualityUnqualifiedMapper.qualityUnqualifiedExport(qualityUnqualified);
        List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.qualityUnqualifiedExport(qualityUnqualified);
        ExcelUtil<QualityUnqualified> util = new ExcelUtil<QualityUnqualified>(QualityUnqualified.class);
        util.exportExcel(response, qualityUnqualifieds, "不合格管理导出");
    }
    @Override
    public int deal(QualityUnqualified qualityUnqualified) {
        QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId());
        QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
        switch (qualityUnqualified.getDealResult()) {
            case "返修":
            case "返工":
                //判断质检表是否有相关的报工id,如果有报工id,那么返工需要重新创建生产订单重新生产
                if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())) {
                    //返工需要重新创建生产订单重新生产
                    ProductOrder productOrder = productionProductMainMapper.getOrderByMainId(qualityInspect.getProductMainId());
                    ProductOrder order = new ProductOrder();
                    BeanUtils.copyProperties(productOrder, order);
                    order.setId(null);
                    order.setQuantity(unqualified.getQuantity());
                    order.setCompleteQuantity(BigDecimal.ZERO);
                    order.setStartTime(null);
                    order.setEndTime(null);
                    productOrderService.save(order);
                    //新增生产订单下的工艺路线主表
                    ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectList(Wrappers.<ProductProcessRoute>lambdaQuery().eq(ProductProcessRoute::getProductOrderId, productOrder.getId()).orderByDesc(ProductProcessRoute::getId)).get(0);
                    ProductProcessRoute newProcessRoute = new ProductProcessRoute();
                    BeanUtils.copyProperties(productProcessRoute, newProcessRoute);
                    newProcessRoute.setId(null);
                    newProcessRoute.setProductOrderId(order.getId());
                    productProcessRouteMapper.insert(newProcessRoute);
                    //新增生产订单下的工艺路线子表
                    List<ProductProcessRouteItem> processRouteItems = productProcessRouteItemMapper.selectList(new QueryWrapper<ProductProcessRouteItem>().lambda().eq(ProductProcessRouteItem::getProductRouteId, productProcessRoute.getId()));
                    // ç”Ÿæˆå½“前日期的前缀:年月日
                    String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                    for (ProductProcessRouteItem processRouteItem : processRouteItems) {
                        ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
                        BeanUtils.copyProperties(processRouteItem, productProcessRouteItem);
                        productProcessRouteItem.setId(null);
                        productProcessRouteItem.setProductRouteId(newProcessRoute.getId());
                        int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
                        if (insert > 0) {
                            // æŸ¥è¯¢ä»Šæ—¥å·²å­˜åœ¨çš„æœ€å¤§å·¥å•号
                            QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
                            queryWrapper.likeRight("work_order_no", datePrefix)
                                    .orderByDesc("work_order_no")
                                    .last("LIMIT 1");
                            ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
                            int sequenceNumber = 1; // é»˜è®¤åºå·
                            if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
                                String lastNo = lastWorkOrder.getWorkOrderNo().toString();
                                if (lastNo.startsWith(datePrefix)) {
                                    String seqStr = lastNo.substring(datePrefix.length());
                                    try {
                                        sequenceNumber = Integer.parseInt(seqStr) + 1;
                                    } catch (NumberFormatException e) {
                                        sequenceNumber = 1;
                                    }
                                }
                            }
                            // ç”Ÿæˆå®Œæ•´çš„工单号
                            String workOrderNoStr = String.format("%s%03d", datePrefix, sequenceNumber);
                            ProductWorkOrder productWorkOrder = new ProductWorkOrder();
                            productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
                            productWorkOrder.setProductOrderId(order.getId());
                            productWorkOrder.setPlanQuantity(order.getQuantity());
                            productWorkOrder.setWorkOrderNo(workOrderNoStr);
                            productWorkOrder.setStatus(1);
                            productWorkOrderMapper.insert(productWorkOrder);
                        }
                    }
                }
                break;
            case "报废":
                //调用不合格库存接口 å…¥ä¸åˆæ ¼åº“
                stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(),unqualified.getId());
                break;
            case "让步放行":
                //调用提交合格的接口
                stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(),unqualified.getId());
                qualityInspect.setCheckResult("合格");
                qualityInspectService.submit(qualityInspect);
                break;
            default:
                break;
        }
        qualityUnqualified.setInspectState(1);//已处理
        return qualityUnqualifiedMapper.updateById(qualityUnqualified);
    }
}
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -9,6 +9,7 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.sales.dto.InvoiceLedgerDto;
import com.ruoyi.sales.dto.SalesLedgerDto;
@@ -284,4 +285,10 @@
        return iPage;
    }
    @ApiOperation("查询销售台账消耗物料信息")
    @GetMapping("/getSalesLedgerWithProductsLoss")
    public R getSalesLedgerWithProductsLoss(Long salesLedgerId) {
        return R.ok(salesLedgerService.getSalesLedgerWithProductsLoss(salesLedgerId));
    }
}
src/main/java/com/ruoyi/sales/dto/LossProductModelDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.sales.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class LossProductModelDto {
    private String productName;
    private String model;
    private String unit;
    //消耗总量
    private BigDecimal lossNum;
    //单位用量
    private BigDecimal unitQuantity;
    //单个用量
    private BigDecimal singleQuantity;
}
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -3,11 +3,14 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.config.MyBaseMapper;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto;
import com.ruoyi.sales.dto.LossProductModelDto;
import com.ruoyi.sales.dto.SalesLedgerProductDto;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
/**
@@ -26,4 +29,6 @@
    IPage<SalesLedgerProductDto> listPagePurchaseLedger(Page page,@Param("req") SalesLedgerProductDto salesLedgerProduct);
    IPage<ProcurementBusinessSummaryDto> procurementBusinessSummaryListPage(Page page,@Param("req") ProcurementBusinessSummaryDto procurementBusinessSummaryDto);
    List<LossProductModelDto> selectProductBomStructure(@Param("salesLedegerId") Long salesLedegerId);
}
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.sales.dto.LossProductModelDto;
import com.ruoyi.sales.dto.MonthlyAmountDto;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.pojo.SalesLedger;
@@ -39,4 +40,7 @@
    IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto);
    AjaxResult importData(MultipartFile file);
    List<LossProductModelDto> getSalesLedgerWithProductsLoss(Long salesLedgerId);
}
src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
@@ -54,53 +54,85 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invoiceRegistrationSave(SalesLedgerDto salesLedgerDto) {
        //  æ–°å¢žå¼€ç¥¨ç™»è®°ä¸»è¡¨
        InvoiceRegistration invoiceRegistration = new InvoiceRegistration();
        BeanUtils.copyProperties(salesLedgerDto, invoiceRegistration);
        invoiceRegistration.setId(null);
        invoiceRegistration.setCustomerId(salesLedgerDto.getCustomerId().intValue());
        invoiceRegistration.setSalesLedgerId(salesLedgerDto.getId().intValue());
        invoiceRegistrationMapper.insert(invoiceRegistration);
        List<SalesLedgerProduct> productData = salesLedgerDto.getProductData();
        BigDecimal invoiceAmountTotal = BigDecimal.ZERO;
        if(CollectionUtils.isNotEmpty(productData)){
            for (SalesLedgerProduct productDatum : productData) {
                // å¦‚果开票数为0 è·³è¿‡
                BigDecimal currentInvoiceNum = productDatum.getCurrentInvoiceNum();
                if(null == currentInvoiceNum || BigDecimal.ZERO.compareTo(currentInvoiceNum) == 0){
                    continue;
                }
                invoiceAmountTotal = invoiceAmountTotal.add(currentInvoiceNum);
                InvoiceRegistrationProduct invoiceRegistrationProduct = new InvoiceRegistrationProduct();
                BeanUtils.copyProperties(productDatum, invoiceRegistrationProduct);
                //更新已开票剩余未开票数
                invoiceRegistrationProductMapper.update(
                        null,
                        new LambdaUpdateWrapper<InvoiceRegistrationProduct>()
                                .eq(InvoiceRegistrationProduct::getSalesLedgerId, salesLedgerDto.getId())
                                .set(InvoiceRegistrationProduct::getNoInvoiceAmount, productDatum.getNoInvoiceAmount())
                );
                invoiceRegistrationProduct.setId(null);
                invoiceRegistrationProduct.setSalesLedgerId(salesLedgerDto.getId().intValue());
                invoiceRegistrationProduct.setInvoiceRegistrationId(invoiceRegistration.getId());
                invoiceRegistrationProduct.setInvoiceAmount(productDatum.getCurrentInvoiceAmount());
                invoiceRegistrationProduct.setInvoiceNum(productDatum.getCurrentInvoiceNum());
                invoiceRegistrationProduct.setSalesLedgerProductId(productDatum.getId().intValue());
        if (CollectionUtils.isEmpty(productData)) {
            return;
        }
                invoiceRegistrationProductMapper.insert(invoiceRegistrationProduct);
                productDatum.setInvoiceNum(currentInvoiceNum);
                productDatum.setInvoiceAmount(productDatum.getCurrentInvoiceAmount());
                salesLedgerProductMapper.updateById(productDatum);
                // æ–°å¢žä¸€æ¡å¼€ç¥¨å°è´¦æ•°æ®
                InvoiceLedger invoiceLedger = new InvoiceLedger();
                invoiceLedger.setInvoiceDate(salesLedgerDto.getIssueDate());
                invoiceLedger.setInvoiceRegistrationProductId(invoiceRegistrationProduct.getId());
                invoiceLedger.setInvoiceTotal(invoiceRegistrationProduct.getInvoiceAmount());
                invoiceLedger.setInvoiceNo(salesLedgerDto.getInvoiceNo());
                invoiceLedger.setCreateUser(SecurityUtils.getUserId().intValue());
                invoiceLedger.setInvoicePerson(productDatum.getRegister());
        for (SalesLedgerProduct productDatum : productData) {
            //  æœ¬æ¬¡å¼€ç¥¨æ•° / é‡‘额
            BigDecimal currentInvoiceNum = productDatum.getCurrentInvoiceNum();
            BigDecimal currentInvoiceAmount = productDatum.getCurrentInvoiceAmount();
                invoiceLedgerMapper.insert(invoiceLedger);
            if (currentInvoiceNum == null || BigDecimal.ZERO.compareTo(currentInvoiceNum) == 0) {
                continue;
            }
            LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductLambdaQueryWrapper = new LambdaQueryWrapper<SalesLedgerProduct>()
                    .eq(SalesLedgerProduct::getId, productDatum.getId())
                    .eq(SalesLedgerProduct::getSalesLedgerId, productDatum.getSalesLedgerId());
            SalesLedgerProduct dbProduct = salesLedgerProductMapper.selectOne(salesLedgerProductLambdaQueryWrapper);
            if (dbProduct == null) {
                throw new RuntimeException("销售台账产品不存在,ID:" + productDatum.getId());
            }
            //  è®¡ç®—累计开票
            BigDecimal newInvoiceNum = dbProduct.getInvoiceNum().add(currentInvoiceNum);
            BigDecimal newInvoiceAmount = dbProduct.getInvoiceAmount().add(currentInvoiceAmount);
            //  è®¡ç®—未开票
            BigDecimal newNoInvoiceNum = dbProduct.getQuantity().subtract(newInvoiceNum);
            BigDecimal newNoInvoiceAmount = dbProduct.getTaxInclusiveTotalPrice().subtract(newInvoiceAmount);
            if (newNoInvoiceNum.compareTo(BigDecimal.ZERO) < 0
                    || newNoInvoiceAmount.compareTo(BigDecimal.ZERO) < 0) {
                throw new RuntimeException("开票数量或金额超过合同总量");
            }
            //  æ›´æ–° sales_ledger_product
            salesLedgerProductMapper.update(
                    null,
                    new LambdaUpdateWrapper<SalesLedgerProduct>()
                            .eq(SalesLedgerProduct::getId, dbProduct.getId())
                            .set(SalesLedgerProduct::getInvoiceNum, newInvoiceNum)
                            .set(SalesLedgerProduct::getInvoiceAmount, newInvoiceAmount)
                            .set(SalesLedgerProduct::getNoInvoiceNum, newNoInvoiceNum)
                            .set(SalesLedgerProduct::getNoInvoiceAmount, newNoInvoiceAmount)
            );
            InvoiceRegistrationProduct invoiceRegistrationProduct = new InvoiceRegistrationProduct();
            BeanUtils.copyProperties(dbProduct, invoiceRegistrationProduct);
            invoiceRegistrationProduct.setId(null);
            invoiceRegistrationProduct.setSalesLedgerId(salesLedgerDto.getId().intValue());
            invoiceRegistrationProduct.setInvoiceRegistrationId(invoiceRegistration.getId());
            invoiceRegistrationProduct.setSalesLedgerProductId(dbProduct.getId().intValue());
            invoiceRegistrationProduct.setInvoiceNum(currentInvoiceNum);
            invoiceRegistrationProduct.setInvoiceAmount(currentInvoiceAmount);
            invoiceRegistrationProduct.setNoInvoiceAmount(newNoInvoiceAmount);
            invoiceRegistrationProductMapper.insert(invoiceRegistrationProduct);
            InvoiceLedger invoiceLedger = new InvoiceLedger();
            invoiceLedger.setInvoiceDate(salesLedgerDto.getIssueDate());
            invoiceLedger.setInvoiceRegistrationProductId(invoiceRegistrationProduct.getId());
            invoiceLedger.setInvoiceTotal(currentInvoiceAmount);
            invoiceLedger.setInvoiceNo(salesLedgerDto.getInvoiceNo());
            invoiceLedger.setCreateUser(SecurityUtils.getUserId().intValue());
            invoiceLedger.setInvoicePerson(dbProduct.getRegister());
            invoiceLedgerMapper.insert(invoiceLedger);
        }
    }
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -35,10 +35,7 @@
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.sales.dto.MonthlyAmountDto;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.dto.SalesLedgerImportDto;
import com.ruoyi.sales.dto.SalesLedgerProductImportDto;
import com.ruoyi.sales.dto.*;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerProductService;
@@ -234,8 +231,8 @@
        // æŸ¥è¯¢åŽŸå§‹æ•°æ®
        LambdaQueryWrapper<SalesLedger> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(SalesLedger::getCustomerId,
                SalesLedger::getCustomerName,
                SalesLedger::getContractAmount)
                        SalesLedger::getCustomerName,
                        SalesLedger::getContractAmount)
                .orderByDesc(SalesLedger::getContractAmount);
        List<SalesLedger> records = salesLedgerMapper.selectList(queryWrapper);
@@ -243,7 +240,7 @@
        Map<Long, GroupedCustomer> groupedMap = new LinkedHashMap<>(); // ä½¿ç”¨LinkedHashMap保持排序
        for (SalesLedger record : records) {
            groupedMap.computeIfAbsent(record.getCustomerId(),
                    k -> new GroupedCustomer(record.getCustomerId(), record.getCustomerName()))
                            k -> new GroupedCustomer(record.getCustomerId(), record.getCustomerName()))
                    .addAmount(record.getContractAmount());
        }
@@ -350,13 +347,13 @@
        try {
            InputStream inputStream = file.getInputStream();
            ExcelUtil<SalesLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(SalesLedgerImportDto.class);
            Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("销售台账数据","销售产品数据"), inputStream, 0);
            if(CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("销售表格为空!");
            Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("销售台账数据", "销售产品数据"), inputStream, 0);
            if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("销售表格为空!");
            // ä¸šåŠ¡å±‚åˆå¹¶
            List<SalesLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("销售台账数据");
            if(CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("销售台账数据为空!");
            if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("销售台账数据为空!");
            List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("销售产品数据");
            if(CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("销售产品数据为空!");
            if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("销售产品数据为空!");
            // å®¢æˆ·æ•°æ®
            List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).toArray(String[]::new)));
@@ -388,14 +385,16 @@
                        .findFirst()
                        .map(SysUser::getUserId)
                        .orElse(null);
                if(aLong == null) throw new RuntimeException("录入人:"+salesLedger.getEntryPerson()+",无对应用户!");
                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()+",无对应产品数据!");
                if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
                    throw new RuntimeException("销售单号:" + salesLedgerImportDto.getSalesContractNo() + ",无对应产品数据!");
                for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
                    SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
                    BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
@@ -427,12 +426,23 @@
            }
            return AjaxResult.success("导入成功");
        }catch (Exception e) {
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success("导入失败");
    }
    @Override
    public List<LossProductModelDto> getSalesLedgerWithProductsLoss(Long salesLedgerId) {
        List<LossProductModelDto> lossProductModelDtos = salesLedgerProductMapper.selectProductBomStructure(salesLedgerId);
        return lossProductModelDtos;
    }
    // å†…部类用于存储聚合结果
    private static class GroupedCustomer {
        private final Long customerId;
src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java
@@ -16,7 +16,9 @@
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@AllArgsConstructor
@Service
@@ -29,16 +31,32 @@
    @Override
    public List<StaffLeaveDto> staffLeaveReasonAnalytics() {
        List<StaffLeaveDto> result = staffLeaveMapper.staffLeaveReasonAnalytics();
        result.forEach(dto -> {
        List<StaffLeaveDto> dbResult = staffLeaveMapper.staffLeaveReasonAnalytics();
        // åˆ›å»ºä¸€ä¸ªMap用于存储所有枚举原因的数量,默认值为0
        Map<String, Integer> reasonCountMap = new HashMap<>();
        for (StaffLeaveReason reasonEnum : StaffLeaveReason.values()) {
            reasonCountMap.put(reasonEnum.getCode(), 0);
        }
        // å°†æ•°æ®åº“查询结果合并到Map中
        for (StaffLeaveDto dto : dbResult) {
            String reasonCode = dto.getReason();
            StaffLeaveReason reasonEnum = StaffLeaveReason.getByCode(reasonCode);
            if (reasonEnum != null) {
                dto.setReasonText(reasonEnum.getInfo());
            } else {
                dto.setReasonText("未知原因");
            if (reasonCountMap.containsKey(reasonCode)) {
                reasonCountMap.put(reasonCode, dto.getCount());
            }
        });
        }
        // å°†Map转换为List<StaffLeaveDto>
        List<StaffLeaveDto> result = new ArrayList<>();
        for (StaffLeaveReason reasonEnum : StaffLeaveReason.values()) {
            StaffLeaveDto dto = new StaffLeaveDto();
            dto.setReason(reasonEnum.getCode());
            dto.setCount(reasonCountMap.get(reasonEnum.getCode()));
            dto.setReasonText(reasonEnum.getInfo());
            result.add(dto);
        }
        return result;
    }
src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -54,9 +54,10 @@
        // æ–°å¢žç¦»èŒè®°å½•
        StaffLeave staffLeave = new StaffLeave();
        staffLeave.setStaffOnJobId(staffLeaveDto.getStaffOnJobId());
        staffLeave.setReason(staffLeaveDto.getReason());
        String reason = staffLeaveDto.getReason();
        if (!StaffLeaveReasonOther.getCode().equals(reason)){
            staffLeave.setRemark("");
        if (StaffLeaveReasonOther.getCode().equals(reason)){
            staffLeave.setRemark(staffLeaveDto.getRemark());
        }
        staffLeaveMapper.insert(staffLeave);
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.ruoyi.stock.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.stock.dto.StockInRecordDto;
import com.ruoyi.stock.service.StockInRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Api(tags = "入库")
@RequestMapping("/stockInRecord")
public class StockInRecordController {
    @Autowired
    private StockInRecordService stockInRecordService;
    @GetMapping("/listPage")
    @Log(title = "生产入库-入库管理-列表", businessType = BusinessType.OTHER)
    @ApiOperation(value = "入库管理列表")
    public AjaxResult listPage(Page page, StockInRecordDto stockInRecordDto) {
        IPage<StockInRecordDto> result = stockInRecordService.listPage(page, stockInRecordDto);
        return AjaxResult.success(result);
    }
    @DeleteMapping("")
    @Log(title = "入库管理-删除入库", businessType = BusinessType.DELETE)
    public AjaxResult delete(@RequestBody List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return AjaxResult.error("请选择至少一条数据");
        }
        return AjaxResult.success(stockInRecordService.batchDelete(ids));
    }
}
src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
package com.ruoyi.stock.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.service.StockInventoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
 * <p>
 * åº“存表 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 04:16:36
 */
@RestController
@RequestMapping("/stockInventory")
@Api(tags = "库存表")
public class StockInventoryController {
    @Autowired
    private StockInventoryService stockInventoryService;
    @GetMapping("/pagestockInventory")
    @ApiOperation("分页查询库存")
    public R pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
        IPage<StockInventoryDto> stockInventoryDtoIPage = stockInventoryService.pagestockInventory(page, stockInventoryDto);
        return R.ok(stockInventoryDtoIPage);
    }
    @PostMapping("/addstockInventory")
    @ApiOperation("新增库存")
    public R addstockInventory(@RequestBody StockInventoryDto stockInventoryDto) {
        stockInventoryDto.setRecordType(String.valueOf(StockQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode()));
        stockInventoryDto.setRecordId(0L);
        return R.ok(stockInventoryService.addstockInventory(stockInventoryDto));
    }
    @PostMapping("/subtractStockInventory")
    @ApiOperation("扣减库存")
    public R subtractStockInventory(@RequestBody StockInventoryDto stockInventoryDto) {
        stockInventoryDto.setRecordType(String.valueOf(StockQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_OUT.getCode()));
        stockInventoryDto.setRecordId(0L);
        return R.ok(stockInventoryService.subtractStockInventory(stockInventoryDto));
    }
    @GetMapping("importStockInventory")
    @ApiOperation("导入库存")
    public R importStockInventory(MultipartFile  file) {
        return R.ok(stockInventoryService.importStockInventory(file));
    }
}
src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.ruoyi.stock.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.service.StockOutRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * <p>
 * å‡ºåº“记录表 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 05:27:04
 */
@Api(tags = "出库")
@RestController
@RequestMapping("/stockOutRecord")
public class StockOutRecordController {
    @Autowired
    private StockOutRecordService stockOutRecordService;
    @GetMapping("/listPage")
    @Log(title = "生产出库-出库管理-列表", businessType = BusinessType.OTHER)
    @ApiOperation(value = "出库管理列表")
    public AjaxResult listPage(Page page, StockOutRecordDto stockOutRecordDto) {
        IPage<StockOutRecordDto> result = stockOutRecordService.listPage(page, stockOutRecordDto);
        return AjaxResult.success(result);
    }
    @PostMapping("")
    @Log(title = "出库管理-新增出库", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody StockOutRecordDto stockOutRecordDto) {
        return AjaxResult.success(stockOutRecordService.add(stockOutRecordDto));
    }
    @PutMapping("/{id}")
    @Log(title = "出库管理-更新出库", businessType = BusinessType.UPDATE)
    public AjaxResult update(@PathVariable("id") Long id, @RequestBody StockOutRecordDto stockOutRecordDto) {
        return AjaxResult.success(stockOutRecordService.update(id, stockOutRecordDto));
    }
    @DeleteMapping("")
    @Log(title = "出库管理-删除出库", businessType = BusinessType.DELETE)
    public AjaxResult delete(@RequestBody List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return AjaxResult.error("请选择至少一条数据");
        }
        return AjaxResult.success(stockOutRecordService.batchDelete(ids));
    }
}
src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.ruoyi.stock.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.service.StockUninventoryService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
 * <p>
 * ä¸åˆæ ¼åº“存表 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-22 10:17:45
 */
@RestController
@RequestMapping("/stockUninventory")
public class StockUninventoryController {
    @Autowired
    private StockUninventoryService stockUninventoryService;
    @GetMapping("/pagestockUninventory")
    @ApiOperation("分页查询库存")
    public R pagestockUninventory(Page page, StockUninventoryDto stockUninventoryDto) {
        IPage<StockUninventoryDto> stockUninventoryDtoIPage = stockUninventoryService.pageStockUninventory(page, stockUninventoryDto);
        return R.ok(stockUninventoryDtoIPage);
    }
    @PostMapping("/addstockUninventory")
    @ApiOperation("新增库存")
    public R addstockUninventory(@RequestBody StockUninventoryDto stockUninventoryDto) {
        stockUninventoryDto.setRecordType(String.valueOf(StockUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_IN.getCode()));
        stockUninventoryDto.setRecordId(0L);
        return R.ok(stockUninventoryService.addStockUninventory(stockUninventoryDto));
    }
    @PostMapping("/subtractstockUninventory")
    @ApiOperation("扣减库存")
    public R subtractstockUninventory(@RequestBody StockUninventoryDto stockUninventoryDto) {
        stockUninventoryDto.setRecordType(String.valueOf(StockUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode()));
        stockUninventoryDto.setRecordId(0L);
        return R.ok(stockUninventoryService.subtractStockUninventory(stockUninventoryDto));
    }
}
src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.stock.dto;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.stock.pojo.StockInRecord;
import lombok.Data;
@Data
public class StockInRecordDto extends StockInRecord {
    /**
     * äº§å“åç§°
     */
    private String productName;
    /**
     * äº§å“è§„æ ¼
     */
    private String model;
    /**
     * äº§å“å•位
     */
    private String unit;
    private String timeStr;
    private String createBy;
}
src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.ruoyi.stock.dto;
import com.ruoyi.stock.pojo.StockInventory;
import lombok.Data;
@Data
public class StockInventoryDto extends StockInventory {
    private String productName;
    private String model;
    private String unit;
    //入库类型
    private String recordType;
    //入库类型对应的id
    private Long recordId;
}
src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.stock.dto;
import com.ruoyi.stock.pojo.StockOutRecord;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StockOutRecordDto extends StockOutRecord {
    /**
     * äº§å“åç§°
     */
    private String productName;
    /**
     * äº§å“è§„æ ¼
     */
    private String model;
    /**
     * äº§å“å•位
     */
    private String unit;
    private String timeStr;
    private String createBy;
}
src/main/java/com/ruoyi/stock/dto/StockUninventoryDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.stock.dto;
import com.ruoyi.stock.pojo.StockUninventory;
import lombok.Data;
@Data
public class StockUninventoryDto  extends StockUninventory {
    private String productName;
    private String model;
    private String unit;
    //入库类型
    private String recordType;
    //入库类型对应的id
    private Long recordId;
}
src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
package com.ruoyi.stock.execl;
public class StockInventoryExportData {
}
src/main/java/com/ruoyi/stock/mapper/StockInRecordMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.ruoyi.stock.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.stock.dto.StockInRecordDto;
import com.ruoyi.stock.pojo.StockInRecord;
import org.apache.ibatis.annotations.Param;
public interface StockInRecordMapper extends BaseMapper<StockInRecord> {
    IPage<StockInRecordDto> listPage(Page page, @Param("params") StockInRecordDto stockInRecordDto);
}
src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.stock.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.pojo.StockInventory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
 * åº“存表 Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 04:16:36
 */
@Mapper
public interface StockInventoryMapper extends BaseMapper<StockInventory> {
    IPage<StockInventoryDto> pagestockInventory(Page page, @Param("ew") StockInventoryDto stockInventoryDto);
    int updateAddStockInventory(@Param("ew") StockInventoryDto stockInventoryDto);
    int updateSubtractStockInventory(@Param("ew") StockInventoryDto stockInventoryDto);
}
src/main/java/com/ruoyi/stock/mapper/StockOutRecordMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.ruoyi.stock.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.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.pojo.StockOutRecord;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
 * å‡ºåº“记录表 Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 05:27:04
 */
@Mapper
public interface StockOutRecordMapper extends BaseMapper<StockOutRecord> {
    IPage<StockOutRecordDto> listPage(Page page, @Param("params") StockOutRecordDto stockOutRecordDto);
}
src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.stock.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.pojo.StockUninventory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
 * ä¸åˆæ ¼åº“存表 Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-22 10:17:45
 */
@Mapper
public interface StockUninventoryMapper extends BaseMapper<StockUninventory> {
    IPage<StockUninventoryDto> pageStockUninventory(Page page, @Param("ew") StockUninventoryDto stockUninventoryDto);
    int updateSubtractStockUnInventory(StockUninventoryDto stockUninventoryDto);
    int updateAddStockUnInventory(StockUninventoryDto stockUninventoryDto);
}
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
package com.ruoyi.stock.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("stock_in_record")
@ApiModel("入库管理")
public class StockInRecord {
    private static final long serialVersionUID = 1L;
    /**
     * åºå·
     */
    @TableId(type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "入库批次")
    private String inboundBatches;
    @ApiModelProperty(value = "入库数量")
    private BigDecimal stockInNum;
    @ApiModelProperty(value = "记录类型  æžšä¸¾")
    private String recordType;
    @ApiModelProperty(value = "记录ID  ")
    private Long recordId;
    @ApiModelProperty(value = "产品规格ID")
    private Long productModelId;
    @ApiModelProperty(value = "备注")
    private String remark;
    @ApiModelProperty(value = "类型  0合格入库 1不合格入库")
    private String type;
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "创建用户")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @ApiModelProperty(value = "修改时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    @ApiModelProperty(value = "修改用户")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
}
src/main/java/com/ruoyi/stock/pojo/StockInventory.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package com.ruoyi.stock.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.lang.Nullable;
import javax.validation.constraints.NotBlank;
/**
 * <p>
 * åº“存表
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 04:16:36
 */
@Getter
@Setter
@TableName("stock_inventory")
@ApiModel(value = "StockInventory对象", description = "库存表")
public class StockInventory implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键id")
    private Long id;
    @ApiModelProperty("规格id")
    @NotBlank(message = "不能为空")
    private Long productModelId;
    @ApiModelProperty("数量")
    private BigDecimal qualitity;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty("更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    @ApiModelProperty("版本号")
    private Integer version;
    @ApiModelProperty("被订单锁定数量")
    private BigDecimal lockedQuantity;
    @ApiModelProperty("预警数量")
    private Integer warnNum;
    @ApiModelProperty("备注")
    private String remark;
}
src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package com.ruoyi.stock.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * <p>
 * å‡ºåº“记录表
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 05:27:04
 */
@Getter
@Setter
@TableName("stock_out_record")
@ApiModel(value = "StockOutRecord对象", description = "出库记录表")
public class StockOutRecord implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("入库批次")
    private String outboundBatches;
    @ApiModelProperty("入库数量")
    private BigDecimal stockOutNum;
    @ApiModelProperty("入库来源id")
    private Long recordId;
    @ApiModelProperty("入库类型")
    private String recordType;
    @ApiModelProperty("产品规格id")
    private Long productModelId;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("创建时间")
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty("更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    @ApiModelProperty("创建人")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @ApiModelProperty("更新人")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @ApiModelProperty(value = "类型  0合格入库 1不合格入库")
    private String type;
}
src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.ruoyi.stock.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
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-22 10:17:45
 */
@Getter
@Setter
@TableName("stock_uninventory")
@ApiModel(value = "StockUninventory对象", description = "不合格库存表")
public class StockUninventory implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键id")
    private Long id;
    @ApiModelProperty("规格id")
    private Long productModelId;
    @ApiModelProperty("数量")
    private BigDecimal qualitity;
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @ApiModelProperty("更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateTime;
    @ApiModelProperty("版本号")
    private Integer version;
    @ApiModelProperty("备注")
    private String remark;
}
src/main/java/com/ruoyi/stock/service/StockInRecordService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.ruoyi.stock.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.pojo.StockInRecord;
import java.util.List;
public interface StockInRecordService extends IService<StockInRecord> {
    IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto);
    int add(StockInRecordDto stockInRecordDto);
    int update(Long id, StockInRecordDto stockInRecordDto);
    int batchDelete(List<Long> ids);
}
src/main/java/com/ruoyi/stock/service/StockInventoryService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.stock.service;
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.stock.dto.StockInventoryDto;
import com.ruoyi.stock.pojo.StockInventory;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;
/**
 * <p>
 * åº“存表 æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 04:16:36
 */
public interface StockInventoryService extends IService<StockInventory> {
    IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto);
    Boolean addstockInventory(StockInventoryDto stockInventoryDto);
    Boolean subtractStockInventory(StockInventoryDto stockInventoryDto);
    Boolean importStockInventory(MultipartFile file);
}
src/main/java/com/ruoyi/stock/service/StockOutRecordService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.stock.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.pojo.StockOutRecord;
import java.util.List;
/**
 * <p>
 * å‡ºåº“记录表 æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 05:27:04
 */
public interface StockOutRecordService extends IService<StockOutRecord> {
    IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto);
    int add(StockOutRecordDto stockOutRecordDto);
    int update(Long id, StockOutRecordDto stockOutRecordDto);
    int batchDelete(List<Long> ids);
}
src/main/java/com/ruoyi/stock/service/StockUninventoryService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.stock.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.pojo.StockUninventory;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * ä¸åˆæ ¼åº“存表 æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-22 10:17:45
 */
public interface StockUninventoryService extends IService<StockUninventory> {
    IPage<StockUninventoryDto> pageStockUninventory(Page page, StockUninventoryDto stockUninventoryDto);
    Integer addStockUninventory(StockUninventoryDto stockUninventoryDto);
    Integer subtractStockUninventory(StockUninventoryDto stockUninventoryDto);
}
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
package com.ruoyi.stock.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;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.staff.pojo.StaffOnJob;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.mapper.StockInRecordMapper;
import com.ruoyi.stock.mapper.StockInventoryMapper;
import com.ruoyi.stock.mapper.StockUninventoryMapper;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.pojo.StockUninventory;
import com.ruoyi.stock.service.StockInRecordService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@AllArgsConstructor
public class StockInRecordServiceImpl extends ServiceImpl<StockInRecordMapper, StockInRecord> implements StockInRecordService {
    private StockInRecordMapper stockInRecordMapper;
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    @Override
    public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) {
        return stockInRecordMapper.listPage(page, stockInRecordDto);
    }
    // æ–°å¢žå…¥åº“
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int add(StockInRecordDto stockInRecordDto) {
        String no = OrderUtils.countTodayByCreateTime(stockInRecordMapper, "RK");
        stockInRecordDto.setInboundBatches(no);
        StockInRecord stockInRecord = new StockInRecord();
        BeanUtils.copyProperties(stockInRecordDto, stockInRecord);
        return stockInRecordMapper.insert(stockInRecord);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(Long id, StockInRecordDto stockInRecordDto) {
        // åˆ¤æ–­å¯¹è±¡æ˜¯å¦å­˜åœ¨
        StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
        if (stockInRecord == null){
            throw new BaseException("该入库记录不存在,无法更新!!!");
        }
        String[] ignoreProperties = {"id", "inbound_batches"};//排除id属性
        BeanUtils.copyProperties(stockInRecordDto, stockInRecord, ignoreProperties);
        return stockInRecordMapper.updateById(stockInRecord);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
            if (stockInRecord.getType().equals("0")) {
                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockInRecord.getProductModelId()));
                if (stockInventory == null) {
                    throw new BaseException("库存记录中没有对应的产品,无法删除!!!");
                }else {
                    StockInventoryDto stockInRecordDto = new StockInventoryDto();
                    stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                    stockInRecordDto.setQualitity(stockInRecord.getStockInNum());
                    stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
                }
            }else if (stockInRecord.getType().equals("1")) {
                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()));
                if (stockUninventory == null) {
                    throw new BaseException("库存记录中没有对应的产品,无法删除!!!");
                }else {
                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                    stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                    stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
                    stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
                }
            }
        }
        return stockInRecordMapper.deleteBatchIds(ids);
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
package com.ruoyi.stock.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.excel.SupplierManageExcelDto;
import com.ruoyi.basic.pojo.SupplierManage;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.execl.StockInventoryExportData;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.mapper.StockInventoryMapper;
import com.ruoyi.stock.service.StockInRecordService;
import com.ruoyi.stock.service.StockInventoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.stock.service.StockOutRecordService;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
 * åº“存表 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 04:16:36
 */
@Service
@AllArgsConstructor
public class StockInventoryServiceImpl extends ServiceImpl<StockInventoryMapper, StockInventory> implements StockInventoryService {
    private  StockInventoryMapper stockInventoryMapper;
    private StockInRecordService stockInRecordService;
    private StockOutRecordService stockOutRecordService;
    @Override
    public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
        return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
    }
    //入库调用
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addstockInventory(StockInventoryDto stockInventoryDto) {
        //新增入库记录再添加库存
        StockInRecordDto stockInRecordDto = new StockInRecordDto();
        stockInRecordDto.setRecordId(stockInventoryDto.getRecordId());
        stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
        stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockInRecordDto.setType("0");
        stockInRecordService.add(stockInRecordDto);
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            StockInventory newStockInventory = new StockInventory();
            newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
            newStockInventory.setQualitity(stockInventoryDto.getQualitity());
            newStockInventory.setVersion(1);
            newStockInventory.setRemark(stockInventoryDto.getRemark());
            stockInventoryMapper.insert(newStockInventory);
        }else {
             stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
        }
        return true;
    }
    //出库调用
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean subtractStockInventory(StockInventoryDto stockInventoryDto) {
            //  æ–°å¢žå‡ºåº“记录
        StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
        stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
        stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
        stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockOutRecordDto.setType("0");
        stockOutRecordService.add(stockOutRecordDto);
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            throw new RuntimeException("产品库存不存在");
        }else {
            stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
        }
        return true;
    }
    @Override
    public Boolean importStockInventory(MultipartFile file) {
        try {
            ExcelUtil<StockInventoryExportData> util = new ExcelUtil<StockInventoryExportData>(StockInventoryExportData.class);
            List<StockInventoryExportData> list = util.importExcel(file.getInputStream());
            ArrayList<StockInventory> stockInventories = new ArrayList<>();
            list.stream().forEach(dto -> {
               // TODO: 2026/1/21 æ·»åŠ å…¥åº“è®°å½•
            });
            this.saveOrUpdateBatch(stockInventories);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
package com.ruoyi.stock.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;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.mapper.StockInventoryMapper;
import com.ruoyi.stock.mapper.StockOutRecordMapper;
import com.ruoyi.stock.mapper.StockUninventoryMapper;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.pojo.StockOutRecord;
import com.ruoyi.stock.pojo.StockUninventory;
import com.ruoyi.stock.service.StockOutRecordService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * <p>
 * å‡ºåº“记录表 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-21 05:27:04
 */
@Service
@AllArgsConstructor
public class StockOutRecordServiceImpl extends ServiceImpl<StockOutRecordMapper, StockOutRecord> implements StockOutRecordService {
    private StockOutRecordMapper stockOutRecordMapper;
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    @Override
    public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
        return stockOutRecordMapper.listPage(page, stockOutRecordDto);
    }
    @Override
    public int add(StockOutRecordDto stockOutRecordDto) {
        String no = OrderUtils.countTodayByCreateTime(stockOutRecordMapper, "CK");
        stockOutRecordDto.setOutboundBatches(no);
        StockInRecord stockInRecord = new StockInRecord();
        BeanUtils.copyProperties(stockOutRecordDto, stockInRecord);
        return stockOutRecordMapper.insert(stockOutRecordDto);
    }
    @Override
    public int update(Long id, StockOutRecordDto stockOutRecordDto) {
        // åˆ¤æ–­å¯¹è±¡æ˜¯å¦å­˜åœ¨
        StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
        if (stockOutRecord == null){
            throw new BaseException("该出库记录不存在,无法更新!!!");
        }
        String[] ignoreProperties = {"id", "outbound_batches"};//排除id属性
        BeanUtils.copyProperties(stockOutRecordDto, stockOutRecord, ignoreProperties);
        return stockOutRecordMapper.updateById(stockOutRecord);
    }
    @Override
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
            if (stockOutRecord.getType().equals("0")) {
                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockOutRecord.getProductModelId()));
                if (stockInventory == null) {
                    throw new BaseException("库存记录中没有对应的产品,无法删除!!!");
                }else {
                    StockInventoryDto stockInRecordDto = new StockInventoryDto();
                    stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                    stockInRecordDto.setQualitity(stockOutRecord.getStockOutNum());
                    stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
                }
            }else if (stockOutRecord.getType().equals("1")) {
                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockOutRecord.getProductModelId()));
                if (stockUninventory == null) {
                    throw new BaseException("库存记录中没有对应的产品,无法删除!!!");
                }else {
                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                    stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                    stockUninventoryDto.setQualitity(stockOutRecord.getStockOutNum());
                    stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
                }
            }
        }
        return stockOutRecordMapper.deleteBatchIds(ids);
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
package com.ruoyi.stock.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.pojo.StockUninventory;
import com.ruoyi.stock.mapper.StockUninventoryMapper;
import com.ruoyi.stock.service.StockInRecordService;
import com.ruoyi.stock.service.StockOutRecordService;
import com.ruoyi.stock.service.StockUninventoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
 * <p>
 * ä¸åˆæ ¼åº“存表 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-22 10:17:45
 */
@Service
@AllArgsConstructor
public class StockUninventoryServiceImpl extends ServiceImpl<StockUninventoryMapper, StockUninventory> implements StockUninventoryService {
    private StockUninventoryMapper stockUninventoryMapper;
    private StockOutRecordService stockOutRecordService;
    private StockInRecordService stockInRecordService;
    @Override
    public IPage<StockUninventoryDto> pageStockUninventory(Page page, StockUninventoryDto stockUninventoryDto) {
        return stockUninventoryMapper.pageStockUninventory(page, stockUninventoryDto);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addStockUninventory(StockUninventoryDto stockUninventoryDto) {
        //新增入库记录再添加库存
        StockInRecordDto stockInRecordDto = new StockInRecordDto();
        stockInRecordDto.setRecordId(stockUninventoryDto.getRecordId());
        stockInRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity());
        stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockInRecordDto.setType("1");
        stockInRecordService.add(stockInRecordDto);
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
        if (ObjectUtils.isEmpty(oldStockUnInventory)) {
            StockUninventory newStockUnInventory = new StockUninventory();
            newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
            newStockUnInventory.setQualitity(stockUninventoryDto.getQualitity());
            newStockUnInventory.setVersion(1);
            newStockUnInventory.setRemark(stockUninventoryDto.getRemark());
            stockUninventoryMapper.insert(newStockUnInventory);
        }else {
            stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
        }
        return 1;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer subtractStockUninventory(StockUninventoryDto stockUninventoryDto) {
        //  æ–°å¢žå‡ºåº“记录
        StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
        stockOutRecordDto.setRecordId(stockUninventoryDto.getRecordId());
        stockOutRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockOutRecordDto.setStockOutNum(stockUninventoryDto.getQualitity());
        stockOutRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockOutRecordDto.setType("1");
        stockOutRecordService.add(stockOutRecordDto);
        StockUninventory oldStockInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            throw new RuntimeException("产品库存不存在");
        }else {
            stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
        }
        return 1;
    }
}
src/main/resources/mapper/collaborativeApproval/StaffContactsPersonalMapper.xml
@@ -17,7 +17,7 @@
            sjlr.phone,
            scp.create_time
        FROM staff_contacts_personal scp
            LEFT JOIN (select * from staff_join_leave_record WHERE staff_state = 1) sjlr ON scp.contact_id=sjlr.id
            LEFT JOIN (select * from staff_on_job WHERE staff_state = 1) sjlr ON scp.contact_id=sjlr.id
        where 1=1
        <if test="staffContactsPersonalDTO.staffName != null and staffContactsPersonalDTO.staffName != ''">
            and sjlr.staff_name like concat('%',#{staffContactsPersonalDTO.staffName},'%')
src/main/resources/mapper/lavorissue/LavorIssueMapper.xml
@@ -10,7 +10,7 @@
               t3.dict_label as dictName,
               t4.dict_label as dictTypeName
        from labor_issue t1
        left join staff_join_leave_record t2 on t1.staff_id = t2.id
        left join staff_on_job t2 on t1.staff_id = t2.id
        left join sys_dict_data t3 on t1.dict_id = t3.dict_value
        left join sys_dict_data t4 on t1.dict_type = t4.dict_value
        <where>
@@ -45,7 +45,7 @@
            t3.dict_label as dictName,
            t4.dict_label as dictTypeName
        from labor_issue t1
                 left join staff_join_leave_record t2 on t1.staff_id = t2.id
                 left join staff_on_job t2 on t1.staff_id = t2.id
                 left join sys_dict_data t3 on t1.dict_id = t3.dict_value
                 left join sys_dict_data t4 on t1.dict_type = t4.dict_value
        <where>
src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -20,6 +20,7 @@
               p.product_name as productName,
               pm.model as productModelName,
               ppo.quantity,
               ppo.scrap_qty,
               pm.unit,
               sl.sales_contract_no salesContractNo
        from
@@ -48,6 +49,13 @@
        order by ppm.id
    </select>
    <select id="getOrderByMainId" resultType="com.ruoyi.production.pojo.ProductOrder">
        select po.*
        from product_order po
        left join  product_work_order pwo on po.id = pwo.product_order_id
        left join production_product_main pm on work_order_id=pwo.id
        where pm.id=#{productMainId}
    </select>
    <delete id="deleteByWorkOrderIds" parameterType="java.util.List">
        DELETE FROM production_product_main
src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml
@@ -27,7 +27,7 @@
        sl.customer_name,
        sl.contract_amount
        ORDER BY
        sl.sales_contract_no;
        sl.sales_contract_no
    </select>
    <select id="listVat" resultType="com.ruoyi.purchase.dto.VatDto">
        select *
src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -312,29 +312,35 @@
    </select>
    <select id="getTopParameters" resultType="com.ruoyi.quality.dto.QualityParameterStatDto">
        WITH parameter_counts AS (SELECT qip.parameter_item AS name, COUNT(*) AS count
                                  FROM quality_inspect_param qip
                                           JOIN quality_inspect qi ON qip.inspect_id = qi.id
        WITH parameter_counts AS (SELECT qip.parameter_item            AS name,
                                         SUM(COALESCE(qi.quantity, 0)) AS count
                                  FROM quality_inspect qi
                                           JOIN quality_inspect_param qip ON qip.inspect_id = qi.id
                                  WHERE qi.inspect_type = #{inspectType}
                                  GROUP BY qip.parameter_item),
             total AS (SELECT SUM(count) as total_count
                       FROM parameter_counts),
             ranked AS (SELECT name, count, ROW_NUMBER() OVER (ORDER BY count DESC) as rn
                        FROM parameter_counts)
             ranked AS (SELECT name,
                               count,
                               ROW_NUMBER() OVER (ORDER BY count DESC) AS rn
                        FROM parameter_counts),
             total AS (SELECT SUM(count) AS total_count
                       FROM parameter_counts)
        SELECT name,
               count,
               CASE
                   WHEN (SELECT total_count FROM total) = 0 THEN 0
                   ELSE ROUND(count / (SELECT total_count FROM total) * 100, 2)
                   END as percentage
                   END AS percentage
        FROM (SELECT name, count, rn
              FROM ranked
              WHERE rn &lt;= 4
              UNION ALL
              SELECT '其他' as name, SUM(count) as count, 5 as rn
              SELECT '其他检测' AS name,
                     SUM(count) AS count,
                     5          AS rn
              FROM ranked
              WHERE rn &gt; 4
              HAVING count &gt; 0) sub
              HAVING SUM(count) &gt; 0) t
        ORDER BY rn
    </select>
</mapper>
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -15,10 +15,10 @@
        <where>
            1=1
            <if test="salesLedgerProduct.salesLedgerId != null and salesLedgerProduct.salesLedgerId != '' ">
                AND  T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
                AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
            </if>
            <if test="salesLedgerProduct.type != null and salesLedgerProduct.type != '' ">
                AND  T1.type = #{salesLedgerProduct.type}
                AND T1.type = #{salesLedgerProduct.type}
            </if>
        </where>
    </select>
@@ -27,7 +27,7 @@
        from quality_inspect qi
                 left join production_product_main ppm on qi.product_main_id = ppm.id
                 left join product_work_order pwo on ppm.work_order_id = pwo.id
                 left join product_order  po on pwo.product_order_id = po.id
                 left join product_order po on pwo.product_order_id = po.id
                 left join sales_ledger_product slp on po.product_model_id = slp.id
        where qi.product_main_id = #{productMainId}
@@ -44,22 +44,22 @@
        <where>
            slp.type = 1
            <if test="req.salesContractNo != null and req.salesContractNo != '' ">
                AND  sl.sales_contract_no like concat('%',#{req.salesContractNo},'%')
                AND sl.sales_contract_no like concat('%',#{req.salesContractNo},'%')
            </if>
            <if test="req.customerContractNo != null and req.customerContractNo != '' ">
                AND  sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
                AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
            </if>
            <if test="req.projectName != null and req.projectName != '' ">
                AND  sl.project_name like concat('%',#{req.projectName},'%')
                AND sl.project_name like concat('%',#{req.projectName},'%')
            </if>
            <if test="req.customerName != null and req.customerName != '' ">
                AND  sl.customer_name like concat('%',#{req.customerName},'%')
                AND sl.customer_name like concat('%',#{req.customerName},'%')
            </if>
            <if test="req.productCategory != null and req.productCategory != '' ">
                AND  slp.product_category like concat('%',#{req.productCategory},'%')
                AND slp.product_category like concat('%',#{req.productCategory},'%')
            </if>
            <if test="req.status != null and req.status ">
                AND  slp.pending_invoice_total &gt; 0
                AND slp.pending_invoice_total &gt; 0
            </if>
        </where>
        order by slp.register_date desc
@@ -76,22 +76,22 @@
        <where>
            slp.type = 2
            <if test="req.purchaseContractNumber != null and req.purchaseContractNumber != '' ">
                AND  sl.purchase_contract_number like concat('%',#{req.purchaseContractNumber},'%')
                AND sl.purchase_contract_number like concat('%',#{req.purchaseContractNumber},'%')
            </if>
            <if test="req.customerContractNo != null and req.customerContractNo != '' ">
                AND  sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
                AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
            </if>
            <if test="req.projectName != null and req.projectName != '' ">
                AND  sl.project_name like concat('%',#{req.projectName},'%')
                AND sl.project_name like concat('%',#{req.projectName},'%')
            </if>
            <if test="req.customerName != null and req.customerName != '' ">
                AND  sl.customer_name like concat('%',#{req.customerName},'%')
                AND sl.customer_name like concat('%',#{req.customerName},'%')
            </if>
            <if test="req.productCategory != null and req.productCategory != '' ">
                AND  slp.product_category like concat('%',#{req.productCategory},'%')
                AND slp.product_category like concat('%',#{req.productCategory},'%')
            </if>
            <if test="req.status != null and req.status ">
                AND  slp.pending_invoice_total &gt; 0
                AND slp.pending_invoice_total &gt; 0
            </if>
        </where>
        order by slp.register_date desc
@@ -126,4 +126,25 @@
        <!-- æŒ‰äº§å“å¤§ç±»æŽ’序 -->
        ORDER BY slp.product_category
    </select>
    <select id="selectProductBomStructure" resultType="com.ruoyi.sales.dto.LossProductModelDto">
        select
            a.model,
            a.product_name,
            a.unit,
            sum(a.single_quantity) AS loss_num
        from (SELECT ps.unit,
                     ps.unit_quantity,
                     pm1.model,
                     p.product_name,
                     ps.unit_quantity * slp.quantity AS single_quantity
              FROM sales_ledger sl
                       LEFT JOIN sales_ledger_product slp ON slp.sales_ledger_id = sl.id
                       LEFT JOIN product_model pm ON pm.id = slp.product_model_id
                       LEFT JOIN product_bom pb ON pb.product_model_id = pm.id
                       LEFT JOIN product_structure ps ON pb.id = ps.bom_id
                       LEFT JOIN product_model pm1 ON pm1.id = ps.product_model_id
                       LEFT JOIN product p ON p.id = pm1.product_id
              WHERE sl.id = #{salesLedegerId}) A
        group by a.model, a.product_name, a.unit
    </select>
</mapper>
src/main/resources/mapper/stock/StockInRecordMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
<?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.stock.mapper.StockInRecordMapper">
    <select id="listPage" resultType="com.ruoyi.stock.dto.StockInRecordDto">
        SELECT
        sir.*,
        p.product_name as productName,
        pm.model,
        pm.unit,
        u.nick_name as createBy
        FROM stock_in_record as sir
        LEFT JOIN product_model as pm on sir.product_model_id = pm.id
        LEFT JOIN product as p on pm.product_id = p.id
        LEFT JOIN sys_user as u on sir.create_user = u.user_id
        <where>
            <if test="params.timeStr != null and params.timeStr != ''">
                and sir.create_time like concat('%',#{params.timeStr},'%')
            </if>
            <if test="params.productName != null and params.productName != ''">
                and p.product_name like concat('%',#{params.productName},'%')
            </if>
            <if test="params.type != null and params.type != ''">
                and sir.type = #{params.type}
            </if>
            <if test="params.recordType != null and params.recordType != ''">
                and sir.record_type = #{params.recordType}
            </if>
        </where>
        order by sir.id desc
    </select>
</mapper>
src/main/resources/mapper/stock/StockInventoryMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
<?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.stock.mapper.StockInventoryMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.stock.pojo.StockInventory">
        <result column="id" property="id" />
        <result column="product_model_id" property="productModelId" />
        <result column="qualitity" property="qualitity" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="version" property="version" />
        <result column="locked_quantity" property="lockedQuantity" />
        <result column="warn_num" property="warnNum" />
    </resultMap>
    <update id="updateAddStockInventory">
        update stock_inventory
        <set>
            <if test="ew.qualitity != null">
                qualitity = qualitity + #{ew.qualitity},
            </if>
           <if test="ew.version != null">
               version = version + 1,
            </if>
            <if test="ew.remark != null and ew.remark !=''">
                remark = #{ew.remark},
            </if>
            update_time = now()
        </set>
        where product_model_id = #{ew.productModelId}
    </update>
    <update id="updateSubtractStockInventory">
        update stock_inventory
        <set>
            <if test="ew.qualitity != null">
                qualitity = qualitity - #{ew.qualitity},
            </if>
            <if test="ew.version != null">
                version = version + 1,
            </if>
            <if test="ew.remark != null and ew.remark !=''">
                remark = #{ew.remark},
            </if>
            update_time = now()
        </set>
        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
    </update>
    <select id="pagestockInventory" resultType="com.ruoyi.stock.dto.StockInventoryDto">
        select si.*,
               pm.model,
               pm.unit,
               p.product_name
        from stock_inventory si
                 left join product_model pm on si.product_model_id = pm.id
                 left join product p on pm.product_id = p.id
        where 1 = 1
        <if test="ew.productName != null and ew.productName !=''">
            and p.product_name like concat('%',#{ew.productName},'%')
        </if>
    </select>
</mapper>
src/main/resources/mapper/stock/StockOutRecordMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
<?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.stock.mapper.StockOutRecordMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.stock.pojo.StockOutRecord">
        <id column="id" property="id" />
        <result column="outbound_batches" property="outboundBatches" />
        <result column="stock_out_num" property="stockOutNum" />
        <result column="record_id" property="recordId" />
        <result column="record_type" property="recordType" />
        <result column="product_model_id" property="productModelId" />
        <result column="remark" property="remark" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_user" property="createUser" />
        <result column="update_user" property="updateUser" />
    </resultMap>
    <select id="listPage" resultType="com.ruoyi.stock.dto.StockOutRecordDto">
        SELECT
        sor.*,
        p.product_name as productName,
        pm.model,
        pm.unit,
        u.nick_name as createBy
        FROM stock_out_record as sor
        LEFT JOIN product_model as pm on sor.product_model_id = pm.id
        LEFT JOIN product as p on pm.product_id = p.id
        LEFT JOIN sys_user as u on sor.create_user = u.user_id
        <where>
            <if test="params.timeStr != null and params.timeStr != ''">
                and sor.create_time like concat('%',#{params.timeStr},'%')
            </if>
            <if test="params.productName != null and params.productName != ''">
                and p.product_name like concat('%',#{params.productName},'%')
            </if>
            <if test="params.type != null and params.type != ''">
                and sor.type = #{params.type}
            </if>
            <if test="params.recordType != null and params.recordType != ''">
                and sor.record_type = #{params.recordType}
            </if>
        </where>
        order by sor.id desc
    </select>
</mapper>
src/main/resources/mapper/stock/StockUninventoryMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
<?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.stock.mapper.StockUninventoryMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.stock.pojo.StockUninventory">
        <result column="id" property="id" />
        <result column="product_model_id" property="productModelId" />
        <result column="qualitity" property="qualitity" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="version" property="version" />
    </resultMap>
    <update id="updateSubtractStockUnInventory">
        update stock_inventory
        <set>
            <if test="ew.qualitity != null">
                qualitity = qualitity - #{ew.qualitity},
            </if>
            <if test="ew.version != null">
                version = version + 1,
            </if>
            <if test="ew.remark != null and ew.remark !=''">
                remark = #{ew.remark},
            </if>
            update_time = now()
        </set>
        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
    </update>
    <update id="updateAddStockUnInventory">
        update stock_inventory
        <set>
            <if test="ew.qualitity != null">
                qualitity = qualitity + #{ew.qualitity},
            </if>
            <if test="ew.version != null">
                version = version + 1,
            </if>
            <if test="ew.remark != null and ew.remark !=''">
                remark = #{ew.remark},
            </if>
            update_time = now()
        </set>
        where product_model_id = #{ew.productModelId}
    </update>
    <select id="pageStockUninventory" resultType="com.ruoyi.stock.dto.StockUninventoryDto">
        select su.*,
               pm.model,
               pm.unit,
               p.product_name
        from stock_uninventory su
                 left join product_model pm on su.product_model_id = pm.id
                 left join product p on pm.product_id = p.id
        where 1 = 1
        <if test="ew.productName != null and ew.productName !=''">
            and p.product_name like concat('%',#{ew.productName},'%')
        </if>
    </select>
</mapper>