ERP项目(进销存仓储管理系统)-1

时间:2024-11-04 16:59:33

主要技术点

一、数据库

1、用户权限

erp项目是给企业内部员工使用的,所以用户就是员工。有关用户权限的表有5张,包括三张主表和两张中间表。主表分别是角色表、用户表、权限表,中间表分别是角色-用户表、角色-权限表

2、表中数据的分级

主要是菜单分级(一般在erp项目中,菜单分级对应的就是权限分级)和部门分级,除了数据本身的id外,还有这条数据的父节点id(该字段一般命名为parent_id),也就是上层数据的id,根节点数据由于没有上级数据,所以其父节点为0。

二、根据数据库中的表自动生成实体类和mapper、service、serviceImpl、controller包及其类等文件

以前常用mybatisX插件来实现,现在发现另一种方式更便捷而且不易出错,就是用mybatisPlus的逆向工程。

1、引入mybatis-plus的增强依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>最新版本</version>
</dependency>

2、执行下面的代码

项目中随便写个类,里面定义个main方法,执行下面的代码即可

// 这些代码不用记,网上搜复制粘贴即可
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

public class Main {
    public static void main(String[] args) {
        AutoGenerator autoGenerator = new AutoGenerator();
        // 数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setPassword("123456");
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/store?useUnicode=true&characterEncoding=UTF-8");
        autoGenerator.setDataSource(dataSourceConfig);
        // 全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOpen(false);
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
        globalConfig.setAuthor("admin");
        globalConfig.setServiceName("%sService");
        autoGenerator.setGlobalConfig(globalConfig);
        // 包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.southwind");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setController("controller");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        autoGenerator.setPackageInfo(packageConfig);
        // 策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setEntityLombokModel(true);
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setInclude("role_authority","role_employee");// 要根据哪些表生成对应的实体类等文件
        autoGenerator.setStrategy(strategyConfig);

        autoGenerator.execute();
    }
}

三、解析excel文件

1、定义模型类

excel表中的每条数据都要解析成一个Java对象,所以要定义一个模型类使得解析excel表时按照这个模型类来解析成Java对象。

// 示例
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;

@Data
public class MaterialInputExcelModel {
    @ExcelProperty("供应商代码") // excel表的列名
    private String supplierCode; // 解析成对象对应的属性名
    @ExcelProperty("到货日期")
    private String orderDate;
    @ExcelProperty("仓库代码")
    private String storageCode;
    @ExcelProperty("物料编码")
    private String materialCode;
    @ExcelProperty("物料名称")
    private String materialName;
    @ExcelProperty("规格型号")
    private String style;
    @ExcelProperty("计量单位")
    private String unitName;
    @ExcelProperty("采购单号")
    private String orderId;
    @ExcelProperty("生产批号")
    private String batchNo;
    @ExcelProperty("数量")
    private BigDecimal orderCount;
}

