SAP库存账龄分析报表(转)

功能概述 
1.1. 业务背景 
本程序是对物料按工厂、库存地点、物料号、销售订单号进行查询当前的库存及库龄的报表。 
1.2. 功能描述 
本程序能够查询出每个物料的数量、金额数据及库龄的明细数据。 
1.2. 使用范围 
所有有库存的事业部都需要查看库存及库龄情况。 
1.3. 权限设定 
所有有查看库存权限的人员都需要有这个权限。 
需要增加权限对象:M_MSEG_LGO、M_MSEG_WMB、M_MSEG_WWA。 
1.4. 处理类型 
前台手动执行。 
1.5. 数据量及使用频率 
本程序为库存相关,用户需要查询时可以进行查询。
功能详述 
2.1. 程序标题及其属性 
程序标题:“库存异常表(库龄报表)” 
2.2. 屏幕设计 
2.2.1. 屏幕流 
2.2.2. 输入屏幕 
 
结果如下: 

显示出结果后,可以用Excel导出。
报表各字段取值逻辑
本程序分为两种情况,一种是普通库存,一种是对应销售订单的库存,需要把两种情况分别处理,然后加在一起显示,普通库存取数逻辑如下: 
描述 参考字段 
工厂 MARD-WERKS 
工厂描述 T001W-NAME1 
库存地点 MARD-LGORT 
库存地点描述 T001L-LGOBE 
物料号 MARD-MATNR 
物料描述 MAKT-MAKTL 
库存类型 普通库存 
销售订单号 MSKA-VBELN   
销售订单行项目MSKA-POSNR 
当前库存数量 MARD-LABST(MSKA-KALAB) 
当前库存金额 当前库存数量 * (MBEW-SALK3 / MBEW-LBKUM),最终结果保留小数点后两位 
库存1-30天数量 1、以每个工厂、库存地点、物料号为条件取 MSEG-MENGE MKPF-BUDAT from ( MSEG inner join MKPF by MSEG-MBLNR = MKPF-MBLNR and MSEG-MJAHR = MKPF-MJAHR) where MSEG-WERKS = MARD-WERKS and MSEG-LGORT = MARD-LGORT and MSEG-MATNR = MARD-MATNR and MSEG-SHKZG = ‘S’ and MSEG-SOBKZ NE ‘E’ ,取物料凭证数据时排除移动类型321和322。 
2、对上面的结果集以MKPF-BUDAT为基础倒排,当入库数据中存在20131231的数据时,到库龄报表期初数据表(ZMM_MSEG)把历史数据取出,把“当前库存数量”分配到这个结果中,20131231的数据不分配,直接跳到以前的历史数据,直到分配完为止,如果历史数据不足按20131231的数据计算。 
3、对以上结果以当前日期为基准,在1-30天内数据累加后放在这个字段中。 
库存1-30天数量 1、以每个工厂、库存地点、物料号为条件取 MSEG-MENGE MKPF-BUDAT from ( MSEG inner join MKPF by MSEG-MBLNR = MKPF-MBLNR and MSEG-MJAHR = MKPF-MJAHR) where MSEG-WERKS = MARD-WERKS and MSEG-LGORT = MARD-LGORT and MSEG-MATNR = MARD-MATNR and MSEG-SHKZG = ‘S’ and MSEG-SOBKZ NE ‘E’ ,取物料凭证数据时排除移动类型321和322。 
2、对上面的结果集以MKPF-BUDAT为基础倒排,当入库数据中存在20131231的数据时,到库龄报表期初数据表(ZMM_MSEG)把历史数据取出,把“当前库存数量”分配到这个结果中,20131231的数据不分配,直接跳到以前的历史数据,直到分配完为止,如果历史数据不足按20131231的数据计算。 
3、对以上结果以当前日期为基准,在1-30天内数据累加后放在这个字段中。 
库存91-180天数量 第1、2步操作前面已经做过,只需要第3步操作,把结果在91-180天内的数据累加放在这个字段中。 
库存91-180天金额 库存91-180天数量 * (MBEW-SALK3 / MBEW-LBKUM),最终结果保留小数点后两位。 
后面天数的数量和金额以此类推

逻辑描述
本程序如果普通库存选中则抽取MARD表的数据为基础取出MARD-LABST不为零的数据然后进行后续处理,如果对应销售订单的库存选中则抽取MSKA表的数据为基础取出MSKA-KALAB不为零的数据然后进行后续处理,如果两个都选中则两个表各自抽取出数据后加到一起显示,默认是全部选中。取到基础数据后再以此为基础取MSEG、MKPF表中的所有入库信息然后按时间倒序排列,当入库数据中存在20131231的数据时,到库龄报表期初数据表(ZMM_MSEG)把历史数据取出,把“当前库存数量”分配到这个结果中,20131231的数据不分配,直接跳到以前的历史数据,直到分配完为止,如果历史数据不足按20131231的数据计算,然后以这个序列的数量以当前日期为基准,分配到各自的库存时间范围内。具体的逻辑请参考以上取值逻辑。 
考虑冲销的情况: 
1、对于初始化入库(20131231)采用从物料凭证表取入出库双向数据,经过累计后计算出一条数据,然后去找历史数据。

2、对于其他数据采用从物料凭证表取单向入库数据,然后到物料凭证表查询是否存在入库数据的冲销凭证数据,如果存在冲销凭证数据,则把这条入库数据删除。

表名:ZMM_MSEG 
描述:库龄报表期初数据 
字段:字段描述 
客户端 
物料编号 
工厂 
库存地点 
销售凭证 
销售凭证项目 
凭证中的过帐日期 
数量 
基本计量单位 
字段名称 
MANDT 
MATNR 
WERKS 
LGORT 
VBELN 
POSNR 
BUDAT 
MENGE 
MEINS 
示例代码如下

*-----------------------------------------------------------------------*
* 程序名称:ZMMEXEC0140
* 程序标题:库存异常表(库龄报表)
* 程序类型:功能报表

* 创建日期:2014-01-16
* 模块    :
* 请求号  :
* 功能描述:
* 相关文档:
*----------------------------------------------------------------------*
* 修改记录:
* 作者          日期       请求号      修改原因描述
*-----------  --------  -----------------------------------------------*
*
*----------------------------------------------------------------------*
REPORT zmmexec0140
  NO STANDARD PAGE HEADING
  MESSAGE-ID zcomm.

*----------------------------------------------------------------------*
*        INCLUDE                                                       *
*----------------------------------------------------------------------*
INCLUDE zslis.

*----------------------------------------------------------------------*
* 声明数据表;
*----------------------------------------------------------------------*
TABLES: mkpf, mseg, mard, mska,t001w.

*----------------------------------------------------------------------*
* 定义结构;
*----------------------------------------------------------------------*
TYPES: gtf_price TYPE p LENGTH 15 DECIMALS 9,
       gtf_dmbtr TYPE vtcur12,
       gtf_menge TYPE p LENGTH 15 DECIMALS 3.

TYPES: BEGIN OF gts_alv_data,
         matnr TYPE mard-matnr,
         werks TYPE mard-werks,
         lgort TYPE mard-lgort,
         maktx TYPE makt-maktx,  " 物料描述
         name1 TYPE t001w-name1, " 工厂描述
         lgobe TYPE t001l-lgobe, " 库存地点描述
         ztype TYPE char10,
         vbeln TYPE mska-vbeln,
         posnr TYPE mska-posnr,
         meins TYPE mara-meins,
         msehl TYPE msehl,
         waers TYPE t001-waers,
         price TYPE gtf_price,
         menge TYPE gtf_menge,
         dmbtr TYPE gtf_dmbtr,
         meng1 TYPE gtf_menge,
         dmbt1 TYPE gtf_dmbtr,
         meng2 TYPE gtf_menge,
         dmbt2 TYPE gtf_dmbtr,
         meng3 TYPE gtf_menge,
         dmbt3 TYPE gtf_dmbtr,
         meng4 TYPE gtf_menge,
         dmbt4 TYPE gtf_dmbtr,
         meng5 TYPE gtf_menge,
         dmbt5 TYPE gtf_dmbtr,
         meng6 TYPE gtf_menge,
         dmbt6 TYPE gtf_dmbtr,
         meng7 TYPE gtf_menge,
         dmbt7 TYPE gtf_dmbtr,
         meng8 TYPE gtf_menge,
         dmbt8 TYPE gtf_dmbtr,
         meng9 TYPE gtf_menge,
         dmbt9 TYPE gtf_dmbtr,
*         meng10 TYPE gtf_menge, "20160615 add
*         dmbt10 TYPE gtf_dmbtr, "20160615 add
         meng99 TYPE gtf_menge,
         dmbt99 TYPE gtf_dmbtr,
         kunnr TYPE kna1-kunnr,
         kunnrt TYPE kna1-name1,
         aufnr TYPE aufk-aufnr,
         aufnrt TYPE aufk-ktext,
         bstkd TYPE vbkd-bstkd,
       END OF gts_alv_data.
TYPES: BEGIN OF gts_alv_base,
         grp      TYPE i,  " 用于分组
         id       TYPE i,
         tag      TYPE i,
         sel      TYPE char1,
         light    TYPE c,
         rowcolor TYPE char4,
         msg      TYPE text255,
       END OF gts_alv_base.
TYPES: BEGIN OF gts_alv.
INCLUDE   TYPE gts_alv_data.
INCLUDE   TYPE gts_alv_base.
TYPES: END OF gts_alv.

TYPES: BEGIN OF gts_t001,
         bwkey TYPE t001k-bwkey,
         bukrs TYPE t001-bukrs,
         waers TYPE t001-waers,
       END OF gts_t001.

*----------------------------------------------------------------------*
* 定义内表;
*----------------------------------------------------------------------*
DATA: gds_alv     TYPE gts_alv,
      gdt_alv     TYPE TABLE OF gts_alv.
DATA: gdt_t001l   TYPE zfit_lgort2 WITH HEADER LINE,
      gdt_t001    TYPE TABLE OF gts_t001 WITH HEADER LINE.

*----------------------------------------------------------------------*
* 定义范围变量;
*----------------------------------------------------------------------*
RANGES: gdr_werks FOR ekpo-werks.

*----------------------------------------------------------------------*
* 定义变量;
*----------------------------------------------------------------------*
DATA: gdf_mandt TYPE mandt,
      gdf_budat TYPE sydatum,
      gdf_datum TYPE sydatum,
      gdf_lfgja TYPE mard-lfgja,
      gdf_lfmon TYPE mard-lfmon.

DATA d1 TYPE p.
DATA d2 TYPE p.
DATA d3 TYPE p.
DATA d4 TYPE p.
DATA d5 TYPE p.
DATA d6 TYPE p.
DATA d7 TYPE p.
DATA d8 TYPE p.

*----------------------------------------------------------------------*
* 定义常量.
*----------------------------------------------------------------------*
*CONSTANTS: gdc_idate TYPE sydatum VALUE '20131231'. " 初始库存倒入日期
*DATA: gdc_idate TYPE sydatum VALUE '20131231'. " 初始库存倒入日期 "add by lumingdao 20160101
DATA: gdc_idate TYPE sydatum VALUE '20151231'. " 初始库存倒入日期

*----------------------------------------------------------------------*
*        SELECTION-SCREEN  检索条件                                    *
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK choi1 WITH FRAME TITLE text-003.
PARAMETERS: p_r1 TYPE char1 RADIOBUTTON GROUP grp1 DEFAULT 'X' USER-COMMAND zks.
PARAMETERS: p_r2 TYPE char1 RADIOBUTTON GROUP grp1.
PARAMETERS: p_budat TYPE sydatum MODIF ID his.
SELECTION-SCREEN END OF BLOCK choi1.

SELECTION-SCREEN BEGIN OF BLOCK selt WITH FRAME TITLE text-001.
PARAMETERS: p_bukrs TYPE t001-bukrs OBLIGATORY DEFAULT '8200'.
SELECT-OPTIONS: so_werks FOR t001w-werks.
SELECT-OPTIONS: so_lgort FOR mard-lgort.
SELECT-OPTIONS: so_matnr FOR mard-matnr.
SELECT-OPTIONS: so_vbeln FOR mska-vbeln.
SELECT-OPTIONS: so_posnr FOR mska-posnr.
************************20160616 add***********************************
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (31) text-004 FOR FIELD p_d1.
PARAMETERS p_d1(4) TYPE n DEFAULT '30'.
PARAMETERS p_d2(4) TYPE n DEFAULT '90'.
PARAMETERS p_d3(4) TYPE n DEFAULT '180'.
PARAMETERS p_d4(4) TYPE n DEFAULT '365'.
PARAMETERS p_d5(4) TYPE n DEFAULT '730'.
PARAMETERS p_d6(4) TYPE n DEFAULT '1095'.
PARAMETERS p_d7(4) TYPE n DEFAULT '1460'.
PARAMETERS p_d8(4) TYPE n DEFAULT '1825'.
SELECTION-SCREEN END OF LINE.
**********************************************************************
SELECTION-SCREEN END OF BLOCK selt.

SELECTION-SCREEN BEGIN OF BLOCK choi WITH FRAME TITLE text-002.
PARAMETERS: p_c1 TYPE char1 AS CHECKBOX DEFAULT 'X'.
PARAMETERS: p_c2 TYPE char1 AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK choi.

*$*$----------------------------------------------------------------$*$*
*$*$                          Main Program                          $*$*
*$*$----------------------------------------------------------------$*$*
*--------- 初始化 ----------
INITIALIZATION.
  p_budat = sy-datum - 1.

*&------------------------------------------------------------
*&     At selection-screen.
*&------------------------------------------------------------
AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    CASE 'X'.
      WHEN p_r1.
        IF screen-group1 = 'HIS'.
          screen-active = 0.
          MODIFY SCREEN.
        ENDIF.
      WHEN p_r2.
        IF screen-group1 = 'HIS'.
          screen-active = 1.
          MODIFY SCREEN.
        ENDIF.
      WHEN OTHERS.
    ENDCASE.
  ENDLOOP.

*&------------------------------------------------------------
*&     At selection-screen.
*&------------------------------------------------------------
AT SELECTION-SCREEN.
* 修改上线日期 “added 20140710
*  PERFORM get_init_date USING sy-mandt '' CHANGING gdc_idate.
* 检查参数输入的合法性 / 检查输入权限
  PERFORM frm_check_parameter.

AT SELECTION-SCREEN ON BLOCK selt.
  PERFORM check_date. "20160616 add

*&------------------------------------------------------------
*&     LOAD-OF-PROGRAM.
*&------------------------------------------------------------
LOAD-OF-PROGRAM.
*--------- START-OF-SELECTION ----------
START-OF-SELECTION.

  "根据公司代码==》获取期初导入日期
  PERFORM frm_get_init_data CHANGING gdc_idate.

* 从数据表去数据并整理
  PERFORM get_data.

END-OF-SELECTION.

  IF gdt_alv[] IS INITIAL.
*   没有找到相关的数据!
    MESSAGE s001 DISPLAY LIKE 'E'.
  ELSE.
*   显示alv界面
    PERFORM frm_display_lvc.
  ENDIF.

  CLEAR:   gdt_alv, gdt_t001l, gdr_werks, gdt_t001.
  REFRESH: gdt_alv, gdt_t001l, gdr_werks, gdt_t001.

  INCLUDE zinitial_data. "added 20140710

************************************************************************
*                         END OF MAIN PROGRAM
************************************************************************



