SSSDJ day10

2.采购订单的模型分析
2.1.从页面怎样判断数据库的关系
如果是下拉列表:一般是多对一,一对一
如果是复选框:一般是多对多,一对多
2.2.类图

2.3.组合关系
2.3.1.页面处理方式
在一个页面同时操作2张表采购订单和采购订单明细
2.3.2.组合关系映射配置要求
1.整体和部分,整体和部分不能分割,本质还是双向一对多
2.一方(主表):
@OneToMany(cascade = CascadeType.ALL, mappedBy = “bill”, fetch = FetchType.LAZY, orphanRemoval = true)
private List items = new ArrayList();
cascade = CascadeType.ALL级联操作最全
mappedBy = "bill"一方放弃管理多方,多方的外键字段bill_id,一方不管
orphanRemoval = true如果在一方解除了和多方的关系,一方是可以删除掉多方
3.多方(从表)billitem:bill_id配置为非空
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = “bill_id”)
private Purchasebill bill;// 组合关系,非空
4.页面管理:一方和多方同时管理
2.3.3.怎样知道关系组合关系呢?
一般只要涉及到订单的表,报销的表都是组合关系,都有总表,从表概念
组合关系在保存的时候:(多方必需知道一方,而一方也必需知道多方)
前提: 订单.get订单明细();/订单明细.get订单()
2.4.采购订单表和员工表有3个关系
2.4.1.关系数据库
CONSTRAINT FK9BD788C83FF7A83F FOREIGN KEY (auditor_id) REFERENCES employee (id),
CONSTRAINT FK9BD788C89FE0CD6A FOREIGN KEY (buyer_id) REFERENCES employee (id),
CONSTRAINT FK9BD788C8A902BD48 FOREIGN KEY (inputUser_id) REFERENCES employee (id)
2.4.2.文字说明
一个采购员buyer_id可以下采购多张采购订单,需要选择框
一个制单员inputUser_id可以填写多张采购订单,录入人就是当前登录用户
一个采购经理auditor_id可以审核多张采购订单,外键可以为空,审核的当前登录用户

2.1.一个供应商可以下多张采购订单

2.2.怎样用Rational Rose Enterprise画组合关系

2.3.采购订单其他属性:
vdate datetime 交易时间,建议可以录入-15天,并且把-15保存到数据库config表里面
totalAmount decimal(19,2) 总金额
totalNum decimal(19,2) 总数量,一般数量都是设计为int,但是现在项目属于产品,设计产品考虑通用性
inputTime datetime 录入时间
auditorTime datetime 审核时间
status int(11) 状态,非常重要字段,根据状态做一些业务操作,0待审,1已审,-1作废
2.4.产品和系统差异
系统是专门给一个特定的客户开发,不具有通用性
产品是对类似的系统抽取公共功能,形成一个系统,具有通用性(二次开发)
2.5.采购订单明细其他属性:
price decimal(19,2) 采购价格
num decimal(19,2) 采购数量
amount decimal(19,2) 采购小计
descs varchar(255) 备注
2.6.那些属性不能为null
2.6.1.采购订单
录入员,采购员,供应商外键值
supplier_id bigint(20) NOT NULL,
inputUser_id bigint(20) NOT NULL,
buyer_id bigint(20) NOT NULL,
2.6.2.采购订单明细
产品,订单外键值
product_id bigint(20) NOT NULL,
bill_id bigint(20) NOT NULL,
3.组合关系-采购订单模型完整代码
3.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 items = new ArrayList();


@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;
}

3.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;// 组合关系,非空
4.订单列表查询
4.1.订单列表显示
4.1.1.purchasebill.jsp展示

4.1.2.purchasebill.js
function formatObj(data) {
if(data){
return data.name;
}
}
function formatEmp(data) {
if(data){
return data.username;
}
}
function formatStatus(action) {
var data = {
0:“

待审
”,
1:“
已审
”,
“-1”:“
作废

};
return data[action];
}

展示出来的效果如下:

4.2.查询条件的添加
4.2.1.purchasebill.jsp

日期 : -
状态 :<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>
查找

4.2.2.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略…

}

效果如下:

4.3.查询的日期问题
4.4.PurchasebillQuery .java结束时间查询处理
4.4.1.最好的设计
应该把vdate设计为date类型(yyyy-MM-dd),而不是datetime时间戳
4.4.2.为什么现在要设计datetime
面试要知道怎样对日期进行加减
4.4.3.不能查询出数据的原因
1.前端的日期时分秒按照0:00:00来处理,如果不对日期+1处理,结束时间是不能成功获取查询的值.
如下单时间是09-30 15:00:00,而endDate输入09-30,后台获取到09-30 0:00:00
2.加了一天之后进行查询,不能写<=,只能写<
4.4.4.方案1:直接计算
if(endDate != null) {
Date date = new Date(endDate.getTime() + 24 * 60 * 60 * 1000);
System.out.println(“date:” + date.toLocaleString());
}
4.4.5.方案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());
}
4.4.6.方案3:org.apache.commons.lang.time.DateUtils
当前日期业务最简单的方法
if(endDate != null) {
Date date = DateUtils.addDays(endDate, 1);
}

4.4.7.功能代码(完整)
@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;

}

5.添加采购订单
5.1.采购订单的form表单
purchasebill.jsp

交易时间:

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

5.2.2.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 getBuyer() {
return employeeRepository.getEmpByDept(“采购部”);
}

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

5.3.数据保存
这时候保存会报错

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

6.明细数据的操作
首先,我们可以去找到相应的插件:
http://www.easyui-extlib.com/ ->Datagrid-Edit -单元格编辑
把相应的示例与js代码拷备下来

6.1.引入支持的js
注意引入的位置

purchasebill管理 <%@include file="/WEB-INF/views/head.jsp" %>

6.2.拷备案例中数据
案例文件:CellEditDemo.html
6.2.1.purchasebill.jsp

6.2.2.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();

最后效果:

6.3.基本数据准备
6.3.1.修改明细数据为产品数据
//defaultRow:默认的行(每次添加一行都是把这个数据加进去)
// 分别加上产品id,产品颜色,产品图片,数量,价格,总价与备注
var gridItems = $("#gridItems"),
defaultRow = { productId: “”, productColor: “”, productImage: “”,num: 0, price: 0, amount: 0, descs: “” },
insertPosition = “bottom”;

6.3.2.后台返回所有产品(可供选择)
@Controller
@RequestMapping("/util")
public class UtilController extends BaseController {

@Autowired
private IProductService productService;

...

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

}

6.3.3.选择产品进行展示
//对于明细数据的初始化
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 “

”;
}
}
},
{
field: ‘productImage’, title: ‘图片’, width: 80,
formatter:function(value,row){
console.debug(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.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;
};

6.3.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);
});
};

效果:

6.4.采购单保存
6.4.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’);
}
})
},

6.4.2.后台进行保存
//添加或者修改
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 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;

}

6.5.其它细节处理
6.5.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”);
},

6.5.2.修改时回显明细
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');
}

},

6.5.3.解决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、付费专栏及课程。

余额充值