14de446d42a23f8823f56ef79214e0d0d634adaa..dee56ed8d52f1d8ee1f89b369561c49e9b3b7c2d
4 天以前 liyong
Merge remote-tracking branch 'origin/dev_New' into dev_New
dee56e 对比 | 目录
4 天以前 liyong
feat(stock):救急修改
44e649 对比 | 目录
4 天以前 maven
Merge remote-tracking branch 'origin/dev_New' into dev_New
2cf52f 对比 | 目录
4 天以前 maven
yys 发货管理修改
6f9031 对比 | 目录
4 天以前 liyong
feat(stock): 不合格库存导出
79cf09 对比 | 目录
4 天以前 liyong
feat(stock): 不合格库存导出
0c2d04 对比 | 目录
4 天以前 liyong
feat(stock): 不合格库存导出
fa696e 对比 | 目录
4 天以前 liyong
feat(stock): 不合格库存导出
1a3e9e 对比 | 目录
4 天以前 liyong
Merge remote-tracking branch 'origin/dev_New' into dev_New
8817c6 对比 | 目录
4 天以前 liyong
feat(stock): 添加库存出入库记录导出功能
7706e5 对比 | 目录
4 天以前 gongchunyi
Merge remote-tracking branch 'origin/dev_New' into dev_New
61fef8 对比 | 目录
4 天以前 gongchunyi
refactor: BOM产品结构保存与查看进行树形处理
0083c9 对比 | 目录
4 天以前 huminmin
增加参数
5db7e1 对比 | 目录
4 天以前 huminmin
修改方法名
a7410c 对比 | 目录
4 天以前 liyong
feat(stock): 库存导出接口开发
8ff828 对比 | 目录
4 天以前 liyong
feat(stock): 库存导出接口开发
5fda07 对比 | 目录
4 天以前 liyong
feat(stock): 库存导出接口开发
03c3c2 对比 | 目录
4 天以前 liyong
feat(stock): 库存导入接口开发
32b536 对比 | 目录
4 天以前 huminmin
将code 改成string
9cc951 对比 | 目录
4 天以前 maven
Merge remote-tracking branch 'origin/dev_New' into dev_New
ec3b3b 对比 | 目录
4 天以前 maven
yys 销售导入
9aec7c 对比 | 目录
4 天以前 yaowanxin
Merge remote-tracking branch 'origin/dev_New' into dev_New
a09143 对比 | 目录
4 天以前 yaowanxin
发货审批状态
bf8919 对比 | 目录
4 天以前 liyong
feat(stock): 库存枚举调整
12c10a 对比 | 目录
4 天以前 liyong
feat(stock): 实现质检库存管理和报废流程
4e45da 对比 | 目录
4 天以前 zss
bom删除把子集也删掉
296d05 对比 | 目录
4 天以前 liyong
feat(sales): 库存
e0afe7 对比 | 目录
4 天以前 chenhj
Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-ma...
481399 对比 | 目录
4 天以前 chenhj
枚举返回通用接口
6a7275 对比 | 目录
4 天以前 liyong
feat(sales): 库存
962dd2 对比 | 目录
4 天以前 liyong
feat(sales): dev
f6537d 对比 | 目录
4 天以前 liyong
feat(sales): dev
dc6762 对比 | 目录
4 天以前 liyong
Merge remote-tracking branch 'origin/dev_New' into dev_New
7e2abb 对比 | 目录
4 天以前 liyong
feat(sales): 库存
f2bcea 对比 | 目录
4 天以前 huminmin
修复出库查询
8cbb5f 对比 | 目录
4 天以前 liyong
feat(sales): 库存
278ee2 对比 | 目录
4 天以前 liyong
feat(sales): 库存
c7cf13 对比 | 目录
4 天以前 zss
Merge remote-tracking branch 'origin/dev_New' into dev_New
5a6ac2 对比 | 目录
4 天以前 zss
知识库导出的知识类型字段就用原本的字段值不需要转换
974a6c 对比 | 目录
4 天以前 liyong
Merge remote-tracking branch 'origin/dev_New' into dev_New
41b6d0 对比 | 目录
4 天以前 liyong
feat(sales): 库存
73ed05 对比 | 目录
4 天以前 zss
消息通知去掉租户id相关参数
394a0d 对比 | 目录
4 天以前 liyong
feat(sales): 不合格库存
d2d106 对比 | 目录
已添加19个文件
已修改57个文件
2109 ■■■■ 文件已修改
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 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | 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/mapper/ProductModelMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | 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/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/FileNameType.java 7 ●●●● 补丁 | 查看 | 原始文档 | 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 25 ●●●●● 补丁 | 查看 | 原始文档 | 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/DateUtils.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/EnumUtil.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductBomController.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductStructureDto.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductStructure.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java 152 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 14 ●●●● 补丁 | 查看 | 原始文档 | 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/service/impl/QualityInspectServiceImpl.java 131 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockInventoryController.java 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockUninventoryDto.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/execl/StockInRecordExportData.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockInRecordMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockOutRecordMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInventory.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockUninventory.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockInRecordService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockInventoryService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockOutRecordService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockUninventoryService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/ProductModelMapper.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/ShippingInfoMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInRecordMapper.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInventoryMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockOutRecordMapper.xml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockUninventoryMapper.xml 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/销售台账导入模板.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/CodeGenerator.java
@@ -19,11 +19,11 @@
// æ¼”示例子,执行 main æ–¹æ³•控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
    public static String database_url = "jdbc:mysql://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
@@ -22,8 +22,10 @@
import com.ruoyi.sales.mapper.CommonFileMapper;
import com.ruoyi.sales.mapper.SalesQuotationMapper;
import com.ruoyi.sales.mapper.SalesQuotationProductMapper;
import com.ruoyi.sales.mapper.ShippingInfoMapper;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.pojo.SalesQuotation;
import com.ruoyi.sales.pojo.ShippingInfo;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
@@ -60,6 +62,9 @@
    @Autowired
    private SalesQuotationMapper salesQuotationMapper;
    @Autowired
    private ShippingInfoMapper shippingInfoMapper;
@@ -176,8 +181,26 @@
            }else if(status.equals(1) && salesQuote != null){
                salesQuote.setStatus("审核中");
            }
            salesQuotationMapper.updateById(salesQuote);
        }
        // å‡ºåº“审批修改
        if(approveProcess.getApproveType().equals(7)){
            String[] split = approveProcess.getApproveReason().split(":");
            ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
                    .eq(ShippingInfo::getShippingNo, split[1])
                    .orderByDesc(ShippingInfo::getCreateTime)
                    .last("limit 1"));
            if(shippingInfo != null){
                if(status.equals(2)){
                    shippingInfo.setStatus("审核通过");
                }else if(status.equals(3)){
                    shippingInfo.setType("审核拒绝");
                }else if(status.equals(1)){
                    shippingInfo.setStatus("审核中");
                }
                shippingInfoMapper.updateById(shippingInfo);
            }
        }
        // ç»‘定附件
        if(!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1){
@@ -200,7 +223,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
@@ -127,7 +127,6 @@
        sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcessVO.getApproveType()),
                approveID + "流程编号的审批需要您审核!!!!!",
                Arrays.asList(Long.valueOf(id)),
                approveProcessVO.getApproveDeptId(),
                "/collaborativeApproval/approvalProcess?approveType=" + approveProcessVO.getApproveType() + "&approveId=" + approveID);
    }
