智能商贸-day10-采购单

1.1. 组合关系-采购订单模型完整代码

1.1.1. Purchasebill组合关系的一方

/**
 * 
 * 采购订单:组合关系的一方
 * 
 */
@Entity
@Table(name = "purchasebill")
public class Purchasebill extends BaseDomain {
  private Date vdate;// 交易时间 -> 需要录入(时间set的时候加上@DateTimeFormat(pattern = "yyyy-MM-dd"))
  private BigDecimal totalAmount; //总金额 -> 明细计算
  private BigDecimal totalNum; //总数量 -> 明细计算
  private Date inputTime = new Date(); //录入时间 ->当前系统时间
  private Date auditorTime; //审核时间 -> 可以为空,审核时自己生成
  /**
   * 0待审,1已审,-1作废
   */
  private Integer status = 0; //单据状态 -> 默认待审
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "supplier_id")
  private Supplier supplier;// 多对一,非空 供应商(需要选择)
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "auditor_id")
  private Employee auditor;// 多对一,可以为空
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "inputUser_id")
  private Employee inputUser;// 多对一,非空 录入人 -> 登录用户就是录入人
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "buyer_id")
  private Employee buyer;// 多对一,非空 采购员 -> 需要
  // 一般组合关系使用List
  @OneToMany(cascade = CascadeType.ALL, mappedBy = "bill", fetch = FetchType.LAZY, orphanRemoval = true)
  private List<Purchasebillitem> items = new ArrayList<Purchasebillitem>();

…
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
public Date getVdate() {
    return vdate;
}

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

1.1.2. purchasebillitem组合关系的多方

/**
 * 
 * 采购订单明细:组合关系的多方
 * 
 */
@Entity
@Table(name = "purchasebillitem")
public class purchasebillitem extends BaseDomain {
  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;// 组合关系,非空

1.2. 订单列表查询

1.2.1. 订单列表显示

  1. 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>
  1. purchasebill.js
function formatObj(data) {
    if(data){
        return data.name;
    }
}
function formatEmp(data) {
    if(data){
        return data.username;
    }
}
function formatStatus(action) {
    var data = {
        0:"<div style='color:red;'>待审</div>",
        1:"<div style='color: green'>已审</div>",
        "-1":"<div><s>作废</s></div>"
    };
    return data[action];
}

1.2.2. 查询条件的添加

  1. purchasebill.jsp
<!-- 这部门是查询的功能 -->
<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. purchasebillQuery.java
package cn.itsource.pss.query;
import cn.itsource.pss.domain.Purchasebill;
import com.github.wenhao.jpa.Specifications;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class PurchasebillQuery extends BaseQuery {

    //SpringMVC接收日期的格式设置(建议写在setter上)
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date beginDate;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date endDate;
    private Integer status;
    @Override
    public Specification createSpecification(){
        //根据条件把数据返回即可
        Specification<Purchasebill> spec = Specifications.<Purchasebill>and()
                .eq(status!=null,"status",status )//等于
                .ge(beginDate!=null, "vdate",beginDate) //大于等于
                .le(endDate!=null, "vdate",endDate) //小于等于
                .build();

        return spec;
    }
    //getter,setter略…
}

1.2.3. 查询的日期问题

if(endDate != null) {
   Date date = new Date(endDate.getTime() +  24 * 60 * 60 * 1000);
   System.out.println("date:" + date.toLocaleString());
}
  1. 方案2:JDK实现
if(endDate != null) {	
System.out.println("endDate:"+this.endDate.toLocaleString());
	Calendar calendar = Calendar.getInstance();
	calendar.setTime(endDate);	
    calendar.add(Calendar.DAY_OF_MONTH, 1);		
    System.out.println("endDate:"+calendar.getTime().toLocaleString());
}
  1. 方案3:org.apache.commons.lang.time.DateUtils
    当前日期业务最简单的方法
if(endDate != null) {	
   Date date = DateUtils.addDays(endDate, 1);
}
  1. 功能代码(完整)
@Override
public Specification createSpecification(){
    //如果日期不为空,结束日期加1
    Date tempDate = null;
    if(endDate!=null){
        tempDate = DateUtils.addDays(endDate, 1);
    }

    //根据条件把数据返回即可
    Specification<Purchasebill> spec = Specifications.<Purchasebill>and()
            .eq(status!=null,"status",status )
            .ge(beginDate!=null, "vdate",beginDate) //大于等于
            .lt(endDate!=null, "vdate",tempDate) //小于
            .build();

    return spec;
}

1.1. 采购订单的form表单

purchasebill.jsp
<div id="purchasebillDialog" class="easyui-dialog" data-options="closed:true,modal:true" title="功能操作" style="width:800px">
    <div style="padding:10px 60px 20px 40px">
        <form id="purchasebillForm" class="easyui-form" method="post" data-options="">
            <input type="hidden" id="purchasebillId" 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/getBuyer'">
                    </td>
                </tr>
            </table>
        </form>
        <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>
    </div>
</div>

1.1.1. UtilController后台下拉支持

