当前位置: 首页 > news >正文

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

主要技术点

一、数据库

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集合中,然后取出数据做后续处理,比如存到数据库中@Overridepublic ImportResult excelImport(InputStream inputStream) {//解析Excel,转换成ListList<MaterialInputExcelModel> list = new ArrayList<>();try {EasyExcel.read(inputStream).head(MaterialInputExcelModel.class).sheet().registerReadListener(new AnalysisEventListener<MaterialInputExcelModel>() {@Overridepublic void invoke(MaterialInputExcelModel excelData, AnalysisContext analysisContext) {list.add(excelData); // 将解析好的每个对象放入到定义好的list中}@Overridepublic 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);//查询物料IDQueryWrapper<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());//查询仓库名称IDQueryWrapper<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());//假设一个userNamematerialInput.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);

http://www.mrgr.cn/news/65011.html

相关文章:

  • 算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
  • PHP手尖上shopro移动端商城系统小程序源码
  • 【时间之外】IT人求职和创业应知【26】
  • 上海亚商投顾:北证50指数跌9.61% 高位股大面积跌停
  • 基于vue3和elementPlus的el-tree组件,实现树结构穿梭框,支持数据回显和懒加载
  • 数据挖掘(六)
  • 11.1 网络编程-套接字
  • C语言-详细讲解-洛谷P1909 [NOIP2016 普及组] 买铅笔
  • 【数据结构】二叉树——层序遍历
  • Python Matplotlib 如何处理大数据集的绘制,提高绘图效率
  • 上尚优选项目
  • interrupt、interrupted、isInterrupted方法详解
  • WPF+MVVM案例实战(二十一)- 制作一个侧边弹窗栏(CD类)
  • LeetCode 0685.冗余连接 II:并查集(和I有何不同分析)——详细题解(附图)
  • Docker容器消耗资源过多导致宿主机死机解决方案
  • 发现不为人知的AI宝藏:深藏功与名! —— 《第十期》
  • js逆向-模拟加密
  • Linux的IP网路命令: 用于显示和操作网络接口(网络设备)的命令ip link详解
  • masm汇编字符串输出演示
  • ChatGPT 和 RAG(检索增强生成)的区别;ChatGPT 和 RAG 的联系
  • AIGC对传统内容创作行业的冲击
  • 【Linux】make/makefile/gdb调试技巧/进度条小程序
  • 无人机场景 - 目标检测数据集 - 夜间车辆检测数据集下载「包含VOC、COCO、YOLO三种格式」
  • 【蓝队技能】【溯源反制】反打红队-蜜罐工具反制
  • SpringBoot集成ELK收集日志管理
  • PyQt5入门级超详细教程中篇