ssj项目-采购订单管理

该博客详细介绍了ssj项目中采购订单管理的实现过程,包括准备工作、添加查询条件和数据明细操作。首先创建实体类并配置关系,接着在前端页面展示,然后添加时间查询条件,并实现采购订单的查询组件。在后台编写查询方法,支持供应商和购买者的下拉选择。在保存数据时遇到问题并在JS中处理N-to-N响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.准备工作 创建 实体类 配置关系和 前端页面 展示

1.Purchasebill组合关系的一方

package cn.itsource.aisell.domain;

import com.fasterxml.jackson.annotation.JsonFormat;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * (Purchasebill)实体类
 *
 * @author jie
 * @since 2019-08-13 18:54:08
 */
@Entity
@Table(name="purchasebill")
public class Purchasebill extends BaseDomain {

    private Date vdate; // 交易时间 前台传过来
    private BigDecimal totalAmount; //订单总金额 后台计算
    private BigDecimal totalNum;// 总数量
    private Date inputtime = new Date(); //录入时间 后台生成
    private Date auditortime; //审核时间 
    private Integer status; //单据状态 0 未审核 -1 不通过 1 通过
    @ManyToOne(fetch = FetchType.LAZY,optional = false)
    @JoinColumn(name = "supplier_id")
    private Supplier supplier;// 多对一  供应商(需要选择) 可以为空

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "auditor_id")
    private Employee auditor; //审核人 录入可以为null

    @ManyToOne(fetch = FetchType.LAZY,optional = false)
    @JoinColumn(name = "inputuser_id")
    private Employee inputuser;//录入人 不能为null 当前登陆用户

    @ManyToOne(fetch = FetchType.LAZY,optional = false)
    @JoinColumn(name = "buyer_id")
    private Employee buyer; //采购员

    //明細  强级联  orphanRemoval 一方解除关系 去删除
    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy ="bill",orphanRemoval = true)
    private List<Purchasebillitem> items = new ArrayList<>();
	//格式化时间  最好写在 getset方法上  
    @JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss",timezone = "GMT+8")
    public Date getVdate() {
        return vdate;
    }
    @JsonFormat(pattern = "yyyy-MM-dd")
    public void setVdate(Date vdate) {
        this.vdate = vdate;
    }


2.purchasebillitem组合关系的多方


    private BigDecimal price; //价格  
    private BigDecimal num; //数量
    private BigDecimal amount; //产品小计 价格*数量
    private String descs; //描述
	//  非空 产品
    @ManyToOne(fetch = FetchType.LAZY,optional = false)
    @JoinColumn(name = "product_id")
    private Product product;

    @ManyToOne(fetch = FetchType.LAZY,optional = false)
    @JoinColumn(name = "bill_id")
    @JsonIgnore //  返回页面 不展示出来  生成json 的时候忽略这个属性
    private Purchasebill bill;

3.purchasebill.jsp

<table id="purchasebillGrid" class="easyui-datagrid" data-options="fit:true,fixed:true,fitColumns:true,toolbar:'#tb',singleSelect:true";
       url="/purchasebill/page"
       iconCls="icon-save"
       rownumbers="true" pagination="true">
    <thead>
    <tr>
        <th width="20"  field="vdate">交易时间</th>
        <th width="20"  field="supplier" data-options="formatter:formatObj">供应商</th>
        <th width="20"  field="buyer"  data-options="formatter:formatEmp">采购员</th>
        <th width="20"  field="totalNum">总数量</th>
        <th width="20"  field="totalAmount" >总金额</th>
        <th width="20"  field="status" data-options="formatter:formatStatus" >状态</th>
    </tr>
    </thead>
</table>

4.purchasebill.js

//表格数据格式化 formatObj 供应商转换
function formatObj(value){
    if(value){
        return value.name;
    }
}
//ormatEmp 采购员
function formatEmp(value){
    if(value){
        return value.username;
    }
}
// 状态转换  0 1 -1
function formatStatus(value){
    var data = {
        0:"<div style='color: green'>审核中</div>",
        1:"<div style='color: red'>审核通过</div>",
        "-1":"<div><s>审核未通过</s></div>"
    };
    return data[value];
}