@@ -239,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());
    }
@@ -298,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/mapper/ProductModelMapper.java
@@ -7,6 +7,9 @@
import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘Mapper接口
@@ -22,4 +25,5 @@
    ProductModel selectLatestRecord();
    List<Map<String, Object>> getProductAndModelList();
}
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/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/FileNameType.java
@@ -1,6 +1,5 @@
package com.ruoyi.common.enums;
import com.ruoyi.approve.pojo.ApproveProcess;
public enum FileNameType {
@@ -11,7 +10,11 @@
    MEASURING(5),  //计量器具台账
    MEASURINGRecord(6),//计量器具台账记录
    ApproveNode(7),  //协同审批节点审核
    ApproveProcess(8);  //协同审批主数据
    ApproveProcess(8),//协同审批主数据
    SHIP(9),//发货台账
    INSPECTION_PRODUCTION_BEFORE(10),
    INSPECTION_PRODUCTION_AFTER(11),
    INSPECTION(12);//巡检 ç”Ÿäº§å‰
    private final int value;
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,25 @@
package com.ruoyi.common.enums;
import lombok.Getter;
@Getter
public enum StockQualifiedRecordTypeEnum implements BaseEnum<String> {
    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 String code;
    private final String value;
    StockQualifiedRecordTypeEnum(String 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<String> {
    PRODUCTION_SCRAP("4", "生产报工-报废"),
    DEFECTIVE_SCRAP("5", "不合格处理-报废"),
    CUSTOMIZATION_UNSTOCK_IN("9", "不合格自定义入库"),
    CUSTOMIZATION_UNSTOCK_OUT("10", "不合格自定义出库"),
    QUALITYINSPECT_UNSTOCK_IN("12", "质检-不合格入库");
    private final String code;
    private final String value;
    StockUnQualifiedRecordTypeEnum(String 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/DateUtils.java
@@ -43,6 +43,15 @@
        return new Date();
    }
    public static LocalDate toLocalDate(Date date){
        if(date == null) return LocalDate.now();
        // 2. æŒ‡å®šå›ºå®šæ—¶åŒºè½¬æ¢ï¼ˆå¦‚东八区UTC+8、UTC零时区)
        return date.toInstant()
                .atZone(ZoneId.of("Asia/Shanghai")) // ä¸œå…«åŒºï¼ˆåŒ—京/上海时区)
                // .atZone(ZoneId.of("UTC")) // å¯é€‰ï¼šUTC零时区
                .toLocalDate();
    }
    /**
     * èŽ·å–å½“å‰æ—¥æœŸ, é»˜è®¤æ ¼å¼ä¸ºyyyy-MM-dd
     * 
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 (Integer.parseInt(String.valueOf(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 (Integer.parseInt(String.valueOf(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 (Integer.parseInt(String.valueOf(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/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java
@@ -137,4 +137,16 @@
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("单位")
    private String unit;
    @ApiModelProperty("部门id")
    private Long deptId;
    @ApiModelProperty("安装位置")
    private String instationLocation;
    private String cycle;
}
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, String 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, String 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, String 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, String 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,8 @@
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;
@@ -46,6 +40,9 @@
    @Autowired
    private ProductProcessRouteService productProcessRouteService;
    @Autowired
    private ProductStructureService productStructureService;
    @GetMapping("/listPage")
    @Log(title = "BOM-分页查询", businessType = BusinessType.OTHER)
@@ -81,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/dto/ProductStructureDto.java
@@ -1,22 +1,34 @@
package com.ruoyi.production.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.production.pojo.ProductStructure;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class ProductStructureDto extends ProductStructure {
    @ApiModelProperty(value = "工艺名称")
    private String processName;
    @ApiModelProperty(value = "产品名称")
    private String productName;
    @ApiModelProperty(value = "产品id")
    private Long productId;
    private String model;
    private List<ProductStructure> productStructureList;
    @TableField(exist = false)
    private String tempId;
    @TableField(exist = false)
    private String parentTempId;
    @TableField(exist = false)
    private List<ProductStructureDto> children;
}
src/main/java/com/ruoyi/production/pojo/ProductStructure.java
@@ -52,5 +52,8 @@
     */
    private Long bomId;
    /**
     * çˆ¶èŠ‚ç‚¹ID
     */
    private Long parentId;
}
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
@@ -1,19 +1,23 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.service.IProductModelService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.production.dto.ProductBomDto;
import com.ruoyi.production.dto.ProductProcessDto;
import com.ruoyi.production.pojo.ProductBom;
import com.ruoyi.production.mapper.ProductBomMapper;
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.mapper.ProductStructureMapper;
import com.ruoyi.production.pojo.ProductBom;
import com.ruoyi.production.pojo.ProductStructure;
import com.ruoyi.production.service.ProductBomService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
/**
 * <p>
@@ -29,12 +33,19 @@
    @Autowired
    private ProductBomMapper productBomMapper;
    @Autowired
    private IProductModelService productModelService;
    @Autowired
    private ProductStructureMapper productStructureMapper;
    @Override
    public IPage<ProductBomDto> listPage(Page page, ProductBomDto productBomDto) {
        return productBomMapper.listPage(page,productBomDto);
        return productBomMapper.listPage(page, productBomDto);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(ProductBom productBom) {
        boolean save = productBomMapper.insert(productBom) > 0;
        if (save) {
@@ -42,6 +53,26 @@
            String no = "BM." + String.format("%05d", productBom.getId());
            productBom.setBomNo(no);
            productBomMapper.updateById(productBom);
            //  æŸ¥è¯¢å‡ºäº§å“æ¨¡åž‹ä¿¡æ¯
            if (productBom.getProductModelId() == null) {
                throw new ServiceException("请选择产品模型");
            }
            ProductModel productModel = productModelService.getById(productBom.getProductModelId());
            if (productModel == null) {
                throw new ServiceException("选择的产品模型不存在");
            }
            //  æ·»åŠ åˆå§‹çš„äº§å“ç»“æž„
            ProductStructure productStructure = new ProductStructure();
            productStructure.setProductModelId(productBom.getProductModelId());
            productStructure.setUnit(productModel.getUnit());
            productStructure.setUnitQuantity(BigDecimal.valueOf(1));
            productStructure.setBomId(Long.valueOf(productBom.getId()));
            productStructureMapper.insert(productStructure);
            return AjaxResult.success();
        }
        return AjaxResult.error();
src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
@@ -1,51 +1,157 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.dto.ProductModelDto;
import com.ruoyi.basic.dto.ProductTreeDto;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.mapper.ProductBomMapper;
import com.ruoyi.production.mapper.ProductStructureMapper;
import com.ruoyi.production.pojo.ProductStructure;
import com.ruoyi.production.service.ProductStructureService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
@Service
public class ProductStructureServiceImpl extends ServiceImpl<ProductStructureMapper, ProductStructure> implements ProductStructureService {
    @Autowired
    private  ProductStructureMapper productStructureMapper;
    private ProductStructureMapper productStructureMapper;
    @Override
    public Boolean addProductStructureDto(ProductStructureDto productStructureDto) {
        this.remove(new QueryWrapper<ProductStructure>().lambda().eq(ProductStructure::getBomId, productStructureDto.getBomId()));
        productStructureDto.getProductStructureList().forEach(productStructure -> {
            productStructure.setBomId(productStructureDto.getBomId());
        });
        return this.saveBatch(productStructureDto.getProductStructureList());
    @Transactional
    public Boolean addProductStructureDto(ProductStructureDto dto) {
        Long bomId = dto.getBomId();
        //  å°†æ ‘扁平化
        List<ProductStructureDto> flatDtoList = new ArrayList<>();
        flattenTree(dto.getChildren(), flatDtoList);
        //  æŸ¥è¯¢æ•°æ®åº“中已有的 BOM æ•°æ®
        List<ProductStructure> dbList = this.list(new LambdaQueryWrapper<ProductStructure>().eq(ProductStructure::getBomId, bomId));
        //  æŸ¥æ‰¾å·²å­˜åœ¨çš„节点 - ID
        Set<Long> frontendIds = flatDtoList.stream()
                .map(ProductStructureDto::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        //  éœ€è¦åˆ é™¤çš„节点 - ID
        Set<Long> deleteIds = dbList.stream()
                .map(ProductStructure::getId)
                .filter(id -> !frontendIds.contains(id))
                .collect(Collectors.toSet());
        if (!deleteIds.isEmpty()) {
            this.removeByIds(deleteIds);
        }
        //  æ–°å¢ž / æ›´æ–°
        List<ProductStructure> insertList = new ArrayList<>();
        List<ProductStructure> updateList = new ArrayList<>();
        // ç”¨äºŽå›žå†™ parentId
        Map<String, ProductStructure> tempEntityMap = new HashMap<>();
        for (ProductStructureDto psDto : flatDtoList) {
            ProductStructure entity = new ProductStructure();
            BeanUtils.copyProperties(psDto, entity);
            entity.setBomId(bomId);
            if (psDto.getId() == null) {
                // æ–°å¢ž
                entity.setId(null);
                entity.setParentId(null);
                insertList.add(entity);
                tempEntityMap.put(psDto.getTempId(), entity);
            } else {
                // æ›´æ–°
                updateList.add(entity);
            }
        }
        //  æ’入新节点
        if (!insertList.isEmpty()) {
            this.saveBatch(insertList);
        }
        //  å›žå†™æ–°å¢žèŠ‚ç‚¹ parentId
        List<ProductStructure> parentFixList = new ArrayList<>();
        //  çœŸå®žçš„父节点 ID
        Long realParentId;
        for (ProductStructureDto psDto : flatDtoList) {
            if (psDto.getId() == null && psDto.getParentTempId() != null) {
                ProductStructure child = tempEntityMap.get(psDto.getTempId());
                if (tempEntityMap.containsKey(psDto.getParentTempId())) {
                    // çˆ¶èŠ‚ç‚¹æ˜¯æ–°èŠ‚ç‚¹
                    realParentId = tempEntityMap.get(psDto.getParentTempId()).getId();
                } else {
                    // çˆ¶èŠ‚ç‚¹æ˜¯è€èŠ‚ç‚¹
                    realParentId = Long.valueOf(psDto.getParentTempId());
                }
                child.setParentId(realParentId);
                parentFixList.add(child);
            }
        }
        if (!parentFixList.isEmpty()) {
            this.updateBatchById(parentFixList);
        }
        if (!updateList.isEmpty()) {
            this.updateBatchById(updateList);
        }
        return true;
    }
    /**
     * å°†å‰ç«¯ä¼ å…¥çš„æ ‘进行扁平化
     *
     * @param source æ•°æ®æ ‘
     * @param result æ‰å¹³åŒ–数据
     */
    private void flattenTree(List<ProductStructureDto> source, List<ProductStructureDto> result) {
        if (source == null) {
            return;
        }
        for (ProductStructureDto node : source) {
            result.add(node);
            flattenTree(node.getChildren(), result);
        }
    }
    @Override
    public List<ProductStructureDto> listBybomId(Long bomId) {
        List<ProductStructureDto> tree = productStructureMapper.listBybomId(bomId);
        return tree;
        List<ProductStructureDto> list = productStructureMapper.listBybomId(bomId);
        Map<Long, ProductStructureDto> map = new HashMap<>();
        for (ProductStructureDto node : list) {
            node.setChildren(new ArrayList<>());
            map.put(node.getId(), node);
        }
        List<ProductStructureDto> tree = new ArrayList<>();
        for (ProductStructureDto node : list) {
            Long parentId = node.getParentId();
            if (parentId == null || parentId == 0) {
                tree.add(node);
            } else {
                ProductStructureDto parent = map.get(parentId);
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        }
        return tree;
    }
}
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;
@@ -272,6 +267,9 @@
            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;
    }
@@ -318,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/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,96 +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
            if (ObjectUtils.isNull(qualityInspect.getProductMainId())){
                //如果是手动新增的出厂检
            }else {
                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);
@@ -188,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()));
@@ -239,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
@@ -7,21 +7,23 @@
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.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.QualityInspectMapper;
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;
@@ -33,8 +35,9 @@
@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;
@@ -42,16 +45,16 @@
    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, "不合格管理导出");
    }