  1. Supplier下拉支持
    SupplierController.java
    //返回所有的供应商
@RequestMapping("/findAllSupplier")
@ResponseBody
public List<Supplier> findAllSupplier(){
    return  supplierService.findAll();
}

  1. Employee下拉支持
    EmployeeRepository
public interface EmployeeRepository extends BaseRepository<Employee,Long> {

 …

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

EmployeeService
@Override
public List<Employee> getBuyer() {
    return employeeRepository.getEmpByDept("采购部");
}

EmployeeController
@RequestMapping("/getBuyer")
@ResponseBody
public List<Employee> getBuyer(){
    return employeeService.getBuyer();
}

1.1.2. 数据保存

解决方案:
EmployeeService

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

1.2. 明细数据的操作

1.2.1. 引入支持的js

注意引入的位置

<head>
    <title>purchasebill管理</title>
    <%@include file="/WEB-INF/views/head.jsp" %>
    <!-- 编辑框支持 -->
    <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>
    <script type="text/javascript" src="/js/model/purchasebill.js"></script>
</head>

1.2.2. 拷备案例中数据

案例文件:CellEditDemo.html

  1. purchasebill.jsp
<!-- 弹出相应的功能框 -->
<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">
          ....
        </table>
        <!-- 采购单的明细编辑 -->
        <table id="gridItems" 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>
  1. purchasebill.js
    (持备过来的还不可以使用,我们下面对它做相应的代码解释)

下面是完整拷备的详细解释

//gridItems:拿到咱们的明细数据
//defaultRow:默认的行(每次添加一行都是把这个数据加进去)
//insertPosition:代表数据插入的位置(bottom代表在底部)
var gridItems = $("#gridItems"),
defaultRow = { ID: "", Code: "", Name: "", StandardModel: "", ApplyCount: "", Remark: "", Stocks: "" },
insertPosition = "bottom";

//对于明细数据的初始化
var dgInit = function () {
    //grid中的每一列的配置
    var getColumns = function () {
        var result = [];

        var normal = [
            {
                field: 'Code', title: '物资编码', width: 180,
                editor: {
                    type: "validatebox",
                    options: {
                        required: true
                    }
                }
            },
            {
                field: 'Name', title: '名称', width: 180,
                editor: {
                    type: "validatebox",
                    options: {
                        required: false,
                        readonly: false
                    }
                }
            },
            {
                field: 'StandardModel', title: '规格型号(只读)', width: 100,
                editor: {
                    type: "validatebox",
                    options: {
                        required: false,
                        readonly: true
                    }
                }
            },
            {
                field: 'ApplyCount', title: '申请数量', width: 100,
                editor: {
                    type: "numberbox",
                    options: {
                        required: true
                    }
                }
            },
            {
                field: 'Remark', title: '备注', width: 100,
                editor: {
                    type: "text"
                }
            },
            {
                field: 'Stocks', title: '库存数量', width: 100,
                editor: {
                    type: "numberbox",
                    options: {
                        readonly: false
                    }
                }
            }
        ];
        result.push(normal);

        return result;
    };
    //grid中基本配置
    var options = {
        idField: "ID",
        rownumbers: true,
        fitColumns: true,
        //fit: true,
        //border: false,
	    toolbar:"#itemBtns",
height:300,
        singleSelect: true,
        columns: getColumns(),
        //表示开启单元格编辑功能
        enableCellEdit: true
    };
    //创建一个grid
    gridItems.datagrid(options);
};
//根据这个确定位置插件在上面还是下面(和上面的insertPosition匹配)
var getInsertRowIndex = function () {
    return insertPosition == "top" ? 0 : gridItems.datagrid("getRows").length;
}

//事件注册的方法
var buttonBindEvent = function () {
    //添加事件(现在没有,先不用管)
    $("#btnInsert").click(function () {
        var targetIndex = getInsertRowIndex(), targetRow = $.extend({}, defaultRow, { ID: $.util.guid() });
        gridItems.datagrid("insertRow", { index: targetIndex, row: targetRow });
        gridItems.datagrid("editCell", { index: 0, field: "Code" });
    });
    //保存数据的事件(现在没有,先不用管)
    $("#btnSave").click(function () {
        var rows = gridItems.datagrid("getRows"), len = rows.length;
        for (var i = 0; i < len; i++) {
            gridItems.datagrid("endEdit", i);
        }
    });
};

//dgInit:执行初始化的方法 buttonBindEvent:注册相应的按钮事件
dgInit(); buttonBindEvent();

1.2.3. 基本数据准备