*&---------------------------------------------------------------------*
*&      Form  FRM_CHECK_PARAMETER
*&---------------------------------------------------------------------*
*       检查参数输入的合法性 / 检查输入的条件
*----------------------------------------------------------------------*
FORM frm_check_parameter.

  "add by luming dao 20151231
  DATA: lt_itab LIKE TABLE OF zmm_bukrs WITH HEADER LINE.
  REFRESH lt_itab.
  IF p_bukrs <> '8100' AND p_bukrs <> '8200' .
    STOP.
  ENDIF.
  SELECT *
         INTO CORRESPONDING FIELDS OF TABLE lt_itab
         FROM zmm_bukrs
         WHERE bukrs EQ p_bukrs
           AND lgort IN so_lgort
           AND werks IN so_werks
         .
  IF lt_itab[] IS INITIAL.
    SET CURSOR FIELD 'P_BUKRS'.
    MESSAGE e000 WITH '没有你要查询的数据!'.
    RETURN.
  ENDIF.

  IF sy-ucomm = 'ZKS'.
    RETURN.
  ENDIF.

  IF p_c1 <> 'X' AND p_c2 <> 'X'.
    SET CURSOR FIELD 'P_C1'.
    MESSAGE e000 WITH '请至少选择一种库存类型'.
    RETURN.
  ENDIF.
  "added by XXX 20160722 begin
  IF  p_bukrs = '8100'.
    gdc_idate = '20131231'.
  ENDIF.
  "added by yangk 20160722 end
  IF p_r2 = 'X'.
    IF p_budat < gdc_idate.
      SET CURSOR FIELD 'P_BUDAT'.
      MESSAGE e000 WITH '历史库龄日期不能小于' gdc_idate.
    ENDIF.
    IF p_budat >= sy-datum.
      SET CURSOR FIELD 'P_BUDAT'.
      MESSAGE e000 WITH '历史库龄日期不能大于等于当天'.
    ENDIF.
    CALL FUNCTION 'RP_LAST_DAY_OF_MONTHS'
      EXPORTING
        day_in            = p_budat
      IMPORTING
        last_day_of_month = gdf_budat
      EXCEPTIONS
        day_in_no_date    = 1
        OTHERS            = 2.
    IF sy-subrc <> 0.
      SET CURSOR FIELD 'P_BUDAT'.
      MESSAGE e000 WITH '历史库龄日期格式不正确'.
    ENDIF.
    gdf_lfgja = gdf_budat+0(4).
    gdf_lfmon = gdf_budat+4(2).
    gdf_datum = p_budat.
  ELSE.
    gdf_datum = sy-datum.
  ENDIF.

** 工厂的权限检查  AUTHORITY-CHECK OBJECT 'M_BEST_WRK'
*  CALL FUNCTION 'ZFI_GET_WERKS'
*    EXPORTING
*      ir_werks   = so_werks[]
*    IMPORTING
*      er_werks   = gdr_werks[]
*    EXCEPTIONS
*      not_found  = 1
*      not_enough = 2
*      OTHERS     = 3.
*  IF sy-subrc <> 0.
*    SET CURSOR FIELD 'SO_WERKS-LOW'.
*    MESSAGE e004 WITH '操作工厂的权限不足!'.
*  ENDIF.
* 工厂的权限检查  AUTHORITY-CHECK OBJECT 'M_MSEG_WMB'
  CALL FUNCTION 'ZFI_GET_WERK2'
    EXPORTING
      ir_werks   = so_werks[]
*     ir_werks   = gdr_werks[]
    IMPORTING
      er_werks   = gdr_werks[]
    EXCEPTIONS
      not_found  = 1
      not_enough = 2
      OTHERS     = 3.
  IF sy-subrc <> 0.
    SET CURSOR FIELD 'SO_WERKS-LOW'.
    MESSAGE e004 WITH '操作工厂的权限不足!'.
  ENDIF.
* 工厂的权限检查  AUTHORITY-CHECK OBJECT 'M_MSEG_WMA'
  CALL FUNCTION 'ZFI_GET_WERK3'
    EXPORTING
      ir_werks   = gdr_werks[]
    IMPORTING
      er_werks   = gdr_werks[]
    EXCEPTIONS
      not_found  = 1
      not_enough = 2
      OTHERS     = 3.
  IF sy-subrc <> 0.
    SET CURSOR FIELD 'SO_WERKS-LOW'.
    MESSAGE e004 WITH '操作工厂的权限不足!'.
  ENDIF.

* 库存地点的权限检查  AUTHORITY-CHECK OBJECT 'M_MSEG_LGO'
  CALL FUNCTION 'ZFI_GET_LGORT'
    EXPORTING
      ir_werks   = gdr_werks[]
      ir_lgort   = so_lgort[]
    TABLES
      et_lgort   = gdt_t001l[]
    EXCEPTIONS
      not_found  = 1
      not_enough = 2
      OTHERS     = 3.
  IF sy-subrc <> 0.
    SET CURSOR FIELD 'SO_LGORT-LOW'.
    MESSAGE e004 WITH '操作库存地点的权限不足!'.
  ENDIF.

* 公司币种信息
  CLEAR: gdt_t001, gdt_t001[].
  SELECT t001k~bwkey
         t001~bukrs
         t001~waers
    INTO TABLE gdt_t001
    FROM t001k INNER JOIN t001 ON t001~bukrs = t001k~bukrs.
  SORT gdt_t001 BY bwkey bukrs.

ENDFORM.                    " FRM_CHECK_PARAMETER

*&---------------------------------------------------------------------*
*&      Form  GET_DATA
*&---------------------------------------------------------------------*
*       逻辑处理
*----------------------------------------------------------------------*
FORM get_data.

  CLEAR:   gdt_alv.
  REFRESH: gdt_alv.

  IF p_c1 = 'X'. " 普通库存
    PERFORM frm_get_data.
  ENDIF.
  IF p_c2 = 'X'. " 销售订单库存
    PERFORM frm_get_data2.
  ENDIF.

  SORT gdt_alv BY werks lgort matnr ztype vbeln posnr.

ENDFORM.                    " GET_DATA

*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DATA
*&---------------------------------------------------------------------*
*       主逻辑
*----------------------------------------------------------------------*
FORM frm_get_data .
  DATA: BEGIN OF ldt_mard OCCURS 10,
         matnr TYPE mard-matnr,
         werks TYPE mard-werks,
         lgort TYPE mard-lgort,
         lfgja TYPE mard-lfgja,
         lfmon TYPE mard-lfmon,
         labst TYPE mard-labst,
         insme TYPE mard-insme,  " 质检库存
         speme TYPE mard-speme,  " 冻结库存
         maktx TYPE makt-maktx,  " 物料描述
         name1 TYPE t001w-name1, " 工厂描述
         lgobe TYPE t001l-lgobe, " 库存地点描述
         meins TYPE mara-meins,
        END OF ldt_mard,
        BEGIN OF ldt_mbew OCCURS 10,
         matnr TYPE mbew-matnr, " 物料编号
         bwkey TYPE mbew-bwkey, " 评估范围
         bwtar TYPE mbew-bwtar, " 评估类型
         lfgja TYPE mbew-lfgja,
         lfmon TYPE mbew-lfmon,
         lbkum TYPE mbew-lbkum, " 总计已估计库存
         salk3 TYPE mbew-salk3, " 估价的总库存价值
         vprsv TYPE mbew-vprsv, " 价格控制指示符
         verpr TYPE mbew-verpr, " 移动平均价格/周期单价
         stprs TYPE mbew-stprs, " 标准价格
         peinh TYPE mbew-peinh, " 价格单位
        END OF ldt_mbew,
        BEGIN OF ldt_mseg OCCURS 10,
         mblnr TYPE mkpf-mblnr,
         mjahr TYPE mkpf-mjahr,
         budat TYPE mkpf-budat,
         zeile TYPE mseg-zeile,
         matnr TYPE mseg-matnr,
         werks TYPE mseg-werks,
         lgort TYPE mseg-lgort,
         shkzg TYPE mseg-shkzg,
         menge TYPE mseg-menge,
         meins TYPE mseg-meins,
        END OF ldt_mseg,
        ldt_msegi LIKE TABLE OF ldt_mseg WITH HEADER LINE,
        BEGIN OF ldt_mseg2 OCCURS 10,
         matnr TYPE mseg-matnr,
         werks TYPE mseg-werks,
         lgort TYPE mseg-lgort,
         meng1 TYPE gtf_menge,
         meng2 TYPE gtf_menge,
         meng3 TYPE gtf_menge,
         meng4 TYPE gtf_menge,
         meng5 TYPE gtf_menge,
         meng6 TYPE gtf_menge,
         meng7 TYPE gtf_menge,
         meng8 TYPE gtf_menge,
         meng9 TYPE gtf_menge,
*         meng10 TYPE gtf_menge, "20160615 add
*         meins type mseg-meins,
        END OF ldt_mseg2,
        BEGIN OF ldt_mbst OCCURS 10,
         mblnr TYPE mseg-mblnr,
         mjahr TYPE mseg-mjahr,
         zeile TYPE mseg-zeile,
         sjahr TYPE mseg-sjahr, " 物料凭证年度
         smbln TYPE mseg-smbln, " 物料凭证编号
         smblp TYPE mseg-smblp, " 物料凭证中的项目
        END OF ldt_mbst,
*        ldt_zmseg TYPE TABLE OF zmm_mseg WITH HEADER LINE, "add by lumingdao 20160108
        ldt_zmseg TYPE TABLE OF zmm_mseg_new WITH HEADER LINE.

  DATA: ldf_price TYPE gtf_price,
        ldf_index TYPE i,
        ldf_count TYPE i,
        ldf_vprsv TYPE mbew-vprsv,
        ldf_menge TYPE gtf_menge,
        ldf_dmbtr TYPE gtf_dmbtr,
        ldf_days  TYPE i,
        ldf_meng1 TYPE mseg-menge,
        ldf_meng2 TYPE mseg-menge.

  CLEAR:   ldt_mard, ldt_mbew, ldt_mseg, ldt_mseg2, ldt_zmseg, ldt_mbst, ldt_msegi.
  REFRESH: ldt_mard, ldt_mbew, ldt_mseg, ldt_mseg2, ldt_zmseg, ldt_mbst, ldt_msegi.

  SELECT mard~matnr
         mard~werks
         mard~lgort
         mard~lfgja
         mard~lfmon
         mard~labst  " 非限制库存
         mard~insme  " 质检库存
         mard~speme  " 冻结库存
         makt~maktx  " 物料描述
         t001w~name1 " 工厂描述
         t001l~lgobe " 库存地点描述
         mara~meins
    INTO TABLE ldt_mard
    FROM mard LEFT OUTER JOIN makt ON makt~matnr = mard~matnr
                                  AND makt~spras = '1'
              LEFT OUTER JOIN t001w ON t001w~werks = mard~werks
              LEFT OUTER JOIN t001l ON t001l~werks = mard~werks
                                   AND t001l~lgort = mard~lgort
              LEFT OUTER JOIN mara ON mara~matnr = mard~matnr
   WHERE mard~matnr IN so_matnr
     AND mard~werks IN gdr_werks.
*     AND mard~lgort IN so_lgort.
  IF p_r2 = 'X'.
    SELECT mardh~matnr
           mardh~werks
           mardh~lgort
           mardh~lfgja
           mardh~lfmon
           mardh~labst  " 非限制库存
           mardh~insme  " 质检库存
           mardh~speme  " 冻结库存
           makt~maktx  " 物料描述
           t001w~name1 " 工厂描述
           t001l~lgobe " 库存地点描述
           mara~meins
      APPENDING TABLE ldt_mard
      FROM mardh LEFT OUTER JOIN makt ON makt~matnr = mardh~matnr
                                     AND makt~spras = '1'
                 LEFT OUTER JOIN t001w ON t001w~werks = mardh~werks
                 LEFT OUTER JOIN t001l ON t001l~werks = mardh~werks
                                      AND t001l~lgort = mardh~lgort
                 LEFT OUTER JOIN mara ON mara~matnr = mardh~matnr
*     WHERE mardh~matnr IN so_matnr
*       AND mardh~werks IN gdr_werks.
**       AND mardh~lgort IN so_lgort.
*    DELETE ldt_mard WHERE lfgja > gdf_lfgja.
*    DELETE ldt_mard WHERE lfgja = gdf_lfgja AND lfmon > gdf_lfmon.
*    SORT ldt_mard BY matnr werks lgort lfgja DESCENDING lfmon DESCENDING.
*    LOOP AT ldt_mard.
*      ldf_index = sy-tabix.
*      AT NEW lgort.
*        ldf_count = 0.
*      ENDAT.
*      ADD 1 TO ldf_count.
*      IF ldf_count > 1.
*        ldt_mard-lfgja = '1900'.
*        ldt_mard-lfmon = '01'.
*        MODIFY ldt_mard INDEX ldf_index.
*      ENDIF.
*    ENDLOOP.
*    DELETE ldt_mard WHERE lfgja = '1900' AND lfmon = '01'.
      WHERE mardh~matnr IN so_matnr
        AND mardh~werks IN gdr_werks
        AND ( lfgja > gdf_lfgja OR lfgja = gdf_lfgja AND lfmon >= gdf_lfmon ).
    SORT ldt_mard BY matnr werks lgort lfgja ASCENDING lfmon ASCENDING.
    LOOP AT ldt_mard.
      ldf_index = sy-tabix.
      AT NEW lgort.
        ldf_count = 0.
      ENDAT.
      ADD 1 TO ldf_count.
      IF ldf_count > 1.
        ldt_mard-lfgja = '9999'.
        ldt_mard-lfmon = '12'.
        MODIFY ldt_mard INDEX ldf_index.
      ENDIF.
    ENDLOOP.
    DELETE ldt_mard WHERE lfgja = '9999' AND lfmon = '12'.


*   查询日期不是月底的时候,需要倒推数量
    IF p_budat < gdf_budat.
      IF ldt_mard[] IS NOT INITIAL.
        SELECT mkpf~mblnr
               mkpf~mjahr
               mkpf~budat
               mseg~zeile
               mseg~matnr
               mseg~werks
               mseg~lgort
               mseg~shkzg
               mseg~menge
               mseg~meins
          INTO TABLE ldt_mseg
          FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                                   AND mkpf~mjahr = mseg~mjahr
         WHERE mseg~matnr IN so_matnr
           AND mseg~werks IN gdr_werks
*           AND mseg~lgort IN so_lgort
           AND mseg~sobkz <> 'E'
           AND mkpf~budat > p_budat
           AND mkpf~budat <= gdf_budat.
        LOOP AT ldt_mseg.
          READ TABLE ldt_mard WITH KEY matnr = ldt_mseg-matnr
                                       werks = ldt_mseg-werks
                                       lgort = ldt_mseg-lgort BINARY SEARCH.
          IF sy-subrc = 0.
            ldf_index = sy-tabix.
            IF ldt_mseg-shkzg = 'S'.
              ldt_mard-labst = ldt_mard-labst - ldt_mseg-menge.
            ELSE.
              ldt_mard-labst = ldt_mard-labst + ldt_mseg-menge.
            ENDIF.
            MODIFY ldt_mard INDEX ldf_index.
          ENDIF.
        ENDLOOP.
        CLEAR: ldt_mseg, ldt_mseg[].
      ENDIF.
    ENDIF.
  ENDIF.
  IF ldt_mard[] IS INITIAL.
    RETURN.
  ENDIF.
  SORT ldt_mard BY matnr werks lgort.

* 在设定中, 工厂werks与评估范围bwkey 是完全一致的,省掉转换的麻烦
  SELECT matnr " 物料编号
         bwkey " 评估范围
         bwtar " 评估类型
         lfgja
         lfmon
         lbkum " 总计已估计库存
         salk3 " 估价的总库存价值
         vprsv " 价格控制指示符
         verpr " 移动平均价格/周期单价
         stprs " 标准价格
         peinh " 价格单位
    INTO TABLE ldt_mbew
    FROM mbew
   WHERE matnr IN so_matnr
     AND bwkey IN gdr_werks
     AND bwtar = ''.
  IF p_r2 = 'X'.
    SELECT matnr " 物料编号
           bwkey " 评估范围
           bwtar " 评估类型
           lfgja
           lfmon
           lbkum " 总计已估计库存
           salk3 " 估价的总库存价值
           vprsv " 价格控制指示符
           verpr " 移动平均价格/周期单价
           stprs " 标准价格
           peinh " 价格单位
      APPENDING TABLE ldt_mbew
      FROM mbewh
     WHERE matnr IN so_matnr
       AND bwkey IN gdr_werks
       AND bwtar = ''
       AND ( lfgja > gdf_lfgja OR lfgja = gdf_lfgja AND lfmon >= gdf_lfmon ).
    SORT ldt_mbew BY matnr bwkey bwtar lfgja ASCENDING lfmon ASCENDING.
    LOOP AT ldt_mbew.
      ldf_index = sy-tabix.
      AT NEW bwtar.
        ldf_count = 0.
      ENDAT.
      ADD 1 TO ldf_count.
      IF ldf_count > 1.
        ldt_mbew-lfgja = '9999'.
        ldt_mbew-lfmon = '12'.
        MODIFY ldt_mbew INDEX ldf_index.
      ENDIF.
    ENDLOOP.
    DELETE ldt_mbew WHERE lfgja = '9999' AND lfmon = '12'.
  ENDIF.
  SORT ldt_mbew BY matnr bwkey bwtar.