@@ -64,7 +67,7 @@
            case "返修":
            case "返工":
                //判断质检表是否有相关的报工id,如果有报工id,那么返工需要重新创建生产订单重新生产
                if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())){
                if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())) {
                    //返工需要重新创建生产订单重新生产
                    ProductOrder productOrder = productionProductMainMapper.getOrderByMainId(qualityInspect.getProductMainId());
                    ProductOrder order = new ProductOrder();
@@ -76,7 +79,7 @@
                    order.setEndTime(null);
                    productOrderService.save(order);
                    //新增生产订单下的工艺路线主表
                    ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectList(Wrappers.<ProductProcessRoute>lambdaQuery().eq(ProductProcessRoute::getProductOrderId,productOrder.getId()).orderByDesc(ProductProcessRoute::getId)).get(0);
                    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);
@@ -125,9 +128,12 @@
                }
                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;
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -26,13 +26,19 @@
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -49,6 +55,7 @@
@RequestMapping("/sales/ledger")
@AllArgsConstructor
@Api(tags = "销售台账")
@Slf4j
public class SalesLedgerController extends BaseController {
    private ISalesLedgerService salesLedgerService;
@@ -76,6 +83,44 @@
        return salesLedgerService.importData(file);
    }
    @ApiOperation("导出销售台账模板")
    @PostMapping("/exportTemplate")
    public void exportTemplate(HttpServletResponse response) {
        // 1. æ¨¡æ¿æ–‡ä»¶åœ¨resources/static下的路径
        String templatePath = "static/销售台账导入模板.xlsx";
        // 2. èŽ·å–æ¨¡æ¿æ–‡ä»¶çš„è¾“å…¥æµ
        try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(templatePath)) {
            if (inputStream == null) {
                throw new FileNotFoundException("模板文件不存在:" + templatePath);
            }
            // 3. è®¾ç½®å“åº”头,触发浏览器下载
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("销售台账导入模板.xlsx", "utf-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            // 4. å°†æ¨¡æ¿æ–‡ä»¶å†™å…¥å“åº”输出流
            try (OutputStream outputStream = response.getOutputStream()) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, len);
                }
                outputStream.flush();
            }
        } catch (IOException e) {
            log.error("导出销售台账模板失败", e);
            // è‹¥æ¨¡æ¿æ–‡ä»¶è¯»å–失败,返回错误提示
            try {
                response.getWriter().write("模板导出失败:" + e.getMessage());
            } catch (IOException ex) {
                log.error("响应输出错误", ex);
            }
        }
    }
    /**
     * æŸ¥è¯¢é”€å”®å°è´¦åˆ—表
     */
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -86,14 +86,16 @@
//            procurementDto.setSalesLedgerProductId(item.getId());
//            procurementDto.setProductCategory(item.getProductCategory());
//            IPage<ProcurementPageDtoCopy> result = procurementRecordService.listPageCopyByProduction(new Page<>(1,-1), procurementDto);
            BigDecimal stockQuantity = stockUtils.getStockQuantity(item.getProductModelId()).get("stockQuantity");
            if(stockQuantity != null) {
//            BigDecimal stockQuantity = stockUtils.getStockQuantity(item.getProductModelId()).get("stockQuantity");
//                ProcurementPageDtoCopy procurementDtoCopy = result.getRecords().get(0);
                if (item.getQuantity().compareTo(stockQuantity) <= 0 && item.getApproveStatus() == 0) {
                    item.setApproveStatus(1);
                    salesLedgerProductService.addOrUpdateSalesLedgerProduct(item);
                if (item.getApproveStatus() != 2) {
                    if (item.getHasSufficientStock() == 0) {
                        item.setApproveStatus(0);
                    }else {
                        item.setApproveStatus(1);
                    }
                }
            }
        });
        return AjaxResult.success(list);
    }
