中东建材城销售项目完结总结

2023-10-31 15:50

本文主要是介绍中东建材城销售项目完结总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

业务简介

采购单的流程

1.根据需求部门提出采购申请表
2.采购员找供应商,询问价格,入库时间
3.根据获得的价格多少,找审核部门领导审核,审核通过,等待财务拨款,向供应商订货
4.供应商开始准备商品,产生一张发货单
5.准备采购入库单

库存模块

采购入库单(+),销售出库单(-),退货单,换货单,调货单,报损报溢,盘点单

一.框架搭建

通过使用 Spring,SpringMVC,SpringDataJPA 进行框架搭建,页面用 EasyUI 来显示。

Spring+SpringDataJPA集成和配置

<!--引入jdbc.properties文件--><context:property-placeholder location="classpath:jdbc.properties" /><!--配置DataSource--><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!--LocalContainerEntityManagerFactoryBean:就是一个FactoryBean对象,返回EntityManagerFactory对象给我们集成JPA:就是把EntityManagerFactory给它搞出来四大金刚,方言,建表策略,显示SQLAlt+Ins--><bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><!--配置连接信息--><property name="dataSource" ref="dataSource"/><!--配置包的扫描(Scan),认识JPA的注解 --><property name="packagesToScan" value="cn.cyj.domain" /><!--配置适配器 Spring+JPA(ORM规范) -> 到底用的是哪一个框架来完成的JPA是有很多实现(Hibernate,OpenJPA,...)--><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><!--方言(确定数据库)--><property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /><!--建表策略  true:update  false:什么都不做--><property name="generateDdl" value="false" /><!--支持SQL显示--><property name="showSql" value="true" /></bean></property></bean>

Spring+SpringMVC集成和配置

    <!-- 扫描controller部分的包 --><!-- @Component组件, @Repository持久层, @Service业务逻辑层, and @Controller控制器 --><context:component-scan base-package="cn.cyj.controller" /><!-- 添加mvc对@RequestMapping等注解的支持 --><mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><property name="supportedMediaTypes"><list><value>application/json; charset=UTF-8</value><value>application/x-www-form-urlencoded; charset=UTF-8</value></list></property><!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 --><property name="objectMapper"><bean class="cn.cyj.common.CustomMapper"></bean></property></bean></mvc:message-converters></mvc:annotation-driven><!--静态资源放行--><mvc:default-servlet-handler /><!-- ViewResolver 视图解析器 (struts2视图类型类似) --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- 设置视图路径的前后缀,该配置可以让我们写视图路径的时候更简单。 --><!-- 希望跳转jsp是[/WEB-INF/views/前缀][xxx变量][.jsp后缀] --><!-- * @see #setPrefix --><property name="prefix" value="/WEB-INF/views/" /><!-- * @see #setSuffix --><property name="suffix" value=".jsp" /></bean><!-- 错误:提示告诉开发者你没有配置文件上传解析器。 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 设置上传文件的最大尺寸为1MB --><property name="maxUploadSize"><value>1048576</value></property></bean>

通过不同的层级实现基本的CRUD:
1.Controller层,是对前端或者接口的响应一个逻辑处理的层,这个层级一般调用的是Service层。这个层级调用java代码实现的。
2.Service层,是对Controller的功能的响应一个逻辑处理的层,是对后台的有关联的逻辑的一个处理。这个层级一般调用的是Service层和Dao层,这个层级调用java代码实现的。
3.Repository层,封装了DAO,还有一些装配工作,把数据装配成一个完整的对象。
4.Common层,通用工具层,把项目中通用的功能放在这里。
5. Query层,把前台传过来的参数,进行封装。

在Repository层,Service层,Qurey层我们把相同的方法抽一个父类,方便再后期修改。

SpringDataJPA 功能虽然已经非常强大,但是它依然满足不了咱们的需要,在很多时候,我们需要自己去对SpringDataJpa的功能进行相应的扩展(即:自定义 Repository )。

1.直接创建BaseRepository来继承JpaRepository接口