* 整理数据
  LOOP AT ldt_mard.
    AT NEW werks.
      CLEAR: ldf_menge, ldf_dmbtr.
*     读取单位价格
      READ TABLE ldt_mbew WITH KEY matnr = ldt_mard-matnr
                                   bwkey = ldt_mard-werks BINARY SEARCH.
      IF sy-subrc = 0.
        IF ldt_mbew-vprsv = 'S'.
          ldf_vprsv = 'S'.
          IF ldt_mbew-peinh = 0 OR ldt_mbew-peinh = 1.
            ldf_price = ldt_mbew-stprs.
          ELSE.
            ldf_price = ldt_mbew-stprs / ldt_mbew-peinh.
          ENDIF.
        ELSE.
          ldf_vprsv = 'V'.
          ldf_menge = ldt_mbew-lbkum.
          ldf_dmbtr = ldt_mbew-salk3.
          IF ldt_mbew-peinh = 0 OR ldt_mbew-peinh = 1.
            IF ldt_mbew-lbkum = 0.
              ldf_price = ldt_mbew-verpr.
            ELSE.
              ldf_price = ldt_mbew-salk3 / ldt_mbew-lbkum.
            ENDIF.
          ELSE.
            IF ldt_mbew-lbkum = 0.
              ldf_price = ldt_mbew-verpr / ldt_mbew-peinh.
            ELSE.
              ldf_price = ldt_mbew-salk3 / ldt_mbew-lbkum / ldt_mbew-peinh.
            ENDIF.
          ENDIF.
        ENDIF.
      ELSE.
        ldf_vprsv = 'S'.
        ldf_price = 0.
*        IF ldt_mbew-lbkum = 0.
*          ldf_price = 0.
*        ELSE.
*          ldf_price = ldt_mbew-salk3 / ldt_mbew-lbkum.
*        ENDIF.
      ENDIF.
    ENDAT.
**   按照库存地点权限进行过滤
*    READ TABLE gdt_t001l WITH KEY werks = ldt_mard-werks
*                                  lgort = ldt_mard-lgort BINARY SEARCH.
*    IF sy-subrc <> 0.
*      CONTINUE.
*    ENDIF.

*   整理常规数据
    CLEAR gds_alv.
    gds_alv-matnr  = ldt_mard-matnr.
    gds_alv-maktx  = ldt_mard-maktx.
    gds_alv-werks  = ldt_mard-werks.
    gds_alv-name1  = ldt_mard-name1.
    gds_alv-lgort  = ldt_mard-lgort.
    gds_alv-lgobe  = ldt_mard-lgobe.
    gds_alv-ztype  = '普通库存'.
    gds_alv-meins  = ldt_mard-meins.
    CALL FUNCTION 'ZTOOL_GET_MSEHL'
      EXPORTING
        meins = gds_alv-meins
      IMPORTING
        msehl = gds_alv-msehl.
    READ TABLE gdt_t001 WITH KEY bwkey = gds_alv-werks BINARY SEARCH.
    IF sy-subrc = 0.
      gds_alv-waers = gdt_t001-waers.
    ENDIF.
*    gds_alv-price  = ldf_price.
    gds_alv-menge  = ldt_mard-labst + ldt_mard-insme + ldt_mard-speme.
    gds_alv-dmbtr  = gds_alv-menge * ldf_price.
    ldf_menge = ldf_menge - gds_alv-menge.
    ldf_dmbtr = ldf_dmbtr - gds_alv-dmbtr.
    APPEND gds_alv TO gdt_alv.
    AT END OF werks.
      IF ldf_vprsv = 'V'.
        IF ldf_menge = 0 AND ldf_dmbtr <> 0.
*         存在尾差的情况下,将尾差写到最后一行
          DESCRIBE TABLE gdt_alv LINES ldf_count.
          READ TABLE gdt_alv INTO gds_alv INDEX ldf_count.
          gds_alv-dmbtr = gds_alv-dmbtr + ldf_dmbtr.
          MODIFY gdt_alv FROM gds_alv INDEX ldf_count TRANSPORTING dmbtr.
        ENDIF.
      ENDIF.
    ENDAT.
  ENDLOOP.
* 去掉库存为零的项目
  DELETE gdt_alv WHERE menge = 0.
  IF so_lgort[] IS NOT INITIAL.
    DELETE gdt_alv WHERE lgort NOT IN so_lgort[].
  ENDIF.
* 按照库存地点权限进行过滤
  IF gdt_t001l[] IS NOT INITIAL.
    LOOP AT gdt_alv INTO gds_alv.
      ldf_index = sy-tabix. "added by yangk 20150831  原因:ldf_index参数未指定,导致数据有问题,权限小的用户会down
      READ TABLE gdt_t001l WITH KEY werks = gds_alv-werks
                                    lgort = gds_alv-lgort BINARY SEARCH.
      IF sy-subrc <> 0.
        gds_alv-menge = 0.
        MODIFY gdt_alv FROM gds_alv INDEX ldf_index TRANSPORTING menge.
      ENDIF.
    ENDLOOP.
    CLEAR ldf_index."added by yangk 20150831
  ENDIF.
  DELETE gdt_alv WHERE menge = 0.

  CLEAR:   ldt_mard, ldt_mbew.
  REFRESH: ldt_mard, ldt_mbew.

* 获取库龄
* 期初库龄
  SELECT *
    INTO TABLE ldt_zmseg
*    FROM zmm_mseg "add by XXX 20160108
    FROM zmm_mseg_new "add by XXX 20160108
     FOR ALL ENTRIES IN gdt_alv
   WHERE matnr = gdt_alv-matnr
     AND werks = gdt_alv-werks
     AND lgort = gdt_alv-lgort
     AND ( vbeln = '' OR vbeln = '0000000000' )
     AND budat <= gdc_idate .
  SORT ldt_zmseg BY matnr werks lgort budat DESCENDING.
* 对2013-12-31的库存数量
* 按照入库的日期,进行逐一匹配比对... 2013-12-31是期初导入,特殊逻辑处理
  SELECT mkpf~mblnr
         mkpf~mjahr
         mkpf~budat
         mseg~zeile
         mseg~matnr
         mseg~werks
         mseg~lgort
         mseg~shkzg
         mseg~menge
         mseg~meins
    INTO TABLE ldt_msegi
    FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                             AND mkpf~mjahr = mseg~mjahr
     FOR ALL ENTRIES IN gdt_alv
   WHERE mseg~matnr = gdt_alv-matnr
     AND mseg~werks = gdt_alv-werks
     AND mseg~lgort = gdt_alv-lgort
     AND mseg~bwart <> '321'
     AND mseg~bwart <> '322'
     AND mseg~sobkz <> 'E'
*     AND mseg~shkzg = 'H'
     AND mkpf~budat = gdc_idate .
  SORT ldt_msegi BY matnr werks lgort.
  LOOP AT ldt_msegi.
    CLEAR ldt_mseg.
    ldt_mseg-matnr = ldt_msegi-matnr.
    ldt_mseg-werks = ldt_msegi-werks.
    ldt_mseg-lgort = ldt_msegi-lgort.
    IF ldt_msegi-shkzg = 'S'.
      ldt_mseg-menge = ldt_msegi-menge.
    ELSE.
      ldt_mseg-menge = 0 - ldt_msegi-menge.
    ENDIF.
    ldt_mseg-meins = ldt_msegi-meins.
    ldt_mseg-budat = gdc_idate.
    COLLECT ldt_mseg.
  ENDLOOP.
* 按照入库的日期,进行逐一匹配比对... 2013-12-31是期初导入,特殊逻辑处理
  SELECT mkpf~mblnr
         mkpf~mjahr
         mkpf~budat
         mseg~zeile
         mseg~matnr
         mseg~werks
         mseg~lgort
         mseg~shkzg
         mseg~menge
         mseg~meins
    APPENDING TABLE ldt_mseg
    FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                             AND mkpf~mjahr = mseg~mjahr
     FOR ALL ENTRIES IN gdt_alv
   WHERE mseg~matnr = gdt_alv-matnr
     AND mseg~werks = gdt_alv-werks
     AND mseg~lgort = gdt_alv-lgort
     AND mseg~bwart <> '321'
     AND mseg~bwart <> '322'
     AND mseg~sobkz <> 'E'
     AND mseg~shkzg = 'S'
     AND mkpf~budat <> gdc_idate.
  IF p_r2 = 'X'.
    DELETE ldt_mseg WHERE budat > gdf_budat.
  ENDIF.
* 获取所有的冲销凭证 - 2013-12-31是期初导入,特殊逻辑处理,冲销从2014年开始判断
  IF p_r2 = 'X'.
    SELECT mseg~mblnr
           mseg~mjahr
           mseg~zeile
           mseg~sjahr " 物料凭证年度
           mseg~smbln " 物料凭证编号
           mseg~smblp " 物料凭证中的项目
      INTO TABLE ldt_mbst
      FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                               AND mkpf~mjahr = mseg~mjahr
     WHERE mseg~smbln <> ''
       AND mseg~mjahr >= '2014'
       AND mseg~bwart <> '321'
       AND mseg~bwart <> '322'
       AND mkpf~budat <= gdf_budat.
  ELSE.
    SELECT mblnr
           mjahr
           zeile
           sjahr " 物料凭证年度
           smbln " 物料凭证编号
           smblp " 物料凭证中的项目
      INTO TABLE ldt_mbst
      FROM mseg
     WHERE smbln <> ''
       AND mjahr >= '2014'
       AND bwart <> '321'
       AND bwart <> '322'.
  ENDIF.
  SORT ldt_mbst BY sjahr smbln smblp.
* 将冲销凭证剔出 - 冲销的情况总是比较少的,所以优先处理
  SORT ldt_mseg BY mjahr mblnr zeile.
  LOOP AT ldt_mbst.
    READ TABLE ldt_mseg WITH KEY mjahr = ldt_mbst-sjahr
                                 mblnr = ldt_mbst-smbln
                                 zeile = ldt_mbst-smblp BINARY SEARCH.
    IF sy-subrc = 0.
*     删除 被冲销凭证
      DELETE ldt_mseg INDEX sy-tabix.
*     删除 冲销凭证
      DELETE ldt_mseg WHERE mjahr = ldt_mbst-mjahr
                        AND mblnr = ldt_mbst-mblnr
                        AND zeile = ldt_mbst-zeile.
    ENDIF.
  ENDLOOP.
* 处理库存
  SORT ldt_mseg BY matnr werks lgort budat DESCENDING.
  LOOP AT ldt_mseg.
    CLEAR ldt_mseg2.
    ldt_mseg2-matnr = ldt_mseg-matnr.
    ldt_mseg2-werks = ldt_mseg-werks.
    ldt_mseg2-lgort = ldt_mseg-lgort.
*   物料凭证中menge数量单位就是物料数据中的基本单位,所以不用做单位换算逻辑
*    ldt_mseg2-meins = ldt_mseg-meins.
    IF ldt_mseg-budat = gdc_idate . " 期初数据处理
      ldf_meng1 = ldt_mseg-menge.
      LOOP AT ldt_zmseg WHERE matnr = ldt_mseg-matnr
                          AND werks = ldt_mseg-werks
                          AND lgort = ldt_mseg-lgort
                          AND menge > 0.
        ldf_index = sy-tabix.
        ldf_days = gdf_datum - ldt_zmseg-budat.
        IF ldt_zmseg-menge >= ldf_meng1.
          ldf_meng2 = ldf_meng1.
        ELSE.
          ldf_meng2 = ldt_zmseg-menge.
        ENDIF.

*        IF ldf_days <= 30.
*          ldt_mseg2-meng1 = ldf_meng2.
*        ELSEIF ldf_days <= 90.
*          ldt_mseg2-meng2 = ldf_meng2.
*        ELSEIF ldf_days <= 180.
*          ldt_mseg2-meng3 = ldf_meng2.
**        ELSEIF ldf_days <= 270. "20160615 add
**          ldt_mseg2-meng10 = ldf_meng2.
*        ELSEIF ldf_days <= 365.
*          ldt_mseg2-meng4 = ldf_meng2.
*        ELSEIF ldf_days <= 730.  " 两年内
*          ldt_mseg2-meng5 = ldf_meng2.
*        ELSEIF ldf_days <= 1095. " 三年内
*          ldt_mseg2-meng6 = ldf_meng2.
*        ELSEIF ldf_days <= 1460. " 四年内
*          ldt_mseg2-meng7 = ldf_meng2.
*        ELSEIF ldf_days <= 1825. " 五年内
*          ldt_mseg2-meng8 = ldf_meng2.
*        ELSE.
*          ldt_mseg2-meng9 = ldf_meng2.
*        ENDIF.
**************************20160616 change*****************************
        IF ldf_days <= d1.
          ldt_mseg2-meng1 = ldf_meng2.
        ELSEIF ldf_days <= d2.
          ldt_mseg2-meng2 = ldf_meng2.
        ELSEIF ldf_days <= d3.
          ldt_mseg2-meng3 = ldf_meng2.
        ELSEIF ldf_days <=  d4.
          ldt_mseg2-meng4 = ldf_meng2.
        ELSEIF ldf_days <=  d5.  " 两年内
          ldt_mseg2-meng5 = ldf_meng2.
        ELSEIF ldf_days <=  d6. " 三年内
          ldt_mseg2-meng6 = ldf_meng2.
        ELSEIF ldf_days <=  d7. " 四年内
          ldt_mseg2-meng7 = ldf_meng2.
        ELSEIF ldf_days <=  d8. " 五年内
          ldt_mseg2-meng8 = ldf_meng2.
        ELSE.
          ldt_mseg2-meng9 = ldf_meng2.
        ENDIF.
**********************************************************************
        COLLECT ldt_mseg2.
        CLEAR: ldt_mseg2-meng1, ldt_mseg2-meng2, ldt_mseg2-meng3, ldt_mseg2-meng4, ldt_mseg2-meng5,
               ldt_mseg2-meng6, ldt_mseg2-meng7, ldt_mseg2-meng8, ldt_mseg2-meng9.
        ldt_zmseg-menge = ldt_zmseg-menge - ldf_meng2.
        MODIFY ldt_zmseg INDEX ldf_index.
        ldf_meng1 = ldf_meng1 - ldf_meng2.
        IF ldf_meng1 <= 0.
          EXIT.
        ENDIF.
      ENDLOOP.
      IF ldf_meng1 > 0..
        ldf_days = gdf_datum - ldt_mseg-budat.
*        IF ldf_days <= 30.
*          ldt_mseg2-meng1 = ldf_meng1.
*        ELSEIF ldf_days <= 90.
*          ldt_mseg2-meng2 = ldf_meng1.
*        ELSEIF ldf_days <= 180.
*          ldt_mseg2-meng3 = ldf_meng1.
*        ELSEIF ldf_days <= 365.
*          ldt_mseg2-meng4 = ldf_meng1.
*        ELSEIF ldf_days <= 730.
*          ldt_mseg2-meng5 = ldf_meng1.
*        ELSEIF ldf_days <= 1095. " 三年内
*          ldt_mseg2-meng6 = ldf_meng1.
*        ELSEIF ldf_days <= 1460. " 四年内
*          ldt_mseg2-meng7 = ldf_meng1.
*        ELSEIF ldf_days <= 1825. " 五年内
*          ldt_mseg2-meng8 = ldf_meng1.
*        ELSE.
*          ldt_mseg2-meng9 = ldf_meng1.
*        ENDIF.
**************************20160616 change*****************************
        IF ldf_days <= d1.
          ldt_mseg2-meng1 = ldf_meng1.
        ELSEIF ldf_days <= d2.
          ldt_mseg2-meng2 = ldf_meng1.
        ELSEIF ldf_days <= d3.
          ldt_mseg2-meng3 = ldf_meng1.
        ELSEIF ldf_days <=  d4.
          ldt_mseg2-meng4 = ldf_meng1.
        ELSEIF ldf_days <=  d5.  " 两年内
          ldt_mseg2-meng5 = ldf_meng1.
        ELSEIF ldf_days <=  d6. " 三年内
          ldt_mseg2-meng6 = ldf_meng1.
        ELSEIF ldf_days <=  d7. " 四年内
          ldt_mseg2-meng7 = ldf_meng1.
        ELSEIF ldf_days <=  d8. " 五年内
          ldt_mseg2-meng8 = ldf_meng1.
        ELSE.
          ldt_mseg2-meng9 = ldf_meng1.
        ENDIF.
