企业信息化 利用物料移动类型 实现通用的出入库操作

时间:04-16来源:作者:点击数:

企业有很多类型的出入库操作,比如:生产入库、采购入库、销售出库、领料出库、调拨入库、调拨出库、盘盈入库、盘亏出库等。企业信息化系统,针对如此繁多的出入库类型,如果每个类型都需要单独实现,则代码量比较大,且不好维护、统一管理。为此,本文引入物料移动类型,统一实现仓库出入库操作。

1、仓库出入库实现基本原理
1)根据原始单据单进行出入库操作

原始单据可能是:

  • 生产入库单:生产车间、入库仓库、入库物料,生产批号,入库数量等
  • 采购入库单:供应商、入库仓库、物料名称、采购数量、采购价、采购金额等
  • 销售出库单:客户、出库仓库、物料名称、出库数量、出库批号等
  • 领料出库(入库)单:领料部门(车间)、发货仓库、物料名称、领料数量、物料批号等
  • … 其它单据
2)物料明细入账
  • 物料明细入账,假设表名为wm_inventory_detail,其行记录大致如下:
ware_id ware_date goods_id batch count price money balance_count balance_money bwart_type ref_billno ref_detailsid
167 2019-05-20 592 0000000 2000 482.8 0.2414 2000 482.8 101 RK201905200003 3450
177 2019-05-24 214 20190524SZ10 100 3018 30.18 721 17261.97 103 RK201905240001 3452

ware_id: 仓库ID

ware_date: 出入库日期

goods_id: 物料ID

batch:物料批号

count:出入库数量

price:出入库价格

money:出入库金额

balance_count: 本次出入库明细对应的 结存数量

balance_money: 本次出入库明细对应的 结存金额

bwart_type:移动类型

ref_billno:参考单据号

ref_detailsid:参考单据明细sid

3)更新库存

需要更新两张表的库存:批次表和仓库库存表。

  • 更新批次库存表,wm_inventory_batch
ware_id goods_id batch balance_count
167 592 0000000 2000
177 214 20190524SZ10 721
  • 更新仓库库存表,wm_inventory
ware_id goods_id balance_count balance_money balance_price
167 592 2000 482.8 0.2414
177 214 721 17261.97 23.94
2、物料移动类型
1)移动类型本质

物料移动类型本质就是一张配置表,如采购入库对应的物料明细账如何记账,仓库库存如何更新(增加还是减少)等,wm_inout_type,关键信息如下:

biz_type bwart_type bwart_name balance_mark is_realprice ref_url
入库 101 采购入库 + Y /views/wm/rk/rk_detail.html
入库 102 采购入库冲销 - Y /views/wm/rk/rk_detail.html
入库 103 生产入库 + N /views/wm/rk/rk_detail.html
         

biz_type: 业务类型

bwart_type:移动类型代码

bwart_name:移动类型名称

balance_mark:库存 增加+/减少- 标记

is_realprice:价格计算依据,Y根据出入库明细影响库存价格,N采用库存物料价格

ref_url:物料明细查看原始单据详情url页面地址

2)移动类型如何使用

编写一个统一的移动类型出入库函数,如下:

	/**
	 * 移动类型.
	 * @param Map{bwart_type:string移动类型, rows:list物料明细}
	 */	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void wmBwart(Map para) {
		DataAdapter adapter = new DataAdapter();
		String bwart_type = (String) para.get(BWART_KEY);
		List<Map> list = (List<Map>) para.get("rows");
		
		// 验证移动类型有效性
		this._verifyBwartType(para);
		
		// 验证仓库有效性
		this._verifyWare(para);
		para.put("ware_id", list.get(0).get("ware_id"));
		
		// 根据移动类型,进行价格、库存增加、减少计算
		for (Map n : list) {
			Map t = CollectionUtil.cloneMap(n, "sid,ware_id,ware_date,batch,goods_id,goods_name,unit_name,memo");
			t.put("is_realprice", bwartObj.get("is_realprice"));	//是否采用实际价格
			t.put("balance_mark", bwartObj.get("balance_mark"));
			
			// 这里的价格需要根据取出的分子 分母进行调整
			t.put("price", n.get("price"));
			t.put(BWART_KEY, bwart_type);
			t.put("ref_billno", n.get("bill_no"));
			t.put("ref_detailsid", n.get("sid"));
			t.put("user_id", para.get("user_id"));
			t.put("write_time", new Date());
			t.put("co_id", para.get("co_id"));
			
			// 出入库明细 数量, 金额
			t.put("count", n.get("count"));
			t.put("money", n.get("money"));
			// 库存影响标记
			if ("0".equals(bwartObj.get("balance_mark"))) {
				t.put("balance", BigDecimal.ZERO);
				t.put("money_balance", BigDecimal.ZERO);
			} else if ("+".equals(bwartObj.get("balance_mark"))) {
				t.put("balance", n.get("count"));
				t.put("money_balance", n.get("money"));
			} else if ("-".equals(bwartObj.get("balance_mark"))) {
				t.put("balance", BigDecimal.ZERO.subtract(TypeUtil.toBigDecimal(n.get("count"),BigDecimal.ZERO)));
				t.put("money_balance", 
BigDecimal.ZERO.subtract(TypeUtil.toBigDecimal(n.get("money"),BigDecimal.ZERO)));
			}
			insertList.add(t);
		}

		// 物料账期检查
		this._wmAccountPeriod(adapter, para);
		
		//出入库操作锁定检查
		this._wmLockCheck(adapter, list.get(0));
		
		// 物料明细入账、更新库存
		List<Map> listCopy = CollectionUtil.cloneListMap(list);
		this._updateWmMainStock(adapter, listCopy);		//更新仓库总库存
		this._updateWmBatchStock(adapter, listCopy);	//更新批次库存
		this._insertDetailStock(adapter, listCopy);		//插入物料明细账
	}

在采购入库、生产入库等具体业务操作里,调用wmBwart(para)即可,以生产入库为例:

	public void auditRkBill(Map para) {
		DataAdapter adapter = new DataAdapter();
		// 更新入库单状态
		String sql = "update wm_rk_bill set status = '已入库', write_uid = #user_id#, write_time = now() "
				+ "where co_id = #co_id# and bill_no = #bill_no# and status = '录入'";
		if (adapter.runSql(sql, para) < 1) {
			throw new AppException("请核实该入库单是否已经审核过账?");
		}
		
		// 移动类型统一出入库
		this.wmBwart(para);
	}
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门