springmvc+JPA销售报表模块的学习

一、报表的分类

一般有图形和表格报表

二、页面准备

  • 查询的展示报表效果
    =springmvc+JPA销售报表模块的学习_第1张图片
  • 需要引入的easyUI的插件EasyUI(datagrid-groupview)
  • easyUI官网的demo
    下载地址
    springmvc+JPA销售报表模块的学习_第2张图片* 页面的准备
    引入插件
    只需要一个table,动态生成
<%--grid顶部工具栏 需要加入报表中--%>
<%--查询条--%>
日期: -   状态: 查询 <%--引入3d图像表--%> 3D

js代码

$(function () {
    //获取常用的组件
    var chartDialog = $("#chartDialog");
    //高级查询
    var querySearch = $("#querySearch");
    var purchasebillitemGrid = $('#purchasebillitemGrid');
    var searchForm = $('#searchForm');
    //动态生成报表
    $('#purchasebillitemGrid').datagrid({
    //标题
        title:'DataGrid - GroupView',
        //自适应父容器
        fit:true,
        //行号
        rownumbers:true,
        remoteSort:false,
        nowrap:false,
        //列的自适应
        fitColumns:true,
        //添加根据栏
        toolbar:"#gridTools",
        
        url:'/purchasebillitem/findItems',
        
        columns:[[
            {field:'id',title:'编号',width:100,sortable:true},
            {field:'supplier',title:'供应商名称',width:100,sortable:true},
            {field:'buyer',title:'采购员名称',width:100,sortable:true},
            {field:'product',title:'产品名称',width:100,sortable:true},
            {field:'productType',title:'产品分类',width:100,sortable:true},
            {field:'vdate',title:'交易时间',width:100,sortable:true},
            {field:'num',title:'采购数量',width:100,sortable:true},
            {field:'price',title:'价格',width:100,sortable:true},
            {field:'amount',title:'小计',width:100,sortable:true},
            {field:'status',title:'审核状态',formatter:statusFormat,width:100,sortable:true},

        ]],
        //根据什么东西分组显示
        groupField:'groudFile',
        view: groupview,
        //rows,所有数据明细的对象
        groupFormatter:function(value, rows){
        //准备计算总数量和总价
            var totalNum=0;
            var totalAmount=0;
            for(let row of rows){
                console.debug(row)
                totalNum +=row.num;
                totalAmount += row.amount;
            }
            console.debug(totalAmount)
            //拼接成需要的格式
            return `${value}-${rows.length}条数据共${totalNum}件商品总金额${totalAmount}`;
        }
    });
    //点击a标签的时候,获取到函数名称  动态调用方法
    //加*匹配所有的a标签
    $("*[data-method]").on("click",function(){
        var methodName = $(this).data("method");
        window.comlr[methodName]();
    })
    //添加方法
    comlr={
    //高级查询的条件
        search(){
            //serializeObject:拿到一个form中的所有数据,封装成json对象,发送到后台
            //查询条件
            var params = searchForm.serializeObject();
            console.debug(params)
            purchasebillitemGrid.datagrid("load",params);
        }
    }
})

  • 审核状态的展示
function statusFormat(v) {
    if (v==0){
        return `待审`
    }else if (v==-1){
        return `删除`
    } else if (v==1){
        return `已审核`
    }
}
  • 添加高级查询条
    条件:beginDate endDate,时间区间条件
    status启用状态,分组显示groupField:‘groudFile’,
    前台提交表单将查询数据封装为查询对象
    注意:后台时间需要加注解,前台的字段对应vo对象字段

三、查询对象PurchasebillitemQuery

用于接收前台的查询条件,没有就是默认

public class PurchasebillitemQuery extends BaseQuery{
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date beginDate;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date endDate;
    private Integer status;

    //分组条件
    private Integer groupBy=0;


    @Override
    public Specification creatSpec(){
        Date teampDate=null;
        if (endDate!=null){
            teampDate = DateUtils.addDays(endDate, 1);
        }
        Specification spec = Specifications.and()
                //Purchasebillitem对象没有status,vdate属性,是其中的字段Purchasebill对象的属性
                .eq(status!=null,"bill.status",status)
                //小于
                .lt(endDate!=null,"bill.vdate",teampDate )
                //大于等于
                .ge(beginDate!=null,"bill.vdate",beginDate )
                .build();
        System.out.println(endDate);
        System.out.println(beginDate);
        return spec;
    }
    。。省略getset。。注意时间的getset需要加上注解因为前后台时间不一样
}