**********************************************************************
        COLLECT ldt_mseg2.
        CLEAR: ldt_mseg2-meng1, ldt_mseg2-meng2, ldt_mseg2-meng3, ldt_mseg2-meng4, ldt_mseg2-meng5,
               ldt_mseg2-meng6, ldt_mseg2-meng7, ldt_mseg2-meng8, ldt_mseg2-meng9.
      ENDIF.
    ELSE.
      ldf_days = gdf_datum - ldt_mseg-budat.
*      IF ldf_days <= 30.
*        ldt_mseg2-meng1 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 90.
*        ldt_mseg2-meng2 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 180.
*        ldt_mseg2-meng3 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 365.
*        ldt_mseg2-meng4 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 730.
*        ldt_mseg2-meng5 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 1095. " 三年内
*        ldt_mseg2-meng6 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 1460. " 四年内
*        ldt_mseg2-meng7 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 1825. " 五年内
*        ldt_mseg2-meng8 = ldt_mseg-menge.
*      ELSE.
*        ldt_mseg2-meng9 = ldt_mseg-menge.
*      ENDIF.
**************************20160616 change*****************************
      IF ldf_days <= d1.
        ldt_mseg2-meng1 = ldt_mseg-menge.
      ELSEIF ldf_days <= d2.
        ldt_mseg2-meng2 = ldt_mseg-menge.
      ELSEIF ldf_days <= d3.
        ldt_mseg2-meng3 = ldt_mseg-menge.
      ELSEIF ldf_days <=  d4.
        ldt_mseg2-meng4 = ldt_mseg-menge.
      ELSEIF ldf_days <=  d5.  " 两年内
        ldt_mseg2-meng5 = ldt_mseg-menge.
      ELSEIF ldf_days <=  d6. " 三年内
        ldt_mseg2-meng6 = ldt_mseg-menge.
      ELSEIF ldf_days <=  d7. " 四年内
        ldt_mseg2-meng7 = ldt_mseg-menge.
      ELSEIF ldf_days <=  d8. " 五年内
        ldt_mseg2-meng8 = ldt_mseg-menge.
      ELSE.
        ldt_mseg2-meng9 = ldt_mseg-menge.
      ENDIF.
**********************************************************************
      COLLECT ldt_mseg2.
      CLEAR: ldt_mseg2-meng1, ldt_mseg2-meng2, ldt_mseg2-meng3, ldt_mseg2-meng4, ldt_mseg2-meng5,
             ldt_mseg2-meng6, ldt_mseg2-meng7, ldt_mseg2-meng8, ldt_mseg2-meng9.
    ENDIF.
*    ldf_days = gdf_datum - ldt_mseg-budat.
*    IF ldf_days <= 30.
*      ldt_mseg2-meng1 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 90.
*      ldt_mseg2-meng2 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 180.
*      ldt_mseg2-meng3 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 365.
*      ldt_mseg2-meng4 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 730.
*      ldt_mseg2-meng5 = ldt_mseg-menge.
*    ELSE.
*      ldt_mseg2-meng6 = ldt_mseg-menge.
*    ENDIF.
*    COLLECT ldt_mseg2.
  ENDLOOP.
  SORT ldt_mseg2 BY matnr werks lgort.

* 计算库龄
  SORT gdt_alv BY matnr werks lgort vbeln posnr.
  LOOP AT gdt_alv INTO gds_alv.
    ldf_index = sy-tabix.
    IF gds_alv-menge = 0.
      gds_alv-price = 0.
    ELSE.
      gds_alv-price = gds_alv-dmbtr / gds_alv-menge.
    ENDIF.
    ldf_menge = gds_alv-menge.
    ldf_dmbtr = gds_alv-dmbtr.
    READ TABLE ldt_mseg2 WITH KEY matnr = gds_alv-matnr
                                  werks = gds_alv-werks
                                  lgort = gds_alv-lgort BINARY SEARCH.
    IF sy-subrc = 0.
      DO 1 TIMES.
        IF ldf_menge < ldt_mseg2-meng1.
          gds_alv-meng1 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng1 = ldt_mseg2-meng1.
        ldf_menge = ldf_menge - ldt_mseg2-meng1.

        IF ldf_menge < ldt_mseg2-meng2.
          gds_alv-meng2 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng2 = ldt_mseg2-meng2.
        ldf_menge = ldf_menge - ldt_mseg2-meng2.

        IF ldf_menge < ldt_mseg2-meng3.
          gds_alv-meng3 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng3 = ldt_mseg2-meng3.
        ldf_menge = ldf_menge - ldt_mseg2-meng3.

****************************20160615 add******************************
*        IF ldf_menge < ldt_mseg2-meng10.
*          gds_alv-meng10 = ldf_menge.
*          ldf_menge = 0.
*          EXIT.
*        ENDIF.
*        gds_alv-meng10 = ldt_mseg2-meng10.
*        ldf_menge = ldf_menge - ldt_mseg2-meng10.
**********************************************************************

        IF ldf_menge < ldt_mseg2-meng4.
          gds_alv-meng4 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng4 = ldt_mseg2-meng4.
        ldf_menge = ldf_menge - ldt_mseg2-meng4.

        IF ldf_menge < ldt_mseg2-meng5.
          gds_alv-meng5 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng5 = ldt_mseg2-meng5.
        ldf_menge = ldf_menge - ldt_mseg2-meng5.

        IF ldf_menge < ldt_mseg2-meng6.
          gds_alv-meng6 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng6 = ldt_mseg2-meng6.
        ldf_menge = ldf_menge - ldt_mseg2-meng6.

        IF ldf_menge < ldt_mseg2-meng7.
          gds_alv-meng7 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng7 = ldt_mseg2-meng7.
        ldf_menge = ldf_menge - ldt_mseg2-meng7.

        IF ldf_menge < ldt_mseg2-meng8.
          gds_alv-meng8 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng8 = ldt_mseg2-meng8.
        ldf_menge = ldf_menge - ldt_mseg2-meng8.

        IF ldf_menge < ldt_mseg2-meng9.
          gds_alv-meng9 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng9 = ldt_mseg2-meng9.
        ldf_menge = ldf_menge - ldt_mseg2-meng9.
      ENDDO.
    ENDIF.
*   初始库存导入
    IF ldf_menge > 0.
      gds_alv-meng99 = ldf_menge.
      ldf_days = gdf_datum - gdc_idate.
*      IF ldf_days <= 30.
*        ADD 1 TO gds_alv-meng1.
*      ELSEIF ldf_days <= 90.
*        ADD 1 TO gds_alv-meng2.
*      ELSEIF ldf_days <= 180.
*        ADD 1 TO gds_alv-meng3.
**      ELSEIF ldf_days <= 270. "20160615 add
**        ADD 1 TO gds_alv-meng10.
*      ELSEIF ldf_days <= 365.
*        ADD 1 TO gds_alv-meng4.
*      ELSEIF ldf_days <= 730.
*        ADD 1 TO gds_alv-meng5.
*      ELSEIF ldf_days <= 1095. " 三年内
*        ADD 1 TO gds_alv-meng6.
*      ELSEIF ldf_days <= 1460. " 四年内
*        ADD 1 TO gds_alv-meng7.
*      ELSEIF ldf_days <= 1825. " 五年内
*        ADD 1 TO gds_alv-meng8.
*      ELSE.
*        ADD 1 TO gds_alv-meng9.
*      ENDIF.
*************************20160616 change******************************
      IF ldf_days <= d1.
        ADD 1 TO gds_alv-meng1.
      ELSEIF ldf_days <= d2.
        ADD 1 TO gds_alv-meng2.
      ELSEIF ldf_days <= d3.
        ADD 1 TO gds_alv-meng3.
      ELSEIF ldf_days <= d4.
        ADD 1 TO gds_alv-meng4.
      ELSEIF ldf_days <= d5.
        ADD 1 TO gds_alv-meng5.
      ELSEIF ldf_days <= d6. " 三年内
        ADD 1 TO gds_alv-meng6.
      ELSEIF ldf_days <= d7. " 四年内
        ADD 1 TO gds_alv-meng7.
      ELSEIF ldf_days <= d8. " 五年内
        ADD 1 TO gds_alv-meng8.
      ELSE.
        ADD 1 TO gds_alv-meng9.
      ENDIF.
**********************************************************************
    ENDIF.
*   计算金额
    gds_alv-dmbt1 = gds_alv-meng1 * gds_alv-price.
    gds_alv-dmbt2 = gds_alv-meng2 * gds_alv-price.
    gds_alv-dmbt3 = gds_alv-meng3 * gds_alv-price.
*    gds_alv-dmbt10 = gds_alv-meng10 * gds_alv-price. "20160615 add
    gds_alv-dmbt4 = gds_alv-meng4 * gds_alv-price.
    gds_alv-dmbt5 = gds_alv-meng5 * gds_alv-price.
    gds_alv-dmbt6 = gds_alv-meng6 * gds_alv-price.
    gds_alv-dmbt7 = gds_alv-meng7 * gds_alv-price.
    gds_alv-dmbt8 = gds_alv-meng8 * gds_alv-price.
    gds_alv-dmbt9 = gds_alv-meng9 * gds_alv-price.
*   处理尾差
    ldf_dmbtr = ldf_dmbtr
              - gds_alv-dmbt1
              - gds_alv-dmbt2
              - gds_alv-dmbt3
*              - gds_alv-dmbt10 "20160615 add
              - gds_alv-dmbt4
              - gds_alv-dmbt5
              - gds_alv-dmbt6
              - gds_alv-dmbt7
              - gds_alv-dmbt8
              - gds_alv-dmbt9.
    IF ldf_dmbtr <> 0.
*      gds_alv-dmbt99 = ldf_dmbtr.
      IF gds_alv-meng1 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt1.
      ELSEIF gds_alv-meng2 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt2.
      ELSEIF gds_alv-meng3 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt3.
*      ELSEIF gds_alv-meng10 <> 0. "20160615 add
*        ADD ldf_dmbtr TO gds_alv-dmbt10.
      ELSEIF gds_alv-meng4 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt4.
      ELSEIF gds_alv-meng5 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt5.
      ELSEIF gds_alv-meng6 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt6.
      ELSEIF gds_alv-meng7 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt7.
      ELSEIF gds_alv-meng8 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt8.
      ELSEIF gds_alv-meng9 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt9.
      ELSE.
        gds_alv-dmbtr = gds_alv-dmbtr - ldf_dmbtr.
      ENDIF.
    ENDIF.
    MODIFY gdt_alv FROM gds_alv INDEX ldf_index.
  ENDLOOP.

  CLEAR:   ldt_mseg, ldt_mseg2, ldt_zmseg, ldt_mbst, ldt_msegi.
  REFRESH: ldt_mseg, ldt_mseg2, ldt_zmseg, ldt_mbst, ldt_msegi.

ENDFORM.                    " FRM_GET_DATA

*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DATA2
*&---------------------------------------------------------------------*
*       主逻辑
*----------------------------------------------------------------------*
FORM frm_get_data2.
  DATA: BEGIN OF ldt_mska OCCURS 10,
         matnr TYPE mska-matnr,
         werks TYPE mska-werks,
         lgort TYPE mska-lgort,
         charg TYPE mska-charg,
         sobkz TYPE mska-sobkz,
         vbeln TYPE mska-vbeln,
         posnr TYPE mska-posnr,
         lfgja TYPE mska-lfgja,
         lfmon TYPE mska-lfmon,
         kalab TYPE mska-kalab,  " 非限制库存
         kains TYPE mska-kains,  " 质量检验中的库存
         kaspe TYPE mska-kaspe,  " 冻结的库存
         maktx TYPE makt-maktx,  " 物料描述
         name1 TYPE t001w-name1, " 工厂描述
         lgobe TYPE t001l-lgobe, " 库存地点描述
         meins TYPE mara-meins,
        END OF ldt_mska,
        BEGIN OF ldt_mska2 OCCURS 10,
         matnr TYPE mska-matnr,
         werks TYPE mska-werks,
         vbeln TYPE mska-vbeln,
         posnr TYPE mska-posnr,
         lgort TYPE mska-lgort,
         lfgja TYPE mska-lfgja,
         lfmon TYPE mska-lfmon,
         kalab TYPE mska-kalab,  " 非限制库存
         kains TYPE mska-kains,  " 质量检验中的库存
         kaspe TYPE mska-kaspe,  " 冻结的库存
         maktx TYPE makt-maktx,  " 物料描述
         name1 TYPE t001w-name1, " 工厂描述
         lgobe TYPE t001l-lgobe, " 库存地点描述
         meins TYPE mara-meins,
        END OF ldt_mska2,
        BEGIN OF ldt_ebew OCCURS 10,
         matnr TYPE ebew-matnr, " 物料编号
         bwkey TYPE ebew-bwkey, " 评估范围
         bwtar TYPE ebew-bwtar, " 评估类型
         sobkz TYPE ebew-sobkz,
         vbeln TYPE ebew-vbeln,
         posnr TYPE ebew-posnr,
         lfgja TYPE ebew-lfgja,
         lfmon TYPE ebew-lfmon,
         lbkum TYPE ebew-lbkum, " 总计已估计库存
         salk3 TYPE ebew-salk3, " 估价的总库存价值
         vprsv TYPE ebew-vprsv, " 价格控制指示符
         verpr TYPE ebew-verpr, " 移动平均价格/周期单价
         stprs TYPE ebew-stprs, " 标准价格
         peinh TYPE ebew-peinh, " 价格单位
        END OF ldt_ebew,
        BEGIN OF ldt_mseg OCCURS 10,
         mblnr TYPE mkpf-mblnr,
         mjahr TYPE mkpf-mjahr,
         budat TYPE mkpf-budat,
         zeile TYPE mseg-zeile,
         matnr TYPE mseg-matnr,
         werks TYPE mseg-werks,
         lgort TYPE mseg-lgort,
         shkzg TYPE mseg-shkzg,
         kdauf TYPE mseg-kdauf,
         kdpos TYPE mseg-kdpos,
         menge TYPE mseg-menge,
         meins TYPE mseg-meins,
         mat_kdauf TYPE mseg-mat_kdauf,
         mat_kdpos TYPE mseg-mat_kdpos,
        END OF ldt_mseg,
        ldt_msegi LIKE TABLE OF ldt_mseg WITH HEADER LINE,
        BEGIN OF ldt_mseg2 OCCURS 10,
         matnr TYPE mseg-matnr,
         werks TYPE mseg-werks,
         lgort TYPE mseg-lgort,
         kdauf TYPE mseg-kdauf,
         kdpos TYPE mseg-kdpos,
         meng1 TYPE gtf_menge,
         meng2 TYPE gtf_menge,
         meng3 TYPE gtf_menge,
         meng4 TYPE gtf_menge,
         meng5 TYPE gtf_menge,
         meng6 TYPE gtf_menge,
         meng7 TYPE gtf_menge,
         meng8 TYPE gtf_menge,
         meng9 TYPE gtf_menge,
*         meng10 TYPE gtf_menge, "20160615 add
*         meins type mseg-meins,
        END OF ldt_mseg2,
        BEGIN OF ldt_mbst OCCURS 10,
         mblnr TYPE mseg-mblnr,
         mjahr TYPE mseg-mjahr,
         zeile TYPE mseg-zeile,
         sjahr TYPE mseg-sjahr, " 物料凭证年度
         smbln TYPE mseg-smbln, " 物料凭证编号
         smblp TYPE mseg-smblp, " 物料凭证中的项目
        END OF ldt_mbst,
        BEGIN OF ldt_vbak OCCURS 10,
          vbeln TYPE vbak-vbeln,
          kunnr TYPE vbak-kunnr,
        END OF ldt_vbak,
        BEGIN OF ldt_vbap OCCURS 10,
          vbeln TYPE vbap-vbeln,
          posnr TYPE vbap-posnr,
          aufnr TYPE vbap-aufnr,
        END OF ldt_vbap,
        BEGIN OF ldt_aufk OCCURS 10,
          aufnr TYPE aufk-aufnr,
          ktext TYPE aufk-ktext,
        END OF ldt_aufk,