  1. 修改明细数据为产品数据
//defaultRow:默认的行(每次添加一行都是把这个数据加进去)
//  分别加上产品id,产品颜色,产品图片,数量,价格,总价与备注
var gridItems = $("#gridItems"),
defaultRow = { productId: "", productColor: "", productImage: "",num: 0, price: 0, amount: 0, descs: "" },
insertPosition = "bottom";
  1. 后台返回所有产品(可供选择)
@Controller
@RequestMapping("/util")
public class UtilController extends BaseController {
   ...
    @Autowired
    private IProductService productService;

    ...

    @RequestMapping("/getProduct")
    @ResponseBody
    public List<Product> getProduct(){
        return productService.findAll();
    }
}
  1. 选择产品进行展示
//对于明细数据的初始化
var dgInit = function () {
    //grid中的每一列的配置
    var getColumns = function () {
        var result = [];
        var normal = [
            {
                field: 'productId', title: '产品', width: 80,
                editor: {
                    type: "combobox",
                    options: {
                        valueField:'id',
                        textField:'name',
                        panelHeight:'auto',
                        url:'/util/getProduct',
                        required: true
                    }
                },
                formatter:function(value,row){
                        return value.name;
                }
            },
            {
                field: 'productColor', title: '颜色', width: 80,
                formatter:function(value,row){
                    if(row && row.productId){
                        return "<div style='width: 20px;height: 20px; background-color: "+row.productId.color+"'></div>";
                    }
                }
            },
            {
                field: 'productImage', title: '图片', width: 80,
                formatter:function(value,row){
                    console.debug(row);
                    if(row && row.productId){
                        return "<img height='40px' src='"+row.productId.smallpic+"'>";
                    }
                }
            },
            {
                field: 'num', title: '数量', width: 100,
                editor: {
                    type: "numberbox",
                    options: {
                        required: true
                    }
                }
            },
            {
                field: 'price', title: '价格', width: 100,
                editor: {
                    type: "numberbox",
                    options: {
                        required: true
                    }
                }
            },
            {
                field: 'amount', title: '小计', width: 100,
                formatter:function(value,row){
                    if(row.num && row.price){
                        var amount = (row.num * row.price).toFixed(2);
                        return amount;
                    }
                    return 0;
                }
            },
            {
                field: 'descs', title: '备注', width: 100,
                editor: {
                    type: "text"
                }
            }
        ];
        result.push(normal);

        return result;
    };

1.2.4. 为按钮添加事件

//事件注册的方法
var buttonBindEvent = function () {
    //添加事件(和之前一样,可以不用管)
    $("#btnInsert").click(function () {
        var targetIndex = getInsertRowIndex(), targetRow = $.extend({}, defaultRow, { ID: $.util.guid() });
        gridItems.datagrid("insertRow", { index: targetIndex, row: targetRow });
        gridItems.datagrid("editCell", { index: targetIndex, field: "productId" });
    });
    //删除一行数据
    $("#btnRemove").click(function () {
        var row = gridItems.datagrid("getSelected");
        //拿到对应的行
        var index = gridItems.datagrid("getRowIndex",row);
        //删除这一行
        gridItems.datagrid("deleteRow",index);
    });
};

1.2.5. 采购单保存

  1. 提交采购明细数据
    咱们提交明细要注意提交的数据格式:
save:function () {
   var url  = "/purchasebill/save";
   var id = $("#purchasebillId").val();
   if(id){
       url = "/purchasebill/update?cmd=update";
   }
   purchasebillForm.form('submit', {
       url:url,
       onSubmit: function(param){
           //这里加上param这个参数,为它设置值,就可以做额外的参数提交
           //拿到当前页的所有参数 并进行名称修改 items[0].product.id /item[1].price,...
           var rows = gridItems.datagrid('getRows');
           //param.items[0].product.id = 1;
           for (var i = 0; i < rows.length; i++) {
               var rowData = rows[i];
               param["items[" + i + "].product.id"] = rowData.productId.id;
               param["items[" + i + "].price"] = rowData.price;
               param["items[" + i + "].num"] = rowData.num;
               param["items[" + i + "].descs"] = rowData.descs;
               //完成当前 这一行数据的验证
               if(!gridItems.datagrid("validateRow",i)){
                   alert("你的明细数据有还有问题!");
                   return false;
               }
           }
           return purchasebillForm.form("validate");
       },
       success:function(data){
           var result = JSON.parse(data);//转成相应的json数据
           if(result.success) {
               $('#purchasebillGrid').datagrid('reload');
           }else{
               $.messager.alert('提示信息','操作失败!,原因:'+result.msg,"error");
           }
           purchasebillDialog.dialog('close');
       }
   })
},
  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;
}

1.2.6.	其它细节处理
1.	添加时清除明细
add:function () {
    //隐藏有data-save属性的元素
    $("*[data-save]").show();
    //禁用有data-save属性的input元素的验证功能
    $("*[data-save] input").validatebox("enableValidation");
    //弹出表单窗口
    purchasebillForm.form("clear");//清除数据
    //把明细的数据清空
    gridItems.datagrid("loadData", []);
    purchasebillDialog.dialog("center").dialog("open");
},
  1. 修改时回显明细
edit:function () {
    //弹出表单窗口
    //选中了某一条数据才删除
    var row = purchasebillGrid.datagrid("getSelected");
    if(row) {
        //隐藏有data-save属性的元素
        $("*[data-save]").hide();
        //禁用有data-save属性的input元素的验证功能
        $("*[data-save] input").validatebox("disableValidation");

        purchasebillForm.form("clear");//清除数据
        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++) {
            row.items[i].productId = row.items[i].product;
        }
        var items = $.extend([], row.items);
        gridItems.datagrid("loadData", items); //必需在弹出界面之后执行
        //为form加载数据
        purchasebillForm.form("load",row);
    }else{
        $.messager.alert('提示信息','请选择一行再进行修改!','info');
    }
},
  1. 解决n-to-n的相应问题
//这里准备一个方法,所有方法执行前都会执行它
@ModelAttribute("edit Purchasebill")
public Purchasebill beforeEdit(Long id, String cmd){
    //有id的时候-> 修改功能
    if(id!=null && "update".equals(cmd)) {
         Purchasebill purchasebill = purchasebillService.findOne(id);
        //把这个要修改的关联对象设置为null,可以解决n-to-n的问题
        //把有关系的对象移除
        purchasebill.setSupplier(null);
        purchasebill.setBuyer(null);
        purchasebill.getItems().clear();
        return purchasebill;
    }
    return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值