@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T>{//根据Query拿到分页对象(分页)Page findPageByQuery(BaseQuery baseQuery);//根据Query拿到对应的所有数据(不分页)List<T> findByQuery(BaseQuery baseQuery);//根据jpql与对应的参数拿到数据List findByJpql(String jpql,Object... values);
}
  1. BaseRepositoryImpl功能实现
    定义好自定义的方法后,我们现在通过一个基本的Repository类来实现该方法:
    首先添加BaseRepositoryImpl类,继承SimpleJpaRepository类,使其拥有Jpa Repository的基本方法。
    我们发现Repository有两个构造函数:
    SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager)
    SimpleJpaRepository(Class domainClass, EntityManager em)
    这里我们实现第二个构造函数,拿到domainClassEntityManager两个对象。
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {private final EntityManager entityManager;//必需要实现父类的这个构造器public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {super(domainClass, em);this.entityManager = em;}@Overridepublic Page findPageByQuery(BaseQuery baseQuery) {//第一步:拿到所有高级查询条件Specification spec = baseQuery.createSpecification();//第二步:拿到排序的值Sort sort = baseQuery.createSort();//第三步:根据条件查询分页数据并且返回Pageable pageable = new PageRequest(baseQuery.getJpaPage(), baseQuery.getPageSize(),sort);Page<T> page = super.findAll(spec, pageable);return page;}@Overridepublic List<T> findByQuery(BaseQuery baseQuery) {//第一步:拿到所有高级查询条件Specification spec = baseQuery.createSpecification();//第二步:拿到排序的值Sort sort = baseQuery.createSort();//第三步:拿到数据返回return findAll(spec, sort);}@Overridepublic List findByJpql(String jpql, Object... values) {//第一步:创建Query对象Query query = entityManager.createQuery(jpql);//第二步:把值设置到Query对象中去if (values!=null) {for (int i = 0; i < values.length; i++) {query.setParameter(i + 1, values[i]);}}//第三步:返回数据return query.getResultList();}
}
  1. 创建自定义创建自定义RepositoryFactoryBean
    接下来我们来创建一个自定义的RepositoryFactoryBean来代替默认的RepositoryFactoryBean
    RepositoryFactoryBean负责返回一个RepositoryFactorySpring Data Jpa 将使用RepositoryFactory来创建Repository具体实现,这里我们用BaseRepositoryImpl代替SimpleJpaRepository作为Repository接口的实现。这样我们就能够达到为所有Repository添加自定义方法的目的。
    我们需要覆写创建RepositoryFactory的方法:createRepositoryFactory