2.添加 查询条件 主要是时间查询 首先添加查询组件

<div id="cc" class="easyui-calendar"></div>
<form id="searchForm" action="/purchasebill/download" method="post">
    日期 : <input name="beginDate" class="easyui-datebox" style="height:32px" sharedCalendar="#cc">
    - <input name="endDate" class="easyui-datebox" style="height:32px" sharedCalendar="#cc">

    状态 :<select class="easyui-combobox" name="status"
                data-options="panelHeight:'auto'"
     >
    <option value="">--请选择--</option>
    <option value="0">待审</option>
    <option value="-1">作废</option>
    <option value="1">已审</option>
</select>
    <a href="#" data-method="search"  class="easyui-linkbutton" iconCls="icon-search">查找</a>
</form>

**1 在query 层 添加查询条件 **


/**
 *  单独的查询对象
 *      PurchasebillQuery
 *      DepartmentQuery
 *
 *      PurchasebillController search(PurchasebillQuery query)
 */
public class PurchasebillQuery extends BaseQuery{

    private String name;

    //接收时间和状态

    private Date beginDate;

    private Date endDate;

    private Integer status;

    public Date getBeginDate() {
        return beginDate;
    }

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    public void setBeginDate(Date beginDate) {
        this.beginDate = beginDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //抽取查询
    @Override
    public Specification createSpecification() {

        // 接收时间
        // 前端的日期时分秒按照0:00:00来处理,如果不对日期+1处理,结束时间是不能成功获取查询的值.
        // 如下单时间是09-30 15:00:00,而endDate输入09-30,后台获取到09-30 0:00:00
        Date tempDate = null;
        if(this.endDate!=null){
            //直接用 DateUtils.addDays 表示在当前日期加上一天 ,如果是月底最后一天 会自动转到下个月
            tempDate =  DateUtils.addDays(this.endDate,1 );
            System.out.println(tempDate);
        }

        Specification<Purchasebill> spe = Specifications.<Purchasebill>and()
                .ge(this.beginDate != null, "vdate",this.beginDate )// 大于等于
                //这里因为上面的时间加了一天 所以不能用小于等于  只能用小于 
                .lt(this.endDate!=null,"vdate",tempDate)

                .eq(this.status!=null && !"".equals(this.status),"status",this.status)
                .build();

        return spe;
    }
}

**2 添加采购订单 的 from表单 和明细表单 **

首先要引用js 其他基本的easyui 的那些就省略了

    <!-- 编辑框支持 -->
    <script src="/easyui/plugin/cellEdit/jeasyui.extensions.datagrid.getColumnInfo.js"></script>
    <script src="/easyui/plugin/cellEdit/jeasyui.extensions.datagrid.editors.js"></script>
    <script src="/easyui/plugin/cellEdit/jeasyui.extensions.datagrid.edit.cellEdit.js"></script>

然后弹出窗口组件

    <!-- 弹出相应的功能框 -->
    <div id="purchasebillDialog" class="easyui-dialog" title="数据操作" data-options="closed:true,modal:true"  style="width:800px;padding:10px">
        <form id="purchasebillForm" method="post">
            <input id="purchasebillId" type="hidden" name="id">
            <table cellpadding="5">
                <tr>
                    <td>交易时间:</td>
                    <td><input class="easyui-datebox"name="vdate" data-options="required:true"></input></td>
                </tr>
                <tr>
                    <td>供应商:</td>
                    <td>
                        <input class="easyui-combobox" name="supplier.id"
                               data-options="valueField:'id',textField:'name',panelHeight:'auto',url:'/util/findAllSupplier'">
                    </td>
                </tr>
                <tr>
                    <td>采购员:</td>
                    <td>
                        <input class="easyui-combobox" name="buyer.id"
                               data-options="valueField:'id',textField:'username',url:'/util/findAllBuyer'">
                    </td>
                </tr>
            </table>
            <!-- 明细表格-->
            <table id="gridItem"  title="明细编辑" style="width:100%;height:300px"></table>
            <!-- 采购单明细的按钮准备 -->
            <div id="itemBtns">
                <a href="javascript:;" id="btnInsert" class="easyui-linkbutton"
                   data-options="iconCls:'icon-add',plain:true">添加</a>
                <a href="javascript:;" id="btnRemove" class="easyui-linkbutton"
                   data-options="iconCls:'icon-remove',plain:true">删除</a>
            </div>
            <div style="text-align:center;padding:5px">
                <a href="javascript:void(0)" class="easyui-linkbutton" data-method="save">提交</a>
                <a href="javascript:void(0)" class="easyui-linkbutton" onclick="$('#purchasebillDialog').dialog('close')">取消</a>
            </div>