*        ldt_zmseg TYPE TABLE OF zmm_mseg WITH HEADER LINE,  "add by lumingdao 20160108
        ldt_zmseg TYPE TABLE OF zmm_mseg_new WITH HEADER LINE."add by lumingdao 20160108

  DATA: ldf_price TYPE gtf_price,
        ldf_index TYPE i,
        ldf_count TYPE i,
        ldf_kdauf TYPE mseg-kdauf,
        ldf_kdpos TYPE mseg-kdpos,
        ldf_vprsv TYPE ebew-vprsv,
        ldf_menge TYPE gtf_menge,
        ldf_meng1 TYPE mseg-menge,
        ldf_meng2 TYPE mseg-menge,
        ldf_dmbtr TYPE gtf_dmbtr,
        ldf_days  TYPE i.
  DATA: ldt_alv TYPE TABLE OF gts_alv WITH HEADER LINE.

  CLEAR:   ldt_mska, ldt_mska2, ldt_ebew, ldt_mseg, ldt_mseg2, ldt_zmseg,
           ldt_alv, ldt_msegi, ldt_mbst, ldt_vbak, ldt_vbap, ldt_aufk.
  REFRESH: ldt_mska, ldt_mska2, ldt_ebew, ldt_mseg, ldt_mseg2, ldt_zmseg,
           ldt_alv, ldt_msegi, ldt_mbst, ldt_vbak, ldt_vbap, ldt_aufk.

  SELECT mska~matnr
         mska~werks
         mska~lgort
         mska~charg
         mska~sobkz
         mska~vbeln
         mska~posnr
         mska~lfgja
         mska~lfmon
         mska~kalab
         mska~kains  " 质检库存
         mska~kaspe  " 冻结库存
         makt~maktx  " 物料描述
         t001w~name1 " 工厂描述
         t001l~lgobe " 库存地点描述
         mara~meins
    INTO TABLE ldt_mska
    FROM mska LEFT OUTER JOIN makt ON makt~matnr = mska~matnr
                                  AND makt~spras = '1'
              LEFT OUTER JOIN t001w ON t001w~werks = mska~werks
              LEFT OUTER JOIN t001l ON t001l~werks = mska~werks
                                   AND t001l~lgort = mska~lgort
              LEFT OUTER JOIN mara ON mara~matnr = mska~matnr
   WHERE mska~matnr IN so_matnr
     AND mska~werks IN gdr_werks
*     AND mska~lgort IN so_lgort
     AND mska~vbeln IN so_vbeln
     AND mska~posnr IN so_posnr.
  IF p_r2 = 'X'.
    SELECT mskah~matnr
           mskah~werks
           mskah~lgort
           mskah~charg
           mskah~sobkz
           mskah~vbeln
           mskah~posnr
           mskah~lfgja
           mskah~lfmon
           mskah~kalab
           mskah~kains  " 质检库存
           mskah~kaspe  " 冻结库存
           makt~maktx  " 物料描述
           t001w~name1 " 工厂描述
           t001l~lgobe " 库存地点描述
           mara~meins
      APPENDING TABLE ldt_mska
      FROM mskah LEFT OUTER JOIN makt ON makt~matnr = mskah~matnr
                                     AND makt~spras = '1'
                 LEFT OUTER JOIN t001w ON t001w~werks = mskah~werks
                 LEFT OUTER JOIN t001l ON t001l~werks = mskah~werks
                                      AND t001l~lgort = mskah~lgort
                 LEFT OUTER JOIN mara ON mara~matnr = mskah~matnr
*     WHERE mskah~matnr IN so_matnr
*       AND mskah~werks IN gdr_werks
**       AND mskah~lgort IN so_lgort
*       AND mskah~vbeln IN so_vbeln
*       AND mskah~posnr IN so_posnr.
*    DELETE ldt_mska WHERE lfgja > gdf_lfgja.
*    DELETE ldt_mska WHERE lfgja = gdf_lfgja AND lfmon > gdf_lfmon.
*    SORT ldt_mska BY matnr werks lgort charg sobkz vbeln posnr lfgja DESCENDING lfmon DESCENDING.
*    LOOP AT ldt_mska.
*      ldf_index = sy-tabix.
*      AT NEW posnr.
*        ldf_count = 0.
*      ENDAT.
*      ADD 1 TO ldf_count.
*      IF ldf_count > 1.
*        ldt_mska-lfgja = '1900'.
*        ldt_mska-lfmon = '01'.
*        MODIFY ldt_mska INDEX ldf_index.
*      ENDIF.
*    ENDLOOP.
*    DELETE ldt_mska WHERE lfgja = '1900' AND lfmon = '01'.
     WHERE mskah~matnr IN so_matnr
       AND mskah~werks IN gdr_werks
*       AND mskah~lgort IN so_lgort
       AND mskah~vbeln IN so_vbeln
       AND mskah~posnr IN so_posnr
       AND ( lfgja > gdf_lfgja OR lfgja = gdf_lfgja AND lfmon >= gdf_lfmon ).
    SORT ldt_mska BY matnr werks lgort charg sobkz vbeln posnr lfgja ASCENDING lfmon ASCENDING.
    LOOP AT ldt_mska.
      ldf_index = sy-tabix.
      AT NEW posnr.
        ldf_count = 0.
      ENDAT.
      ADD 1 TO ldf_count.
      IF ldf_count > 1.
        ldt_mska-lfgja = '9999'.
        ldt_mska-lfmon = '12'.
        MODIFY ldt_mska INDEX ldf_index.
      ENDIF.
    ENDLOOP.
    DELETE ldt_mska WHERE lfgja = '9999' AND lfmon = '12'.

*   查询日期不是月底的时候,需要倒推数量
    IF p_budat < gdf_budat.
      IF ldt_mska[] IS NOT INITIAL.
        SELECT mkpf~mblnr
               mkpf~mjahr
               mkpf~budat
               mseg~zeile
               mseg~matnr
               mseg~werks
               mseg~lgort
               mseg~shkzg
               mseg~kdauf
               mseg~kdpos
               mseg~menge
               mseg~meins
               mseg~mat_kdauf
               mseg~mat_kdpos
          INTO TABLE ldt_mseg
          FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                                   AND mkpf~mjahr = mseg~mjahr
         WHERE mseg~matnr IN so_matnr
           AND mseg~werks IN gdr_werks
*           AND mseg~lgort IN so_lgort
           AND mseg~sobkz = 'E'
           AND ( ( mseg~kdauf IN so_vbeln AND mseg~kdpos IN so_posnr )
              OR ( mseg~mat_kdauf IN so_vbeln AND mseg~mat_kdpos IN so_posnr ) )
           AND mkpf~budat > p_budat
           AND mkpf~budat <= gdf_budat.
        SORT ldt_mska BY matnr werks lgort vbeln posnr charg sobkz.
        LOOP AT ldt_mseg.
          IF ldt_mseg-kdauf IS INITIAL.
            ldf_kdauf = ldt_mseg-mat_kdauf.
            ldf_kdpos = ldt_mseg-mat_kdpos.
          ELSE.
            ldf_kdauf = ldt_mseg-kdauf.
            ldf_kdpos = ldt_mseg-kdpos.
          ENDIF.
          READ TABLE ldt_mska WITH KEY matnr = ldt_mseg-matnr
                                       werks = ldt_mseg-werks
                                       lgort = ldt_mseg-lgort
                                       vbeln = ldf_kdauf
                                       posnr = ldf_kdpos BINARY SEARCH.
          IF sy-subrc = 0.
            ldf_index = sy-tabix.
            IF ldt_mseg-shkzg = 'S'.
              ldt_mska-kalab = ldt_mska-kalab - ldt_mseg-menge.
            ELSE.
              ldt_mska-kalab = ldt_mska-kalab + ldt_mseg-menge.
            ENDIF.
            MODIFY ldt_mska INDEX ldf_index.
          ENDIF.
        ENDLOOP.
        CLEAR: ldt_mseg, ldt_mseg[].
      ENDIF.
    ENDIF.
  ENDIF.
  IF ldt_mska[] IS INITIAL.
    RETURN.
  ENDIF.
  LOOP AT ldt_mska.
    MOVE-CORRESPONDING ldt_mska TO ldt_mska2.
    COLLECT ldt_mska2.
  ENDLOOP.

* 在设定中, 工厂werks与评估范围bwkey 是完全一致的,省掉转换的麻烦
  SELECT matnr " 物料编号
         bwkey " 评估范围
         bwtar " 评估类型
         sobkz
         vbeln
         posnr
         lfgja
         lfmon
         lbkum " 总计已估计库存
         salk3 " 估价的总库存价值
         vprsv " 价格控制指示符
         verpr " 移动平均价格/周期单价
         stprs " 标准价格
         peinh " 价格单位
    INTO TABLE ldt_ebew
    FROM ebew
   WHERE matnr IN so_matnr
     AND bwkey IN gdr_werks
     AND bwtar = ''
     AND sobkz = 'E'
     AND vbeln IN so_vbeln
     AND posnr IN so_posnr.
  IF p_r2 = 'X'.
    SELECT matnr " 物料编号
           bwkey " 评估范围
           bwtar " 评估类型
           sobkz
           vbeln
           posnr
           lfgja
           lfmon
           lbkum " 总计已估计库存
           salk3 " 估价的总库存价值
           vprsv " 价格控制指示符
           verpr " 移动平均价格/周期单价
           stprs " 标准价格
           peinh " 价格单位
      APPENDING TABLE ldt_ebew
      FROM ebewh
*     WHERE matnr IN so_matnr
*       AND bwkey IN gdr_werks
*       AND bwtar = ''
*       AND sobkz = 'E'
*       AND vbeln IN so_vbeln
*       AND posnr IN so_posnr.
*    DELETE ldt_ebew WHERE lfgja > gdf_lfgja.
*    DELETE ldt_ebew WHERE lfgja = gdf_lfgja AND lfmon > gdf_lfmon.
*    SORT ldt_ebew BY matnr bwkey bwtar sobkz vbeln posnr lfgja DESCENDING lfmon DESCENDING.
*    LOOP AT ldt_ebew.
*      ldf_index = sy-tabix.
*      AT NEW posnr.
*        ldf_count = 0.
*      ENDAT.
*      ADD 1 TO ldf_count.
*      IF ldf_count > 1.
*        ldt_ebew-lfgja = '1900'.
*        ldt_ebew-lfmon = '01'.
*        MODIFY ldt_ebew INDEX ldf_index.
*      ENDIF.
*    ENDLOOP.
*    DELETE ldt_ebew WHERE lfgja = '1900' AND lfmon = '01'.
     WHERE matnr IN so_matnr
       AND bwkey IN gdr_werks
       AND bwtar = ''
       AND sobkz = 'E'
       AND vbeln IN so_vbeln
       AND posnr IN so_posnr
       AND ( lfgja > gdf_lfgja OR lfgja = gdf_lfgja AND lfmon >= gdf_lfmon ).
    SORT ldt_ebew BY matnr bwkey bwtar sobkz vbeln posnr lfgja ASCENDING lfmon ASCENDING.
    LOOP AT ldt_ebew.
      ldf_index = sy-tabix.
      AT NEW posnr.
        ldf_count = 0.
      ENDAT.
      ADD 1 TO ldf_count.
      IF ldf_count > 1.
        ldt_ebew-lfgja = '9999'.
        ldt_ebew-lfmon = '12'.
        MODIFY ldt_ebew INDEX ldf_index.
      ENDIF.
    ENDLOOP.
    DELETE ldt_ebew WHERE lfgja = '9999' AND lfmon = '12'.

  ENDIF.
  SORT ldt_ebew BY matnr bwkey sobkz vbeln posnr.

* 整理数据
  SORT ldt_mska2 BY matnr werks vbeln posnr lgort.
  LOOP AT ldt_mska2.
    AT NEW posnr.
      CLEAR: ldf_menge, ldf_dmbtr.
*     读取单位价格
      READ TABLE ldt_ebew WITH KEY matnr = ldt_mska2-matnr
                                   bwkey = ldt_mska2-werks
*                                   sobkz = ldt_mska-sobkz
                                   vbeln = ldt_mska2-vbeln
                                   posnr = ldt_mska2-posnr BINARY SEARCH.
      IF sy-subrc = 0.
        IF ldt_ebew-vprsv = 'S'.
          ldf_vprsv = 'S'.
          IF ldt_ebew-peinh = 0 OR ldt_ebew-peinh = 1.
            ldf_price = ldt_ebew-stprs.
          ELSE.
            ldf_price = ldt_ebew-stprs / ldt_ebew-peinh.
          ENDIF.
        ELSE.
          ldf_vprsv = 'V'.
          ldf_menge = ldt_ebew-lbkum.
          ldf_dmbtr = ldt_ebew-salk3.
          IF ldt_ebew-peinh = 0 OR ldt_ebew-peinh = 1.
            IF ldt_ebew-lbkum = 0.
              ldf_price = ldt_ebew-verpr.
            ELSE.
              ldf_price = ldt_ebew-salk3 / ldt_ebew-lbkum.
            ENDIF.
          ELSE.
            IF ldt_ebew-lbkum = 0.
              ldf_price = ldt_ebew-verpr / ldt_ebew-peinh.
            ELSE.
              ldf_price = ldt_ebew-salk3 / ldt_ebew-lbkum / ldt_ebew-peinh.
            ENDIF.
          ENDIF.
        ENDIF.
      ELSE.
        ldf_vprsv = ''.
        ldf_price = 0.
      ENDIF.
    ENDAT.
**   按照库存地点权限进行过滤
*    READ TABLE gdt_t001l WITH KEY werks = ldt_mska-werks
*                                  lgort = ldt_mska-lgort BINARY SEARCH.
*    IF sy-subrc <> 0.
*      CONTINUE.
*    ENDIF.

*   整理常规数据
    CLEAR gds_alv.
    gds_alv-matnr  = ldt_mska2-matnr.
    gds_alv-maktx  = ldt_mska2-maktx.
    gds_alv-werks  = ldt_mska2-werks.
    gds_alv-name1  = ldt_mska2-name1.
    gds_alv-lgort  = ldt_mska2-lgort.
    gds_alv-lgobe  = ldt_mska2-lgobe.
    gds_alv-ztype  = '销售订单库存'.
    gds_alv-vbeln  = ldt_mska2-vbeln.
    gds_alv-posnr  = ldt_mska2-posnr.
    gds_alv-meins  = ldt_mska2-meins.

    SELECT SINGLE bstkd FROM vbkd
      INTO gds_alv-bstkd
      WHERE vbeln = gds_alv-vbeln
        AND posnr = ''.

    CALL FUNCTION 'ZTOOL_GET_MSEHL'
      EXPORTING
        meins = gds_alv-meins
      IMPORTING
        msehl = gds_alv-msehl.
    READ TABLE gdt_t001 WITH KEY bwkey = gds_alv-werks BINARY SEARCH.
    IF sy-subrc = 0.
      gds_alv-waers = gdt_t001-waers.
    ENDIF.
    gds_alv-price  = ldf_price.
    gds_alv-menge  = ldt_mska2-kalab + ldt_mska2-kains + ldt_mska2-kaspe.
    gds_alv-dmbtr  = gds_alv-menge * ldf_price.
    ldf_dmbtr = ldf_dmbtr - gds_alv-dmbtr.
    ldf_menge = ldf_menge - gds_alv-menge.
    APPEND gds_alv TO ldt_alv.
    AT END OF posnr.
      IF ldf_vprsv = 'V'.
        IF ldf_menge = 0 AND ldf_dmbtr <> 0.
