Commit da1c9307 authored by reedmi's avatar reedmi

完成实时库存查看

parent f759ed43
......@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.originspark.drp.models.User;
import com.originspark.drp.service.projects.inventories.InventoryService;
import com.originspark.drp.service.projects.invoices.StockInInvoiceService;
import com.originspark.drp.service.projects.invoices.StockOutInvoiceService;
import com.originspark.drp.service.resources.VendorService;
......@@ -40,6 +41,9 @@ public class BaseController extends HandlerInterceptorAdapter {
@Autowired
protected StockOutInvoiceService stockOutInvoiceService;
@Autowired
protected InventoryService inventoryService;
private static final ThreadLocal<HttpServletRequest> REQUEST = new ThreadLocal<HttpServletRequest>();
private static final ThreadLocal<HttpServletResponse> RESPONSE = new ThreadLocal<HttpServletResponse>();
......
package com.originspark.drp.controllers.projects.inventories;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.originspark.drp.controllers.BaseController;
import com.originspark.drp.util.FileUtil;
import com.originspark.drp.util.poi.exporter.MonthendInventoryGenerator;
import com.originspark.drp.models.User;
import com.originspark.drp.web.models.projects.inventories.CurrentInventoryUI;
import com.originspark.drp.web.models.projects.inventories.Ware;
@Controller
@RequestMapping("project")
@RequestMapping("inventories")
public class InventoryController extends BaseController {
/*@RequestMapping(value = "/{id}/inventories/current", method = RequestMethod.GET)
@RequestMapping(value = "/current", method = RequestMethod.GET)
@ResponseBody
@AuthRoleGroup(type={RoleEnum.WAREKEEPER,RoleEnum.PROJECTMANAGER,RoleEnum.LEADER})
public String currentInventories(@PathVariable Long id){
Project project = projectService.findById(id);
if(project == null){
return failure("你所查询的项目不存在");
}
List<CurrentInventoryUI> inventories = new ArrayList<CurrentInventoryUI>();
//如果是项目
if(project.getProject() == null){
for(Project system : project.getSystems()){
inventories.addAll(projectService.getCurrentInventories(system.getId()));
}
return ok(inventories);
}
inventories.addAll(projectService.getCurrentInventories(id));
return ok(inventories);
public String currentInventories(@RequestParam int start, @RequestParam int limit) {
List<CurrentInventoryUI> data = inventoryService.pagedCurrentInventories(start, limit);
Long count = inventoryService.pagedCurrentInventoriesCount();
return ok(data, count);
}
/*
@ResponseBody
@RequestMapping(value = "/{id}/inventories/monthend", method = RequestMethod.GET)
@AuthRoleGroup(type={RoleEnum.PROJECTMANAGER,RoleEnum.LEADER})
......
......@@ -34,12 +34,11 @@ public class VendorController extends BaseController {
public String create(@RequestBody Vendor vendor) {
String contactMan = vendor.getContactMan();
if (contactMan == null || contactMan.trim().equals("")) {
if (StringUtils.isEmpty(contactMan)) {
return failure("联系人不能为空");
}
String name = vendor.getName();
if (!StringUtils.isEmpty(name) && vendorService.findByName(name) != null) {
if (vendorService.have(vendor)) {
return failure("该供应商已经存在,不可重复添加");
}
......@@ -84,14 +83,12 @@ public class VendorController extends BaseController {
return failure("您要更新的供应商不存在");
}
String name = vendor.getName();
if (name == null || name.trim().equals("")) {
logger.warn(">更新失败:商品名称不能为空");
return failure("供应商名称不能为空");
String contactMan = vendor.getContactMan();
if (StringUtils.isEmpty(contactMan)) {
return failure("联系人不能为空");
}
if (vendorService.findByName(name) != null) {
logger.warn(">更新失败:该供应商已经存在,不可重复添加");
if (vendorService.have(vendor)) {
return failure("该供应商已经存在,不可重复添加");
}
......@@ -100,11 +97,9 @@ public class VendorController extends BaseController {
existingVendor.setAddress(vendor.getAddress());
existingVendor.setPhone(vendor.getPhone());
existingVendor.setNote(vendor.getNote());
existingVendor.setUpdatedBy(SessionUtil.getCurrentUserName(request));
existingVendor.setUpdatedBy(getCurrentUser().getName());
vendorService.update(existingVendor);
logger.info(">更新成功:"+existingVendor.toString());
return ok("更新成功");
}
......
......@@ -98,10 +98,10 @@ public class WareController extends BaseController {
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
@ResponseBody
public String update(@PathVariable Long id, @RequestBody Ware ware,HttpServletRequest request) {
public String update(@PathVariable Long id, @RequestBody Ware ware) {
Ware existingWare = wareService.findById(Ware.class, id);
//validation
if (existingWare == null) {
return failure("您要更新的商品不存在");
......@@ -130,8 +130,8 @@ public class WareController extends BaseController {
existingWare.setUnit(ware.getUnit());
existingWare.setNote(ware.getNote());
existingWare.setVendor(ware.getVendor());
existingWare.setUpdatedBy(SessionUtil.getCurrentUserName(request));
existingWare.setCategory(ware.getCategory());
existingWare.setUpdatedBy(SessionUtil.getCurrentUserName(request()));
wareService.update(existingWare);
logger.info(">更新成功:"+existingWare.toString());
......@@ -141,7 +141,6 @@ public class WareController extends BaseController {
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public String list(@RequestParam int start, @RequestParam int limit, @RequestParam(required = false) Object filter, HttpServletRequest request) {
List<FilterRequest> filters = new ArrayList<FilterRequest>();
if (filter != null) {
......
package com.originspark.drp.models.projects.costs;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.originspark.drp.models.AbstractModel;
@MappedSuperclass
public abstract class AbstractCost extends AbstractModel{
public abstract class AbstractCost extends AbstractModel {
private static SimpleDateFormat forYearMonthFormatter = new SimpleDateFormat("yyyy-MM");
/**
* 该字段和对应invoice的时间字段保持一致,为冗余字段,
* 只为简化盘点计算,forYearMonth同理
* 日期:年-月-日
*/
@Temporal(TemporalType.DATE)
private Date forDate;
/**
* 日期:年-月
*/
@JsonIgnore
@Column(columnDefinition = "char(7)", nullable = false)
private String forYearMonth;
/**
* 单价
......@@ -60,12 +81,31 @@ public abstract class AbstractCost extends AbstractModel{
public void setTotal(BigDecimal total) {
this.total = total;
}
public Date getForDate() {
return forDate;
}
public void setForDate(Date forDate) {
this.forDate = forDate;
if (forDate != null) {
setForYearMonth(forYearMonthFormatter.format(forDate));
}
}
public String getForYearMonth() {
return forYearMonth;
}
public void setForYearMonth(String forYearMonth) {
this.forYearMonth = forYearMonth;
}
@Override
public String toString() {
return super.toString()+", unitPrice="+unitPrice+", quantity="+quantity;
}
@PrePersist
public void prePersist(){
if(getUnitPrice() == null || getQuantity() == null){
......@@ -73,7 +113,7 @@ public abstract class AbstractCost extends AbstractModel{
}
setTotal(getUnitPrice().multiply(getQuantity()));
}
@PreUpdate
public void PreUpdate(){
if(getUnitPrice() == null || getQuantity() == null){
......
......@@ -11,7 +11,6 @@ import javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.originspark.drp.models.AbstractModel;
import com.sun.istack.internal.NotNull;
/**
* 单据
......@@ -33,7 +32,6 @@ public abstract class AbstractInvoice extends AbstractModel{
private Date forDate;
@JsonIgnore
@NotNull
@Column(columnDefinition = "char(7)", nullable = false)
private String forYearMonth;
......
package com.originspark.drp.service.projects.inventories;
import java.util.List;
import com.originspark.drp.dao.BaseDAO;
import com.originspark.drp.web.models.projects.inventories.CurrentInventoryUI;
public interface InventoryService extends BaseDAO {
List<CurrentInventoryUI> pagedCurrentInventories(int start, int limit);
Long pagedCurrentInventoriesCount();
}
package com.originspark.drp.service.projects.inventories;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.originspark.drp.dao.BaseDAOSupport;
import com.originspark.drp.web.models.projects.inventories.CurrentInventoryUI;
@Transactional
@Service
public class InventoryServiceBean extends BaseDAOSupport implements InventoryService {
// 实时入库量统计
final String CURRENT_IN_SQL = "(SELECT DISTINCT(ware) as wid, sum(quantity) as incount, SUM(total) as outcome FROM cost_stock_in GROUP BY ware) as t1";
// 实时出库量统计
final String CURRENT_OUT_SQL = "(SELECT DISTINCT(ware) as wid, sum(quantity) as outcount, SUM(total) as income FROM cost_stock_out GROUP BY ware) as t2";
// 实时库存量统计
final String CURRENT_SUM_SQL = "SELECT t3.name, t3.model, t3.unit, t3.brand, t1.outcome, t1.incount, t2.income, t2.outcount FROM "
+ CURRENT_IN_SQL + " LEFT JOIN " + CURRENT_OUT_SQL + " ON t1.wid = t2.wid"
+ " JOIN wares as t3 WHERE t1.wid = t3.id";
// 实时库存量总数计算
final String CURRENT_COUNT = "SELECT COUNT(DISTINCT(ware)) FROM cost_stock_in";
@SuppressWarnings("unchecked")
@Override
public List<CurrentInventoryUI> pagedCurrentInventories(int start, int limit) {
Query query = em.createNativeQuery(CURRENT_SUM_SQL);
List<Object[]> res = query.setFirstResult(start).setMaxResults(limit).getResultList();
List<CurrentInventoryUI> currentInventories = new ArrayList<CurrentInventoryUI>();
Object[] objAry;
for (int i = 0, length = res.size(); i < length; i++) {
CurrentInventoryUI inventory = new CurrentInventoryUI();
objAry = res.get(i);
inventory.setName(objAry[0] + "");
inventory.setModel(objAry[1] + "");
inventory.setUnit(objAry[2] + "");
inventory.setBrand(objAry[3] + "");
inventory.setOutcome(objAry[4] == null ? BigDecimal.ZERO : (BigDecimal) objAry[4]);
inventory.setIncount(objAry[5] == null ? 0L : ((BigDecimal)objAry[5]).longValue());
inventory.setIncome(objAry[6] == null ? BigDecimal.ZERO : (BigDecimal) objAry[6]);
inventory.setOutcount(objAry[7] == null ? 0L : ((BigDecimal)objAry[7]).longValue());
currentInventories.add(inventory);
}
return currentInventories;
}
@Override
public Long pagedCurrentInventoriesCount() {
Query query = em.createNativeQuery(CURRENT_COUNT);
BigInteger count = (BigInteger)query.getSingleResult();
return count.longValue();
}
}
......@@ -3,20 +3,19 @@ package com.originspark.drp.service.resources;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.originspark.drp.dao.BaseDAO;
import com.originspark.drp.models.resources.Vendor;
import com.originspark.drp.util.json.FilterRequest;
public interface VendorService extends BaseDAO<Vendor>{
List<Vendor> pagedDataSet(int start, int limit, List<FilterRequest> filters);
Long pagedDataCount(List<FilterRequest> filters);
Map<String,String> validate();
Vendor findByName(String name);
boolean have(Vendor vendor);
}
......@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import com.originspark.drp.dao.BaseDAOSupport;
import com.originspark.drp.models.resources.Vendor;
import com.originspark.drp.models.resources.Ware;
import com.originspark.drp.models.resources.Vendor.COLUMNS;
import com.originspark.drp.util.json.FilterRequest;
......@@ -123,4 +124,18 @@ public class VendorServiceBean extends BaseDAOSupport<Vendor> implements VendorS
return vendors.get(0);
}
@Override
public boolean have(Vendor vendor) {
String jpql = "from Vendor where name =:name and contactMan =:contactMan";
TypedQuery<Vendor> query = em.createQuery(jpql, Vendor.class)
.setParameter("name", vendor.getName())
.setParameter("contactMan", vendor.getContactMan());
List<Vendor> vendors = query.getResultList();
if(vendors.isEmpty()){
return false;
}
return true;
}
}
......@@ -138,13 +138,14 @@ public class WareServiceBean extends BaseDAOSupport<Ware> implements WareService
@Override
public boolean have(Ware ware) {
String jpql = "from Ware where name =:name and model =:model and unit =:unit and brand =:brand";
TypedQuery<Ware> query = em.createQuery(jpql,Ware.class)
String jpql = "from Ware where name =:name and model =:model and unit =:unit and brand =:brand and category =:category";
TypedQuery<Ware> query = em.createQuery(jpql, Ware.class)
.setParameter("name", ware.getName())
.setParameter("model", ware.getModel())
.setParameter("unit", ware.getUnit())
.setParameter("brand", ware.getBrand());
.setParameter("brand", ware.getBrand())
.setParameter("category", ware.getCategory());
List<Ware> wares = query.getResultList();
if(wares.isEmpty()){
return false;
......
......@@ -2,56 +2,78 @@ package com.originspark.drp.web.models.projects.inventories;
import java.math.BigDecimal;
/**
* 剩余量、盈利额会自动计算
* @author ReedMi
*/
public class CurrentInventoryUI {
private String wareName;
private String wareBrand;
private String wareModel;
private String wareUnit;
private BigDecimal currentStockIn;
private BigDecimal currentStockOut;
public String getWareName() {
return wareName;
private String name;
private String brand;
private String model;
private String unit;
private Long incount;// 入库量
private Long outcount;// 出库量
private BigDecimal income;// 收入
private BigDecimal outcome;// 支出
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setWareName(String wareName) {
this.wareName = wareName;
public String getBrand() {
return brand;
}
public String getWareBrand() {
return wareBrand;
public void setBrand(String brand) {
this.brand = brand;
}
public void setWareBrand(String wareBrand) {
this.wareBrand = wareBrand;
public String getModel() {
return model;
}
public String getWareModel() {
return wareModel;
public void setModel(String model) {
this.model = model;
}
public void setWareModel(String wareModel) {
this.wareModel = wareModel;
public String getUnit() {
return unit;
}
public String getWareUnit() {
return wareUnit;
public void setUnit(String unit) {
this.unit = unit;
}
public void setWareUnit(String wareUnit) {
this.wareUnit = wareUnit;
public Long getIncount() {
return incount;
}
public BigDecimal getCurrentStockIn() {
return currentStockIn;
public void setIncount(Long incount) {
this.incount = incount;
}
public void setCurrentStockIn(BigDecimal currentStockIn) {
this.currentStockIn = currentStockIn;
public Long getOutcount() {
return outcount;
}
public BigDecimal getCurrentStockOut() {
return currentStockOut;
public void setOutcount(Long outcount) {
this.outcount = outcount;
}
public void setCurrentStockOut(BigDecimal currentStockOut) {
this.currentStockOut = currentStockOut;
public BigDecimal getIncome() {
return income;
}
public void setIncome(BigDecimal income) {
this.income = income;
}
public BigDecimal getOutcome() {
return outcome;
}
public void setOutcome(BigDecimal outcome) {
this.outcome = outcome;
}
// 剩余量
public Long getRestcount() {
return getIncount() - getOutcount();
}
//json util
public BigDecimal getCurrentStockRest(){
return getCurrentStockIn().subtract(getCurrentStockOut());
// 盈利
public BigDecimal getProfit() {
return getIncome().subtract(getOutcome());
}
}
Ext.define('drp.app.controller.projects.inventories.CurrentInventoryController', {
extend : 'Ext.app.Controller',
currentInventoryGrid : null,
init : function() {
me = this;
this.control({
'currentinventoryview' : {
afterrender : function(panel) {
currentInventoryGrid = panel.down('gridpanel');
}
},
'currentinventoryview > treepanel' : {
select : function(treepanel, record){
var id = record.data.id;
var _url = "project/"+id+"/inventories/current";
currentInventoryGrid.getStore().getProxy().url = _url;
currentInventoryGrid.getStore().reload();
},
afterrender : function(treepanel){
var store = treepanel.getStore();
Ext.apply(store.proxy.extraParams, {
userType : user.type,
userId : user.id
});
store.load({
node : store.getRootNode()
});
var grid = panel.down('gridpanel');
grid.getStore().load();
}
}
});
},
views : ['drp.app.view.projects.inventories.CurrentInventoryView'],
models :['drp.app.model.projects.ProjectModel','drp.app.model.projects.inventories.CurrentInventoryModel'],
models :['drp.app.model.projects.inventories.CurrentInventoryModel'],
stores : ['drp.app.store.projects.inventories.CurrentInventoryStore']
});
\ No newline at end of file
......@@ -5,7 +5,6 @@ Ext.define("drp.app.controller.resources.WareController", {
me : null,
init : function() {
me = this;
this.control({
......
Ext.define("drp.app.model.projects.inventories.CurrentInventoryModel", {
extend : "Ext.data.Model",
fields : [{
name : "wareName"
name : "name"
}, {
name : "wareBrand"
name : "brand"
}, {
name : "wareModel"
name : "model"
}, {
name : "wareUnit"
name : "unit"
}, {
name : "currentStockIn",
name : "incount",
type : 'int'
}, {
name : "currentStockOut",
name : "outcount",
type : 'int'
}, {
name : "currentStockRest",
name : "restcount",
type : 'int'
} ],
}, {
name : "income"
}, {
name : "outcome"
}, {
name : "profit"
}],
proxy : {
type : 'ajax',
url : 'inventories/current',
reader : {
type : "json",
root : "data",
......
Ext.define("drp.app.store.projects.inventories.CurrentInventoryStore", {
extend : 'Ext.data.Store',
model : 'drp.app.model.projects.inventories.CurrentInventoryModel',
pageSize : 50
pageSize : 50,
autoLoad : false
});
\ No newline at end of file
......@@ -12,67 +12,56 @@ Ext.define('drp.app.view.projects.inventories.CurrentInventoryView', {
Ext.applyIf(me, {
items : [{
xtype : 'treepanel',
region : 'west',
width : 200,
rootVisible : false,
title : '项目列表',
store : Ext.create("Ext.data.TreeStore",{
defaultRootId : '',
//防止store自动加载
//http://www.sencha.com/forum/showthread.php?150004-How-to-stop-TreeStore-autoload
root : {
data : []
},
model : 'drp.app.model.projects.ProjectModel'
}),
columns : [{
xtype : 'treecolumn',
dataIndex : 'name',
text : '名称',
flex : 1
}]
}, {
xtype : 'gridpanel',
region : 'center',
title : '库存量',
title : '实时库存量',
columnLines : true,
store : 'drp.app.store.projects.inventories.CurrentInventoryStore',
columns : [{
xtype : 'gridcolumn',
dataIndex : 'wareName',
dataIndex : 'name',
flex : 1,
text : '品名'
}, {
xtype : 'gridcolumn',
dataIndex : 'wareBrand',
flex : 1,
text : '品牌'
}, {
xtype : 'gridcolumn',
dataIndex : 'wareModel',
dataIndex : 'model',
flex : 1,
text : '规格'
}, {
xtype : 'gridcolumn',
dataIndex : 'wareUnit',
dataIndex : 'unit',
flex : 1,
text : '单位'
}, {
xtype : 'gridcolumn',
dataIndex : 'currentStockIn',
dataIndex : 'incount',
flex : 1,
text : '当前入库量'
}, {
xtype : 'gridcolumn',
dataIndex : 'currentStockOut',
dataIndex : 'outcount',
flex : 1,
text : '当前出库量'
}, {
xtype : 'gridcolumn',
dataIndex : 'currentStockRest',
dataIndex : 'restcount',
flex : 1,
text : '当前剩余量'
}, {
xtype : 'gridcolumn',
dataIndex : 'income',
flex : 1,
text : '收入'
}, {
xtype : 'gridcolumn',
dataIndex : 'outcome',
flex : 1,
text : '支出'
}, {
xtype : 'gridcolumn',
dataIndex : 'profit',
flex : 1,
text : '盈余'
}],
dockedItems : [{
xtype : 'pagingtoolbar',
......
......@@ -82,25 +82,25 @@ Ext.define('drp.app.view.resources.VendorView', {
stripeRows : true,
autoScroll : true,
columns : [{
xtype : 'gridcolumn',
width : 160,
dataIndex : 'name',
text : '名称'
}, {
xtype : 'gridcolumn',
width : 90,
dataIndex : 'contactMan',
text : '联系人'
}, {
xtype : 'gridcolumn',
width : 180,
dataIndex : 'address',
text : '地址'
}, {
xtype : 'gridcolumn',
width : 130,
dataIndex : 'phone',
text : '联系电话'
}, {
xtype : 'gridcolumn',
width : 160,
dataIndex : 'name',
text : '公司名称'
}, {
xtype : 'gridcolumn',
width : 180,
dataIndex : 'address',
text : '公司地址'
}, {
xtype : 'gridcolumn',
width : 100,
......
......@@ -16,7 +16,7 @@ Ext.define("drp.base.view.WestView", {
activeOnTop : true
},
items : [{
title : "库存查看",
title : "库存管理",
titleAlign: 'center',
autoScroll : true,
items:[{
......@@ -32,7 +32,7 @@ Ext.define("drp.base.view.WestView", {
id : 'menu_current_inventory',
leaf : true
}, {
text : "<span style='font-weight:bold'>月末盘点</span>",
text : "<span style='font-weight:bold'>每日总账</span>",
id : 'menu_monthend_inventory',
leaf : true
}]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment