一、我的销售订单
1、需求及实现思路
与采购订单功能类似,只列出我的销售订单且状态是未出库的
2、代码实现
(1)修改orders.js添加一些判断,以及当现实不同的页面时创建不同的按钮
(2)修改OrdersBiz
(3)修改orders_add.js
(4)修改orders.html
(5)继续修改orders.js
(6)继续修改orders_add.js
3、销售订单查询
(1)修改orders.js当中的内容
(2)修改orders.js当中的getState方法
(3)orders.js当中创建getColums方法
/*
* getColums
* 根据订单类型,获取不同列的内容
*/
function getColums(){
if(Request['type'] * 1 == 1){
return [[
{
field:'uuid',title:'编号',width:100},
{
field:'createtime',title:'生成日期',width:100,formatter:formatDate},
{
field:'checktime',title:'审核日期',width:100,formatter:formatDate},
{
field:'starttime',title:'确认日期',width:100,formatter:formatDate},
{
field:'endtime',title:'入库日期',width:100,formatter:formatDate},
{
field:'createrName',title:'下单员',width:100},
{
field:'checkerName',title:'审核员',width:100},
{
field:'starterName',title:'采购员',width:100},
{
field:'enderName',title:'库管员',width:100},
{
field:'supplierName',title:'供应商',width:100},
{
field:'totalmoney',title:'合计金额',width:100},
{
field:'state',title:'状态',width:100,formatter:getState},
{
field:'waybillsn',title:'运单号',width:100}
]];
}
if(Request['type'] * 1 == 2){
return [[
{
field:'uuid',title:'编号',width:100},
{
field:'createtime',title:'生成日期',width:100,formatter:formatDate},
{
field:'endtime',title:'出库日期',width:100,formatter:formatDate},
{
field:'createrName',title:'下单员',width:100},
{
field:'enderName',title:'库管员',width:100},
{
field:'supplierName',title:'客户',width:100},
{
field:'totalmoney',title:'合计金额',width:100},
{
field:'state',title:'状态',width:100,formatter:getState},
{
field:'waybillsn',title:'运单号',width:100}
]];
}
}
(4)在调用getColums()方法
(5)实现的效果
5、销售订单出库
(1)需求及实现思路
1)此功能与“采购订单入库”功能极为类似
2)需要注意的问题是出库时需要校验库存是否大于出库量
3)销售订单的流程比采购流程简单,没有审核、确认环节
(2)在IOrderdetailBiz接口当中添加出库的方法
(3)在Orderdetail当中添加出库的属性
(4)在上述接口的的实现方法当中
/*
* 出库
*/
@Override
public void doOutStore(Long uuid, Long storeuuid, Long empuuid) {
// 一、第一步,更新订单信息
// 1、更新明细的状态,获取明细信息
Orderdetail orderdetail = orderdetailDao.get(uuid);// 通过uuid获取订单明细
// 2、在入库前判断订单明细的状态是否为入库的状态
if (!Orderdetail.STATE_NO_OUT.equals(orderdetail.getState())) {
throw new ErpException("亲!该明细已经出库了,不能重复出库哦!");
}
// 3、修改状态已经出库
orderdetail.setState(Orderdetail.STATE_IN);
// 4、出库时间
orderdetail.setEndtime(new Date());
// 5.出库管理人员
orderdetail.setEnder(empuuid);
// 6、出到哪一个仓库
orderdetail.setStoreuuid(storeuuid);
// 以上设置的值会自动保存到数据库当中
// 第二步出库
// 1、构建查询条件 查询的条件,查询对应
Storedetail storedetail = new Storedetail();
storedetail.setGoodsuuid(orderdetail.getGoodsuuid());
storedetail.setStoreuuid(storeuuid);
// 2、通常查询 检查是否在库存信息(对应订单详情的库存信息)
List<Storedetail> storeList = storedetailDao.getList(storedetail, null, null);
// 如果通过订单明细可以查询到对应的库存信息
if (storeList.size() > 0) {
// 存在的话,则应该累加数据
Storedetail sd = storeList.get(0);
sd.setNum(sd.getNum() - orderdetail.getNum() );
if(sd.getNum() < 0) {
throw new ErpException("库存不足");
}
} else {
throw new ErpException("库存不足");
}
/* 第三步增加操作记录 */
Storeoper log = new Storeoper();// 获取操作记录的对象
// 设置操作员的id
log.setEmpuuid(empuuid);
// 设置商品id,当前商品id就是当前订单的id
log.setGoodsuuid(orderdetail.getGoodsuuid());
// 设置数量操作记录的数量为当前订单详情的数量
log.setNum(orderdetail.getNum());
// 设置操作时间为当前订单入库的时间
log.setOpertime(orderdetail.getEndtime());
// 设置入库到那个仓库的记录
log.setStoreuuid(storeuuid);
// 设置当前记录的状态为1
log.setType(Storeoper.TYPE_OUT);
// 保存到数据库当中(将操作记录保存到数据库当中)
storeoperDao.add(log);
/*
* 第四部,判断当前订单下 所有的订单是否都已经更新完成(即出库完成)
*/
// 1、查询当前订单是否还存在,状态为0 (0为未出库)的明细
// 2、count(1) where state = 0 orderuuid = 为当前订单的uuid
// 构建查询条件
Orderdetail queryParam = new Orderdetail();
Orders orders = orderdetail.getOrders();// 获取订单明细对应的订单信息
queryParam.setOrders(orders);// 设置订单是当前订单明细,对应的订单
queryParam.setState(Orderdetail.STATE_NO_OUT);// 设置查询条件状态为0,未审核
// 3、调用getCount方法,来计算是否存在状态为0的明细
long count = orderdetailDao.getCount(queryParam, null, null);
if (count == 0) {
// 4、 代表的所有订单当中 的订单明细都已经出库了
orders.setState(Orders.STATE_OUT);// 设置当前订单装为结束
orders.setEndtime(orderdetail.getEndtime());// 并设置当前订单结束时间为当前订单明细 的结束时间
orders.setEnder(empuuid);// 设置库管员
// 应为在上面过去过订单 状态
}
}
(5)在OrderdetailAction当中
(6)销售出库前端实现
修改orders.js以及添加一些方法
将doInStore改为doInOutStore并添加一些判断和属性
入库演示
出库演示
6、商品库存管理
6.1设置查询以及查询显示
(1)商品库存查询:修改storedetail.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>仓库库存管理</title>
<link rel="stylesheet" type="text/css" href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>
<script type="text/javascript" src="js/storedetail.js"></script>
<script type="text/javascript">
var name="storedetail";
var columns=[[
{
field:'uuid',title:'编号',width:100},
{
field:'storeuuid',title:'仓库编号',width:100},
{
field:'goodsuuid',title:'商品编号',width:100},
{
field:'num',title:'数量',width:100},
{
field:'-',title:'操作',width:200,formatter:function(value,row,index)
{
return "<a href='#' οnclick='edit("+row.uuid+")'>修改</a> <a href='#' οnclick='dele("+row.uuid+")'>删除</a>";
}}
]];
</script>
</head>
<body>
<div class="easyui-panel" style="padding-left:4px;border-bottom:0px;" >
<div style="height:2px;"></div>
<form id="searchForm">
仓库:<input name="t1.storeuuid" class="easyui-combobox" data-options="
url:'store_list',valueField:'uuid',textField:'name'
" >
商品:<input name="t1.goodsuuid" class="easyui-combobox" data-options="
url:'goods_list',valueField:'uuid',textField:'name'
" >
<button type="button" id="btnSearch">查询</button>
</form>
<div style="height:2px;"></div>
</div>
<table id="grid"></table>
</body>
</html>
(2)修改创建storedetail.js
$(function(){
// 列表
$('#grid').datagrid({
url : 'storedetail_listByPage',
columns : [[
{
field:'uuid',title:'编号',width:100},
{
field:'storeName',title:'仓库',width:100},
{
field:'goodName',title:'商品',width:100},
{
field:'num',title:'数量',width:100}
]],
singleSelect : true,
pagination : true
});
})
(3)修改Storedetail,添加一些属性,添加仓库名称和商品名称
(4)在StoredetailBiz当中重写getListByPage方法,通过反射设置对应的属性以及一些其他的方法
/*
* 分页查询
*/
public List<Storedetail> getListByPage(Storedetail t1, Storedetail t2, Object param, int firstResult,
int maxResults) {
List<Storedetail> list = super.getListByPage(t1, t2, param, firstResult, maxResults);
Map<Long, String> goodsNameMap = new HashMap<Long, String>();
Map<Long, String> storeNameMap = new HashMap<Long, String>();
for(Storedetail sd : list) {
//遍历库存集合,
//通过商品的id取到的商品的集合,将其放入到库存当中的商品库存集合当中
sd.setGoodsName(getGoodsName(sd.getGoodsuuid(), goodsNameMap));
//通过仓库的id取到的仓库的集合,将其放入到库存的仓库库存的集合当中
sd.setStoreName(getStoreName(sd.getStoreuuid(),storeNameMap));
}
return list;
}
private String getGoodsName(Long uuid, Map<Long, String> goodsNameMap) {
// 通过当前集合当中的uuid获取对应的值的员工姓名
if (null == uuid) {
return null;
}
String goodsName = goodsNameMap.get(uuid);
// 先从Map集合当中通过对应的id获取name如果有就不需要获取对应的姓名,如果没有就通过id、
// 重新向数据库查询对应id的name并将其id】和姓名放入到map 集合当中
if (null == goodsName) {
// 如果没有找到员工的名称,则进行数据库查询
goodsName = goodsDao.get(uuid).getName();// 通过id查询对应员工的姓名
// 存入缓存中
goodsNameMap.put(uuid, goodsName);// 将员工的id和姓名存入emp集合当中
}
return goodsName;
}
private String getStoreName(Long uuid, Map<Long, String> storeNameMap) {
// 通过当前集合当中的uuid获取对应的值的员工姓名
if (null == uuid) {
return null;
}
String storeName = storeNameMap.get(uuid);
// 先从Map集合当中通过对应的id获取name如果有就不需要获取对应的姓名,如果没有就通过id、
// 重新向数据库查询对应id的name并将其id】和姓名放入到map 集合当中
if (null == storeName) {
// 如果没有找到员工的名称,则进行数据库查询
storeName = storeDao.get(uuid).getName();// 通过id查询对应员工的姓名
// 存入缓存中
storeNameMap.put(uuid, storeName);// 将员工的id和姓名存入emp集合当中
}
return storeName;
}
(5)在applicationContext_biz.xml配置文件当中注入对应的内容
6.2设置查询搜索
7、库存变动记录查询
(1)需求分析
需求:库存变动记录表查询,查询条件为商品(自动补全下拉列表)仓库(下拉列表)、日期范围搜索、操作员(自动补全下拉列表)、类型(出库,入库)
(2)代码实现
1)修改Storeoper的getDetachedCriteria方法,在StoreoperDao 当中添加条件BaseDao当中实现查询
package com.itzheng.erp.dao.impl;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import com.itzheng.erp.dao.IStoreoperDao;
import com.itzheng.erp.entity.Storeoper;
/**
* 仓库操作记录数据访问类
* @author Administrator
*
*/
public class StoreoperDao extends BaseDao<Storeoper> implements IStoreoperDao {
/**
* 构建查询条件
* @param dep1
* @param dep2
* @param param
* @return
*/
public DetachedCriteria getDetachedCriteria(Storeoper storeoper1,Storeoper storeoper2,Object param){
DetachedCriteria dc=DetachedCriteria.forClass(Storeoper.class);
if(storeoper1!=null){
//根据类型查询
if(storeoper1.getType()!=null && storeoper1.getType().trim().length()>0)
{
dc.add(Restrictions.eq("type", storeoper1.getType()));
}
//商品查询
if(storeoper1.getGoodsuuid()!=null)
{
dc.add(Restrictions.eq("goodsuuid", storeoper1.getGoodsuuid()));
}
//仓库
if(storeoper1.getStoreuuid() != null)
{
dc.add(Restrictions.eq("storeuuid", storeoper1.getStoreuuid()));
}
//员工
if(storeoper1.getEmpuuid() !=null)
{
dc.add(Restrictions.eq("empuuid", storeoper1.getEmpuuid()));
}
//操作时间,开始
if(null != storeoper1.getOpertime()) {
dc.add(Restrictions.ge("opertime", storeoper1.getOpertime()));
}
}
if(null != storeoper2) {
//操作时间结束
if(null != storeoper2.getOpertime()) {
dc.add(Restrictions.le("opertime", storeoper1.getOpertime()));
}
}
return dc;
}
}
2)在StoreoperBiz中,重写listByPage方法:
package com.itzheng.erp.biz.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import com.itzheng.erp.biz.IStoreoperBiz;
import com.itzheng.erp.dao.IStoreoperDao;
import com.itzheng.erp.entity.Storeoper;
/**
* 仓库操作记录业务逻辑类
* @author Administrator
*
*/
public class StoreoperBiz extends BaseBiz<Storeoper> implements IStoreoperBiz {
private IStoreoperDao storeoperDao;
public void setStoreoperDao(IStoreoperDao storeoperDao) {
this.storeoperDao = storeoperDao;
setBaseDao(storeoperDao);
}
/**
* 分页条件查询
*/
public List<Storeoper> getListByPage(Storeoper t1, Storeoper t2, Object param, int firstResult, int maxResults) {
List<Storeoper> logList = super.getListByPage(t1, t2, param, firstResult, maxResults);
return logList;
}
}
3)修改BaseBiz,添加getGoodsName和getStoreName以及getEmpName
public String getGoodsName(Long uuid, Map<Long, String> goodsNameMap, IGoodsDao goodsDao) {
// 通过当前集合当中的uuid获取对应的值的员工姓名
if (null == uuid) {
return null;
}
String goodsName = goodsNameMap.get(uuid);
// 先从Map集合当中通过对应的id获取name如果有就不需要获取对应的姓名,如果没有就通过id、
// 重新向数据库查询对应id的name并将其id】和姓名放入到map 集合当中
if (null == goodsName) {
// 如果没有找到员工的名称,则进行数据库查询
goodsName = goodsDao.get(uuid).getName();// 通过id查询对应员工的姓名
// 存入缓存中
goodsNameMap.put(uuid, goodsName);// 将员工的id和姓名存入emp集合当中
}
return goodsName;
}
public String getStoreName(Long uuid, Map<Long, String> storeNameMap, IStoreDao storeDao) {
// 通过当前集合当中的uuid获取对应的值的员工姓名
if (null == uuid) {
return null;
}
String storeName = storeNameMap.get(uuid);
// 先从Map集合当中通过对应的id获取name如果有就不需要获取对应的姓名,如果没有就通过id、
// 重新向数据库查询对应id的name并将其id】和姓名放入到map 集合当中
if (null == storeName) {
// 如果没有找到员工的名称,则进行数据库查询
storeName = storeDao.get(uuid).getName();// 通过id查询对应员工的姓名
// 存入缓存中
storeNameMap.put(uuid, storeName);// 将员工的id和姓名存入emp集合当中
}
return storeName;
}
// 获取员工的名称
// uuid 员工编号
// empNameMap 员工编号以及员工的名称
// 返回员工的名称
public String getEmpName(Long uuid, Map<Long, String> empNameMap,IEmpDao empDao) {
// 通过当前集合当中的uuid获取对应的值的员工姓名
if (null == uuid) {
return null;
}
String empName = empNameMap.get(uuid);
// 先从Map集合当中通过对应的id获取name如果有就不需要获取对应的姓名,如果没有就通过id、
// 重新向数据库查询对应id的name并将其id】和姓名放入到map 集合当中
if (null == empName) {
// 如果没有找到员工的名称,则进行数据库查询
empName = empDao.get(uuid).getName();// 通过id查询对应员工的姓名
// 存入缓存中
empNameMap.put(uuid, empName);// 将员工的id和姓名存入emp集合当中
}
return empName;
}
4)修改OrdersBiz删除getEmpName方法修改getListByPage方法
5)修改Storeoper设置属性并生成对应的值
6)回到StoreoperBiz当中,注入biz,修改getListByPage方法并设置对应的缓存分别查询员工集合
package com.itzheng.erp.biz.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.criterion.DetachedCriteria;
import com.itzheng.erp.biz.IStoreoperBiz;
import com.itzheng.erp.dao.IEmpDao;
import com.itzheng.erp.dao.IGoodsDao;
import com.itzheng.erp.dao.IStoreDao;
import com.itzheng.erp.dao.IStoreoperDao;
import com.itzheng.erp.entity.Storeoper;
/**
* 仓库操作记录业务逻辑类
*
* @author Administrator
*
*/
public class StoreoperBiz extends BaseBiz<Storeoper> implements IStoreoperBiz {
private IStoreoperDao storeoperDao;
private IEmpDao empDao;
private IGoodsDao goodsDao;
private IStoreDao storeDao;
public void setEmpDao(IEmpDao empDao) {
this.empDao = empDao;
}
public void setGoodsDao(IGoodsDao goodsDao) {
this.goodsDao = goodsDao;
}
public void setStoreDao(IStoreDao storeDao) {
this.storeDao = storeDao;
}
public void setStoreoperDao(IStoreoperDao storeoperDao) {
this.storeoperDao = storeoperDao;
setBaseDao(storeoperDao);
}
/**
* 分页条件查询
*/
public List<Storeoper> getListByPage(Storeoper t1, Storeoper t2, Object param, int firstResult, int maxResults) {
List<Storeoper> logList = super.getListByPage(t1, t2, param, firstResult, maxResults);
Map<Long, String> empNameMap = new HashMap<Long, String>();
Map<Long, String> goodsNameMap = new HashMap<Long, String>();
Map<Long, String> storeNameMap = new HashMap<Long, String>();
for(Storeoper log : logList ) {
log.setEmpName(getEmpName(log.getEmpuuid(),empNameMap,empDao));
log.setGoodsName(getGoodsName(log.getGoodsuuid(), goodsNameMap, goodsDao));
log.setStoreName(getStoreName(log.getStoreuuid(), storeNameMap, storeDao));
}
return logList;
}
}
7)在配置文件当中注入该上述的biz,applicationContext_biz.xml当中
8)修改storeoper.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>仓库操作记录管理</title>
<link rel="stylesheet" type="text/css" href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>
<script type="text/javascript" src="ui/date.js"></script>
<script type="text/javascript" src="js/storeoper.js"></script>
</head>
<body>
<div class="easyui-panel">
<form id="searchForm">
操作员号:<input name="t1.empuuid" class="easyui-combobox" data-options="
url:'emp_list',valueField:'uuid',textField:'name'
" >
操作日期:<input name="t1.opertime" class="easyui-datebox">-><input name="t2.opertime" class="easyui-datebox">
仓库:<input name="t1.storeuuid" class="easyui-combobox" data-options="
url:'store_list',valueField:'uuid',textField:'name'
" >
商品:<input name="t1.goodsuuid" class="easyui-combobox" data-options="
url:'goods_list',valueField:'uuid',textField:'name'
" >
类型:<input name="t1.type" class="easyui-combobox" data-options="
data:[{
uuid:'',name:'全部'},{
uuid:'1',name:'入库'},{
uuid:'2',name:'出库'}],valueField:'uuid',textField:'name'
" >
<button type="button" id="btnSearch">查询</button>
</form>
</div>
<table id="grid"></table>
</body>
</html>
9)创建storeoper.js
$(function(){
$('#grid').datagrid({
url:'storeoper_listByPage',
columns:[[
{
field:'uuid',title:'编号',width:100},
{
field:'empName',title:'操作员工编号',width:100},
{
field:'opertime',title:'操作日期',width:100:formatDate},
{
field:'storeName',title:'仓库编号',width:100},
{
field:'goodsName',title:'商品编号',width:100},
{
field:'num',title:'数量',width:100},
{
field:'type',title:'类型',width:100,formatter:function(value){
//1:入库,2:出库
if(value * 1 == 1){
return "入库";
}
if(value * 1 == 2){
return "出库";
}
}}
]],
singleSelect:true,//设置只选择一行
pagination:true,
fitColumns:true
});
//点击查询按钮
$('#btnSearch').bind('click',function(){
//把表单数据转换成json对象
var formData = $('#searchForm').serializeJSON();
$('#grid').datagrid('load',formData);//将表单数据加载到id为grid的标签当中去
});
})
function formatDate(value){
return new Date(value).Format('yyyy-MM-dd hh:mm:ss');
}
10)筛选日期时发现有问题修改StoreoperDao
//操作时间,开始
if(null != storeoper1.getOpertime()) {
Calendar car = Calendar.getInstance();
car.setTime(storeoper1.getOpertime());
car.set(Calendar.HOUR, 0);
car.set(Calendar.MINUTE, 0);
car.set(Calendar.SECOND, 0);
car.set(Calendar.MILLISECOND, 0);
//2020-02-01 15:30:05 通过上诉的操作,将前面的日期转换为 2020-02-01 00:00:00
dc.add(Restrictions.ge("opertime", car.getTime()));
}
}
if(null != storeoper2) {
if(null != storeoper2.getOpertime()) {
Calendar car = Calendar.getInstance();
car.setTime(storeoper2.getOpertime());
car.set(Calendar.HOUR, 23);
car.set(Calendar.MINUTE, 59);
car.set(Calendar.SECOND, 59);
car.set(Calendar.MILLISECOND, 999);
//2020-02-01 15:30:05 通过上诉的操作,将前面的日期转换为 2020-02-01 23:59:59
//操作时间结束
dc.add(Restrictions.le("opertime", car.getTime()));
}
}
二、自动补全
1、需求分析
在采购申请(销售订单录入)界面中,当用户在供应商(客户)输入部分内容,
下拉面板中的数据会自动模糊搜索给出结果