*         存在尾差的情况下,调整尾差
          DESCRIBE TABLE ldt_alv LINES ldf_count.
          READ TABLE ldt_alv INTO gds_alv INDEX ldf_count.
          gds_alv-dmbtr = gds_alv-dmbtr + ldf_dmbtr.
          MODIFY ldt_alv FROM gds_alv INDEX ldf_count.
        ENDIF.
      ENDIF.
    ENDAT.
  ENDLOOP.
* 去掉库存为零的项目
  DELETE ldt_alv WHERE menge = 0.
  IF so_lgort[] IS NOT INITIAL.
    DELETE ldt_alv WHERE lgort NOT IN so_lgort.
  ENDIF.
* 按照库存地点权限进行过滤
  IF gdt_t001l[] IS NOT INITIAL.
    LOOP AT ldt_alv INTO gds_alv.
      ldf_index = sy-tabix. "added by yangk 20150831  原因:ldf_index参数未指定,导致数据有问题,权限小的用户会down
      READ TABLE gdt_t001l WITH KEY werks = gds_alv-werks
                                    lgort = gds_alv-lgort BINARY SEARCH.
      IF sy-subrc <> 0.
        gds_alv-menge = 0.
        MODIFY ldt_alv FROM gds_alv INDEX ldf_index TRANSPORTING menge.
      ENDIF.
      CLEAR ldf_index.
    ENDLOOP.
  ENDIF.
  DELETE ldt_alv WHERE menge = 0.

  CLEAR:   ldt_mska, ldt_mska2, ldt_ebew.
  REFRESH: ldt_mska, ldt_mska2, ldt_ebew.

* 获取库龄
* 期初库龄
  SELECT *
    INTO TABLE ldt_zmseg
*    FROM zmm_mseg "add by lumingdao 20160108
    FROM zmm_mseg_new "add by lumingdao 20160108
     FOR ALL ENTRIES IN ldt_alv
   WHERE matnr = ldt_alv-matnr
     AND werks = ldt_alv-werks
     AND lgort = ldt_alv-lgort
     AND ( vbeln <> '' AND vbeln <> '0000000000' )
     AND budat <= gdc_idate.
  SORT ldt_zmseg BY matnr werks lgort vbeln posnr budat DESCENDING.
* 对2013-12-31的库存数量
* 按照入库的日期,进行逐一匹配比对... 2013-12-31是期初导入,特殊逻辑处理
  SELECT mkpf~mblnr
         mkpf~mjahr
         mkpf~budat
         mseg~zeile
         mseg~matnr
         mseg~werks
         mseg~lgort
         mseg~shkzg
         mseg~kdauf
         mseg~kdpos
         mseg~menge
         mseg~meins
         mseg~mat_kdauf
         mseg~mat_kdpos
    INTO TABLE ldt_msegi
    FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                             AND mkpf~mjahr = mseg~mjahr
     FOR ALL ENTRIES IN ldt_alv
   WHERE mseg~matnr = ldt_alv-matnr
     AND mseg~werks = ldt_alv-werks
     AND mseg~lgort = ldt_alv-lgort
     AND mseg~bwart <> '321'
     AND mseg~bwart <> '322'
     AND mseg~sobkz = 'E'
     AND ( ( mseg~kdauf = ldt_alv-vbeln
       AND mseg~kdpos = ldt_alv-posnr )
       OR ( mseg~mat_kdauf = ldt_alv-vbeln
       AND mseg~mat_kdpos = ldt_alv-posnr ) )
     AND  mkpf~budat = gdc_idate.
  SORT ldt_msegi BY matnr werks lgort.
  LOOP AT ldt_msegi.
    CLEAR ldt_mseg.
    ldt_mseg-matnr = ldt_msegi-matnr.
    ldt_mseg-werks = ldt_msegi-werks.
    ldt_mseg-lgort = ldt_msegi-lgort.
    ldt_mseg-mat_kdauf = ldt_msegi-mat_kdauf.
    ldt_mseg-mat_kdpos = ldt_msegi-mat_kdpos.
    ldt_mseg-kdauf = ldt_msegi-kdauf.
    ldt_mseg-kdpos = ldt_msegi-kdpos.
    IF ldt_msegi-shkzg = 'S'.
      ldt_mseg-menge = ldt_msegi-menge.
    ELSE.
      ldt_mseg-menge = 0 - ldt_msegi-menge.
    ENDIF.
    ldt_mseg-meins = ldt_msegi-meins.
    ldt_mseg-budat = gdc_idate.
    COLLECT ldt_mseg.
  ENDLOOP.
* 按照入库的日期,进行逐一匹配比对...
  SELECT mkpf~mblnr
         mkpf~mjahr
         mkpf~budat
         mseg~zeile
         mseg~matnr
         mseg~werks
         mseg~lgort
         mseg~shkzg
         mseg~kdauf
         mseg~kdpos
         mseg~menge
         mseg~meins
         mseg~mat_kdauf
         mseg~mat_kdpos
    APPENDING TABLE ldt_mseg
    FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                             AND mkpf~mjahr = mseg~mjahr
     FOR ALL ENTRIES IN ldt_alv
   WHERE mseg~matnr = ldt_alv-matnr
     AND mseg~werks = ldt_alv-werks
     AND mseg~lgort = ldt_alv-lgort
     AND mseg~bwart <> '321'
     AND mseg~bwart <> '322'
     AND mseg~sobkz = 'E'
     AND ( ( mseg~kdauf = ldt_alv-vbeln
       AND mseg~kdpos = ldt_alv-posnr )
       OR ( mseg~mat_kdauf = ldt_alv-vbeln
       AND mseg~mat_kdpos = ldt_alv-posnr ) )
     AND mseg~shkzg = 'S'
     AND mkpf~budat <> gdc_idate .
  IF p_r2 = 'X'.
    DELETE ldt_mseg WHERE budat > gdf_budat.
  ENDIF.
* 获取所有的冲销凭证 - 2013-12-31是期初导入,特殊逻辑处理,冲销从2014年开始判断
  IF p_r2 = 'X'.
    SELECT mseg~mblnr
           mseg~mjahr
           mseg~zeile
           mseg~sjahr " 物料凭证年度
           mseg~smbln " 物料凭证编号
           mseg~smblp " 物料凭证中的项目
      INTO TABLE ldt_mbst
      FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                               AND mkpf~mjahr = mseg~mjahr
     WHERE mseg~smbln <> ''
       AND mseg~mjahr >= '2014'
       AND mseg~bwart <> '321'
       AND mseg~bwart <> '322'
       AND mkpf~budat <= gdf_budat.
  ELSE.
    SELECT mblnr
           mjahr
           zeile
           sjahr " 物料凭证年度
           smbln " 物料凭证编号
           smblp " 物料凭证中的项目
      INTO TABLE ldt_mbst
      FROM mseg
     WHERE smbln <> ''
       AND mjahr >= '2014'
       AND mseg~bwart <> '321'
       AND mseg~bwart <> '322'.
  ENDIF.
  SORT ldt_mbst BY sjahr smbln smblp.
* 将冲销凭证剔出 - 冲销的情况总是比较少的,所以优先处理
  SORT ldt_mseg BY mjahr mblnr zeile.
  LOOP AT ldt_mbst.
    READ TABLE ldt_mseg WITH KEY mjahr = ldt_mbst-sjahr
                                 mblnr = ldt_mbst-smbln
                                 zeile = ldt_mbst-smblp BINARY SEARCH.
    IF sy-subrc = 0.
*     删除 被冲销凭证
      DELETE ldt_mseg INDEX sy-tabix.
*     删除 冲销凭证
      DELETE ldt_mseg WHERE mjahr = ldt_mbst-mjahr
                        AND mblnr = ldt_mbst-mblnr
                        AND zeile = ldt_mbst-zeile.
    ENDIF.
  ENDLOOP.
* 处理库存
  SORT ldt_mseg BY matnr werks lgort kdauf kdpos budat DESCENDING.
  LOOP AT ldt_mseg.
    CLEAR ldt_mseg2.
    ldt_mseg2-matnr = ldt_mseg-matnr.
    ldt_mseg2-werks = ldt_mseg-werks.
    ldt_mseg2-lgort = ldt_mseg-lgort.
    "修改 20150112  hou
    IF  ldt_mseg2-werks <> '8130'.
      IF ldt_mseg-kdauf IS INITIAL.
        ldt_mseg2-kdauf = ldt_mseg-mat_kdauf.
        ldt_mseg2-kdpos = ldt_mseg-mat_kdpos.
      ELSE.
        ldt_mseg2-kdauf = ldt_mseg-kdauf.
        ldt_mseg2-kdpos = ldt_mseg-kdpos.
      ENDIF.
    ELSE.
      IF ldt_mseg-mat_kdauf IS  NOT INITIAL.
        ldt_mseg2-kdauf = ldt_mseg-mat_kdauf.
        ldt_mseg2-kdpos = ldt_mseg-mat_kdpos.
      ELSE.
        ldt_mseg2-kdauf = ldt_mseg-kdauf.
        ldt_mseg2-kdpos = ldt_mseg-kdpos.
      ENDIF.
    ENDIF.
*   物料凭证中menge数量单位就是物料数据中的基本单位,所以不用做单位换算逻辑
*    ldt_mseg2-meins = ldt_mseg-meins.
    IF ldt_mseg-budat = gdc_idate. " 期初数据处理
      ldf_meng1 = ldt_mseg-menge.
      LOOP AT ldt_zmseg WHERE matnr = ldt_mseg-matnr
                          AND werks = ldt_mseg-werks
                          AND lgort = ldt_mseg-lgort
                          AND vbeln = ldt_mseg2-kdauf
                          AND posnr = ldt_mseg2-kdpos
                          AND menge > 0.
        ldf_index = sy-tabix.
        ldf_days = gdf_datum - ldt_zmseg-budat.
        IF ldt_zmseg-menge >= ldf_meng1.
          ldf_meng2 = ldf_meng1.
        ELSE.
          ldf_meng2 = ldt_zmseg-menge.
        ENDIF.
*        IF ldf_days <= 30.
*          ldt_mseg2-meng1 = ldf_meng2.
*        ELSEIF ldf_days <= 90.
*          ldt_mseg2-meng2 = ldf_meng2.
*        ELSEIF ldf_days <= 180.
*          ldt_mseg2-meng3 = ldf_meng2.
**        ELSEIF ldf_days <= 270. "20160615 add
**          ldt_mseg2-meng10 = ldf_meng2.
*        ELSEIF ldf_days <= 365.
*          ldt_mseg2-meng4 = ldf_meng2.
*        ELSEIF ldf_days <= 730.
*          ldt_mseg2-meng5 = ldf_meng2.
*        ELSEIF ldf_days <= 1095. " 三年内
*          ldt_mseg2-meng6 = ldf_meng2.
*        ELSEIF ldf_days <= 1460. " 四年内
*          ldt_mseg2-meng7 = ldf_meng2.
*        ELSEIF ldf_days <= 1825. " 五年内
*          ldt_mseg2-meng8 = ldf_meng2.
*        ELSE.
*          ldt_mseg2-meng9 = ldf_meng2.
*        ENDIF.
***************************20160616 change****************************
        IF ldf_days <= d1.
          ldt_mseg2-meng1 = ldf_meng2.
        ELSEIF ldf_days <= d2.
          ldt_mseg2-meng2 = ldf_meng2.
        ELSEIF ldf_days <= d3.
          ldt_mseg2-meng3 = ldf_meng2.
        ELSEIF ldf_days <= d4.
          ldt_mseg2-meng4 = ldf_meng2.
        ELSEIF ldf_days <= d5.
          ldt_mseg2-meng5 = ldf_meng2.
        ELSEIF ldf_days <= d6. " 三年内
          ldt_mseg2-meng6 = ldf_meng2.
        ELSEIF ldf_days <= d7. " 四年内
          ldt_mseg2-meng7 = ldf_meng2.
        ELSEIF ldf_days <= d8. " 五年内
          ldt_mseg2-meng8 = ldf_meng2.
        ELSE.
          ldt_mseg2-meng9 = ldf_meng2.
        ENDIF.
**********************************************************************
        COLLECT ldt_mseg2.
        CLEAR: ldt_mseg2-meng1, ldt_mseg2-meng2, ldt_mseg2-meng3, ldt_mseg2-meng4, ldt_mseg2-meng5,
               ldt_mseg2-meng6, ldt_mseg2-meng7, ldt_mseg2-meng8, ldt_mseg2-meng9.
        ldt_zmseg-menge = ldt_zmseg-menge - ldf_meng2.
        MODIFY ldt_zmseg INDEX ldf_index.
        ldf_meng1 = ldf_meng1 - ldf_meng2.
        IF ldf_meng1 <= 0.
          EXIT.
        ENDIF.
      ENDLOOP.
      IF ldf_meng1 > 0..
        ldf_days = gdf_datum - ldt_mseg-budat.
*        IF ldf_days <= 30.
*          ldt_mseg2-meng1 = ldf_meng1.
*        ELSEIF ldf_days <= 90.
*          ldt_mseg2-meng2 = ldf_meng1.
*        ELSEIF ldf_days <= 180.
*          ldt_mseg2-meng3 = ldf_meng1.
**        ELSEIF ldf_days <= 270. "20160615 add
**          ldt_mseg2-meng10 = ldf_meng1.
*        ELSEIF ldf_days <= 365.
*          ldt_mseg2-meng4 = ldf_meng1.
*        ELSEIF ldf_days <= 730.
*          ldt_mseg2-meng5 = ldf_meng1.
*        ELSEIF ldf_days <= 1095. " 三年内
*          ldt_mseg2-meng6 = ldf_meng1.
*        ELSEIF ldf_days <= 1460. " 四年内
*          ldt_mseg2-meng7 = ldf_meng1.
*        ELSEIF ldf_days <= 1825. " 五年内
*          ldt_mseg2-meng8 = ldf_meng1.
*        ELSE.
*          ldt_mseg2-meng9 = ldf_meng1.
*        ENDIF.
*************************20160616 change******************************
        IF ldf_days <= d1.
          ldt_mseg2-meng1 = ldf_meng1.
        ELSEIF ldf_days <= d2.
          ldt_mseg2-meng2 = ldf_meng1.
        ELSEIF ldf_days <= d3.
          ldt_mseg2-meng3 = ldf_meng1.
        ELSEIF ldf_days <= d4.
          ldt_mseg2-meng4 = ldf_meng1.
        ELSEIF ldf_days <= d5.
          ldt_mseg2-meng5 = ldf_meng1.
        ELSEIF ldf_days <= d6. " 三年内
          ldt_mseg2-meng6 = ldf_meng1.
        ELSEIF ldf_days <= d7. " 四年内
          ldt_mseg2-meng7 = ldf_meng1.
        ELSEIF ldf_days <= d8. " 五年内
          ldt_mseg2-meng8 = ldf_meng1.
        ELSE.
          ldt_mseg2-meng9 = ldf_meng1.
        ENDIF.
**********************************************************************
        COLLECT ldt_mseg2.
        CLEAR: ldt_mseg2-meng1, ldt_mseg2-meng2, ldt_mseg2-meng3, ldt_mseg2-meng4, ldt_mseg2-meng5,
               ldt_mseg2-meng6, ldt_mseg2-meng7, ldt_mseg2-meng8, ldt_mseg2-meng9.
      ENDIF.
    ELSE.
      ldf_days = gdf_datum - ldt_mseg-budat.
*      IF ldf_days <= 30.
*        ldt_mseg2-meng1 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 90.
*        ldt_mseg2-meng2 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 180.
*        ldt_mseg2-meng3 = ldt_mseg-menge.
**      ELSEIF ldf_days <= 270. "20160615 add
**        ldt_mseg2-meng10 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 365.
*        ldt_mseg2-meng4 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 730.
*        ldt_mseg2-meng5 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 1095. " 三年内
*        ldt_mseg2-meng6 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 1460. " 四年内
*        ldt_mseg2-meng7 = ldt_mseg-menge.
*      ELSEIF ldf_days <= 1825. " 五年内
*        ldt_mseg2-meng8 = ldt_mseg-menge.
*      ELSE.
*        ldt_mseg2-meng9 = ldt_mseg-menge.
*      ENDIF.
*************************20160616 change******************************
      IF ldf_days <= d1.
        ldt_mseg2-meng1 = ldt_mseg-menge.
      ELSEIF ldf_days <= d2.
        ldt_mseg2-meng2 = ldt_mseg-menge.
      ELSEIF ldf_days <= d3.
        ldt_mseg2-meng3 = ldt_mseg-menge.
      ELSEIF ldf_days <= d4.
        ldt_mseg2-meng4 = ldt_mseg-menge.
      ELSEIF ldf_days <= d5.
        ldt_mseg2-meng5 = ldt_mseg-menge.
      ELSEIF ldf_days <= d6. " 三年内
        ldt_mseg2-meng6 = ldt_mseg-menge.
      ELSEIF ldf_days <= d7. " 四年内
        ldt_mseg2-meng7 = ldt_mseg-menge.
      ELSEIF ldf_days <= d8. " 五年内
        ldt_mseg2-meng8 = ldt_mseg-menge.
      ELSE.
        ldt_mseg2-meng9 = ldt_mseg-menge.
      ENDIF.
