准备domin:
package cn.itsource.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity//采购单
@Table(name = "purchasebill")
public class Purchasebill extends BaseDaomain{
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;
}
@Entity//采购明细
@Table(name = "purchasebillitem")
public class Purchasebillitem extends BaseDaomain{
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;// 组合关系,非空
@Entity//供货商
@Table(name="supplier")
public class Supplier extends BaseDaomain{
private String name;
query层:
public class PurchasebillQuery extends BaseQuery{
// //自身条件
// //自身条件
private Date beginDate ;//开始时间
private Date endDate;//结束时间
private String status;//审核状态
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
public Date getBeginDate() {
return beginDate;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
public Date getEndDate() {
return endDate;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Specification createSpecification() {
//处理结束时间
Date tempDate=null;
if(this.getEndDate() != null){
tempDate = DateUtils.addDays(this.getEndDate(), 1);
}
//ge 大于等 vdate>= beginDate and vdate< endDate+1
//高级查询
Specification<Purchasebill> specification = Specifications.<Purchasebill>and()
.ge(this.beginDate!=null,"vdate",this.getBeginDate())
.lt(this.endDate!=null,"vdate",this.getEndDate())
.eq(StringUtils.isNotBlank(this.status),"status",this.getStatus())
.build();
return specification;
}
}
public class PurchasebillitemQuery extends BaseQuery{
// //自身条件
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Specification createSpecification() {
Specification<Purchasebillitem> specification = Specifications.<Purchasebillitem>and()
.like(StringUtils.isNotBlank(this.getName()),"name", "%"+this.getName()+"%")
.build();
return specification;
}
}
public class SupplierQuery extends BaseQuery{
// //自身条件
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Specification createSpecification() {
Specification<Supplier> specification = Specifications.<Supplier>and()
.like(StringUtils.isNotBlank(this.getName()),"name", "%"+this.getName()+"%")
.build();
return specification;
}
}
repository层:
public interface PurchasebillRepository extends BaseRepository<Purchasebill,Long> {
}
public interface PurchasebillitemRepository extends BaseRepository<Purchasebillitem,Long> {
}
public interface SupplierRepository extends BaseRepository<Supplier,Long> {
}
serviec层
public interface IPurchasebillService extends IBaseService<Purchasebill,Long> {
}
实现:
@Service
public class PurchasebillServiceImpl extends BaseServiceImpl<Purchasebill,Long> implements IPurchasebillService {
}
public interface IPurchasebillitemService extends IBaseService<Purchasebillitem,Long> {
}
实现:
@Service
public class PurchasebilltiemServiceImpl extends BaseServiceImpl<Purchasebillitem,Long> implements IPurchasebillitemService {
}
public interface ISupplierService extends IBaseService<Supplier,Long> {
}
实现:
@Service
public class SupplierServiceImpl extends BaseServiceImpl<Supplier,Long> implements ISupplierService {
}
controller层:
package cn.itsource.web.controller;
import cn.itsource.domain.*;
import cn.itsource.query.PurchasebillQuery;
import cn.itsource.query.PurchasebillitemQuery;
import cn.itsource.service.IPurchasebillService;
import cn.itsource.util.AjaxResult;
import cn.itsource.util.PageUi;
import cn.itsource.util.UserContent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("/purchasebill")
public class PurchasebillController {
@Autowired
private IPurchasebillService purchasebillService;
@RequestMapping("/list")
@ResponseBody
public PageUi<Purchasebill> findAll(PurchasebillQuery purchasebillQuery){
System.out.println("56565656565");
Page pageByQuery = purchasebillService.findPageByQuery(purchasebillQuery);
System.out.println(pageByQuery);
PageUi pageUi=new PageUi(pageByQuery);
return pageUi;
}
@RequestMapping("/index")
public String main(){
return "purchasebill";
}
@RequestMapping("/delete")
@ResponseBody
public AjaxResult delete(Long[] ids){
try {
for (Long id : ids) {
purchasebillService.delete(id);
}
return new AjaxResult();
} catch (Exception e) {
e.printStackTrace();
return new AjaxResult("操作失败"+e.getMessage());
}
}
//保存
@RequestMapping("/save")
@ResponseBody
public AjaxResult save(Purchasebill purchasebill){
//System.out.println("21121212");
return saveOrUpdate(purchasebill);
}
public AjaxResult saveOrUpdate(Purchasebill purchasebill){
try {
//计算总金额 总数量 录入时间 录入人 状态
BigDecimal totalAmount = new BigDecimal(0);//总金额
BigDecimal totalNum = new BigDecimal(0);//总数量
//从明细里面计算
List<Purchasebillitem> items = purchasebill.getItems();
for (Purchasebillitem item : items) {
//计算总金额 //数量 //单价
totalAmount = totalAmount.add(item.getNum().multiply(item.getPrice()));
totalNum=totalNum.add(item.getNum());
//计算明细小计
item.setAmount(item.getNum().multiply(item.getPrice()));
//建立多方到一方 一方放弃管理 交个多方来维护外键
item.setBill(purchasebill);
}
//录入总金额
purchasebill.setTotalAmount(totalAmount);
//录入总数量
purchasebill.setTotalNum(totalNum);
//录入时间
purchasebill.setInputTime(new Date());
//获取当前登录用户
Employee employee = (Employee)UserContent.getuser();
//录入人员插入
purchasebill.setInputUser(employee);
//默认待审状态
purchasebill.setStatus(0);
//级联保存
purchasebillService.save(purchasebill);
return new AjaxResult();
} catch (Exception e) {
e.printStackTrace();
return new AjaxResult("操作失败"+e.getMessage());
}
}
//解决修改数据丢失问题
@ModelAttribute("editPurchasebill")
public Purchasebill beforeEdit(Long id,String cmd){
// System.out.println("---------------------");
//System.out.println(id);
//System.out.println(cmd);
if (id!=null&&"update".equals(cmd)){
System.out.println("=====================");
Purchasebill purchasebill = purchasebillService.findOne(id);
purchasebill.setBuyer(null);
purchasebill.setSupplier(null);
purchasebill.getItems().clear();
return purchasebill;
}else {
return null;
}
}
//修改
@RequestMapping("/update")
@ResponseBody
public AjaxResult update(@ModelAttribute("editPurchasebill") Purchasebill purchasebill){
return saveOrUpdate(purchasebill);
}
}
准备前端jsp:
<%--
Created by IntelliJ IDEA.
User: 12575
Date: 2019/10/15
Time: 18:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/WEB-INF/head.jsp"%>
// 用于添加时弹出框里嵌入表格的插件
<script src="/easyui/plugin/editcell/jeasyui.extensions.datagrid.getColumnInfo.js"></script>
<script src="/easyui/plugin/editcell/jeasyui.extensions.datagrid.editors.js"></script>
<script src="/easyui/plugin/editcell/jeasyui.extensions.datagrid.edit.cellEdit.js"></script>
<script type="text/javascript" src="/js/purchasebill.js"></script>
<html>
<head>
<title>Title</title>
</head>
<body>
<table id="purchasebillGrid" class="easyui-datagrid" data-options="fit:true,fixed:true,fitColumns:true,toolbar:'#tb',singleSelect:false";
url="/purchasebill/list"
iconCls="icon-save"
rownumbers="true" pagination="true">
<thead>
<tr>
<th data-options="field:'id',checkbox:true,width:'2%'">ID</th>
<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>
<!-- 高级查询-->
<div id="tb" style="padding:10px;height:auto">
<div>
<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>
</div>
<div style="margin-bottom:5px">
<a href="javascript:void(0);" data-method="add" class="easyui-linkbutton" iconCls="icon-add" plain="true"></a>
<a href="javascript:void(0);" data-method="edit" class="easyui-linkbutton" iconCls="icon-edit" plain="true"></a>
<a href="javascript:void(0);" data-method="delete" class="easyui-linkbutton" iconCls="icon-remove"
plain="true"></a>
</div>
</div>
<%--弹出框对应的按钮--%>
<div id="bb">
<a href="javascript:void(0);" data-method="saveData" class="easyui-linkbutton c3" data-options="plain:true">保存</a>
<a href="javascript:void(0);" onclick="$('#dlg').dialog('close')" class="easyui-linkbutton c4"
data-options="plain:true">关闭</a>
</div>
<%--
easyui的时候,查看默认属性与事件
$.fn.{plugin}.defaults
弹出框html代码
--%>
<div id="dlg" class="easyui-dialog" data-options="width:800,height:500,buttons:'#bb',closed:true">
<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>
<!-- 采购单的明细编辑 -->
<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>
</form>
</div>
</body>
</html>
因为添加时需要供货商和采购人员所有我们要准备两给查询方法:
//findAllSupplier
//查询供货商
@RequestMapping("/findAllSupplier")
@ResponseBody
public List<Supplier> findAllSupplier(){
return supplierService.findAll();
}
//查询所有的采购部人员
@RequestMapping("/getBuyer")
@ResponseBody
public List<Employee> getBuyer(){
return employeeService.getBuyer();
}
因为我们要做明细数据所以我们要引用easyui的插件上面已经引入了下面准备js代码:
$(function () {
//产品productId productColor颜色 productImage 图像 amount 小计。。。。
var dg = $("#gridItems"),
defaultRow = { productId: "", productColor: "", productImage: "", 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: {
valueField:'id',
textField:'name',
panelHeight:'auto',
url:'/util/getProduct',
required: true
}
},
formatter:function(value,row){
return value.name;
}
},
{
field: 'productColor', title: '颜色', width: 180,
formatter:function(value,row){
if(row && row.productId){
return ""
}
}
},
{
field: 'productImage', title: '产品图片', width: 100,
formatter:function(value,row){
if(row && row.productId){
return ""
}
}
},
{
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 && row.productId){
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;
};
var options = {
idField: "ID",
rownumbers: true,
fitColumns: true,
fit: true,
toolbar:'#itemBtns',
border: false,
singleSelect: true,
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: "Code" });
});
$("#btnSave").click(function () {
var rows = dg.datagrid("getRows"), len = rows.length;
for (var i = 0; i < len; i++) {
dg.datagrid("endEdit", i);
}
});
$("#btnRemove").click(function () {
//获取选中行
var row = dg.datagrid("getSelected");
//获取选中行的索引 getRowIndex
var index = dg.datagrid("getRowIndex",row);
//根据索引删除行
dg.datagrid("deleteRow",index);
});
};
dgInit(); buttonBindEvent();
});
因为表格有些数据时链接的所以我们要做处理:
//供货商的处理
function formatObj(obj){
if(obj){
return obj.name;
}
return "";
}
//采购员
function formatEmp(obj){
if(obj){
return obj.username;
}
return "";
}
//formatStatus 审核的处理
function formatStatus(value){
var data = {
0:"待审",
1:"已审",
"-1":"作废"
}
return data[value];
}
整个明细表单的crud:
$(function () {
//给所有a标签都注册一个事件
$("a").on("click", function () {
//动态获取data-method属性对应的值
var method = $(this).data("method");
//method不能为空
if(method){
//动态触发事件
itsource[method]();
}
});
//datagrid对应的jquery对象
var purchasebillGrid = $("#purchasebillGrid");
//弹出框对应的jquery对象
var dlg = $("#dlg");
//form表单对应的jquery对象(弹出框)
var purchasebillForm = $("#purchasebillForm");
//编辑明细表格
var gridItem = $("#gridItems");
itsource = {
//高级查询
"search":function(){
//把form表单元素,直接封装成一个json对象
var jsonObj = $("#searchForm").serializeObject();
//加载datagrid
purchasebillGrid.datagrid('load',jsonObj);
},
//删除
"delete":function(){
//获取选中的行
var rows = purchasebillGrid.datagrid("getSelections");
//在js中认为false的值:0 false "" null NaN undefined
if(!rows.length){
$.messager.alert('操作错误','亲!请选中数据进行删除!','error');
return;
}
//定义一个数组,该数组把所有的id都给装进来
var ids = [];
//循环数组中的所有数据
$.each(rows, function (i, o) {
//把id装进数组中
ids.push(o.id);
});
$.messager.confirm('确认', '你确定要离我而去吗?', function(r){
if (r){
$.get("/purchasebill/delete",{"ids":ids.toString()},function(result){
if(result.success){
//刷新界面
purchasebillGrid.datagrid("reload");
}else{
$.messager.alert('失败',result.msg,'error');
}
});
}
});
},
//添加按钮,弹出窗体
"add":function(){
//弹出窗体,居中,并且设置标题,动态修改高度
dlg.dialog("open").dialog("center").dialog("setTitle","添加采购数据").dialog("resize",{
height:450
});
//清空form表单中所有的值
purchasebillForm.form("clear");
//清空f表格
gridItem.datagrid('loadData',[]);
},
//修改按钮,弹出窗体
"edit":function(){
//获取即将要修改的数据(单个对象)
//var row = purchasebillGrid.datagrid("getSelections");
var row = purchasebillGrid.datagrid("getSelected");
//没有选中就会返回null
if(!row){
$.messager.alert('操作错误','亲!请选中数据进行修改!','error');
return;
}
//弹出窗体,居中,设置标题 动态修改它的宽度和高度
dlg.dialog("open").dialog("center").dialog("setTitle","修改采购数据").dialog("resize",{
height:450
});
if(row.supplier){
row["supplier.id"]=row.supplier.id;
}
if(row.buyer){
row["buyer.id"]=row.buyer.id;
}
//回显数据
purchasebillForm.form('load',row);
//循环取出明细数据
for (var i = 0; i < row.items.length; i++) {
row.items[i].productId = row.items[i].product;
}
var items = $.extend([], row.items);
gridItem.datagrid("loadData", items);
},
//保存数据
"saveData":function(){
var url = "/purchasebill/save";
if($("#purchasebillid").val()){
url = "/purchasebill/update?cmd=update";
}
//提交form表单
purchasebillForm.form('submit', {
url:url,
onSubmit: function(params){//提交之前先做验证
//获取编辑表格所有数据
var rows = gridItem.datagrid('getRows');
for(var i=0;i<rows.length;i++){
//明细表格每个数据
var rowData = rows[i];
params["items["+i+"].product.id"] = rowData.productId.id;
params["items["+i+"].price"] = rowData.price;
params["items["+i+"].num"] = rowData.num;
params["items["+i+"].descs"] = rowData.descs;
if(!gridItem.datagrid('validateRow',i)){
alert('明细行还有问题,请编辑');
return false;
}
}
return true;//验证通过之后才返回true,否则返回false,false它会阻止你提交
},
success:function(data){
//把json字符串转为对象
var result = $.parseJSON(data);
if(result.success){
//关闭窗体
dlg.dialog("close");
//刷新界面
purchasebillGrid.datagrid("reload");
}else{
$.messager.alert('操作错误',result.msg,'error');
}
}
});
}
}
});