四、vo类

返回数据如果只用普通domain来查询返回,所有的字段都返回了,很浪费性能
所以准备一个vo类,原来将需要的数据返回,注意前台的字段要对应

  • PurchaseBillItemVo
public class PurchaseBillItemVo {

    private Long id; //编号
    private String supplier; //供应商名称
    private String buyer; //采购员名称
    private String product; //产品名称
    private String productType; //产品分类
    private Date vdate; //交易时间
    private BigDecimal num; //采购数量
    private BigDecimal price; //价格
    private BigDecimal amount; //小计 = 价格*数量
    private Integer status;//状态

    private String groudFile;

    public PurchaseBillItemVo(){}
    public PurchaseBillItemVo(Purchasebillitem item, PurchasebillitemQuery query){
        this.id = item.getId();
        this.supplier = item.getBill().getSupplier().getName();
        this.buyer = item.getBill().getBuyer().getUsername();
        this.product = item.getProduct().getName();
        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();
 
        Integer groupBy = query.getGroupBy();
        if (groupBy==null){
            groupBy=0;
        }
        if (groupBy==0){
            this.groudFile=supplier;
        }else if (groupBy==1){
            this.groudFile=buyer;
        }else if (groupBy==2){
            Calendar cal = Calendar.getInstance();
            cal.setTime(vdate);
            //月份是从0开始
            String month = (cal.get(Calendar.MONTH)+1) + "";
            this.groudFile = month;
        }
    }
    省略getset方法
    }

PurchaseBillItemVo对象的构造方法,将Purchasebillitem 明细对象传进来,封装为vo对象返回,实际还是查询的明细,只是在service层查询出来遍历,将明细对象变成vo对象
注意分组条件是在PurchaseBillItemVo,应该在查询对象中获得所以在构造方法中也传一个查询对象方便实用

  • PurchasebillitemServiceImpl层查询对象
@Autowired
    private PurchasebillitemRepository purchasebillitemRepository;
    @Override
    public List findItems(PurchasebillitemQuery query) {
    //准备返回的vo对象集合
        List itemVos = new ArrayList<>();
        List list = purchasebillitemRepository.findByQuery(query);
        //查询的明细对象遍历,包装为vo对象
        for (Purchasebillitem purchasebillitem:list) {
            PurchaseBillItemVo purchaseBillItemVo = new 										PurchaseBillItemVo(purchasebillitem,query);
            itemVos.add(purchaseBillItemVo);
        }
        return itemVos;
    }
  • controller层调用返回前台数据
    打上json注解
 //返回所有的PurchaseBillItemVo对象
    @RequestMapping("/findItems")
    @ResponseBody
    public List list1(PurchasebillitemQuery query){
        List all = iPurchasebillitemService.findItems(query);
        //System.out.println(all);
        return all;
    }

前台报表关于分组的展示就完成了,注意报表一般只需要查询

五、制作图形报表

  • 插件准备
  • HighChart
    flash:写actionScript代码(flex)
    flash:容易崩溃,影响性能,安全性低
    HTML5:用画布功能
    HTML:IE低版本不支持
    引入HighChart
    官网
    效果展示
    springmvc+JPA销售报表模块的学习_第3张图片

六、页面准备

在报表的工具栏中添加一个展示3D报表图
点击a标签,动态展示,数据应该是高级查询,提交查询条件获取
动态展示

<%--grid顶部工具栏--%>
<%--查询条--%>
日期: -   状态: 选择分组: 查询 <%--引入3d图像表--%> 3D
<%--显示图表的弹出框--%>

js代码
只需要将 chart3d()方法放在后面,动态调用就可以完成弹出展示,
设置一些属性,发送Ajax请求,将数据返回给页面,
注意页面需要的格式
官网展示数据的demo是:
springmvc+JPA销售报表模块的学习_第4张图片

七、查询,返回图形的数据

  • 我们查询的数据应该是list形式,创建一个类来将数据封装成key和value的形式用于返回
  • 要查询的应该是分类和总共的数据展示,所以查询对象的条件不满足需要
  • 添加一个jpql查询的方法,但是也需要使用到查询语句的封装回来的条件
  • 拼接查询语句,进行查询,然后封装返回前台