**********************************************************************
      COLLECT ldt_mseg2.
      CLEAR: ldt_mseg2-meng1, ldt_mseg2-meng2, ldt_mseg2-meng3, ldt_mseg2-meng4, ldt_mseg2-meng5,
             ldt_mseg2-meng6, ldt_mseg2-meng7, ldt_mseg2-meng8, ldt_mseg2-meng9.
    ENDIF.
*    ldf_days = gdf_datum - ldt_mseg-budat.
*    IF ldf_days <= 30.
*      ldt_mseg2-meng1 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 90.
*      ldt_mseg2-meng2 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 180.
*      ldt_mseg2-meng3 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 365.
*      ldt_mseg2-meng4 = ldt_mseg-menge.
*    ELSEIF ldf_days <= 730.
*      ldt_mseg2-meng5 = ldt_mseg-menge.
*    ELSE.
*      ldt_mseg2-meng6 = ldt_mseg-menge.
*    ENDIF.
*    COLLECT ldt_mseg2.
  ENDLOOP.
  SORT ldt_mseg2 BY matnr werks lgort kdauf kdpos.

* 销售订单
  IF ldt_alv[] IS NOT INITIAL.
    SELECT vbeln kunnr
      INTO TABLE ldt_vbak
      FROM vbak
       FOR ALL ENTRIES IN ldt_alv
     WHERE vbeln = ldt_alv-vbeln.
    SORT ldt_vbak BY vbeln.
    SELECT vbeln posnr aufnr
      INTO TABLE ldt_vbap
      FROM vbap
       FOR ALL ENTRIES IN ldt_alv
     WHERE vbeln = ldt_alv-vbeln
       AND posnr = ldt_alv-posnr.
    SORT ldt_vbap BY vbeln posnr.
    IF ldt_vbap[] IS NOT INITIAL.
      SELECT aufnr ktext
        INTO TABLE ldt_aufk
        FROM aufk
         FOR ALL ENTRIES IN ldt_vbap
       WHERE aufnr = ldt_vbap-aufnr
         AND autyp = '01'.
      SORT ldt_aufk BY aufnr.
    ENDIF.
  ENDIF.

* 计算库龄
  SORT ldt_alv BY matnr werks lgort vbeln posnr.
  LOOP AT ldt_alv INTO gds_alv.
    ldf_index = sy-tabix.
    READ TABLE ldt_vbak WITH KEY vbeln = gds_alv-vbeln BINARY SEARCH.
    IF sy-subrc = 0.
      gds_alv-kunnr = ldt_vbak-kunnr.
      CALL FUNCTION 'ZTOOL_GET_KNAME'
        EXPORTING
          kunnr = gds_alv-kunnr
        IMPORTING
          name1 = gds_alv-kunnrt.
    ENDIF.
    READ TABLE ldt_vbap WITH KEY vbeln = gds_alv-vbeln
                                 posnr = gds_alv-posnr BINARY SEARCH.
    IF sy-subrc = 0.
      gds_alv-aufnr = ldt_vbap-aufnr.
      READ TABLE ldt_aufk WITH KEY aufnr = gds_alv-aufnr BINARY SEARCH.
      IF sy-subrc = 0.
        gds_alv-aufnrt = ldt_aufk-ktext.
      ENDIF.
    ENDIF.
    ldf_menge = gds_alv-menge.
    ldf_dmbtr = gds_alv-dmbtr.
    READ TABLE ldt_mseg2 WITH KEY matnr = gds_alv-matnr
                                  werks = gds_alv-werks
                                  lgort = gds_alv-lgort
                                  kdauf = gds_alv-vbeln
                                  kdpos = gds_alv-posnr BINARY SEARCH.
    IF sy-subrc = 0.
      DO 1 TIMES.
        IF ldf_menge < ldt_mseg2-meng1.
          gds_alv-meng1 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng1 = ldt_mseg2-meng1.
        ldf_menge = ldf_menge - ldt_mseg2-meng1.

        IF ldf_menge < ldt_mseg2-meng2.
          gds_alv-meng2 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng2 = ldt_mseg2-meng2.
        ldf_menge = ldf_menge - ldt_mseg2-meng2.

        IF ldf_menge < ldt_mseg2-meng3.
          gds_alv-meng3 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng3 = ldt_mseg2-meng3.
        ldf_menge = ldf_menge - ldt_mseg2-meng3.

****************************20160615 add******************************
*        IF ldf_menge < ldt_mseg2-meng10.
*          gds_alv-meng10 = ldf_menge.
*          ldf_menge = 0.
*          EXIT.
*        ENDIF.
*        gds_alv-meng10 = ldt_mseg2-meng10.
*        ldf_menge = ldf_menge - ldt_mseg2-meng10.
**********************************************************************

        IF ldf_menge < ldt_mseg2-meng4.
          gds_alv-meng4 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng4 = ldt_mseg2-meng4.
        ldf_menge = ldf_menge - ldt_mseg2-meng4.

        IF ldf_menge < ldt_mseg2-meng5.
          gds_alv-meng5 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng5 = ldt_mseg2-meng5.
        ldf_menge = ldf_menge - ldt_mseg2-meng5.

        IF ldf_menge < ldt_mseg2-meng6.
          gds_alv-meng6 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng6 = ldt_mseg2-meng6.
        ldf_menge = ldf_menge - ldt_mseg2-meng6.

        IF ldf_menge < ldt_mseg2-meng7.
          gds_alv-meng7 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng7 = ldt_mseg2-meng7.
        ldf_menge = ldf_menge - ldt_mseg2-meng7.

        IF ldf_menge < ldt_mseg2-meng8.
          gds_alv-meng8 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng8 = ldt_mseg2-meng8.
        ldf_menge = ldf_menge - ldt_mseg2-meng8.

        IF ldf_menge < ldt_mseg2-meng9.
          gds_alv-meng9 = ldf_menge.
          ldf_menge = 0.
          EXIT.
        ENDIF.
        gds_alv-meng9 = ldt_mseg2-meng9.
        ldf_menge = ldf_menge - ldt_mseg2-meng9.
      ENDDO.
    ENDIF.
*   初始库存导入
    IF ldf_menge > 0.
      gds_alv-meng99 = ldf_menge.
      ldf_days = gdf_datum - gdc_idate.
*      IF ldf_days <= 30.
*        ADD ldf_menge TO gds_alv-meng1.
*      ELSEIF ldf_days <= 90.
*        ADD ldf_menge TO gds_alv-meng2.
*      ELSEIF ldf_days <= 180.
*        ADD ldf_menge TO gds_alv-meng3.
**      ELSEIF ldf_days <= 270. "20160615 add
**        ADD ldf_menge TO gds_alv-meng10.
*      ELSEIF ldf_days <= 365.
*        ADD ldf_menge TO gds_alv-meng4.
*      ELSEIF ldf_days <= 730.
*        ADD ldf_menge TO gds_alv-meng5.
*      ELSEIF ldf_days <= 1095. " 三年内
*        ADD ldf_menge TO gds_alv-meng6.
*      ELSEIF ldf_days <= 1460. " 四年内
*        ADD ldf_menge TO gds_alv-meng7.
*      ELSEIF ldf_days <= 1825. " 五年内
*        ADD ldf_menge TO gds_alv-meng8.
*      ELSE.
*        ADD ldf_menge TO gds_alv-meng9.
*      ENDIF.
************************20160616 change*******************************
      IF ldf_days <= d1.
        ADD ldf_menge TO gds_alv-meng1.
      ELSEIF ldf_days <= d2.
        ADD ldf_menge TO gds_alv-meng2.
      ELSEIF ldf_days <= d3.
        ADD ldf_menge TO gds_alv-meng3.
      ELSEIF ldf_days <= d4.
        ADD ldf_menge TO gds_alv-meng4.
      ELSEIF ldf_days <= d5.
        ADD ldf_menge TO gds_alv-meng5.
      ELSEIF ldf_days <= d6. " 三年内
        ADD ldf_menge TO gds_alv-meng6.
      ELSEIF ldf_days <= d7. " 四年内
        ADD ldf_menge TO gds_alv-meng7.
      ELSEIF ldf_days <= d8. " 五年内
        ADD ldf_menge TO gds_alv-meng8.
      ELSE.
        ADD ldf_menge TO gds_alv-meng9.
      ENDIF.
**********************************************************************
    ENDIF.
*   计算金额
    gds_alv-dmbt1 = gds_alv-meng1 * gds_alv-price.
    gds_alv-dmbt2 = gds_alv-meng2 * gds_alv-price.
    gds_alv-dmbt3 = gds_alv-meng3 * gds_alv-price.
*    gds_alv-dmbt10 = gds_alv-meng10 * gds_alv-price. "20160615 add
    gds_alv-dmbt4 = gds_alv-meng4 * gds_alv-price.
    gds_alv-dmbt5 = gds_alv-meng5 * gds_alv-price.
    gds_alv-dmbt6 = gds_alv-meng6 * gds_alv-price.
    gds_alv-dmbt7 = gds_alv-meng7 * gds_alv-price.
    gds_alv-dmbt8 = gds_alv-meng8 * gds_alv-price.
    gds_alv-dmbt9 = gds_alv-meng9 * gds_alv-price.
*   处理尾差
    ldf_dmbtr = ldf_dmbtr
              - gds_alv-dmbt1
              - gds_alv-dmbt2
              - gds_alv-dmbt3
*              - gds_alv-dmbt10 "20160615 add
              - gds_alv-dmbt4
              - gds_alv-dmbt5
              - gds_alv-dmbt6
              - gds_alv-dmbt7
              - gds_alv-dmbt8
              - gds_alv-dmbt9.
    IF ldf_dmbtr <> 0.
*      gds_alv-dmbt9 = ldf_dmbtr.
      IF gds_alv-meng1 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt1.
      ELSEIF gds_alv-meng2 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt2.
      ELSEIF gds_alv-meng3 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt3.
*      ELSEIF gds_alv-meng10 <> 0. "20160615 add
*        ADD ldf_dmbtr TO gds_alv-dmbt10.
      ELSEIF gds_alv-meng4 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt4.
      ELSEIF gds_alv-meng5 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt5.
      ELSEIF gds_alv-meng6 <> 0.
        ADD ldf_dmbtr TO gds_alv-dmbt6.
*      ELSEIF ldf_days <= 1095. " 三年内
*        ADD ldf_dmbtr TO gds_alv-dmbt7.
*      ELSEIF ldf_days <= 1460. " 四年内
*        ADD ldf_dmbtr TO gds_alv-dmbt8.
*      ELSEIF ldf_days <= 1825. " 五年内
*        ADD ldf_dmbtr TO gds_alv-dmbt9.
***********************20160616 change********************************
      ELSEIF ldf_days <= d6. " 三年内
        ADD ldf_dmbtr TO gds_alv-dmbt7.
      ELSEIF ldf_days <= d7. " 四年内
        ADD ldf_dmbtr TO gds_alv-dmbt8.
      ELSEIF ldf_days <= d8. " 五年内
        ADD ldf_dmbtr TO gds_alv-dmbt9.
**********************************************************************
      ELSE.
        gds_alv-dmbtr = gds_alv-dmbtr - ldf_dmbtr.
      ENDIF.
    ENDIF.
    MODIFY ldt_alv FROM gds_alv INDEX ldf_index.
  ENDLOOP.

  APPEND LINES OF ldt_alv TO gdt_alv.

  CLEAR:   ldt_mseg, ldt_mseg2, ldt_zmseg, ldt_alv, ldt_msegi, ldt_mbst,
           ldt_vbak, ldt_vbap, ldt_aufk.
  REFRESH: ldt_mseg, ldt_mseg2, ldt_zmseg, ldt_alv, ldt_msegi, ldt_mbst,
           ldt_vbak, ldt_vbap, ldt_aufk.

ENDFORM.                    " FRM_GET_DATA2

*&---------------------------------------------------------------------*
*&      Form  FRM_DISPLAY_ALV
*&---------------------------------------------------------------------*
*       显示alv界面
*----------------------------------------------------------------------*
FORM frm_display_lvc.

* 设定报表输出样式。
  PERFORM set_layout_lvc.
* 设定报表列标题格式
  PERFORM set_fieldcat_lvc.
* 输出ALV报表
  PERFORM alv_grid_display_lvc.

ENDFORM.                    " FRM_DISPLAY_ALV

*&---------------------------------------------------------------------*
*&      Form  SET_LAYOUT_LVC
*&---------------------------------------------------------------------*
*       设定报表输出样式。
*----------------------------------------------------------------------*
FORM set_layout_lvc.
  CLEAR: gds_alv_layout_lvc.
* 设置Grid的字段列宽度自动适应
  gds_alv_layout_lvc-cwidth_opt = 'X'.
* 设置Grid的行颜色变换显示
  gds_alv_layout_lvc-zebra  = 'X'.
* 置弹出窗口的标题栏
  gds_alv_layout_lvc-detailtitl = '详细内容'.
* 设置Grid的多行选择列,其中BOX必须为内表的一列,为一个字符长度
  gds_alv_layout_lvc-box_fname = 'SEL'.
** 行颜色字段设置
*  gds_alv_layout_lvc-info_fname = 'ROWCOLOR'.
* 信号灯设置
*  IF r3 = 'X'.
*    gds_alv_layout_lvc-excp_fname = 'LIGHT'.
**   gds_alv_layout_lvc-excp_led = 'X'.
*  ENDIF.
ENDFORM.                    " SET_LAYOUT_LVC

*&---------------------------------------------------------------------*
*&      Form  SET_FIELDCAT_LVC
*&---------------------------------------------------------------------*
*       设定报表列标题格式
*----------------------------------------------------------------------*
FORM set_fieldcat_lvc.
  DATA dat TYPE p.
  DATA text TYPE scrtext_l.

  DATA l_d1(4) TYPE c.
  DATA l_d2(4) TYPE c.
  DATA l_d3(4) TYPE c.
  DATA l_d4(4) TYPE c.
  DATA l_d5(4) TYPE c.
  DATA l_d6(4) TYPE c.
  DATA l_d7(4) TYPE c.
  DATA l_d8(4) TYPE c.
  DATA l_dat(4) TYPE c.

* ------ initial valuation
  CLEAR   gdt_alv_fieldcat_lvc.
  REFRESH gdt_alv_fieldcat_lvc.

  gdf_alv_col_pos = 0.
  DEFINE fieldcat_macro.
    gdf_alv_col_pos = gdf_alv_col_pos + 1.
    gds_alv_fieldcat_lvc-tabname   = 'GDT_ALV'.
    gds_alv_fieldcat_lvc-fieldname = '&1'.
    gds_alv_fieldcat_lvc-scrtext_l = &2.
    gds_alv_fieldcat_lvc-key       = &3.
    gds_alv_fieldcat_lvc-emphasize = &4.
    gds_alv_fieldcat_lvc-no_out    = &5.
    gds_alv_fieldcat_lvc-convexit  = &6.
*   gds_alv_fieldcat_lvc-edit      = &6.
*   gds_alv_fieldcat_lvc-hotspot   = &6.
*   GdS_ALV_FIELDCAT_LVC-DECIMALS  = &6.
*   gds_alv_fieldcat_lvc-checkbox  = &6.
    gds_alv_fieldcat_lvc-outputlen = &7.
    gds_alv_fieldcat_lvc-no_zero   = &8.
    gds_alv_fieldcat_lvc-just      = &9.
    gds_alv_fieldcat_lvc-col_pos   = gdf_alv_col_pos.
    append gds_alv_fieldcat_lvc to gdt_alv_fieldcat_lvc.
    clear gds_alv_fieldcat_lvc.
  END-OF-DEFINITION.