        </form>
    </div>

2 在 UtilController后台 写查询方法 来支持下拉

2.1 findAllSupplier 直接查询就行了

  @RequestMapping("/findAllSupplier")
    @ResponseBody
    public List<Supplier> findAllSupplier() {
        return supplierService.findAll();
    }

2.2 findAllBuyer 需要在底层覆写查询条件

EmployeeRepository 层

这里可以根据部门ID 和名字查询 都是一样的

    @Query("select o from Employee o where o.department.name = ?1 ")
    List<Employee> getEmpByDept(String deptName);

在service 层添加方法

    //根据部门名称 查询
    List<Employee> getEmpByDept(String deptName);

实现层


    @Override
    public List<Employee> getEmpByDept(String deptName) {
        return employeeRepository2.getEmpByDept(deptName);
    }

    @RequestMapping("/findAllBuyer")
    @ResponseBody
    public List<Employee> findAllBuyer() {
        return employeeService.getEmpByDept("采购部");
    }

**3 保存出错 在save方法里 **

@Override
public void save(Purchasebill purchasebill) {
    //当前登录用户为录入人 从作用域取当前登录用户
    Employee loginUser = UserContext.getUser();
    purchasebill.setInputUser(loginUser);
    super.save(purchasebill);
}

3 数据明细操作

在utilcontroller 工具类里 在添加一个查询 所有员工的方法