src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -3,11 +3,20 @@
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.ruoyi.approve.mapper.ApproveProcessMapper;
import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
import com.ruoyi.approve.vo.ApproveProcessVO;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.service.impl.TempFileServiceImpl;
import com.ruoyi.sales.dto.ShippingInfoDto;
import com.ruoyi.sales.mapper.ShipmentApprovalMapper;
import com.ruoyi.sales.mapper.ShippingInfoMapper;
import com.ruoyi.sales.pojo.SalesLedger;
@@ -17,6 +26,7 @@
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.sales.service.ISalesLedgerService;
import com.ruoyi.sales.service.ShippingInfoService;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
@@ -25,6 +35,8 @@
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
/**
@@ -43,6 +55,15 @@
    @Autowired
    private ISalesLedgerProductService salesLedgerProductService;
    @Autowired
    private TempFileServiceImpl tempFileService;
    @Autowired
    private CommonFileServiceImpl commonFileService;
    @Autowired
    private ApproveProcessServiceImpl approveProcessService;
    @GetMapping("/listPage")
    @ApiOperation("发货信息列表")
@@ -54,45 +75,54 @@
    @PostMapping("/add")
    @ApiOperation("添加发货信息")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@RequestBody ShippingInfo req) {
        LambdaQueryWrapper<ShippingInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShippingInfo::getSalesLedgerId, req.getSalesLedgerId());
        wrapper.eq(ShippingInfo::getSalesLedgerProductId, req.getSalesLedgerProductId());
        List<ShippingInfo> list = shippingInfoService.list(wrapper);
        if(!CollectionUtils.isEmpty(list)){
            return AjaxResult.error("发货信息已存在");
        }
    @Log(title = "发货信息管理", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody ShippingInfoDto req) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String sh = OrderUtils.countTodayByCreateTime(shippingInfoMapper, "SH");
        // å‘货审批
        ApproveProcessVO approveProcessVO = new ApproveProcessVO();
        approveProcessVO.setApproveType(7);
        approveProcessVO.setApproveDeptId(loginUser.getTenantId());
        approveProcessVO.setApproveReason(req.getType() + ":" +sh);
        approveProcessVO.setApproveUserIds(req.getApproveUserIds());
        approveProcessVO.setApproveUser(loginUser.getUserId());
        approveProcessVO.setApproveTime(LocalDate.now().toString());
        approveProcessService.addApprove(approveProcessVO);
        // æ·»åŠ å‘è´§æ¶ˆæ¯
        req.setShippingNo(sh);
        req.setStatus("待审核");
        boolean save = shippingInfoService.save(req);
        if(save){
            ShippingInfo shippingInfo = shippingInfoService.getOne(wrapper);
            ShipmentApproval shipmentApproval = new ShipmentApproval();
            shipmentApproval.setSalesLedgerId(req.getSalesLedgerId());
            shipmentApproval.setSalesLedgerProductId(req.getSalesLedgerProductId());
            shipmentApproval.setApproveUserId(req.getApproverId());
            shipmentApproval.setApproveStatus(2);
            shipmentApproval.setShippingInfoId(shippingInfo.getId());
            shipmentApprovalMapper.insert(shipmentApproval);
            SalesLedgerProduct salesLedgerProduct = salesLedgerProductService.getById(req.getSalesLedgerProductId());
            if(salesLedgerProduct != null){
                salesLedgerProduct.setApproveStatus(2);
                salesLedgerProductService.updateById(salesLedgerProduct);
            }
        }
        return save ? AjaxResult.success() : AjaxResult.error();
    }
    @PostMapping("/update")
    @ApiOperation("修改发货信息")
    public AjaxResult update(@RequestBody ShippingInfo req) {
    @ApiOperation("发货扣库存")
    @PostMapping("/deductStock")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "发货信息管理", businessType = BusinessType.UPDATE)
    public AjaxResult deductStock(@RequestBody ShippingInfoDto req) throws IOException {
        ShippingInfo byId = shippingInfoService.getById(req.getId());
        if (byId == null) {
            return AjaxResult.error("发货信息不存在");
        }
        Long userId = getLoginUser().getUserId();
        if(!userId.equals(Long.parseLong(byId.getCreateUser().toString()))){
            return AjaxResult.error("您没有权限修改此发货信息");
        byId.setExpressNumber(req.getExpressNumber());
        byId.setExpressCompany(req.getExpressCompany());
        byId.setShippingCarNumber(req.getShippingCarNumber());
        boolean update = shippingInfoService.updateById(req);
        // è¿ç§»æ–‡ä»¶
        if(CollectionUtils.isNotEmpty(req.getTempFileIds())){
            tempFileService.migrateTempFilesToFormal(req.getId(), req.getTempFileIds(), FileNameType.SHIP.getValue());
        }
        return update ? AjaxResult.success() : AjaxResult.error();
    }
    @PostMapping("/update")
    @ApiOperation("修改发货信息")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "发货信息管理", businessType = BusinessType.UPDATE)
    public AjaxResult update(@RequestBody ShippingInfo req) {
        ShippingInfo byId = shippingInfoService.getById(req.getId());
        if (byId == null) {
            return AjaxResult.error("发货信息不存在");
        }
        boolean update = shippingInfoService.updateById(req);
        return update ? AjaxResult.success() : AjaxResult.error();
@@ -100,17 +130,10 @@
    @DeleteMapping("/delete")
    @ApiOperation("删除发货信息")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "发货信息管理", businessType = BusinessType.DELETE)
    public AjaxResult delete(@RequestBody List<Long> ids) {
        Long userId = getLoginUser().getUserId();
        ids.forEach(id -> {
            ShippingInfo byId = shippingInfoService.getById(id);
            if (byId == null) {
                throw new RuntimeException("发货信息不存在");
            }
            if(!userId.equals(Long.parseLong(byId.getCreateUser().toString()))){
                throw new RuntimeException("您没有权限删除此发货信息");
            }
        });
        commonFileService.deleteByBusinessIds(ids, FileNameType.SHIP.getValue());
        boolean delete = shippingInfoService.removeBatchByIds(ids);
        return delete ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
    }
src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
@@ -31,6 +31,8 @@
    private String salesman;
    @Excel(name = "客户名称")
    private String customerName;
    @Excel(name = "项目名称")
    private String projectName;
    @Excel(name = "录入人")
    private String entryPerson;
    @Excel(name = "备注")
@@ -44,5 +46,9 @@
    @Excel(name = "合同金额")
    private BigDecimal contractAmount;
    @ApiModelProperty(value = "付款方式")
    @Excel(name = "付款方式")
    private String paymentMethod;
}
src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.ruoyi.sales.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.pojo.ShippingInfo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author :yys
 * @date : 2026/1/23 16:35
 */