* 列标题设定
  fieldcat_macro werks '工厂' 'X' '' '' '' '' '' ''.
  fieldcat_macro name1 '工厂描述' '' '' '' '' '' '' ''.
  fieldcat_macro lgort '库存地点' 'X' '' '' '' '' '' ''.
  fieldcat_macro lgobe '库存地点描述' '' '' '' '' '' '' ''.
  fieldcat_macro matnr '物料号' 'X' '' '' 'MATN1' '' '' ''.
  fieldcat_macro maktx '物料描述' '' '' '' '' '' '' ''.
  fieldcat_macro ztype '库存类型' '' 'X' '' '' '' '' ''.
  IF p_c2 = 'X'. " 销售订单库存
    fieldcat_macro bstkd 'IMIS合同号' '' 'X' '' '' '' '' ''.
    fieldcat_macro vbeln '销售订单号' 'X' '' '' 'ALPHA' '' '' ''.
    fieldcat_macro posnr '销售订单行项目' 'X' '' '' '' '' 'X' ''.
    fieldcat_macro kunnr '客户编码' '' '' '' 'ALPHA' '' '' ''.
    fieldcat_macro kunnrt '客户描述' '' '' '' '' '' '' ''.
    fieldcat_macro aufnr '内部订单' '' '' '' 'ALPHA' '' '' ''.
    fieldcat_macro aufnrt '项目描述' '' '' '' '' '' '' ''.
  ENDIF.
  fieldcat_macro menge '当前库存数量' '' 'C700' '' '' '' 'X' ''.
  fieldcat_macro meins '单位' '' '' 'X' 'CUNIT' '' '' ''.
  fieldcat_macro msehl '单位描述' '' '' '' '' '' '' ''.
  fieldcat_macro dmbtr '当前库存金额' '' 'C300' '' '' '' 'X' ''.
  fieldcat_macro waers '币种' '' '' '' '' '' '' ''.
*  fieldcat_macro meng99 '期初库存' '' 'C500' '' '' '' 'X' ''.
*  fieldcat_macro dmbt99 '尾差金额' '' 'C500' '' '' '' 'X' ''.
*  fieldcat_macro meng1 '库存1-30天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt1 '库存1-30天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng2 '库存31-90天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt2 '库存31-90天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng3 '库存91-180天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt3 '库存91-180天金额' '' 'C300' '' '' '' 'X' ''.
**************************20160615 add*********************************
**  fieldcat_macro meng10 '库存181-270天数量' '' 'C700' '' '' '' 'X' ''.
**  fieldcat_macro dmbt10 '库存181-270天金额' '' 'C300' '' '' '' 'X' ''.
**  fieldcat_macro meng4 '库存271-365天数量' '' 'C700' '' '' '' 'X' ''.
**  fieldcat_macro dmbt4 '库存271-365天金额' '' 'C300' '' '' '' 'X' ''.
***********************************************************************
*  fieldcat_macro meng4 '库存181-365天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt4 '库存181-365天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng5 '库存366-730天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt5 '库存366-730天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng6 '库存731-1095天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt6 '库存731-1095天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng7 '库存1095-1460天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt7 '库存1095-1460天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng8 '库存1460-1825天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt8 '库存1460-1825天金额' '' 'C300' '' '' '' 'X' ''.
*  fieldcat_macro meng9 '库存大于1825天数量' '' 'C700' '' '' '' 'X' ''.
*  fieldcat_macro dmbt9 '库存大于1825天金额' '' 'C300' '' '' '' 'X' ''.
******************************20160616 change*************************

*  PERFORM form_change CHANGING d1.
  l_d1 = d1.
  CONCATENATE '库存1-' l_d1 '天数量' INTO text.
  fieldcat_macro meng1 text '' 'C700' '' '' '' 'X' ''.
  CONCATENATE '库存1-' l_d1 '天金额' INTO text.
  fieldcat_macro dmbt1 text '' 'C300' '' '' '' 'X' ''.
  PERFORM dat_change USING d1 CHANGING dat.

*  PERFORM form_change CHANGING d2.
  IF dat LT d2.
    l_d2 = d2.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d2 '天数量' INTO text.
    fieldcat_macro meng2 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d2 '天金额' INTO text.
    fieldcat_macro dmbt2 text '' 'C300' '' '' '' 'X' ''.
    PERFORM dat_change USING d2 CHANGING dat.
  ENDIF.

*  PERFORM form_change CHANGING d3.
  IF dat LT d3.
    l_d3 = d3.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d3 '天数量' INTO text.
    fieldcat_macro meng3 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d3 '天金额' INTO text.
    fieldcat_macro dmbt3 text '' 'C300' '' '' '' 'X' ''.
    PERFORM dat_change USING d3 CHANGING dat.
  ENDIF.

*  PERFORM form_change CHANGING d4.
  IF dat LT d4.
    l_d4 = d4.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d4 '天数量' INTO text.
    fieldcat_macro meng4 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d4 '天金额' INTO text.
    fieldcat_macro dmbt4 text '' 'C300' '' '' '' 'X' ''.
    PERFORM dat_change USING d4 CHANGING dat.
  ENDIF.

*  PERFORM form_change CHANGING d5.
  IF dat LT d5.
    l_d5 = d5.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d5 '天数量' INTO text.
    fieldcat_macro meng5 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d5 '天金额' INTO text.
    fieldcat_macro dmbt5 text '' 'C300' '' '' '' 'X' ''.
    PERFORM dat_change USING d5 CHANGING dat.
  ENDIF.

*  PERFORM form_change CHANGING d6.
  IF dat LT d6.
    l_d6 = d6.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d6 '天数量' INTO text.
    fieldcat_macro meng6 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d6 '天金额' INTO text.
    fieldcat_macro dmbt6 text '' 'C300' '' '' '' 'X' ''.
    PERFORM dat_change USING d6 CHANGING dat.
  ENDIF.

*  PERFORM form_change CHANGING d7.
  IF dat LT d7.
    l_d7 = d7.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d7 '天数量' INTO text.
    fieldcat_macro meng7 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d7 '天金额' INTO text.
    fieldcat_macro dmbt7 text '' 'C300' '' '' '' 'X' ''.
    PERFORM dat_change USING d7 CHANGING dat.
  ENDIF.

*  PERFORM form_change CHANGING d8.
  IF dat LT d8.
    l_d8 = d8.
    l_dat = dat.
    CONCATENATE '库存' l_dat '-' l_d8 '天数量' INTO text.
    fieldcat_macro meng8 text '' 'C700' '' '' '' 'X' ''.
    CONCATENATE '库存' l_dat '-' l_d8 '天金额' INTO text.
    fieldcat_macro dmbt8 text '' 'C300' '' '' '' 'X' ''.
  ENDIF.

  IF l_d8 IS INITIAL.
    l_d8 = d8.
  ENDIF.
  CONCATENATE '库存大于' l_d8 '天数量' INTO text.
  fieldcat_macro meng9 text '' 'C700' '' '' '' 'X' ''.
  CONCATENATE '库存大于' l_d8 '天金额' INTO text.
  fieldcat_macro dmbt9 text '' 'C300' '' '' '' 'X' ''.
**********************************************************************

* 其他项目补充
  CALL FUNCTION 'ZTOOL_BUILD_FIELDCAT'
    EXPORTING
      im_fieldcat = gdt_alv_fieldcat_lvc
    IMPORTING
      fieldcat    = gdt_alv_fieldcat_lvc
    TABLES
      itab        = gdt_alv.

ENDFORM.                    " SET_FIELDCAT_LVC

*&---------------------------------------------------------------------*
*&      Form  ALV_GRID_DISPLAY_LVC
*&---------------------------------------------------------------------*
*       输出ALV报表
*----------------------------------------------------------------------*
FORM alv_grid_display_lvc.
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid
      i_callback_pf_status_set = 'SET_PF_STATUS_LVC'
      i_callback_user_command  = 'USER_COMMAND_LVC'
      is_layout_lvc            = gds_alv_layout_lvc  "设定报表输出样式。
      it_fieldcat_lvc          = gdt_alv_fieldcat_lvc[]
*     it_sort_lvc              = gdt_alv_sortinfo_lvc
      i_default                = 'X'
      i_save                   = 'A'  "设定是否可以保存报表布局
*     i_html_height_top        = 12
*     i_html_height_end        = 8
    TABLES
      t_outtab                 = gdt_alv[]
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

ENDFORM.                    " ALV_GRID_DISPLAY_LVC

*&---------------------------------------------------------------------*
*&      Form  PF_STATUS_SET_LVC
*&---------------------------------------------------------------------*
*       定义用户自定义的屏幕菜单。
*----------------------------------------------------------------------*
FORM set_pf_status_lvc USING im_extab TYPE slis_t_extab.
  DATA: l_count TYPE i.
  DATA: ldt_fcode TYPE TABLE OF sy-ucomm.

  CLEAR:   ldt_fcode.
  REFRESH: ldt_fcode.

  DESCRIBE TABLE gdt_alv[] LINES l_count.
  SET TITLEBAR  'TITLE' WITH l_count.

*  APPEND '&SUM' TO ldt_fcode.   " 小计
*  APPEND '&ABC' TO ldt_fcode.   " ABC分析
*  APPEND '&GRAPH' TO ldt_fcode. " 图形分析
  APPEND 'SAVE' TO ldt_fcode.   " 保存
  SET PF-STATUS 'STANDARD' EXCLUDING ldt_fcode.
ENDFORM.                    "SET_PF_STATUS_LVC


*&---------------------------------------------------------------------*
*&      Form  USER_COMMAND_LVC
*&---------------------------------------------------------------------*
*       响应菜单项及相应事件。
*----------------------------------------------------------------------*
FORM user_command_lvc USING im_ucomm   TYPE sy-ucomm
                            im_filecat TYPE slis_selfield.
  DATA: lv_tag  TYPE i.

  CASE im_ucomm .
*   返回/退出
    WHEN  'BACK' OR  'EXIT'.
      LEAVE TO SCREEN 0.
    WHEN 'CANCEL'.
      LEAVE PROGRAM.

*   刷新
    WHEN 'REFR'.
*     从数据表取数据并整理
      PERFORM get_data.
      IF gdt_alv[] IS INITIAL.
        MESSAGE i001.  " 没有找到相关的数据!
        LEAVE TO SCREEN 0.
      ELSE.
        im_filecat-refresh = 'X'.
      ENDIF.

*   双击
    WHEN '&IC1' .
      READ TABLE gdt_alv INTO gds_alv INDEX im_filecat-tabindex.
      IF sy-subrc = 0.
        PERFORM frm_alv_dbclick USING gds_alv im_filecat CHANGING lv_tag.
        IF lv_tag <> 0.
        ENDIF.
      ENDIF .

    WHEN OTHERS.
  ENDCASE.
ENDFORM.                    "user_command_lvc
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_INIT_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM frm_get_init_data  CHANGING c_date.

  DATA:lt_itab LIKE TABLE OF zmm_bukrs WITH HEADER LINE,
       BEGIN OF lt_bukrs OCCURS 0,
         werks TYPE lgort-werks,
       END OF lt_bukrs,
       BEGIN OF lt_lgort OCCURS 0,
         lgort TYPE mseg-lgort,
       END OF lt_lgort.

  IF sy-mandt EQ '810'.
    c_date = '20131231'.
  ELSEIF sy-mandt EQ '820' OR sy-mandt EQ '600' OR sy-mandt = '401'.
    IF p_bukrs EQ '8100'.
      c_date = '20140630'.
    ELSEIF p_bukrs EQ '8200'.
      c_date = '20151231'.
    ENDIF.
  ENDIF.

  IF so_werks[] IS INITIAL AND so_lgort[] IS INITIAL.
    "获取库龄报表:公司代码工厂库存地点
    SELECT *
           INTO CORRESPONDING FIELDS OF TABLE lt_itab
           FROM zmm_bukrs
           WHERE bukrs EQ p_bukrs
           .

    LOOP AT lt_itab.
      lt_bukrs-werks = lt_itab-werks.
      lt_lgort-lgort = lt_itab-lgort.
      APPEND: lt_bukrs,
              lt_lgort.
      CLEAR:lt_bukrs,
            lt_lgort.
    ENDLOOP.
    SORT lt_bukrs.
    SORT lt_lgort.

    DELETE ADJACENT DUPLICATES FROM lt_bukrs.
    DELETE ADJACENT DUPLICATES FROM lt_lgort.

    "将库龄报表:公司代码工厂库存地点 写入到选择屏幕中的变量中
    LOOP AT lt_bukrs.
      PERFORM frm_add_werks_data  USING so_werks[] lt_bukrs-werks  '' 'EQ'.
    ENDLOOP.

    LOOP AT lt_lgort.
      PERFORM frm_add_lgort_data  USING so_lgort[] lt_lgort-lgort  '' 'EQ'.
    ENDLOOP.


  ENDIF.

*  BREAK-POINT.

ENDFORM.                    " FRM_GET_INIT_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_ADD_WERKS_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM frm_add_werks_data  USING    r_range LIKE so_werks[]
                                  u_low
                                  u_high
                                  u_option
                                   .
  DATA: lw_range LIKE LINE OF so_werks.
  lw_range-sign   = 'I'."  I -> include  E -> exclude (包含、排除)
  lw_range-option = u_option." EQ, BT, NE,CP....
  lw_range-low    = u_low.
  lw_range-high   = u_high.
  APPEND lw_range TO r_range.

ENDFORM.                    " FRM_ADD_WERKS_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_ADD_LGORT_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM frm_add_lgort_data  USING   r_range LIKE so_lgort[]
                                  u_low
                                  u_high
                                  u_option
                                   .

  DATA: lw_range LIKE LINE OF so_lgort.
  lw_range-sign   = 'I'."  I -> include  E -> exclude (包含、排除)
  lw_range-option = u_option." EQ, BT, NE,CP....
  lw_range-low    = u_low.
  lw_range-high   = u_high.
  APPEND lw_range TO r_range.

ENDFORM.                    " FRM_ADD_LGORT_DATA
*&---------------------------------------------------------------------*
*&      Form  CHECK_DATE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM check_date .
  FIELD-SYMBOLS: <date1>,
                 <date2>.
  DATA name(4) TYPE c.
  DATA l_num TYPE n.

  DO 7 TIMES.
    l_num = l_num + 1.
    CONCATENATE 'P_D' l_num INTO name.
    ASSIGN (name) TO <date1>.
    l_num = l_num + 1.
    CONCATENATE 'P_D' l_num INTO name.
    ASSIGN (name) TO <date2>.
    IF <date2> IS INITIAL.
      <date2> = <date1>.
    ENDIF.
    IF <date2> LT <date1>.
      MESSAGE e000 WITH '请输入正确日期顺序'.
    ENDIF.
    l_num = l_num - 1.
  ENDDO.

  d1 = p_d1.
  d2 = p_d2.
  d3 = p_d3.
  d4 = p_d4.
  d5 = p_d5.
  d6 = p_d6.
  d7 = p_d7.
  d8 = p_d8.
ENDFORM.                    " CHECK_DATE
*&---------------------------------------------------------------------*
*&      Form  DAT_CHANGE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_D1  text
*      <--P_DAT  text
*----------------------------------------------------------------------*
FORM dat_change  USING    date
                 CHANGING dat.
  CLEAR dat.
  dat = date + 1.
*  CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
*    EXPORTING
*      input  = dat
*    IMPORTING
*      output = dat.
ENDFORM.                    " DAT_CHANGE
*&---------------------------------------------------------------------*
*&      Form  FORM_CHANGE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_D1  text
*----------------------------------------------------------------------*
FORM form_change  CHANGING date.

  CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
    EXPORTING
      input  = date
    IMPORTING
      output = date.
ENDFORM.                    " FORM_CHANGE

 

posted on 2021-02-20 09:34  tongxiaohu  阅读(1461)  评论(0编辑  收藏  举报

导航