SAP知识——历史库存的逻辑

SAP的库存报表一直都是很令人头疼的。

因为出入库业务非常复杂,导致库存逻辑也非常复杂,本文仅对库存逻辑中的历史库存部分,进行详细的解释,并提供一些实用高效的代码,希望能帮到大家。

示例


以普通库存的普通库存数量为例,直接上例子。

物料:A

工厂:0001

库存地点:0100

时间来到2017年5月,为物料A在库存地点初始化库存,假设数量为100。此时:

  • MARD表

对主键A-0001-0100,产生一条记录,其LFGJA、LFMON的值为2017、05,数量(这里均指普通库存数量)为100。

  • MARDH表

对主键A-0001-0100-2017-04,产生一条记录,其数量值均为0

(MARDH比MARD的主键字段多了年度和月份)

(注意:

这里说的2017年5月,指的是在2017年5月时,做当期的账务。

而如果在2018年2月打开2017年5月的账期,并且在2017年5月进行初始化库存记账的话,MARD表中的年月是201802,MARDH表中的数据则会有两条,多出一条A-0001-0100-2017-05的数据,数量值为100)

时间来到2017年6月,物料A在0001-0100出库数量10

  • MARD表

对主键A-0001-0100,年月变为201706,数量值变为90

  • MARDH表

新增一条A-0001-0100-2017-05的记录,数量值为100

(年月为上一个月)

时间来到2017年7月和8月,物料A无任何变化

  • MARD表

无变化

  • MARDH表

无变化

时间来到2017年9月,物料A在0001-0100出库数量20

  • MARD表

对主键A-0001-0100,年月变为201709,数量值变为70

  • MARDH表

新增一条A-0001-0100-2017-08的记录,数量值为90

(年月为上一个月)

之后,物料A的库存一直未变化,时间来到2018年2月6日

这时候打开2018年3月的账期,在2018年3月出库数量5。

  • MARD表

对主键A-0001-0100,年月为201803,数量值为65

  • MARDH表

存在四条记录

A-0001-0100-2017-04 0

A-0001-0100-2017-05 100

A-0001-0100-2017-08 90

A-0001-0100-2018-02 70(刚刚新增的)

而实际情况中,月底的库存情况如下:

201704 0

201705 100

201706 90(6月出库10)

201707 90

201708 90

201709 70(9月出库20)

201710 70

201711 70

201712 70

201801 70

201802 70

201803 65(3月出库5,且假设3月不再有出库)

结合到表MARD和MARDH,我们发现取201704、201705、201708、201802的月底库存,还都是很方便的,因为MARDH中有对应的主键。

但是如果要取2017年6月底的库存,该怎么办呢?

分析解释


根据实际库存的结果和MARDH表的数据,我们可以分析得知,如果要取物料在某月底的库存数据,要在表MARDH中寻找月份大于等于查询月份,且与查询月份最接近的数据

即:

要取201706月底的数据,就要找MARDH中大于等于201706且与之最接近的201708的数据,结果为90。

要取201711月底的数据,就要找MARDH中大于等于201711且与之最接近的201802的数据,结果为70。

要取201611月底的数据,就要找MARDH中大于等于201611且与之最接近的201704的数据,结果为0。

在这里有个ABAP的知识如下:

  • 取某一个月月底的普通库存数据

select single * into ls_mardh from mardh where 

matnr = 'A' 

and werks = '0001'

and lgort = '0100' 

and ( lfgja > p_lfgja or ( lfgja = p_lfgja and lfmon >= p_lfmon) ).

  • 取多个物料多个月月底的普通库存数据

select * into table lt_mardh from mardh where 

matnr in s_matnr

and werks in s_werks

and lgort in s_lgort.

sort lt_mardh by matnr werks lgort lfgja lfmon.

"先根据二分查找,查找到大于等于当前条目且最接近当前条目的索引

read table lt_mardh with key …… binary search transporting no fields.

(请详细测试或查看帮助系统,以了解二分查找的这个神奇作用)

"根据索引读取内表

read table lt_mardh index sy-tabix into ls_mardh.

if sy-subrc = 0

and ls_mardh-matnr = p_matnr 

and ls_mardh-werks = p_werks 

and ls_mardh-lgort = p_lgort.

"ls_mardh就是你要找的数据

endif.

但是问题还没有结束。

假如从现在开始到了2018年10月,我们对物料A在0001-0100无任何变动,那么表MARD和MARDH的数据也就不会变。

按照刚才的逻辑,我们只能取到该物料在201802及以前的数据,而201803及以后的库存一直都是65,存在于表MARD中。

所以,按照上述办法,在MARDH表中取不到库存数据的时候,MARD的数据就是其库存数据

这样,在上面判断if sy-subrc = 0 and....的代码后面,我们可以加上ELSE,在ELSE里面,取MARD表的数据即可。

总结


1、取物料在某月底的库存数据时,首先要在表MARDH中寻找月份大于等于查询月份,且与查询月份最接近的数据

2、按照第一条,在MARDH表中取不到库存数据的时候,MARD的数据就是其库存数据

3、MARD表中的年、月,表示物料数量上一次发生变化时的年、月

4、MSPR、MSKA、MCHB等表中的库存逻辑,与MARD基本一致,也都存在对应的H表

5、MBEW、QBEW、EBEW等库存价值的逻辑,也是差不多的,也都存在对应的H表。但不应想当然的认为,对于同样一个物料,MARD和MBEW的年月是一致的。因为数量变更影响库存数量,数量变更和价值变更都会影响MBEW。而价值变更的来源不一定是数量变更

6、二分查找的妙用,还是请测试一下以加深理解吧


IOS/ANDROID用户打赏——赞赏码

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容