@Data
public class ShippingInfoDto extends ShippingInfo {
    /**
     * å®¡æ‰¹äººid列表
     */
    // å®¡æ‰¹äºº
    private String approveUserIds;
    private String type; // å‘货类型
    @TableField(exist = false)
    private List<String> tempFileIds;
    @TableField(exist = false)
    private List<CommonFile> commonFileList;
}
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -20,6 +20,8 @@
 * @date 2025-05-08
 */
public interface SalesLedgerProductMapper extends MyBaseMapper<SalesLedgerProduct> {
     List<SalesLedgerProduct> selectProduct() ;
    List<SalesLedgerProduct> selectSalesLedgerProductList(@Param("salesLedgerProduct") SalesLedgerProduct salesLedgerProduct);
    SalesLedgerProduct selectSalesLedgerProductByMainId(@Param("productMainId") Long productMainId);
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -200,14 +200,14 @@
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date shippingDate;
//    @TableField(exist = false)
//    @ApiModelProperty(value = "生产状态")
//    private String productionStatus = "未开始";
    @TableField(exist = false)
    @ApiModelProperty(value = "发货状态")
    private String shippingStatus;
    /**
     * å‘货审批状态
     * äº§å“çŠ¶æ€
     */
//    @TableField(exist = false)
    @ApiModelProperty(value = "审批状态:0未生产,1已生产,2已发货")
    @ApiModelProperty(value = "产品状态:1-充足")
    private Integer approveStatus;
    @ApiModelProperty(value = "待回款总金额")
@@ -224,4 +224,7 @@
    @ApiModelProperty(value = "是否质检")
    private Boolean isChecked;
    @TableField(exist = false)
    private Integer hasSufficientStock;
}
src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java
@@ -18,13 +18,6 @@
@TableName("shipping_info")
public class ShippingInfo {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "销售台账id")
    private Long salesLedgerId;
    @ApiModelProperty(value = "销售报价产品表id")
    private Long salesLedgerProductId;
    @TableField(exist = false)
    @ApiModelProperty(value = "销售合同号")
    @Excel(name = "销售合同号")
@@ -35,11 +28,40 @@
    @Excel(name = "客户名称")
    private String customerName;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "销售台账id")
    private Long salesLedgerId;
    @ApiModelProperty(value = "销售报价产品表id")
    private Long salesLedgerProductId;
    @ApiModelProperty(value = "状态")
    @Excel(name = "状态")
    private String status;
    @ApiModelProperty(value = "发货日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "发货日期", width = 30, dateFormat = "yyyy-MM-dd")
    private Date shippingDate;
    @ApiModelProperty(value = "发货编号")
    @Excel(name = "发货编号")
    private String shippingNo;
    @ApiModelProperty(value = "快递单号")
    @Excel(name = "快递单号")
    private String expressNumber;
    @ApiModelProperty(value = "快递公司")
    @Excel(name = "快递公司")
    private String expressCompany;
    @ApiModelProperty(value = "发货类型")
    @Excel(name = "发货类型")
    private String type;
    @ApiModelProperty(value = "发货车牌号")
    @Excel(name = "发货车牌号")
@@ -65,8 +87,5 @@
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty(value = "审批人id")
    @TableField(exist = false)
    private Integer approverId;
}
src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.sales.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.other.mapper.TempFileMapper;
@@ -39,6 +40,16 @@
    @Value("${file.upload-dir}")
    private String uploadDir;
    public void deleteByBusinessId(Long businessId,Integer type) {
        commonFileMapper.delete(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, businessId)
                .eq(CommonFile::getType, type));
    }
    public void deleteByBusinessIds(List<Long> businessId,Integer type) {
        commonFileMapper.delete(new LambdaQueryWrapper<CommonFile>().in(CommonFile::getCommonId, businessId)
                .eq(CommonFile::getType, type));
    }
    @Override
    public int deleteSalesLedgerByIds(Long[] ids) {
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -19,6 +19,7 @@
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -356,19 +357,21 @@
            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)));
            // è§„格型号数据
            List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>().in(ProductModel::getModel,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getSpecificationModel).toArray(String[]::new)));
            // äº§å“å¤§ç±»æ•°æ®
            List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getProductName,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getProductCategory).toArray(String[]::new)));
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).collect(Collectors.toList())));
//            // è§„格型号数据
//            List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>().in(ProductModel::getModel,
//                    salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getSpecificationModel).collect(Collectors.toList())));
//            // äº§å“å¤§ç±»æ•°æ®
//            List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getProductName,
//                    salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getProductCategory).collect(Collectors.toList())));
            List<Map<String,Object>> list = productModelMapper.getProductAndModelList();
            // å½•入人数据
            List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).toArray(String[]::new)));
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).collect(Collectors.toList())));
            for (SalesLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) {
                SalesLedger salesLedger = new SalesLedger();
                BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
                salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
                // é€šè¿‡å®¢æˆ·åç§°æŸ¥è¯¢å®¢æˆ·ID,客户合同号
                salesLedger.setCustomerId(customers.stream()
                        .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
@@ -404,25 +407,29 @@
                    salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
                    salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                    salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
                    salesLedgerProduct.setProductId(productList.stream()
                            .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
                    list.stream()
                            .filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel()))
                            .findFirst()
                            .map(Product::getId)
                            .orElse(null));
                    salesLedgerProduct.setProductModelId(productModels.stream()
                            .filter(productModel -> productModel.getModel().equals(salesLedgerProduct.getSpecificationModel()))
                            .findFirst()
                            .map(ProductModel::getId)
                            .orElse(null));
                            .ifPresent(map -> {
                                salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
                                salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
                            });