    @RequestMapping("/findAllProduct")
    @ResponseBody
    public List<Product> findAllProduct(){
        return productService.findAll();
    }

purchasebill.js (包含所有的CRUD 以及事务处理,逻辑判断等等)

//表格数据格式化
function formatObj(value){
    if(value){
        return value.name;
    }
}
function formatEmp(value){
    if(value){
        return value.username;
    }
}
function formatStatus(value){
    var data = {
        0:"<div style='color: green'>审核中</div>",
        1:"<div style='color: red'>审核通过</div>",
        "-1":"<div><s>审核未通过</s></div>"
    };
    return data[value];
}

$(function(){
    //定义form表单
    var searchForm = $("#searchForm");
    var purchasebillGrid = $("#purchasebillGrid");
    //获取purchasebillDialog
    var purchasebillDialog = $("#purchasebillDialog");
    //定义表单新增的form
    var purchasebillForm = $("#purchasebillForm");

    //绑定事件 easyui 第二天的时候
    $("a[data-method]").on('click',function(){
       //获取 data-method属性 <a data-method="seacher">
        var methodName = $(this).data("method");
        //动态调用方法 itsource["seacher"]
        itsource[methodName]();
    });
    //对象
    var itsource = {
        search:function(){
          //怎么完成高级查询 jquery.jdirk.js 这个方法 这是jquery扩展方法
            //该方法返回一个 JSON Object,返回对象中的每个数据都表示一个表单控件值。
            var param = searchForm.serializeObject();
            //发送查询数据库 --加载表格 发送请求 /purchasebill/page
            purchasebillGrid.datagrid('load',param);
        },
        add:function(){
            
            //清空表单
            purchasebillForm.form('clear');
            //新增 --弹出一个对话框--装一个表单
            purchasebillDialog.dialog('center').dialog('open');
             //把明细的数据清空
            $("#gridItem").datagrid('load',[]);

        },
        edit:function(){
            //选择一条数据进行修改
            var row = purchasebillGrid.datagrid('getSelected');
            if(row){
                //弹出对话框
                purchasebillDialog.dialog('center').dialog('open');
                //供货商
                if(row.supplier){
                    row["supplier.id"] = row.supplier.id;
                }
                //供货商
                if(row.buyer){
                    row["buyer.id"] = row.buyer.id;
                }
                
                // 回显  加载相应的数据(要看product的名称是否可以对应上)
                for(var i=0;i<row.items.length;i++){
                    var item = row.items[i];
                    item["productId"] = item.product;
                }
                var items = $.extend([], row.items);
                //明细表格回显
                $("#gridItem").datagrid('loadData',items);
                //修改 -- 回显示数据
                purchasebillForm.form('load',row);
            }else{
                //提示用户
                $.messager.alert('温馨提示:','请选中一条数据进行修改','info');
                return;
            }

        },
        del:function(){
            //判断表格里面是否选中得数据
            var row = purchasebillGrid.datagrid('getSelected');
            if(row){
                //是否确认要删除数据
                $.messager.confirm('温馨提示','你确定要删除吗?',function(value){
                    if(value){
                        //获取id值

                        //发送ajax到后台进行删除数据
                        $.get('/purchasebill/delete',{"id":row.id},function(data){
                            //返回json对象
                            if(data.success){
                                $.messager.alert('温馨提示:','删除成功','info');
                                //重新加载数据
                                purchasebillGrid.datagrid('reload');
                            }else{
                                $.messager.alert('温馨提示:','删除失败'+data.msg,'error');
                            }
                        });
                    }
                })

            }else{
                //提示用户
                $.messager.alert('温馨提示:','请选中一条数据进行删除','info');
                return;
            }

        },
        save:function(){
            var url = "/purchasebill/save";
            //获取隐藏域里面id值
            var id = $("#purchasebillId").val();
            if(id){
                url = "/purchasebill/update?cmd=update"
            }
            //保存方法 --提交表单的数据到后台
            purchasebillForm.form('submit', {
                    url:url,
                    onSubmit: function(){
                        //提交 封装 items
                        //得到明细表格所有的数据 price num descs
                        //获取当前行 的所有数据
                        var rows = $("#gridItem").datagrid('getRows');
                        for(var i=0;i<rows.length;i++){
                            var rowData = rows[i];
                            param["items["+i+"].descs"] = rowData.descs;
                            param["items["+i+"].price"] = rowData.price;
                            param["items["+i+"].num"] = rowData.num;
                            param["items["+i+"].product.id"] = rowData.productId.id;
                        }
                        // 提交之前的验证
                       return purchasebillForm.form('validate');
                     },
                success:function(data){
                        //字符串 转换成json对象
                      var dataJson =  $.parseJSON(data);
                      if(dataJson.success){
                          $.messager.alert('温馨提示:','操作成功','info');
                          //重新加载数据
                          purchasebillGrid.datagrid('reload');
                          //关闭对话框
                          purchasebillDialog.dialog('close');
                      }else{
                          $.messager.alert('温馨提示:','保存失败'+dataJson.msg,'error');
                          purchasebillDialog.dialog('close');
                      }
                }
            });
        }
    }

});

$(function () {
    //明细表格
    var dg = $("#gridItem"),
        //默认行
        defaultRow = { productId: "", color: "", smallpic: "", num: 0, price: 0, amount: 0, descs: "" },
        insertPosition = "bottom";//插的位置

    //表格初始化
    var dgInit = function () {
        //得到所有列
        var getColumns = function () {
            var result = [];
            //具体列的配置
            var normal = [
                {
                    field: 'productId', title: '产品', width: 180,
                    editor: {
                        type: "combobox",
                        options: {
                            required: true,
                            valueField:'id',
                            textField:'name',
                            url:'/util/findAllProduct',
                            panelHeight:'auto'
                        }
                    },
                    formatter:function(value,row){
                        //value当前这个单元格的值 row整个行的值
                        return value.name;
                    }
                },
                {
                    field: 'color', title: '颜色', width: 180,
                    /* editor: {
                         type: "validatebox",
                         options: {
                             required: false,
                             readonly: true
                         }
                     },*/
                    formatter:function(value,row){
                        console.log(value);
                        console.log(row.productId.color);
                        if(row && row.productId){
                            return "<div style='width:20px;height:20px;background-color: "+row.productId.color+"' ></div>"
                        }
                    }
                },
                {
                    field: 'smallpic', title: '图片', width: 100,
                    formatter:function(value,row){
                        console.log(row.productId);
                        if(row && row.productId.smallPic){
                            return "<img src='"+row.productId.smallPic+"' width='20px' height='20px'/>"
                        }
                    }
                },
                {
                    field: 'num', title: '产品数量', width: 100,
                    editor: {
                        type: "numberbox",
                        options: {
                            required: true
                        }
                    }
                },
                {
                    field: 'price', title: '价格', width: 100,
                    editor: {
                        type: "numberbox",
                        required: true
                    }
                },
                {
                    field: 'amount', title: '小计', width: 100,
                    formatter:function(value,row){
                        //小计
                        if(row.num && row.price) {
                            return row.num * row.price;
                        }
                    }
                },
                {
                    field: 'descs', title: '备注', width: 100,
                    editor: {
                        type: "text"
                    }
                }
            ];
            result.push(normal);

            return result;
        };
        //设置表格配置
        var options = {
            idField: "productId",
            rownumbers: true,
            fitColumns: true,
            fit: true,
            border: true,//边框
            singleSelect: true,
            toolbar:"#itemBtns",
            columns: getColumns(),//得到所有列
            //表示开启单元格编辑功能
            enableCellEdit: true
        };

        //创建编辑表格
        dg.datagrid(options);

    };

    //定义方法 得到插入的行的索引
    var getInsertRowIndex = function () {
        return insertPosition == "top" ? 0 : dg.datagrid("getRows").length;
    }

    //按钮的绑定的事件
    var buttonBindEvent = function () {
        //插入行的按钮
        $("#btnInsert").click(function () {
            //获取插入表里面位置 最末尾
            var targetIndex = getInsertRowIndex(),targetRow = $.extend({}, defaultRow, { ID: $.util.guid() });
            //在表格里面添加一行
            dg.datagrid("insertRow", { index: targetIndex, row: targetRow });
            //插入一行之后,定义到第一个单元格
            dg.datagrid("editCell", { index: 0, field: "productId" });
        });
        //删除表格里面单元格
        $("#btnRemove").click(function () {
            //得到选中的行
            var row = dg.datagrid('getSelected');
            if(row) {
                //得到行索引
                var index =    dg.datagrid('getRowIndex', row);
                //通过索引删除
                dg.datagrid('deleteRow',index);
            }
        });
    };

    //调用初始化表格 创建表格
    dgInit();
    buttonBindEvent();//绑定事件


});

1.后台进行保存

//添加或者修改
private Map<String,Object> saveOrUpdate( Purchasebill purchasebill){
    Map<String,Object> map = new HashMap<>();
    try {
        //1 准备总数量与总金额
        BigDecimal totalAmount = new BigDecimal(0);
        BigDecimal totalNum = new BigDecimal(0);
        //2 拿到相应的明细
        List<Purchasebillitem> items = purchasebill.getItems();
        for (Purchasebillitem item : items) {
            item.setBill(purchasebill);//让一方也多方也建立关系
            item.setAmount(item.getNum().multiply(item.getPrice()));//计算明细小计
            //总数量与总金额累加
            totalAmount = totalAmount.add(item.getAmount());
            totalNum = totalNum.add(item.getNum());
        }
        //3 设置总数量与总金额
        purchasebill.setTotalAmount(totalAmount);
        purchasebill.setTotalNum(totalNum);

        purchasebillService.save(purchasebill);
        map.put(SUCCESS, true);
    } catch (Exception e) {
        e.printStackTrace();
        map.put(SUCCESS, false);
        map.put("msg", e.getMessage());
    }
    return map;
}

2 解决n-to-n的相应问题

 @ModelAttribute("editPurchasebill")
    public Purchasebill beforeEdit(Long id,String cmd){
        Purchasebill purchasebill = null;
        if("update".equals(cmd) && id != null && !"".equals(id) ){
            purchasebill = purchasebillService.findOne(id);
            //就住这就话:在修改的时候的时候,关联对象设置null,保永生
            //purchasebill.setDepartment(null);
            //把有关系的对象移除
            purchasebill.setSupplier(null);
            purchasebill.setBuyer(null);
            purchasebill.getItems().clear();
        }
        return purchasebill;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值