PurchasebillitemQuery增加方法,在内部增加获取查询的where条件方法,获取分组条件 的方法,还需要将查询语句中的问号需要的参数设置

 //用于存储查询语句问好需要提供的参数
    private List params = new ArrayList<>();
    //拼接jpql中的where条件语句
    public String getWhere(){
        StringBuilder jpql =  new StringBuilder();
        if(beginDate!=null){
            jpql.append(" and o.bill.vdate >= ? ");
            //存储时间大于等于?
            params.add(beginDate);
        }
        if(endDate!=null){
            Date tempDate = DateUtils.addDays(endDate, 1);
            jpql.append(" and o.bill.vdate < ? ");
            params.add(tempDate);
        }
        if(status!=null){
            jpql.append(" and o.bill.status =? ");
            params.add(status);
        }
        //将第一个条件后面的and换成where,拼接sql语句
        return jpql.toString().replaceFirst("and","where");
    }

    //获取到分组的字符串
    //service层调用获取到分组的条件,拼接sql语句
    public String getGroupJPQL(){
        if (groupBy==null){
            groupBy=0;
        }
        if(groupBy==1){
            //根据采购员分组
            return "o.bill.buyer.username";
        }else if(groupBy==2){
            //根据月份分组
            return "MONTH(o.bill.vdate)";
        }else{
            //根据供应商分组
            return "o.bill.supplier.name";
        }
    }
    public List getParams() {
        return params;
    }
    public void setParams(List params) {
        this.params = params;
    }

  • PurchasebillitemServiceImpl覆写方法findByJpql
    方法来自于BaseRepository父类抽取,jpa自动实现
//父接口的方法
//根据jpql与对应的参数拿到数据
    List findByJpql(String jpql, Object... values);
  • 方法覆写
    也需要用到查询对象,查询对象内部完成条件语句的部分需要
//通过findByJpql,查询出条件是供应商,采购员,月份分组时的产品数量
    //拼接需要的条件,条件都来自于前台form表单提交的查询条件
    @Override
    public List findCharts(PurchasebillitemQuery query) {

        //1.获取到分组的条件
        String group = query.getGroupJPQL();
        //2.获取到相应的JPQL
        String whereJPQL = query.getWhere();
        //3.获取到JPQL中?对应的值
        List params = query.getParams();
        //这里要将查询的数据直接封装为对象就必需使用全限定名
        //完成jpql 的拼接,查询产品明细中,先按where条件过滤时间启用状态的数据,然后再进行分组查询,统计数量
        //封装到对象中返回前台
        String jpql = "select new com.lirui.domain.vo.ItemChartVo("+group
                +",sum(amount)) from Purchasebillitem o "+whereJPQL+" group by "+group;
        //将可变数变成数组
        List vos = super.findByJpql(jpql,params.toArray());
        return vos;
    }

  • ItemChartVo 返回前台的图形数据需要的类
public class ItemChartVo {

    private Object name;

    private Object y;

    public Object getName() {
        return name;
    }

    public ItemChartVo() {
    }

    public ItemChartVo(Object name, Object y) {
        this.name = name;
        this.y = y;
    }
    public ItemChartVo(String name, Object y) {
        this.name = name;
        this.y = y;
    }
    。。。
}

注意前台的参数的名字貌似是y才能接收

  • 点击3D图像表展示,加载数据
//查询3D图片
        chart3d(){
            //打开3d弹出框
            chartDialog.dialog("center").dialog("open");
            //获取到表单中的所有值
            var params = searchForm.serializeObject();
            //请求的时候把值传到后台
            $.post("/purchasebillitem/findCharts",params,function(result){
                console.debug(result)
                //展示图表
                Highcharts.chart('container', {
                    chart: {
                        type: 'pie',
                        options3d: {
                            enabled: true,
                            alpha: 45, //倾斜度
                            beta: 0
                        }
                    },
                    title: {
                        text: '销售情况占比'
                    },
                    //鼠标移上去后显示的数据
                    tooltip: {
                        pointFormat: '{series.name}: {point.percentage:.1f}%'
                    },
                    plotOptions: {
                        pie: {
                            //是否自己可以选择
                            allowPointSelect: true,
                            //鼠标指上来后的样式
                            cursor: 'pointer',
                            depth: 35, //深度
                            dataLabels: {
                                enabled: true,
                                format: '{point.name}'
                            }
                        }
                    },
                    series: [{

                        type: 'pie',
                        name: '销售占比',

                        data: result
                    }]
                });
            })
        }

注意修改路径

你可能感兴趣的:(Java,销售模块,jpa)