//                    salesLedgerProduct.setProductId(productList.stream()
//                            .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
//                            .findFirst()
//                            .map(Product::getId)
//                            .orElse(null));
//                    salesLedgerProduct.setProductModelId(productModels.stream()
//                            .filter(productModel -> productModel.getModel().equals(salesLedgerProduct.getSpecificationModel()))
//                            .findFirst()
//                            .map(ProductModel::getId)
//                            .orElse(null));
                    salesLedgerProduct.setRegister(loginUser.getNickName());
                    salesLedgerProduct.setRegisterDate(LocalDateTime.now());
                    salesLedgerProduct.setApproveStatus(0);
                    salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                }
            }
            return AjaxResult.success("导入成功");
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
@@ -6,6 +6,7 @@
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.dto.StockInventoryDto;
import com.ruoyi.stock.service.StockInRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -13,6 +14,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@@ -30,17 +32,7 @@
        return AjaxResult.success(result);
    }
    @PostMapping("")
    @Log(title = "入库管理-新增入库", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody StockInRecordDto stockInRecordDto) {
        return AjaxResult.success(stockInRecordService.add(stockInRecordDto));
    }
    @PutMapping("/{id}")
    @Log(title = "入库管理-更新入库", businessType = BusinessType.UPDATE)
    public AjaxResult update(@PathVariable("id") Long id, @RequestBody StockInRecordDto stockInRecordDto) {
        return AjaxResult.success(stockInRecordService.update(id, stockInRecordDto));
    }
    @DeleteMapping("")
    @Log(title = "入库管理-删除入库", businessType = BusinessType.DELETE)