public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {@Overrideprotected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {return new MyRepositoryFactory<T,ID>(entityManager); //注:这里创建是我们的自定义类}//继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现private static  class MyRepositoryFactory<T,ID extends Serializable>   extends JpaRepositoryFactory{private final EntityManager entityManager;/*** Creates a new {@link JpaRepositoryFactory}.** @param entityManager must not be {@literal null}*/public MyRepositoryFactory(EntityManager entityManager) {super(entityManager);this.entityManager = entityManager;}//这里返回最后的功能对象@Overrideprotected Object getTargetRepository(RepositoryInformation information) {return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);}//确定功能对象的类型@Overrideprotected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {return BaseRepositoryImpl.class;}}
}
  1. applicationContext.xml 中修改配置
<!--用SpringDataJpa的方案去扫描它只要发现接口继承了JpaRepository接口,就自动完成CRUD以及分页等功能--><jpa:repositories base-package="cn.cyj.repository"entity-manager-factory-ref="entityManagerFactory"transaction-manager-ref="transactionManager"factory-class="cn.cyj.repository.BaseRepositoryFactoryBean"/>

在完成修改的时候,发现在修改完成后,密码不见了,于是我们做了以下修改:

var itsource={//保存数据save:function () {var url  = "/employee/save";var id = $("#employeeId").val();if(id){url = "/employee/update?cmd=update";}employeeForm.form('submit', {url:url,onSubmit: function(){//做验证return $("#employeeForm").form("validate");},success:function(data){$('#employeeGrid').datagrid('reload');employeeDialog.dialog('close');}})}
}
/*** 特性:在执行相应方法之前都会先执行这个方法*/
@ModelAttribute("editEmployee")
public Employee beforeEdit(Long id, String cmd){//有id的时候-> 修改功能if(id!=null && "update".equals(cmd)) {Employee employee = employeeService.findOne(id); return employee;}return null;
}
@RequestMapping("/save")
@ResponseBody
public Map<String,Object> save(Employee employee){return saveOrUpdate(employee);
}
@RequestMapping("/update")
@ResponseBody
public Map<String,Object> update(@ModelAttribute("editEmployee")Employee employee){return saveOrUpdate(employee);}

部门修改的n-to-n

@ModelAttribute("editEmployee")
public Employee beforeEdit(Long id, String cmd){//有id的时候-> 修改功能if(id!=null && "update".equals(cmd)) {Employee employee = employeeService.findOne(id);//把这个要修改的关联对象设置为null,可以解决n-to-n的问题employee.setDepartment(null);return employee;}return null;
}

因为表单多,为避免过多的重复代码,我们基本功能CRUD,通过代码生成器生成–>EasyCode

目前市面上主流模板技术 velocity 和 freemarker

二.权限模块

权限

Apache Shiro是一个强大且易用的Java安全框架,有身份验证授权密码学会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
Spring security 重量级安全框架
Apache Shiro轻量级安全框架

导入Jar

<!-- shiro的支持包 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-all</artifactId><version>1.4.0</version><type>pom</type>
</dependency><!-- shiro与Spring的集成包 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency>

自定义Realm一般直接继承AuthorizingRealm接口即可(里面包含身份认证授权两个方法)

/*** 自定义一个Realm*/
public class MyRealm extends AuthorizingRealm {//获取到这个Realm的名称(随便取)@Overridepublic String getName() {return "MyRealm";}//进行授权判断(权限)@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}//进行身份认证(登录)@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {return null;}
}

web.xml中配置

<!-- Spring与shiro集成:需要定义一个shiro过滤器(这是一个代理过滤器,它会到spring的配置中找一个名称相同的真实过滤器) -->
<filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><init-param><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

Spring+Shiro配置

  <!-- securityManager:Spring创建核心对象 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"></bean><!-- 建议大家把它留着,它可以支持我们做注解权限判断 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"depends-on="lifecycleBeanPostProcessor"/><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/></bean><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><!--如果你没有登录,就会进入这个页面--><property name="loginUrl" value="/login"/><!--如果登录成功,就会进入这个页面--><property name="successUrl" value="/s/main.jsp"/><!--如果没有权限,就会进入这个页面--><property name="unauthorizedUrl" value="/s/unauthorized.jsp"/><property name="filterChainDefinitions"><value>/s/login.jsp = anon/** = authc</value></property></bean>

加密认证

  <bean id="aiSellRealm" class="cn.cyj.shiro.AiSellRealm"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="MD5"/><property name="hashIterations" value="10" /></bean></property></bean>

菜单

用户拥有对应的权限就拥有对应的菜单(二级菜单),如果此菜单有父菜单(一级菜单)也同时拥有

@Override
public List<Menu> findByLoginUser(Long userId) {//准备父菜单容器List<Menu> parentMenus = new ArrayList<>();//从数据库中拿到子菜单List<Menu> childrenMenus = menuRepository.findByLoginUser(userId);//遍历子菜单(如果有父菜单放进入,没有单独创建)for (Menu childrenMenu : childrenMenus) {//拿到子菜单对应的父菜单Menu parent = childrenMenu.getParent();//判断如果父菜单中是否有这个菜单if(parentMenus.contains(parent)){//有的话,咱们就把子菜单放到父菜单中去int i = parentMenus.indexOf(parent);Menu parentMenu = parentMenus.get(i);parentMenu.getChildren().add(childrenMenu);}else{//如果没有,再单独把父菜单放进去parentMenus.add(parent);parent.getChildren().add(childrenMenu);}}return parentMenus;
}

业务模块

导入导出

jxl:只能对Excel进行操作,属于比较老的框架。
POI:是apache的项目,可对ms的word,Excel,PPT进行操作,包括office2003和2007。
在这我们使用EasyPOI

采购订单

在这里插入图片描述

组合关系映射配置要求

  1. 整体和部分,整体和部分不能分割,本质还是双向一对多
  2. 一方(主表):
@OneToMany(cascade = CascadeType.ALL, mappedBy = "bill", fetch = FetchType.LAZY, orphanRemoval = true)
private List<purchasebillitem> items = new ArrayList<purchasebillitem>();
cascade = CascadeType.ALL级联操作最全
mappedBy = "bill"一方放弃管理多方,多方的外键字段bill_id,一方不管
orphanRemoval = true如果在一方解除了和多方的关系,一方是可以删除掉多方
  1. 多方(从表)billitem:bill_id配置为非空
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "bill_id")
private Purchasebill bill;// 组合关系,非空
  1. 页面管理:一方和多方同时管理

报表

在domain层下面新建vo层:

public class PurchasebillitemVO {//编号private Long id;//供应商名称private String supplierName;//采购员名称private String buyerNmae;//产品名称private String productNmae;//产品图片private String productImages;//产品分类private String productType;//交易时间private Date vdate;//采购数量private BigDecimal num;//价格private BigDecimal price;//小计private BigDecimal amount;//状态private Integer status = 0;...
}

解决分组的问题,根据前台的传参使用不同的分组方案

 public PurchasebillitemVO(Purchasebillitem item, PurchasebillitemQuery query) {this.id = item.getId();this.supplierName = item.getBill().getSupplier().getName();this.buyerNmae = item.getBill().getBuyer().getUsername();this.productNmae = item.getProduct().getName();this.productImages = item.getProduct().getPic();this.productType = item.getProduct().getProducttype().getName();this.vdate = item.getBill().getVdate();this.num = item.getNum();this.price = item.getPrice();this.amount = item.getAmount();this.status = item.getBill().getStatus();switch (query.getGroupField()){case 1:this.groupField = this.supplierName;break;case 2:this.groupField = this.productNmae;break;case 3:this.groupField = this.buyerNmae;break;case 4:Calendar calendar = Calendar.getInstance();calendar.setTime(vdate);this.groupField = (calendar.get(Calendar.MONTH)+1) + "月";break;default:this.groupField = this.supplierName;break;}}

图形报表

效果更佳直接
使用HighChart 完成

这篇关于中东建材城销售项目完结总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/316440

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

用Microsoft.Extensions.Hosting 管理WPF项目.

首先引入必要的包: <ItemGroup><PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /><PackageReference Include="Serilog

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

Java注解详细总结

什么是注解?         Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序。         注解不光可以用在方法上,还可以用在类上、变量上、构造器上等位置。 自定义注解  现在我们自定义一个MyTest注解 public @interface MyTest{String aaa();boolean bbb()

tensorboard-----summary用法总结

Tensorflow学习笔记——Summary用法         最近在研究tensorflow自带的例程speech_command,顺便学习tensorflow的一些基本用法。 其中tensorboard 作为一款可视化神器,可以说是学习tensorflow时模型训练以及参数可视化的法宝。 而在训练过程中,主要用到了tf.summary()的各类方法,能够保存训练过程以及参数分布图并在

vue3项目将所有访问后端springboot的接口统一管理带跨域

vue3项目将所有访问后端springboot的接口统一管理带跨域 一、前言1.安装Axios2.创建Axios实例3.创建API服务文件4.在组件中使用API服务 二、跨域三、总结 一、前言 在Vue 3项目中,统一管理所有访问后端Spring Boot接口的最佳实践是创建一个专门的API服务层。这可以让你的代码更加模块化、可维护和集中管理。你可以使用Axios库作为HTT