2、解析逻辑

    // serviceImpl中解析excel表的逻辑
    // 就是将excel表中的每条数据解析成Java对象(上面定义的模型对象),将这些对象放入到list集合中,然后取出数据做后续处理,比如存到数据库中
    @Override
    public ImportResult excelImport(InputStream inputStream) {
        //解析Excel,转换成List
        List<MaterialInputExcelModel> list = new ArrayList<>();
        try {
            EasyExcel.read(inputStream)
                    .head(MaterialInputExcelModel.class)
                    .sheet()
                    .registerReadListener(new AnalysisEventListener<MaterialInputExcelModel>() {
                        @Override
                        public void invoke(MaterialInputExcelModel excelData, AnalysisContext analysisContext) {
                            list.add(excelData); // 将解析好的每个对象放入到定义好的list中
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

                        }
                    }).doRead();
        } catch (Exception e){
            e.getStackTrace();
        }
        // 解析完成,进行后续操作
        //把List数据存入数据库,持久化
        ImportResult importResult = new ImportResult();
        int row = 0;
        for (MaterialInputExcelModel materialInputExcelModel : list) {
            row++;
            MaterialInput materialInput = new MaterialInput();
            BeanUtils.copyProperties(materialInputExcelModel, materialInput);
            //查询物料ID
            QueryWrapper<Material> materialQueryWrapper = new QueryWrapper<>();
            materialQueryWrapper.eq("material_code", materialInput.getMaterialCode());
            Material material = this.materialMapper.selectOne(materialQueryWrapper);
            if(material == null){
                importResult.setCode(-1);
                importResult.setMsg("【第"+row+"行错误】,物料不存在!");
                return importResult;
            }
            materialInput.setMaterialId(material.getMaterialId());
            //查询供应商名称
            QueryWrapper<Supplier> supplierQueryWrapper = new QueryWrapper<>();
            supplierQueryWrapper.eq("supplier_code", materialInputExcelModel.getSupplierCode());
            Supplier supplier = this.supplierMapper.selectOne(supplierQueryWrapper);
            if(supplier == null) {
                importResult.setCode(-1);
                importResult.setMsg("【第"+row+"行错误】,供应商不存在!");
                return importResult;
            }
            materialInput.setSupplierId(supplier.getSupplierId());
            materialInput.setSupplierName(supplier.getSupplierName());
            //查询仓库名称ID
            QueryWrapper<Storage> storageQueryWrapper = new QueryWrapper<>();
            storageQueryWrapper.eq("storage_code", materialInputExcelModel.getStorageCode());
            Storage storage = this.storageMapper.selectOne(storageQueryWrapper);
            if(storage == null){
                importResult.setCode(-1);
                importResult.setMsg("【第"+row+"行错误】,仓库不存在!");
                return importResult;
            }
            materialInput.setStorageName(storage.getStorageName());
            materialInput.setStorageId(storage.getStorageId());
            //假设一个userName
            materialInput.setUserName("张三");
            materialInput.setStatus(0);
            //日期
            materialInput.setOrderDate(CommonUtils.parseString(materialInputExcelModel.getOrderDate()));
            //判断批号是否重复,如果不重复则保存,如果重复则覆盖
            QueryWrapper<MaterialInput> materialInputQueryWrapper = new QueryWrapper<>();
            materialInputQueryWrapper.eq("batch_no", materialInput.getBatchNo());
            MaterialInput materialInput1 = this.materialInputMapper.selectOne(materialInputQueryWrapper);
            if(materialInput1 != null){
                Integer materialInputId = materialInput1.getMaterialInputId();
                //判断订单状态,如果是未审核则进行覆盖
                if(materialInput1.getStatus().equals(0)){
                    //覆盖
                    BeanUtils.copyProperties(materialInput, materialInput1);
                    materialInput1.setMaterialInputId(materialInputId);
                    int updateById = this.materialInputMapper.updateById(materialInput1);
                    if(updateById != 1) {
                        importResult.setCode(-1);
                        importResult.setMsg("更新失败!");
                        return importResult;
                    }
                }
            } else {
                int insert = this.materialInputMapper.insert(materialInput);
                if(insert != 1) {
                    importResult.setCode(-1);
                    importResult.setMsg("保存失败!");
                    return importResult;
                }
            }
        }
        importResult.setCode(0);
        importResult.setMsg("导入成功!");
        return importResult;
    }

3、可能会遇到的问题:解析报错

报错信息
错误原因:excel表中的到货日期列中的数据是数字类型的,如2024/1/26,而模型类中对应的属性是LocalDateTime类型的,类型不匹配,导致解析错误。
解决办法:将模型类中对应的属性改成String类型即可,后续对其有逻辑处理再转换成日期类型。

四、字符串类型的时间数据转换成LocalDateTime类型的时间数据

如果字符串是这种"2024-08-26 10:30:56"年月日以短横线相隔的,直接用DateTimeFormatter转换即可。

String str = "2024-08-26 10:30:56"
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date = LocalDateTime.parse(str, dateTimeFormatter);

如果字符串是这种"2024/8/26"年月日以斜线相隔的,而且还没有时分秒,则要先将这个字符串改写成这种"2024-08-26 00:00:00"年月日以短横线相隔的,没有时分秒也要补上时分秒,然后再用DateTimeFormatter转换。

String string = "2024/8/26"
String[] split = string.split("/");
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < split.length; i++) {
    if(i < split.length - 1){
        if(split[i].length() == 1){
            stringBuffer.append("0").append(split[i]).append("-");
        } else {
            stringBuffer.append(split[i]).append("-");
        }
    } else {
        if(split[i].length() == 1){
            stringBuffer.append("0").append(split[i]);
        } else {
            stringBuffer.append(split[i]);
        }
    }
}
stringBuffer.append(" 00:00:00");
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date = LocalDateTime.parse(stringBuffer.toString(), dateTimeFormatter);