@@ -51,4 +43,10 @@
        return AjaxResult.success(stockInRecordService.batchDelete(ids));
    }
    @PostMapping("/exportStockInRecord")
    @ApiOperation("导出入库记录")
    public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) {
        stockInRecordService.exportStockInRecord(response,stockInRecordDto);
    }
}
src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -2,17 +2,24 @@
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.utils.poi.ExcelUtil;
import com.ruoyi.compensationperformance.pojo.CompensationPerformance;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.execl.StockInventoryExportData;
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
@@ -39,14 +46,39 @@
    @PostMapping("/addstockInventory")
    @ApiOperation("新增库存")
    public R addstockInventory(StockInventoryDto stockInventoryDto) {
    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(StockInventoryDto stockInventoryDto) {
    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 stockInventoryService.importStockInventory(file);
    }
    @Log(title = "下载库存导入模板", businessType = BusinessType.EXPORT)
    @PostMapping("/downloadStockInventory")
    public void downloadStockInventory(HttpServletResponse response) {
        List<StockInventoryExportData> list = new ArrayList<>();
        ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
        util.exportExcel(response, list, "库存模板");
    }
    @PostMapping("/exportStockInventory")
    @ApiOperation("导出库存")
    public void exportStockInventory(HttpServletResponse response,StockInventoryDto stockInventoryDto) {
         stockInventoryService.exportStockInventory(response,stockInventoryDto);
    }
}
src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java
@@ -5,7 +5,9 @@
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.dto.StockOutRecordDto;
import com.ruoyi.stock.pojo.StockOutRecord;
import com.ruoyi.stock.service.StockOutRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -13,6 +15,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@@ -58,4 +61,11 @@
        }
        return AjaxResult.success(stockOutRecordService.batchDelete(ids));
    }
    @PostMapping("/exportStockOutRecord")
    @ApiOperation("导出出库记录")
    public void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto) {
        stockOutRecordService.exportStockOutRecord(response,stockOutRecordDto);
    }
}
src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
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.*;
import javax.servlet.http.HttpServletResponse;
/**
 * <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));
    }
    @PostMapping("/exportStockUninventory")
    @ApiOperation("导出库存")
    public void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto) {
        stockUninventoryService.exportStockUninventory(response,stockUninventoryDto);
    }
}
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/StockInRecordExportData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.ruoyi.stock.execl;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class StockInRecordExportData {
    @Excel(name = "入库批次")
    private String inboundBatches;
    @Excel(name = "产品名称")
    private String productName;
    @Excel(name = "规格型号")
    private String model;
    @Excel(name = "单位")
    private String unit;
    @Excel(name = "入库来源")
    private String recordType;
    @Excel(name = "入库数量")
    private String stockInNum;
    @Excel(name = "入库时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @Excel(isExport = false)
    private String type;
}
src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package com.ruoyi.stock.execl;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class StockInventoryExportData {
    @Excel(name = "产品名称")
    private String productName;
    @Excel(name = "规格")
    private String model;
    @Excel(name = "单位")
    private String unit;
    @Excel(name = "库存数量")
    private BigDecimal qualitity;
    @Excel(name = "备注")
    private String remark;
    @Excel(name = "最新更新时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
}
src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.ruoyi.stock.execl;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class StockOutRecordExportData {
    @Excel(name = "出库批次")
    private String outboundBatches;
    @Excel(name = "产品名称")
    private String productName;
    @Excel(name = "规格型号")
    private String model;
    @Excel(name = "单位")
    private String unit;
    @Excel(name = "出库来源")
    private String recordType;
    @Excel(name = "出库数量")
    private String stockInNum;
    @Excel(name = "出库时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @Excel(isExport = false)
    private String type;
}
src/main/java/com/ruoyi/stock/mapper/StockInRecordMapper.java
@@ -4,9 +4,14 @@
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.execl.StockInRecordExportData;
import com.ruoyi.stock.pojo.StockInRecord;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface StockInRecordMapper extends BaseMapper<StockInRecord> {
    IPage<StockInRecordDto> listPage(Page page, @Param("params") StockInRecordDto stockInRecordDto);
    List<StockInRecordExportData> listStockInRecordExportData(@Param("params") StockInRecordDto stockInRecordDto);
}
src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
@@ -3,10 +3,13 @@
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.execl.StockInventoryExportData;
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;
import java.util.List;
/**
 * <p>
@@ -25,4 +28,7 @@
    int updateAddStockInventory(@Param("ew") StockInventoryDto stockInventoryDto);
    int updateSubtractStockInventory(@Param("ew") StockInventoryDto stockInventoryDto);
    List<StockInventoryExportData> listStockInventoryExportData(@Param("ew") StockInventoryDto stockInventoryDto);
}
src/main/java/com/ruoyi/stock/mapper/StockOutRecordMapper.java
@@ -4,9 +4,12 @@
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.execl.StockOutRecordExportData;
import com.ruoyi.stock.pojo.StockOutRecord;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <p>
@@ -20,4 +23,6 @@
public interface StockOutRecordMapper extends BaseMapper<StockOutRecord> {
    IPage<StockOutRecordDto> listPage(Page page, @Param("params") StockOutRecordDto stockOutRecordDto);
    List<StockOutRecordExportData> listStockOutRecordExportData(@Param("params") StockOutRecordDto stockOutRecordDto);
}
src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
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.execl.StockInventoryExportData;
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;
import java.util.List;
/**
 * <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);
    List<StockInventoryExportData> listStockInventoryExportData(@Param("ew") StockUninventoryDto stockUninventoryDto);
}
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -28,10 +28,10 @@
    @ApiModelProperty(value = "入库数量")
    private BigDecimal stockInNum;
    @ApiModelProperty(value = "记录类型  é‡‡è´­å…¥åº“/生产入库/质量入库/自定义入库")
    @ApiModelProperty(value = "记录类型  æžšä¸¾")
    private String recordType;
    @ApiModelProperty(value = "记录ID  salesProductId/ProductrMainId/qualityInspectId/0")
    @ApiModelProperty(value = "记录ID  ")
    private Long recordId;
    @ApiModelProperty(value = "产品规格ID")
src/main/java/com/ruoyi/stock/pojo/StockInventory.java
@@ -62,4 +62,7 @@
    @ApiModelProperty("预警数量")
    private Integer warnNum;
    @ApiModelProperty("备注")
    private String remark;
}
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
@@ -6,6 +6,7 @@
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.pojo.StockInRecord;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
public interface StockInRecordService extends IService<StockInRecord> {
@@ -16,4 +17,6 @@
    int update(Long id, StockInRecordDto stockInRecordDto);
    int batchDelete(List<Long> ids);
    void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto);
}
src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -6,6 +6,9 @@
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;
import javax.servlet.http.HttpServletResponse;
/**
 * <p>
@@ -22,4 +25,8 @@
    Boolean addstockInventory(StockInventoryDto stockInventoryDto);
    Boolean subtractStockInventory(StockInventoryDto stockInventoryDto);
    R importStockInventory(MultipartFile file);
    void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto);
}
src/main/java/com/ruoyi/stock/service/StockOutRecordService.java
@@ -6,6 +6,7 @@
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.pojo.StockOutRecord;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@@ -24,4 +25,6 @@
    int update(Long id, StockOutRecordDto stockOutRecordDto);
    int batchDelete(List<Long> ids);
    void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto);
}
src/main/java/com/ruoyi/stock/service/StockUninventoryService.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.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.pojo.StockUninventory;
import com.baomidou.mybatisplus.extension.service.IService;
import javax.servlet.http.HttpServletResponse;
/**
 * <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);
    void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto);
}
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -4,29 +4,41 @@
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.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
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.execl.StockInRecordExportData;
import com.ruoyi.stock.execl.StockInventoryExportData;
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 javax.servlet.http.HttpServletResponse;
import java.util.List;
@Service
@AllArgsConstructor
public class StockInRecordServiceImpl extends ServiceImpl<StockInRecordMapper, StockInRecord> implements StockInRecordService {
    @Autowired
    private StockInRecordMapper stockInRecordMapper;
    @Autowired
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    @Override
    public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) {
@@ -63,16 +75,42 @@
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
            StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, id));
            if (stockInventory == null) {
                throw new BaseException("该入库记录下没有对应的产品,无法删除!!!");
            }else {
                StockInventoryDto stockInRecordDto = new StockInventoryDto();
                stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                stockInRecordDto.setQualitity(stockInRecord.getStockInNum());
                stockInventoryMapper.updateSubtractStockInventory(stockInRecordDto);
            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);
    }
    @Override
    public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) {
        List<StockInRecordExportData> list = stockInRecordMapper.listStockInRecordExportData(stockInRecordDto);
        for (StockInRecordExportData stockInRecordExportData : list) {
            if (stockInRecordExportData.getType().equals("0")) {
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
            }else {
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockUnQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
            }
        }
        ExcelUtil<StockInRecordExportData> util = new ExcelUtil<>(StockInRecordExportData.class);
        util.exportExcel(response,list, "入库记录信息");
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -4,20 +4,29 @@
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.account.pojo.BorrowInfo;
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.execl.StockInventoryExportData;
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 org.springframework.beans.factory.annotation.Autowired;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
 * <p>
@@ -28,16 +37,13 @@
 * @since 2026-01-21 04:16:36
 */
@Service
@AllArgsConstructor
public class StockInventoryServiceImpl extends ServiceImpl<StockInventoryMapper, StockInventory> implements StockInventoryService {
    @Autowired
    private  StockInventoryMapper stockInventoryMapper;
    @Autowired
    private StockInRecordService stockInRecordService;
    @Autowired
    private StockOutRecordService stockOutRecordService;
    private SalesLedgerProductMapper salesLedgerProductMapper;
    @Override
    public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
        return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
@@ -53,6 +59,7 @@
        stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
        stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockInRecordDto.setType("0");
        stockInRecordService.add(stockInRecordDto);
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
@@ -62,6 +69,7 @@
            newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
            newStockInventory.setQualitity(stockInventoryDto.getQualitity());
            newStockInventory.setVersion(1);
            newStockInventory.setRemark(stockInventoryDto.getRemark());
            stockInventoryMapper.insert(newStockInventory);
        }else {
             stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
@@ -79,6 +87,7 @@
        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)) {
@@ -88,4 +97,42 @@
        }
        return true;
    }
    @Override
    public R importStockInventory(MultipartFile file) {
        try {
            final StringBuffer[] errorMsg = {new StringBuffer()};
            //查询所有的产品
            List<SalesLedgerProduct> salesLedgerProducts =salesLedgerProductMapper.selectProduct();
            ExcelUtil<StockInventoryExportData> util = new ExcelUtil<StockInventoryExportData>(StockInventoryExportData.class);
            List<StockInventoryExportData> list = util.importExcel(file.getInputStream());
            list.stream().forEach(dto -> {
                salesLedgerProducts.stream().forEach(item->{
                    if (item.getProductCategory().equals(dto.getProductName())&&item.getSpecificationModel().equals(dto.getModel())) {
                            //更新库存
                        StockInventoryDto stockInventoryDto = new StockInventoryDto();
                        stockInventoryDto.setRecordId(0L);
                        stockInventoryDto.setRecordType(StockQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode());
                        stockInventoryDto.setQualitity(dto.getQualitity());
                        stockInventoryDto.setProductModelId(item.getProductModelId());
                        this.addstockInventory(stockInventoryDto);                    }else {
                        errorMsg[0] = errorMsg[0].append("产品名称:"+dto.getProductName()+"规格:"+dto.getModel()+"不存在").append("\n");
                    }
                });
            });
            return R.ok(errorMsg[0]);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }
    @Override
    public void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto) {
        List<StockInventoryExportData> list = stockInventoryMapper.listStockInventoryExportData(stockInventoryDto);
        ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
        util.exportExcel(response,list, "库存信息");
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -4,20 +4,31 @@
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.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.execl.StockInRecordExportData;
import com.ruoyi.stock.execl.StockOutRecordExportData;
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 javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@@ -29,11 +40,11 @@
 * @since 2026-01-21 05:27:04
 */
@Service
@AllArgsConstructor
public class StockOutRecordServiceImpl extends ServiceImpl<StockOutRecordMapper, StockOutRecord> implements StockOutRecordService {
    @Autowired
    private StockOutRecordMapper stockOutRecordMapper;
    @Autowired
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    @Override
    public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
@@ -66,16 +77,42 @@
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
            StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, id));
            if (stockInventory == null) {
                throw new BaseException("该入库记录下没有对应的产品,无法删除!!!");
            }else {
                StockInventoryDto stockInRecordDto = new StockInventoryDto();
                stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                stockInRecordDto.setQualitity(stockOutRecord.getStockOutNum());
                stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
            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);
    }
    @Override
    public void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto) {
        List<StockOutRecordExportData> list = stockOutRecordMapper.listStockOutRecordExportData(stockOutRecordDto);
        for (StockOutRecordExportData stockInRecordExportData : list) {
            if (stockInRecordExportData.getType().equals("0")) {
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
            }else {
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockUnQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
            }
        }
        ExcelUtil<StockOutRecordExportData> util = new ExcelUtil<>(StockOutRecordExportData.class);
        util.exportExcel(response,list, "出库记录信息");
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
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.common.utils.poi.ExcelUtil;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.execl.StockInventoryExportData;
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;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
 * <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;
    }
    @Override
    public void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto) {
        List<StockInventoryExportData> list = stockUninventoryMapper.listStockInventoryExportData(stockUninventoryDto);
        ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
        util.exportExcel(response,list, "不合格库存信息");
    }
}
src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -97,5 +97,14 @@
        ORDER BY pm.id DESC
    </select>
    <select id="getProductAndModelList" resultType="java.util.Map">
        select p.id as id,
               pm.id as modelId,
               p.product_name as productName ,
               pm.model as  model
        from product_model pm
        left join product p on p.id = pm.product_id
        order by p.id,pm.id desc
    </select>
</mapper>
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml
@@ -22,7 +22,11 @@
        create_time,
        update_user,
        update_time,
        tenant_id
        tenant_id,
        unit,
        dept_id,
        instation_location,
        cycle
        FROM
        measuring_instrument_ledger
        <where>
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -8,10 +8,17 @@
        SELECT
        T1.*,
        t3.shipping_car_number,
        t3.shipping_date
        t3.shipping_date,
        t3.status as shippingStatus
        t3.shipping_date,
        CASE
        WHEN t2.qualitity > T1.quantity THEN 1
        ELSE 0
        END as has_sufficient_stock
        FROM
        sales_ledger_product T1
        left join shipping_info t3 on T1.id = t3.sales_ledger_product_id
        LEFT JOIN stock_inventory t2 ON T1.product_model_id = t2.product_model_id
        LEFT JOIN shipping_info t3 ON T1.id = t3.sales_ledger_product_id
        <where>
            1=1
            <if test="salesLedgerProduct.salesLedgerId != null and salesLedgerProduct.salesLedgerId != '' ">
@@ -147,4 +154,12 @@
              WHERE sl.id = #{salesLedegerId}) A
        group by a.model, a.product_name, a.unit
    </select>
    <select id="selectProduct" resultType="com.ruoyi.sales.pojo.SalesLedgerProduct">
        select
            p.product_name as product_category,
            pm.model as specification_model,
            pm.id
        from product_model pm
        left join product p on pm.product_id = p.id
    </select>
</mapper>
src/main/resources/mapper/sales/ShippingInfoMapper.xml
@@ -8,6 +8,11 @@
        s.sales_ledger_id,
        s.shipping_date,
        s.shipping_car_number,
        s.express_number,
        s.express_company,
        s.shipping_no,
        s.type,
        s.status,
        s.create_time,
        s.update_time,
        s.create_user,
src/main/resources/mapper/stock/StockInRecordMapper.xml
@@ -5,7 +5,7 @@
    <select id="listPage" resultType="com.ruoyi.stock.dto.StockInRecordDto">
        SELECT
        sir.*,
        p.product_name as productName,
        p.product_name as product_name,
        pm.model,
        pm.unit,
        u.nick_name as createBy
@@ -20,6 +20,39 @@
            <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>
    <select id="listStockInRecordExportData" resultType="com.ruoyi.stock.execl.StockInRecordExportData">
        SELECT
        sir.*,
        p.product_name as product_name,
        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>
src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -22,6 +22,10 @@
           <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>
@@ -34,6 +38,10 @@
            <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>
@@ -50,5 +58,20 @@
            and p.product_name like concat('%',#{ew.productName},'%')
        </if>
    </select>
    <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData">
        select si.qualitity,
        pm.model,
        pm.unit,
        p.product_name,
        si.remark,
        si.update_time
        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
@@ -30,10 +30,43 @@
        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('%',#{param.timeStr},'%')
                and sor.create_time like concat('%',#{params.timeStr},'%')
            </if>
            <if test="params.productName != null and params.productName != ''">
                and p.product_name like concat('%',#{param.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>
    <select id="listStockOutRecordExportData" resultType="com.ruoyi.stock.execl.StockOutRecordExportData">
        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
src/main/resources/mapper/stock/StockUninventoryMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
<?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>
    <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData">
        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>
src/main/resources/static/ÏúÊŲ̂Õ˵¼ÈëÄ£°å.xlsx
Binary files differ