SAP LCM存货减值

库存料号中有原料、半品、成品、辅料。原料可以按照BOM生产成成品料号,LCM存货减值就是根据库存中的料号,算出对应的存货成本,然后按照BOM推算出对应的成品料号,按照原料料号的成本价和成品料号的售价、成本价  的比值,计算存货跌价。当然,按照会计谨慎性原则,如果是溢价是不提减值准备的,也不会抵消。

此程序的逻辑则更显复杂。

其中遇到了些问题,

APPEND LINES OF lt_dstuf TO gt_dstuf.

MOVE-CORRESPONDING gt_lcm1 TO gt_ztco0043b_lcm.

此语法,如果遇到了内表上百万行、乃至千万行时会发生数据溢出错误。

用了WITH +data的方法也是不行

最后只能用submit一个料号一个料号运行,写入底表中,然后用SQL重新读取底表,再把其他栏位数据补全的方法,进行下去。当然了上千万行的ALV数据,也是相当难的导出。

为啥会有如此多的数据呢,原因就是出在可配置BOM上面,由于会根据原料通过BOM再去取成品料号,如果是可配置的BOM的话,那么就有非常非常多的成品料号可供选择了,成品料号会非常的多。再叠加每个料号的批次也非常多的话,完整计算出原料料号的每个批次对应的成品料号,那数据是非常庞大的。

在跨工厂的可配置BOM中,如何计算原料对应成品料号的QPA,要精确计算感觉是非常的难,目前只是通过一些判断,只取了特性中的一个料号的QPA计算,并不能精确计算到底原料料号对应的那么多成品料号的QPA的细微差别。

具体还是看附件中的PPT研究研究。

*&---------------------------------------------------------------------*
*& Responsibility
*&---------------------------------------------------------------------*
* Program Name: ZCOD0046B
* Date written: 2023-12-22
* Author's name: C10089213 
* Last update:
* Program title: LCM存货减值
* Project Name:
* Version: V1.0


REPORT zcod0046b MESSAGE-ID zfi001.

*----------------------------------------------------------------------*
*              INCLUDE 、 TYPES_POOLS 、 TABLES  引 用 区              *
*----------------------------------------------------------------------*
TABLES:ztco0043b_item,ztco0043b_lcm,ztco0043b_bom,ztco0043b_raw,t001,bseg,bkpf,ekko,ekpo,ekpa,t161t,mseg,makt,mbew,marc,lfa1,rc29l,stpov_alv,stpov.
"ztco0043b_item 是旧表,ztco0043b_lcm 是新表

*----------------------------------------------------------------------*
*                 TYPES 结构定义  & DATA 定义                          *
*----------------------------------------------------------------------*
DATA: lv_ndate1 TYPE d ,  "当前日期,期初,确定后不可修改
      lv_ndate2 TYPE d ,  "当前日期,期末,确定后不可修改
      lv_nrq(6) TYPE c,   "当前日期 年月,确定后不可修改
      lv_fdate1 TYPE d ,  "未来日期,期初,确定后不可修改
      lv_fdate2 TYPE d ,  "未来日期,期末,确定后不可修改
      lv_frq(6) TYPE c.   "未来日期 年月,确定后不可修改

DATA:lv_del_date  TYPE d ,             "删除日期
     lv_del_gjahr TYPE bseg-gjahr,     "删除年份
     lv_del_monat TYPE bseg-h_monat .  "删除月份


*"由于后续需要排序,声明不能轻易改变
*TYPES: BEGIN OF ty_lcm,
*         zitem             TYPE zco_item,              ""项次
*         erfmg             TYPE erfmg,                 ""成品工单未来入库量
*         matnr             TYPE matnr,                 ""物料编号
*         werks             TYPE werks_d,               ""工厂
*         lgort             TYPE lgort_d,               ""库存地点
*         charg             TYPE charg_d,               ""批次
*         matnr_head(80)   TYPE c,                     ""成品料号(复数),原表为1333,但modfiy后显示不了
*         werks_head        TYPE werks_d,               ""成品料号的工厂
*         zn_gjahr          TYPE lfgja,                 ""当前年度
*         zn_monat          TYPE lfmon,                 ""当前月份
*         zf_gjahr          TYPE gjahr,                 ""未来年度
*         zf_monat          TYPE monat,                 ""未来月份
*         bukrs             TYPE bukrs,                 ""公司代码
*         bklas             TYPE bklas,                 ""评估分类
*         beskz             TYPE beskz,                 ""采购类型
*         zqm01_qty         TYPE ze_zqm01_qty,          ""库存数量
*         zqm01_amount      TYPE p DECIMALS 6,          ""料件成本单价
*         zqm02_amount      TYPE p DECIMALS 6,          ""成本金额
*         zpro_cost         TYPE p DECIMALS 6,          ""成品成本单价
*         zpro_fut_cost     TYPE p DECIMALS 6,          ""成品未来期间成本单价
*         zbsale_price      TYPE p DECIMALS 6,          ""成品未来期间售价(CNY)
*         zsale_price       TYPE p DECIMALS 6,          ""成品未来期间售价(原币)
*         zpro_waerk        TYPE waerk,                 ""成品未来期间售价的币别
*         zsale_rate(12)    TYPE c,                     ""未来期间销售费用率
*         zpro_gross_loss   TYPE p DECIMALS 6,          ""成品未来毛损
*         zhalf_gross_loss  TYPE p DECIMALS 6,          ""库存料毛损
*         zloss_amount      TYPE p DECIMALS 6,          ""损失金额
*         zraw_werks        TYPE werks_d,               ""原材料号的工厂
*         zraw_matnr        TYPE matnr,                 ""原材料号
*         zraw_cost         TYPE p DECIMALS 6,          ""原材成本价
*         zraw_purchasep_oc TYPE p DECIMALS 6,          ""原材未来期间采购单价(CNY)
*         zraw_purchasep_hc TYPE p DECIMALS 6,          ""原材未来期间采购单价(原币)
*         zraw_waerk        TYPE waerk,                 ""原材未来期间采购单价的币别
*         maktx             TYPE maktx,                 ""物料描述
*         lgobe             TYPE lgobe,                 ""库存地点描述
*         lgort_p(6)        TYPE c,                     ""仓库属性
*         hsdat             TYPE hsdat,                 ""批号生成日期
*         prdha             TYPE prodh_d,               ""产品层次
*         zcmcc             TYPE zcmcc,                 ""机种
*         prctr             TYPE prctr,                 ""利润中心
*         dull_month        TYPE zedullm,               ""呆滞月份
*         stday             TYPE charg_d,               ""库龄天数
*         insign            TYPE c,                     ""内置分类(LCM公式分类)"
*       END OF ty_lcm.


DATA: gt_lcm1          TYPE TABLE OF ztco0043b_lcm,
      gt_lcm2          TYPE TABLE OF ztco0043b_lcm,
      gt_lcm3          TYPE TABLE OF ztco0043b_lcm,
      gt_lcm4          TYPE TABLE OF ztco0043b_lcm,
      gt_lcm5          TYPE TABLE OF ztco0043b_lcm,
      gt_lcm6          TYPE TABLE OF ztco0043b_lcm,
      gt_ztco0043b_lcm TYPE TABLE OF ztco0043b_lcm,
      lt_ztco0043b_lcm TYPE TABLE OF ztco0043b_lcm,
      gt_ylcm          TYPE TABLE OF ztco0043b_lcm,
      gs_lcm1          TYPE ztco0043b_lcm,
      gs_lcm2          TYPE ztco0043b_lcm,
      gs_lcm3          TYPE ztco0043b_lcm,
      gs_lcm4          TYPE ztco0043b_lcm.


DATA : BEGIN OF gtz_lcm OCCURS 0,
         matnr TYPE matnr,                 ""物料编号
         werks TYPE werks_d,               ""工厂
         datas TYPE STANDARD TABLE OF ztco0043b_lcm,
       END OF gtz_lcm.


DATA: gt_ztco0043b_item TYPE TABLE OF ztco0043b_item.


DATA: gt_ztco0043b_raw TYPE TABLE OF ztco0043b_raw,
      gs_ztco0043b_raw TYPE ztco0043b_raw.


TYPES:BEGIN OF ty_ztco0043b_bom,
        gjahr  TYPE lfgja,            ""当前年度
        monat  TYPE lfmon,            ""当前月份
        bukrs  TYPE bukrs,            ""公司代码
        zwerks TYPE werks_d,          ""工厂
        zmatnr TYPE matnr,            ""物料编号
        werks  TYPE werks_d,          ""成品料的工厂
        matnr  TYPE matnr,            ""成品料的物料编号
        bklas  TYPE bklas,            ""成品料的评估类 "
        qpa2   TYPE ztco0043b_bom-qpa2,          ""查询料号QPA
      END OF ty_ztco0043b_bom.

DATA: gt_ztco0043b_bom TYPE TABLE OF ty_ztco0043b_bom,
      gs_ztco0043b_bom TYPE ty_ztco0043b_bom.

DATA : lt_ztco0043b_bom TYPE TABLE OF ztco0043b_bom,
       ls_ztco0043b_bom TYPE ztco0043b_bom.


"跨工厂取成品料号

TYPES:BEGIN OF ty_ztco0046c,
        matnr TYPE matnr,            ""物料编号
        werk1 TYPE werks_d,          ""转出工厂
        werk2 TYPE werks_d,          ""转入工厂"
      END OF ty_ztco0046c.

DATA : gt1_ztco0046c TYPE TABLE OF ty_ztco0046c,
       gt2_ztco0046c TYPE TABLE OF ty_ztco0046c,
       gs1_ztco0046c TYPE ty_ztco0046c,
       gs2_ztco0046c TYPE ty_ztco0046c.

DATA : BEGIN OF gtz1_ztco0046c OCCURS 0,
         matnr TYPE matnr,            ""物料编号
         werk1 TYPE werks_d,          ""转出工厂
         datas TYPE STANDARD TABLE OF ty_ztco0046c,
       END OF gtz1_ztco0046c.

DATA : BEGIN OF gtz2_ztco0046c OCCURS 0,
         werk1 TYPE werks_d,          ""转出工厂
         datas TYPE STANDARD TABLE OF ty_ztco0046c,
       END OF gtz2_ztco0046c.



TYPES: BEGIN OF ty_mara,
         werks        TYPE werks_d,               ""工厂
         matnr        TYPE matnr,                 ""物料编号
         zqm01_qty    TYPE ze_zqm01_qty,          ""期末数量
         zqm02_amount TYPE p DECIMALS 6,          ""期末金额"
       END OF ty_mara.

DATA: gt_mara1 TYPE TABLE OF ty_mara,
      gt_mara2 TYPE TABLE OF ty_mara,
      gs_mara1 TYPE ty_mara,
      gs_mara2 TYPE ty_mara.

TYPES: BEGIN OF ty_ckis,
         zmatnr TYPE matnr,              ""查询物料编号
         zwerks TYPE werks_d,            ""查询的工厂
         price  TYPE p DECIMALS 6,           ""金额
         matnr  TYPE matnr,              ""物料编号
         werks  TYPE werks_d,            ""工厂
         bklas  TYPE bklas,              ""评估类
         wertn  TYPE ck_kwt,             ""控制区域货币的值
         peinh  TYPE ck_kpeinh,          ""以控制范围货币记价的单位价格"
       END OF ty_ckis.

DATA: gt1_ckis TYPE TABLE OF ty_ckis,
      gt2_ckis TYPE TABLE OF ty_ckis,
      gt3_ckis TYPE TABLE OF ty_ckis,
      gs1_ckis TYPE ty_ckis,
      gs2_ckis TYPE ty_ckis.


TYPES: BEGIN OF ty_zraw,
         stlty  TYPE stlty,          ""物料清单类别
         stlnr  TYPE stnum,          ""物料清单
         stlal  TYPE stalt,          ""备选物料清单
         stlkn  TYPE stlkn,          ""BOM 项目节点号 "
         zmatnr TYPE matnr,                 ""查询物料编号
         zwerks TYPE werks_d,               ""查询的工厂
         price  TYPE p DECIMALS 6,          ""金额
         matnr  TYPE idnrk,                 ""物料编号
         werks  TYPE werks_d,               ""工厂
         bklas  TYPE bklas,                 ""评估类
         beskz  TYPE beskz,                 ""采购类型
         verpr  TYPE verpr,                 ""移动平均价格/周期单价
         peinh  TYPE peinh,                 ""价格单位
         menge  TYPE kmpmg,                 ""组件数量"
         datuv  TYPE datuv,                "有效起始日期>>作为截止日期
       END OF ty_zraw.

DATA: gt1_zraw TYPE TABLE OF ty_zraw,
      gt2_zraw TYPE TABLE OF ty_zraw,
      gs1_zraw TYPE ty_zraw,
      gs2_zraw TYPE ty_zraw.

" 运行 G2DNP23CAN001A-N 2023年10月日善时报了溢出错误
"   Overflow during an arithmetic operation (type P) in program "ZCOD0046B".
TYPES: BEGIN OF ty_raw,
         zmatnr    TYPE matnr,                 ""查询物料编号
         zwerks    TYPE werks_d,               ""查询的工厂
         price(16) TYPE p,              ""金额
         matnr     TYPE idnrk,                 ""物料编号
         werks     TYPE werks_d,               ""工厂
         bklas     TYPE bklas,                 ""评估类
         beskz     TYPE beskz,                 ""采购类型
         verpr     TYPE verpr,                 ""移动平均价格/周期单价
         peinh     TYPE peinh,                 ""价格单位
         menge     TYPE kmpmg,                 ""组件数量"
         zprice    TYPE string,              ""金额
         "datuv  TYPE datuv,                "有效起始日期>>作为截止日期
       END OF ty_raw.

DATA: gt1_raw TYPE TABLE OF ty_raw,
      gt2_raw TYPE TABLE OF ty_raw,
      gt3_raw TYPE TABLE OF ty_raw,
      gt4_raw TYPE TABLE OF ty_raw,
      gs1_raw TYPE ty_raw,
      gs2_raw TYPE ty_raw.


TYPES: BEGIN OF ty_ztco0011a,
         werks        TYPE werks_d,               ""工厂
         matnr        TYPE matnr,                 ""物料编号
         zqm01_qty    TYPE ze_zqm01_qty,          ""期末数量
         zqm02_amount TYPE p DECIMALS 6,          ""期末金额"
       END OF ty_ztco0011a.

DATA: gt1_ztco0011a TYPE TABLE OF ty_ztco0011a,
      gt2_ztco0011a TYPE TABLE OF ty_ztco0011a,
      gs1_ztco0011a TYPE ty_ztco0011a,
      gs2_ztco0011a TYPE ty_ztco0011a.


TYPES: BEGIN OF ty_ztco0013,
         matnr TYPE matnr,               ""物料编号
         werks TYPE werks_d,             ""工厂
         waers TYPE waers,               ""货币码
         pvprs TYPE ck_pvprs_1,          ""周期单位价格
         peinh TYPE ck_peinh_1,          ""价格单位"
       END OF ty_ztco0013.

DATA: gt1_ztco0013 TYPE TABLE OF ty_ztco0013,
      gt2_ztco0013 TYPE TABLE OF ty_ztco0013,
      gs1_ztco0013 TYPE ty_ztco0013,
      gs2_ztco0013 TYPE ty_ztco0013.


TYPES: BEGIN OF ty_mbewh,
         matnr TYPE matnr,          ""物料编号
         bwkey TYPE bwkey,          ""估价范围
         verpr TYPE verpr,          ""移动平均价格/周期单价
         peinh TYPE peinh,          ""价格单位"
       END OF ty_mbewh.

DATA: gt1_mbewh TYPE TABLE OF ty_mbewh,
      gt2_mbewh TYPE TABLE OF ty_mbewh,
      gt3_mbewh TYPE TABLE OF ty_mbewh,
      gs1_mbewh TYPE ty_mbewh,
      gs2_mbewh TYPE ty_mbewh,
      gs3_mbewh TYPE ty_mbewh.


TYPES: BEGIN OF ty_zmbewh,
         matnr TYPE matnr,          ""物料编号
         bwkey TYPE bwkey,          ""估价范围
         lfgja TYPE lfgja,          ""当前期间的会计年度
         lfmon TYPE lfmon,          ""当前期间(过账期间)
         verpr TYPE verpr,          ""移动平均价格/周期单价
         peinh TYPE peinh,          ""价格单位"
       END OF ty_zmbewh.

DATA: gt1_zmbewh TYPE TABLE OF ty_zmbewh,
      gt2_zmbewh TYPE TABLE OF ty_zmbewh,
      gt3_zmbewh TYPE TABLE OF ty_zmbewh,
      gs1_zmbewh TYPE ty_zmbewh,
      gs2_zmbewh TYPE ty_zmbewh,
      gs3_zmbewh TYPE ty_zmbewh.


TYPES: BEGIN OF ty_ckmlcr,
         matnr  TYPE matnr,          ""物料编号
         bwkey  TYPE bwkey,          ""估价范围
         insign TYPE c,               ""内置分类(实际价格优先于标准价格)
         lfgja  TYPE lfgja,          ""当前期间的会计年度
         lfmon  TYPE lfmon,          ""当前期间(过账期间)
         price  TYPE p DECIMALS 6,          ""价格
         verpr  TYPE verpr,          ""移动平均价格/周期单价
         stprs  TYPE ck_stprs_1,          "标准价格
         peinh  TYPE peinh,          ""价格单位"
       END OF ty_ckmlcr.

DATA: gt1_ckmlcr TYPE TABLE OF ty_ckmlcr,
      gt2_ckmlcr TYPE TABLE OF ty_ckmlcr,
      gt3_ckmlcr TYPE TABLE OF ty_ckmlcr,
      gs1_ckmlcr TYPE ty_ckmlcr,
      gs2_ckmlcr TYPE ty_ckmlcr,
      gs3_ckmlcr TYPE ty_ckmlcr.



TYPES: BEGIN OF ty_ekpo,
         matnr      TYPE matnr,             ""物料编号
         "WERKS TYPE WERKS_D,           ""工厂
         budat_mkpf TYPE budat,             ""凭证中的过账日期
         waers      TYPE waers,             ""货币码
         zzprice    TYPE p DECIMALS 6,    "实际单价
         netpr      TYPE bprei,             ""采购凭证中的净价(以凭证货币计)
         peinh      TYPE epein,             ""价格单位
         dmbtr      TYPE dmbtr_cs,          ""以本币表示的金额
         menge      TYPE menge_d,           ""数量"
       END OF ty_ekpo.

DATA: gt_ekpo1 TYPE TABLE OF ty_ekpo,
      gt_ekpo2 TYPE TABLE OF ty_ekpo,
      gs_ekpo1 TYPE ty_ekpo,
      gs_ekpo2 TYPE ty_ekpo.



DATA lv_zsale_rate(12) TYPE c.                    ""未来期间销售费用率


TYPES: BEGIN OF ty_rate,
         waerk TYPE waerk,                 ""币别
         rate  TYPE p DECIMALS 8,           ""汇率
       END OF ty_rate.

DATA: gt_rate1 TYPE TABLE OF ty_rate,
      gs_rate1 TYPE ty_rate,
      gt_rate2 TYPE TABLE OF ty_rate,
      gs_rate3 TYPE ty_rate.



"--------------------------反查BOM-----------------------------------------------------
"显示的ALV数据  "与ZCOR00565 不同

"为了重新排序,计算QPA等,与ZCOR0055不同
TYPES: BEGIN OF ty_zstpov,
         zmatnr      TYPE matnr,                 ""查询的物料
         zwerks      TYPE werks_d,               ""查询的工厂
         dstuf(3)    TYPE c,                     ""成本阶(文本型)与其他的不同
         matnr       TYPE matnr,                 ""物料编号
         werks       TYPE werks_d,               ""工厂
         alpgr2(3)   TYPE c,                     ""替代项目:组(修订)
         idnrk       TYPE idnrk,                 ""BOM组件
         idnrk_werks TYPE werks_d,               ""BOM组件的工厂
         ewahr       TYPE ewahr,                 ""以百分比表示的使用概率(备选项目)
         qpa1        TYPE p DECIMALS 8,          ""单层QPA
         qpa2        TYPE p DECIMALS 8,          ""查询料号QPA
         "receive1     TYPE p DECIMALS 8,          ""领用比例
         "udate(6)     TYPE c,                     ""领用数量取值的日期,仅用来检查 年、月的数据,但不显示出来
         "ztransaction TYPE p DECIMALS 8,          ""关联交易比例
         "zidnrk       TYPE string,                ""领用料号(复数)
         "receive2     TYPE string,                ""领用比例(复数)"
         "bukr1        TYPE bukrs,                  ""库存方
         "alpgr3       TYPE cs_alpgr,              ""替代项目:组(补充)
         "alpgr4(3)    TYPE c,                     ""替代项目:组(补充的修订)
       END OF ty_zstpov.

DATA: gt1_zstpov TYPE TABLE OF ty_zstpov,
      gt2_zstpov TYPE TABLE OF ty_zstpov,
      gt3_zstpov TYPE TABLE OF ty_zstpov,
      gs1_zstpov TYPE  ty_zstpov,
      gs2_zstpov TYPE  ty_zstpov,
      gs3_zstpov TYPE  ty_zstpov,
      gs4_zstpov TYPE  ty_zstpov,
      gs5_zstpov TYPE  ty_zstpov,
      gs6_zstpov TYPE  ty_zstpov.




TYPES: BEGIN OF ty_stpov,
         zmatnr      TYPE matnr,                 ""查询的物料
         zwerks      TYPE werks_d,               ""查询的工厂
         erfmg1      TYPE erfmg,               ""以录入项单位表示的数量,要放前面
         matnr       TYPE matnr,                 ""物料编号
         werks       TYPE werks_d,               ""工厂
         beskz       TYPE beskz,                 ""BOM组件的采购类型
         erfmg2      TYPE erfmg,                 ""工单入库总数
         "erfmgsign TYPE c,                       ""入库量标识
         "------------Start 为了算BOM用量(QPA)-----------------"
         idnrk       TYPE idnrk,                 ""BOM组件
         idnrk_werks TYPE werks_d,               ""BOM组件的工厂
         dstuf       TYPE ttidx,                 ""成本阶
         alpgr1      TYPE cs_alpgr,              ""替代项目:组
         alpgr2(3)   TYPE c,                     ""替代项目:组(修订)
         "alpgr3    TYPE cs_alpgr,              ""替代项目:组(补充)
         qpa1        TYPE p DECIMALS 8,          ""单层QPA"
         qpa2        TYPE p DECIMALS 8,          ""单层QPA"
         ewahr       TYPE ewahr,                 ""以百分比表示的使用概率(备选项目)
         "------------End 为了算BOM用量(QPA)-----------------"
       END OF ty_stpov.

DATA: gt_stpov     TYPE TABLE OF ty_stpov,
      gt_stpov_fin TYPE TABLE OF ty_stpov, "成品料号
      lt_stpov_fin TYPE TABLE OF ty_stpov,
      lt_stpov1    TYPE TABLE OF ty_stpov,
      lt_stpov2    TYPE TABLE OF ty_stpov,
      gt_zstpov1   TYPE TABLE OF ty_stpov,
      gt_zstpov2   TYPE TABLE OF ty_stpov,
      gt_zstpov3   TYPE TABLE OF ty_stpov,
      gs_stpov     TYPE  ty_stpov,
      wa_stpov     TYPE  ty_stpov.


DATA : BEGIN OF gtz_stpov OCCURS 0,
         zmatnr TYPE matnr,                 ""查询的物料
         zwerks TYPE werks_d,               ""查询的工厂
         "matnrs(80) TYPE c,                    ""成品物料(复数)
         stpov  TYPE STANDARD TABLE OF ty_stpov,
       END OF gtz_stpov.

TYPES: BEGIN OF ty_erfmg,
         zmatnr     TYPE matnr,                 ""查询的物料
         zwerks     TYPE werks_d,               ""查询的工厂
         matnr      TYPE matnr,                 ""成品料号
         werks      TYPE werks_d,               ""工厂
         erfmg1     TYPE erfmg,               ""以录入项单位表示的数量,这个放后面
         erfmg2     TYPE erfmg,                 ""工单入库总数
         matnrs(80) TYPE c,                    ""成品物料(复数)
       END OF ty_erfmg.

DATA: gt_erfmg1 TYPE TABLE OF ty_erfmg,
      gt_erfmg2 TYPE TABLE OF ty_erfmg,
      gs_erfmg  TYPE  ty_erfmg,
      wa_erfmg  TYPE  ty_erfmg.



"为了递归时重复输入料号,做个记录,此内表无数据时递归停止
"由于一个料号有可能多次重复出现不同的成本阶,之后要做特殊修正
"另外。此表会有多次反复使用,使用之后一定要清除内表和工作区
TYPES: BEGIN OF ty_marc,
         zmatnr TYPE matnr,            ""查询的物料
         zwerks TYPE werks_d,          ""查询的工厂
         matnr  TYPE matnr,            ""物料编号
         werks  TYPE werks_d,          ""工厂
         dstuf  TYPE ttidx,            ""成本阶"
         alpgr1 TYPE cs_alpgr,         ""替代项目:组
       END OF ty_marc.

DATA: gt_marc  TYPE TABLE OF ty_marc, "每次使用后都要清空
      gs_marc  TYPE  ty_marc,
      lt_marc1 TYPE TABLE OF ty_marc,
      wa_marc1 TYPE  ty_marc,
      lt_marc2 TYPE TABLE OF ty_marc,
      wa_marc2 TYPE  ty_marc,
      ls_marc  TYPE  ty_marc.

DATA lv_recursion TYPE c.


"BOM,物料对应BOM组件 ,要考虑跨工厂
TYPES:BEGIN OF ty_matnrs,
        matnr  TYPE matnr,            ""物料编号
        werks  TYPE werks_d,          ""工厂
        matnrs TYPE matnr,            ""物料编号
        werkss TYPE werks_d,          ""工厂
      END OF ty_matnrs.

DATA: gt_matnrs TYPE TABLE OF ty_matnrs,
      gs_matnrs TYPE  ty_matnrs,
      wa_matnrs TYPE  ty_matnrs.

DATA : BEGIN OF gt_zmatnrs OCCURS 0,
         matnr  TYPE matnr,                   ""物料编号
         werks  TYPE werks_d,          ""工厂
         matnrs TYPE STANDARD TABLE OF ty_matnrs,
       END OF gt_zmatnrs.


"调用函数时的一些参数,给默认值,不进行屏幕显示
DATA: lv_datub TYPE rc29l-datub,    "有效截止日期
      lv_postp TYPE rc29l-postp VALUE 'L',    "项目类别
      lv_stlan TYPE rc29l-stlan.   " 物料清单用途  取消默认值 VALUE '1'

"单次记录物料出现的成本阶,下一个查询料号要清除
TYPES:BEGIN OF ty_dstuf,
        matnr  TYPE rc29l-matnr,   ""物料
        werks  TYPE werks_d,       ""工厂 "专门为跨工厂加的
        dstuf  TYPE ttidx,         ""成本阶
        alpgr3 TYPE cs_alpgr,      ""替代项目:组(补充)
      END OF ty_dstuf.

DATA: gt_dstuf TYPE TABLE OF ty_dstuf,
      lt_dstuf TYPE TABLE OF ty_dstuf,
      ls_dstuf TYPE ty_dstuf,
      gs_dstuf TYPE ty_dstuf,
      wa_dstuf TYPE ty_dstuf.

"SELECT 查询的条件
RANGES: s_zmatnr FOR rc29l-matnr, "物料
        s_zwerks FOR rc29l-werks. "工厂


TYPES: BEGIN OF ty_aufm,
         matnr TYPE co_matnr,          ""入库物料
         werks TYPE werks_d,           ""入库物料的工厂
         erfmg TYPE erfmg,             ""以录入项单位表示的数量 改为  “MENGE 数量”
         aufnr TYPE aufnr,              ""订单号
         mblnr TYPE mblnr,             ""物料凭证编号
       END OF ty_aufm.

DATA: gt_aufm1 TYPE TABLE OF ty_aufm,
      gt_aufm2 TYPE TABLE OF ty_aufm,
      gs_aufm1 TYPE ty_aufm,
      gs_aufm2 TYPE ty_aufm.



DATA l_factor TYPE p DECIMALS 3. "算转换因子
DATA: cw_rate LIKE bapi1093_0. "算汇率


TYPES: BEGIN OF ty_ztsdr0047,
         matnr     TYPE ztsdr0047-matnr,              ""物料编号
         "werks     TYPE ztsdr0047-werks,              ""工厂
         "vkorg     TYPE ztsdr0047-vkorg,              ""销售组织
         insign    TYPE c,                            ""内置分类(用于日期排序)"
         udate     TYPE d,                            ""排序日期
         wadat_ist TYPE ztsdr0047-wadat_ist,          ""实际货物移动日期
         bldat     TYPE ztsdr0047-bldat,              ""凭证中的凭证日期
         "yyyymm    TYPE ztsdr0047-yyyymm,             ""年月
         waerk     TYPE ztsdr0047-waerk,              ""销售和分销凭证货币
         netpr2    TYPE ztsdr0047-netpr2,             ""净价值 "
         vbeln     TYPE ztsdr0047-vbeln,          "销售和分销凭证号
       END OF ty_ztsdr0047.

DATA: gt1_ztsdr0047 TYPE TABLE OF ty_ztsdr0047,
      gt2_ztsdr0047 TYPE TABLE OF ty_ztsdr0047,
      gt3_ztsdr0047 TYPE TABLE OF ty_ztsdr0047,
      gs1_ztsdr0047 TYPE ty_ztsdr0047,
      gs2_ztsdr0047 TYPE ty_ztsdr0047.

"销售订单价格
TYPES: BEGIN OF ty_vbap,
         matnr   TYPE matnr,          ""物料编号
         prsdt   TYPE prsdt,          ""定价日期和汇率
         waerk   TYPE waerk,          ""销售和分销凭证货币
         netpr   TYPE netpr,          ""净价
         kpein   TYPE kpein,          ""条件定价单位"
         zzprice TYPE p DECIMALS 6,    "原币单价
       END OF ty_vbap.

DATA: gt1_vbap TYPE TABLE OF ty_vbap,
      gt2_vbap TYPE TABLE OF ty_vbap,
      gs1_vbap TYPE ty_vbap,
      gs2_vbap TYPE ty_vbap.

"销售订单价格,关联方
TYPES: BEGIN OF ty_vbkd,
         matnr   TYPE matnr,          ""物料编号
         prsdt   TYPE prsdt,          ""定价日期和汇率
         waers   TYPE waers,          ""货币码
         netpr   TYPE bprei,          ""采购凭证中的净价(以凭证货币计)
         peinh   TYPE epein,          ""价格单位"
         zzprice TYPE p DECIMALS 6,    "原币单价
       END OF ty_vbkd.

DATA: gt1_vbkd TYPE TABLE OF ty_vbkd,
      gt2_vbkd TYPE TABLE OF ty_vbkd,
      gs1_vbkd TYPE ty_vbkd,
      gs2_vbkd TYPE ty_vbkd.


TYPES: BEGIN OF ty_ztsdr0048,
         matnr    TYPE ztsdr0048-matnr,             ""物料编号
         "vkorg    TYPE ztsdr0048-vkorg,             ""销售组织
         datab    TYPE ztsdr0048-datab,             ""开始生效日期
         datbi    TYPE ztsdr0048-datbi,             ""有效期截止日期
         "erdat    TYPE ztsdr0048-erdat,             ""记录建立日期
         "yyyymm   TYPE ztsdr0048-yyyymm,            ""年月
         konwa    TYPE ztsdr0048-konwa,             ""条件单位(货币或百分比)
         pc_kbetr TYPE ztsdr0048-pc_kbetr,          ""实际单价(单价/基数) "
       END OF ty_ztsdr0048.

DATA: gt1_ztsdr0048 TYPE TABLE OF ty_ztsdr0048,
      gt2_ztsdr0048 TYPE TABLE OF ty_ztsdr0048,
      gt3_ztsdr0048 TYPE TABLE OF ty_ztsdr0048,
      gs1_ztsdr0048 TYPE ty_ztsdr0048,
      gs2_ztsdr0048 TYPE ty_ztsdr0048.


TYPES: BEGIN OF tyb_ztmmr1098,
         matnr   TYPE eina-matnr,      "物料编码
         datab   TYPE     a018-datab,      "有效期开始日期
         datbi   TYPE     a018-datbi,      "有效期截止日期
         konwa   TYPE konwa,           "币别
         zzprice TYPE p DECIMALS 6,    "实际单价
         "lifnr   TYPE ekko-lifnr, "供应商
         "zzpricecny TYPE p DECIMALS 6,    "实际单价(CNY)
       END OF tyb_ztmmr1098.

DATA: gtb1_ztmmr1098 TYPE TABLE OF tyb_ztmmr1098,
      gtb2_ztmmr1098 TYPE TABLE OF tyb_ztmmr1098,
      gsb1_ztmmr1098 TYPE tyb_ztmmr1098,
      gsb2_ztmmr1098 TYPE tyb_ztmmr1098.


TYPES: BEGIN OF tys_ztmmr1098,
         matnr   TYPE eina-matnr,      "物料编码
         datab   TYPE     a018-datab,      "有效期开始日期
         datbi   TYPE     a018-datbi,      "有效期截止日期
         konwa   TYPE konwa,           "币别
         zzprice TYPE p DECIMALS 6,    "实际单价
         lifnr   TYPE ekko-lifnr, "供应商
         "zzpricecny TYPE p DECIMALS 6,    "实际单价(CNY)
       END OF tys_ztmmr1098.

DATA: gts1_ztmmr1098 TYPE TABLE OF tys_ztmmr1098,
      gts2_ztmmr1098 TYPE TABLE OF tys_ztmmr1098,
      gss1_ztmmr1098 TYPE tys_ztmmr1098,
      gss2_ztmmr1098 TYPE tys_ztmmr1098.


"物料信息表
TYPES:BEGIN OF ty_matnr,
        matnr  TYPE matnr,            ""物料编号
        werks  TYPE werks_d,          ""工厂
        maktx  TYPE maktx,            ""物料描述
        meins  TYPE meins,            ""基本计量单位
        bklas  TYPE bklas,            ""评估类
        beskz  TYPE beskz,            "采购类型
        zzcmcc TYPE zcmcc,            ""机种
        prctr  TYPE prctr,            ""利润中心"
      END OF ty_matnr.

DATA: gt_matnr TYPE TABLE OF ty_matnr,
      gs_matnr TYPE ty_matnr.


"显示成本单价
TYPES: BEGIN OF ty_price,
         matnr     TYPE matnr,               ""物料编号
         bwkey     TYPE bwkey,               ""估价范围
         waers     TYPE waers,               ""货币码 "
         peinh     TYPE ck_peinh_1,          ""价格单位
         pvprs     TYPE ck_pvprs_1,          ""周期单位价格
         costprice TYPE p DECIMALS 6,           ""成本价
         gjahr     TYPE gjahr,                  ""会计年度
         monat     TYPE monat,                  ""会计期间
       END OF ty_price.

DATA: gt_price TYPE TABLE OF ty_price,
      lt_price TYPE TABLE OF ty_price,
      gs_price TYPE  ty_price,
      wa_price TYPE  ty_price.

DATA: lv_result TYPE p LENGTH 6 DECIMALS 2,
      lv_line   TYPE i,
      lv_stxt   TYPE string,
      lv_str    TYPE string,
      lv_restex TYPE char8,
      lv_ztime  TYPE ztime.

DATA lv_n(8) TYPE n. "每次循环后要修改成0!!!
DATA lv_i(8) TYPE n. "每次循环后要修改成0!!!

DATA lv_zerodel TYPE c. "删除零




TYPES: BEGIN OF ty_stpo,
         matnr  TYPE matnr,             ""物料编号
         werks  TYPE werks_d,           ""工厂
         zmatnr TYPE idnrk,             ""查询的物料
         zwerks TYPE werks_d,           ""查询的工厂
         datuv  TYPE datuv,             ""有效起始日期
         alprf  TYPE cs_alprf,          ""替代项目:评比定单   优先级
         alpgr1 TYPE cs_alpgr,          ""替代项目:组"
         stlnr  TYPE stnum,             "物料清单
       END OF ty_stpo.

DATA: gt_stpo  TYPE TABLE OF ty_stpo,
      gs_stpo  TYPE  ty_stpo,
      lt_stpo  TYPE TABLE OF ty_stpo,
      wa_stpo  TYPE  ty_stpo,
      gt_zstpo TYPE TABLE OF ty_stpo.



TYPES: BEGIN OF ty_msgbox,
         c1 TYPE string,
         c2 TYPE string,
         c3 TYPE string,
         c4 TYPE string,
         c5 TYPE string,
         c6 TYPE string,
         c7 TYPE string,
         c8 TYPE string,
         c9 TYPE string,
       END OF ty_msgbox.

DATA: gt_msgbox TYPE TABLE OF ty_msgbox,
      gs_msgbox TYPE  ty_msgbox.

DATA : lv_content TYPE string.

RANGES s_lgort_p FOR ztco0043_slm-lgort_p. "



*----------------------------------------------------------------------*
*                  ALV 定义
*----------------------------------------------------------------------*
DATA: lt_fieldcat TYPE lvc_t_fcat, "fieldcat 字段目录 参考结构 LVC_T_FCAT
      ls_fieldcat LIKE LINE OF lt_fieldcat,
      wa_layout   TYPE lvc_s_layo. "layout 布局控制 参考结构 lvc_s_layo

DATA : lt_event TYPE slis_t_event, "事件的内表
       ls_event TYPE slis_alv_event.


*----------------------------------------------------------------------*
*                  选 择 屏 幕 定 义 块
*----------------------------------------------------------------------*

"SPRO>>控制>> 一般控制>>组织结构>>维护成本控制范围>>维护成本控制范围>> 定位>>2688,货币是CNY,
"OB08维护汇率。
"需要知道关系人,2688则指代的是立铠集团,开始用的是LXCA这个科目表,虽然在透明表中T001中查询LXCA科目表下确实都是立铠集团的公司,
"但是2575立讯集团也是LXCA这个科目表,之所以T001里查不到立讯的公司是因为进入的是688这个客户端的原因,使用2688会更严谨。

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-a01.
PARAMETERS: p_1 RADIOBUTTON GROUP g1 DEFAULT 'X' USER-COMMAND db ,  "LCM减值报表-计算
            p_2 RADIOBUTTON GROUP g1,                               "LCM减值报表-显示
            p_7 RADIOBUTTON GROUP g1,                              "LCM减值跨工厂取成品料号维护作业
            p_3 RADIOBUTTON GROUP g1,                              "物料与成品料号对比表-计算
            p_4 RADIOBUTTON GROUP g1,                              "物料与成品料号对比表-显示
            p_5 RADIOBUTTON GROUP g1,                              "物料与原材料号对比表-计算
            p_6 RADIOBUTTON GROUP g1.                              "物料与原材料号对比表-显示
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-a02.


PARAMETERS p_bukrs LIKE bseg-bukrs MODIF ID f0.   ""公司代码
PARAMETERS pn_gjahr LIKE bseg-gjahr  MODIF ID f0 .   ""当前年份
PARAMETERS pn_monat LIKE bseg-h_monat  MODIF ID f0.   ""当前月份

PARAMETERS pf_gjahr LIKE bseg-gjahr  MODIF ID f2.   ""未来年份
PARAMETERS pf_monat LIKE bseg-h_monat MODIF ID f2.   ""未来月份

SELECT-OPTIONS:
s_zitem FOR ztco0043b_lcm-zitem MODIF ID f4, "项次

s_matnr FOR rc29l-matnr MODIF ID f3,    "物料编号
s_werks FOR rc29l-werks MODIF ID f3,  "工厂

s_bklas FOR mbew-bklas MODIF ID f4 ,   ""评估分类
s_beskz FOR marc-beskz MODIF ID f4.   ""采购类型"


PARAMETERS p_q1 TYPE char1 AS CHECKBOX MODIF ID f6. "查询条目

PARAMETERS p_s1 TYPE char1 AS CHECKBOX  MODIF ID f1. "良品
PARAMETERS p_s2 TYPE char1 AS CHECKBOX MODIF ID f1. "不良品
PARAMETERS p_s3 TYPE char1 AS CHECKBOX  MODIF ID f1. "呆滞品

"PARAMETERS p_p1 TYPE char1 AS CHECKBOX DEFAULT 'X' MODIF ID f1. "更新

"PARAMETERS p_p2 TYPE char1 AS CHECKBOX  MODIF ID f1. "删除

PARAMETERS p_p3 TYPE char1 AS CHECKBOX  MODIF ID f1. "取前十

"PARAMETERS p_p4 TYPE char1 AS CHECKBOX  MODIF ID f5. "特殊

"PARAMETERS p2_var LIKE disvariant-variant MODIF ID f2 .   ""ALV表格布局变式

SELECTION-SCREEN END OF BLOCK b2.




*----------------------------------------------------------------------*
*                  初 始 化 块                                         *
*----------------------------------------------------------------------*
*该事件在屏幕未显示之前执行,对程式设置值及屏幕元素进行初始化赋值*
INITIALIZATION.


*----------------------------------------------------------------------*
*                  选 择 屏 幕 字 段 处 理 块
*----------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.


  LOOP AT SCREEN .
    IF p_1 IS NOT INITIAL.
      IF screen-group1 = 'F4' OR screen-group1 = 'F6' OR screen-group1 = 'F3' ."OR screen-group1 = 'F5'
        screen-active = 0 . "不活动,相当于隐藏
      ENDIF.
    ELSEIF p_2 IS NOT INITIAL.
      IF screen-group1 = 'F1' . "OR screen-group1 = 'F5'
        screen-active = 0 . "不活动,相当于隐藏
      ENDIF.
    ELSEIF p_3 IS NOT INITIAL.
      IF screen-group1 = 'F1' OR  screen-group1 = 'F2' OR screen-group1 = 'F4' OR screen-group1 = 'F6'.
        screen-active = 0 . "不活动,相当于隐藏
      ENDIF.
    ELSEIF p_4 IS NOT INITIAL.
      IF screen-group1 = 'F1' OR  screen-group1 = 'F2' OR screen-group1 = 'F4' .
        screen-active = 0 . "不活动,相当于隐藏
      ENDIF.
    ELSEIF p_7 IS NOT INITIAL  .
      IF screen-group1 = 'F0' OR screen-group1 = 'F1' OR  screen-group1 = 'F2' OR screen-group1 = 'F3' OR screen-group1 = 'F4' OR screen-group1 = 'F6'." OR screen-group1 = 'F5'
        screen-active = 0 . "不活动,相当于隐藏
      ENDIF.
    ELSE.
      IF screen-group1 = 'F1' OR  screen-group1 = 'F2' OR screen-group1 = 'F4' OR screen-group1 = 'F6'."  OR screen-group1 = 'F5'
        screen-active = 0 . "不活动,相当于隐藏
      ENDIF.
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.


*----------------------------------------------------------------------*
*                  逻 辑 处 理 块                                      *
*----------------------------------------------------------------------*

START-OF-SELECTION. "执行按钮后触发

  PERFORM frm_main.



*&---------------------------------------------------------------------*
*& Form FRM_MAIN
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_main.

  IF p_1 IS NOT INITIAL."LCM计算

    PERFORM frm_selection_check_p1. "屏幕检查

    PERFORM frm_authority_check. "检查权限

    "PERFORM get_suod. "程序锁定

    "IF p_p1 = 'X'.
    "分料号一个一个运行的方法

    PERFORM frm_delete_ztco0043b_lcm. "删除当前数据

    PERFORM frm_getdata_zcod0046d. "调用ZCOD0046D一个一个运行数据

    PERFORM frm_getdata_ztco0043b_lcm. "重新取数

*---------------------------------------------------------------------------*
    PERFORM frm_getdata_matnr_head_2. "成品料号 方法二

    "PERFORM frm_getdata_zcor0011. "ZCOR0011 进销存报表导出 (来源于ZCOD0046的找成本价的方法,其之一,并不全部正确)
    "例如:物料G1FAPJK242010-Z0Y 工厂 RMK0 年 2023 月 3 ,计算的成本价是负数

    "PERFORM frm_getdata_zcor0013. "ZCOR13MA 物料成本批量分析

    PERFORM frm_getdata_mbewh. "(来源于ZCOD0046的找成本价的方法,其之二,核对后与ZCOR13MA 物料成本批量分析是一样的)

    "PERFORM frm_getdata_zmmd0023c."有点类似于 ZMMD0023C 工单入库,但是用MB51去核对

    "PERFORM frm_getdata_calculate. "计算出库存料号对应的成品料号的入库数量

    PERFORM frm_getdata_zsdr0047. "ZSDR0047 出货明细查询报表
    "PERFORM frm_getdata_ztsdr0047. "直接取内表售价有些是对不上的

    PERFORM frm_getdata_zsdr0051_vbap."可以用“ZSDR0051 订单明细查询表”核对

    PERFORM frm_getdata_zsdr0051_vbkd."可以用“ZSDR0051 订单明细查询表”核对

    PERFORM frm_getdata_zsdr0048. "ZSDR0048 客户报价明细查询报表
    "PERFORM frm_getdata_ztsdr0048. "ZCOD0046 使用的方法,但有数据取不到

    PERFORM frm_getdata_zmmr1098_sell. "ZMMR1098 采购价格历史报表

    CLEAR:s_zmatnr,s_zwerks.
    REFRESH:s_zmatnr,s_zwerks.
*---------------------------------------------------------------------------*

    "PERFORM frm_report_1.

    PERFORM frm_getdata_ztco0043b_raw. "取数-原材料,不能下物料、工厂的条件

    PERFORM frm_getdata_matnr_raw_2. "原材料号 方法二

    PERFORM frm_getdata_ekpo. "采购价

    PERFORM frm_getdata_zmmr1098_buy. "ZMMR1098 采购价格历史报表

    PERFORM frm_getdata_mbewh_raw. "原材成本单价

    CLEAR:s_zmatnr,s_zwerks.
    REFRESH:s_zmatnr,s_zwerks.

    PERFORM frm_getdata_sale_rate. "取销售费用率,不要放到前面,如果跨年会报错,从而看不到前面的进度条
    " PERFORM frm_getdata_sales_expenses.  "大致是ZCOD0046 取销售费用的逻辑,在算C111时会错误

    PERFORM frm_report_2.

    PERFORM frm_update. "更新底表

    "PERFORM frm_jies.

*    ELSE. "一次性运行的方法
*
*      PERFORM frm_getdata_zcod0046. "取库存数量,ZCOD0046 LCM SLM查询报表
*
*      PERFORM frm_getdata_ztco0043b_bom. "取数-成品料号,不能下物料、工厂的条件
*
**---------------------------------------------------------------------------*
*      PERFORM frm_getdata_matnr_head_1. "成品料号 方法一
*
*      "PERFORM frm_getdata_zcor0011. "ZCOR0011 进销存报表导出 (来源于ZCOD0046的找成本价的方法,其之一,并不全部正确)
*      "例如:物料G1FAPJK242010-Z0Y 工厂 RMK0 年 2023 月 3 ,计算的成本价是负数
*
*      "PERFORM frm_getdata_zcor0013. "ZCOR13MA 物料成本批量分析
*
*      PERFORM frm_getdata_mbewh. "(来源于ZCOD0046的找成本价的方法,其之二,核对后与ZCOR13MA 物料成本批量分析是一样的)
*
*      PERFORM frm_getdata_zmmd0023c."有点类似于 ZMMD0023C 工单入库,但是用MB51去核对
*
*      PERFORM frm_getdata_calculate. "计算出库存料号对应的成品料号的入库数量
*
*      PERFORM frm_getdata_zsdr0047. "ZSDR0047 出货明细查询报表
*      "PERFORM frm_getdata_ztsdr0047. "直接取内表售价有些是对不上的
*
*      PERFORM frm_getdata_zsdr0051_vbap."可以用“ZSDR0051 订单明细查询表”核对
*
*      PERFORM frm_getdata_zsdr0051_vbkd."可以用“ZSDR0051 订单明细查询表”核对
*
*      PERFORM frm_getdata_zsdr0048. "ZSDR0048 客户报价明细查询报表
*      "PERFORM frm_getdata_ztsdr0048. "ZCOD0046 使用的方法,但有数据取不到
*
*      PERFORM frm_getdata_zmmr1098_sell. "ZMMR1098 采购价格历史报表
*
*      CLEAR:s_zmatnr,s_zwerks.
*      REFRESH:s_zmatnr,s_zwerks.
**---------------------------------------------------------------------------*
*
*      PERFORM frm_report_1.
*
*      PERFORM frm_getdata_sale_rate. "取销售费用率,不要放到前面,如果跨年会报错,从而看不到前面的进度条
*      " PERFORM frm_getdata_sales_expenses.  "大致是ZCOD0046 取销售费用的逻辑,在算C111时会错误
*
*      PERFORM frm_getdata_ztco0043b_raw. "取数-原材料,不能下物料、工厂的条件
*
*      PERFORM frm_getdata_matnr_raw_1. "原材料号 方法一
*
*      PERFORM frm_getdata_ekpo. "采购价
*
*      PERFORM frm_getdata_zmmr1098_buy. "ZMMR1098 采购价格历史报表
*
*      PERFORM frm_getdata_mbewh_raw. "原材成本单价
*
*      CLEAR:s_zmatnr,s_zwerks.
*      REFRESH:s_zmatnr,s_zwerks.
*
*      PERFORM frm_report_2.
*
*      "PERFORM frm_alv_event.  "事件
*      PERFORM frm_alv_layout. "布局
*      PERFORM frm_alv_fieldcat. "列
*      PERFORM frm_alv_output_lcm. "输出
*    ENDIF.

  ELSEIF p_2 IS NOT INITIAL. "LCM显示

    PERFORM frm_selection_check_p2. "屏幕检查
    PERFORM frm_authority_check. "检查权限

    IF p_q1 = 'X'.
      PERFORM frm_getdata_ztco0043b_lcm_n. "条目
    ELSE.
      PERFORM frm_getdata_ztco0043b_lcm_alv. "取数

      "PERFORM frm_alv_event.  "事件
      PERFORM frm_alv_layout. "布局
      PERFORM frm_alv_fieldcat. "列

      IF gt_ztco0043b_lcm IS NOT INITIAL. "新表没数据就取旧表
        PERFORM frm_alv_output_lcm. "输出
      ELSEIF gt_ztco0043b_item IS NOT INITIAL.
        PERFORM frm_alv_output_item. "输出
      ELSE.
        MESSAGE s000 WITH '没有数据!' DISPLAY LIKE 'E'.
      ENDIF.
    ENDIF.

  ELSEIF p_3 IS NOT INITIAL."成品料计算

    PERFORM frm_selection_check_p3. "屏幕检查
    PERFORM frm_authority_check. "检查权限

    PERFORM frm_getdata_zcod0046_bom. "取库存数量,ZCOD0046 LCM SLM查询报表

    PERFORM frm_getdata_zcod0046c. "取跨工厂数据

    PERFORM frm_getdata_zcor0055. "类似于 ZCOR0055 批量反查BOM

    IF lv_recursion IS NOT INITIAL.
      MESSAGE s000 WITH '有料号出现成本阶异常!请查询“ZCOR0055 批量反查BOM”的“成本阶”是“100”的“料号”!' DISPLAY LIKE 'W'.
    ENDIF.

    PERFORM frm_update_ztco0043b_bom. "更新底表

  ELSEIF p_4 IS NOT INITIAL.

    PERFORM frm_selection_check_p3. "屏幕检查
    PERFORM frm_authority_check. "检查权限

    IF p_q1 = 'X'.
      PERFORM frm_getdata_ztco0043b_bom_n. "条目
    ELSE.

      PERFORM frm_getdata2_ztco0043b_bom. "取数,"要下物料、工厂的条件
      PERFORM frm_alv_layout. "布局
      PERFORM frm_alv_fieldcat_bom. "列
      PERFORM frm_alv_output_bom. "输出
    ENDIF.

  ELSEIF p_5 IS NOT INITIAL. "原料计算

    PERFORM frm_selection_check_p3. "屏幕检查
    PERFORM frm_authority_check. "检查权限
    PERFORM frm_getdata_zcod0046_raw.

  ELSEIF p_6 IS NOT INITIAL."原料显示


    PERFORM frm_selection_check_p3. "屏幕检查
    PERFORM frm_authority_check. "检查权限

    PERFORM frm_getdata2_ztco0043b_raw. "取数,要下物料、工厂的条件

    PERFORM frm_alv_layout. "布局
    PERFORM frm_alv_fieldcat_raw. "列
    PERFORM frm_alv_output_raw. "输出

  ELSEIF p_7 IS NOT INITIAL.
    SUBMIT zcod0046c VIA SELECTION-SCREEN.

  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      FORM  getaction
*&---------------------------------------------------------------------*
*       处理用户权限
*----------------------------------------------------------------------*
FORM frm_authority_check.
  DATA:BEGIN OF lt_bukrs OCCURS 0,
         bukrs LIKE t001-bukrs,
       END OF lt_bukrs.

  SELECT bukrs INTO CORRESPONDING FIELDS OF TABLE lt_bukrs FROM t001 WHERE bukrs = p_bukrs.
  LOOP AT lt_bukrs.
    AUTHORITY-CHECK OBJECT  'F_SKA1_BUK'
    ID 'BUKRS' FIELD lt_bukrs-bukrs."检查字段
    IF sy-subrc <> 0.
      MESSAGE s021 WITH lt_bukrs-bukrs DISPLAY LIKE 'E'.
      LEAVE LIST-PROCESSING.
    ENDIF.
  ENDLOOP.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form GET_SUOD
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM get_suod .


  CALL FUNCTION 'ENQUEUE_ES_PROG'
    EXPORTING
      mode_trdir     = 'E'
      name           = 'ZCOD0046B'
*     x_name         =
*     _SCOPE         = '2'
*     _WAIT          = ' '
*     _COLLECT       = ' '
    EXCEPTIONS
      foreign_lock   = 1
      system_failure = 2
      OTHERS         = 3.
*  IF sy-subrc <> 0.
* Implement suitable error handling here
*  ENDIF.

  IF sy-subrc <> 0.
    MESSAGE '程序已被' && sy-uname && '锁定,请稍后执行' TYPE 'E'.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_JIES
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_jies .
  CALL FUNCTION 'DEQUEUE_ES_PROG'
    EXPORTING
      mode_trdir = 'E'
      name       = 'ZCOD0046B'
*     X_NAME     = ' '
*     _SCOPE     = '3'
*     _SYNCHRON  = ' '
*     _COLLECT   = ' '
    .

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_SELECTION_CHECK_P3
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_selection_check_p3 .

  IF p_bukrs IS INITIAL.
    MESSAGE s000 WITH '“公司代码”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pn_gjahr IS INITIAL.
    MESSAGE s000 WITH '“当前年份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pn_monat IS INITIAL.
    MESSAGE s000 WITH '“当前月份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

*  IF s_matnr IS INITIAL.
*    MESSAGE s000 WITH '“物料编号”为空!' DISPLAY LIKE 'E'.
*    LEAVE LIST-PROCESSING.
*  ENDIF.
*
*  IF s_werks IS INITIAL.
*    MESSAGE s000 WITH '“工厂”为空!' DISPLAY LIKE 'E'.
*    LEAVE LIST-PROCESSING.
*  ENDIF.

  lv_nrq = pn_gjahr && pn_monat.
  lv_ndate1 = pn_gjahr && pn_monat && '01'.

  "获取当前期末日期
  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = lv_ndate1
    IMPORTING
      last_day_of_month = lv_ndate2.

  CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      date      = lv_ndate1
      days      = '00'
      months    = '01'
      signum    = '-'
      years     = '03'
    IMPORTING
      calc_date = lv_del_date.

  lv_del_gjahr = lv_del_date+0(4).
  lv_del_monat = lv_del_date+4(2).


ENDFORM.



*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOD0046
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcod0046 .


  "事实上进销存和库龄报表逻辑是不一致的,建议进销存和SAP标准库存报表/进销存报表比对
  "料号:G1CMM028089A-N,工厂:0511,CKM3N对不上ZCOR0013 库龄报表,可以对上ZCOR0011 进销存月报。
  "物料凭证4904092666,107 评估冻结库存的收货,没有库存地点,还需要进行 109 冻结库存评估的收货 ,库龄报表不会获取没有库存地点的料号的数量

  "注意:LCM的数量来源于SLM,金额不来源于,料号单价来源于进销存
  SELECT
      ztco0043_slm~lfgja AS zn_gjahr,                  ""当前年度
      ztco0043_slm~lfmon AS zn_monat,                  ""当前月份
      @pf_gjahr AS zf_gjahr,                           ""未来年度
      @pf_monat AS zf_monat,                           ""未来月份
      ztco0043_slm~bukrs,                             ""公司代码
      ztco0043_slm~werks,                             ""工厂
      ztco0043_slm~matnr,                             ""物料编号
      ztco0043_slm~bklas,                             ""评估分类
      ztco0043_slm~beskz,                             ""采购类型
      ztco0043_slm~totqty AS zqm01_qty,               ""库存数量
      ztco0043_slm~salk3 AS zqm02_amount,             ""成本金额
      ztco0043_slm~maktx,                             ""物料描述
      ztco0043_slm~lgort,                             ""库存地点
      ztco0043_slm~lgobe,                             ""库存地点描述
      ztco0043_slm~lgort_p,                           ""仓库属性
      ztco0043_slm~charg,                             ""批次
      ztco0043_slm~hsdat,                             ""批号生成日期"
      mara~prdha,                                     ""产品层次
      ztco0043_slm~zcmcc,                             ""机种
      ztco0043_slm~prctr,                             ""利润中心
      ztco0043_slm~dull_month,                        ""呆滞月份
      ztco0043_slm~stday                             ""库龄天数"
  FROM ztco0043_slm
    LEFT JOIN mara AS mara ON mara~matnr = ztco0043_slm~matnr
  WHERE bukrs = @p_bukrs
    AND lfgja = @pn_gjahr "当前年度
    AND lfmon = @pn_monat "当前月份
    AND ztco0043_slm~matnr IN @s_matnr "物料
    AND ztco0043_slm~werks IN @s_werks "工厂
    AND substring( werks, 1, 2 ) <> 'NV'
    "AND bklas IN ('3000','7900','7920')
    AND lgort_p IN  @s_lgort_p
  INTO CORRESPONDING FIELDS OF TABLE @gt_lcm1.

  "没有满足条件的数据,提示信息并终止程序
  IF gt_lcm1 IS INITIAL.
    MESSAGE s000 WITH TEXT-c00 DISPLAY LIKE 'E'. "“ZCOD0046 LCM SLM查询报表”没有数据!
    LEAVE LIST-PROCESSING.
  ENDIF.


  "物料编号 工厂 库存地点 批次
  SORT gt_lcm1 BY matnr werks lgort charg.

  LOOP AT gt_lcm1 INTO gs_lcm1.
    gs_mara1-werks = gs_lcm1-werks.                        ""工厂
    gs_mara1-matnr = gs_lcm1-matnr.                        ""物料编号
    gs_mara1-zqm01_qty = gs_lcm1-zqm01_qty.                ""库存数量
    gs_mara1-zqm02_amount = gs_lcm1-zqm02_amount.          ""成本金额"
    COLLECT gs_mara1 INTO gt_mara1.
  ENDLOOP.
  CLEAR:gs_lcm1,gs_mara1.

  SORT gt_mara1 BY werks matnr.


  LOOP AT gt_lcm1 INTO gs_lcm1.
    "按理说,如果期末库存金额对应的单价是一样的,可以用这种方法
    "    IF gs_lcm1-zqm01_qty <> 0 . ""库存数量 不等于零
    "      gs_lcm1-zqm01_amount = gs_lcm1-zqm02_amount / gs_lcm1-zqm01_qty.          ""料件成本单价 = 成本金额" /  库存数量
    "    ELSE.
    "      gs_lcm1-zqm01_amount = 0.
    "    ENDIF.
    "    MODIFY gt_lcm1 FROM gs_lcm1 TRANSPORTING zqm01_amount.

    READ TABLE gt_mara1 INTO gs_mara1 WITH KEY werks = gs_lcm1-werks          ""工厂
                                               matnr = gs_lcm1-matnr          ""物料编号
                                               BINARY SEARCH."
    IF sy-subrc = 0.
      IF gs_mara1-zqm01_qty <> 0 . ""期末数量 不等于零
        gs_lcm1-zqm01_amount = gs_mara1-zqm02_amount / gs_mara1-zqm01_qty.          ""料件成本单价 = 期末金额" /  期末数量
        "按照现有的单价保留两位数的逻辑,金额是乘不回去的
        "gs_lcm1-zqm02_amount = gs_lcm1-zqm01_qty * gs_lcm1-zqm01_amount.                   ""成本金额 = 库存数量 *  料件成本单价
        MODIFY gt_lcm1 FROM gs_lcm1 TRANSPORTING zqm01_amount.
      ENDIF.
    ENDIF.

    IF ( gs_lcm1-bklas = '7920' AND gs_lcm1-beskz <> 'F' ) OR gs_lcm1-bklas = '3061' . "废料也用成品料号的逻辑计算
      gs_lcm1-werks_head = gs_lcm1-werks.          ""成品料号的工厂
      gs_lcm1-matnr_head = gs_lcm1-matnr.          ""成品料号
      MODIFY gt_lcm1 FROM gs_lcm1 TRANSPORTING werks_head matnr_head.
    ENDIF.

  ENDLOOP.
  CLEAR:gs_lcm1,gs_mara1.
  CLEAR gt_mara1.
  lv_n = 0.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0055.



  TYPES:BEGIN OF ty_mbew,
          matnr TYPE matnr,            ""物料编号
          werks TYPE werks_d,          ""工厂
          bklas TYPE bklas,            ""评估类
        END OF ty_mbew.

  DATA: gt_mbew TYPE TABLE OF ty_mbew,
        gs_mbew TYPE ty_mbew.


  IF gt_lcm1 IS INITIAL.
    RETURN.
  ENDIF.

  "取库存料号的存货部分,不筛选,默认都要
  LOOP AT gt_lcm1 INTO gs_lcm1.
    gs_marc-matnr = gs_lcm1-matnr.          ""物料
    gs_marc-werks = gs_lcm1-werks.           ""工厂
    COLLECT gs_marc INTO gt_marc.
  ENDLOOP.
  CLEAR:gs_lcm1,gs_marc.

  IF gt_marc IS INITIAL.
    RETURN.
  ENDIF.

  lv_ztime = sy-uzeit.
  lv_str = |{ lv_ztime+0(2) }:{ lv_ztime+2(2) }:{ lv_ztime+4(2) }|.

  LOOP AT gt_marc INTO gs_marc.
    gs_stpov-zmatnr = gs_marc-matnr.          ""查询的物料
    gs_stpov-zwerks = gs_marc-werks.          ""查询的工厂
    gs_stpov-dstuf = 1.                       ""成本阶
    gs_stpov-werks = gs_marc-werks.           ""工厂
    gs_stpov-matnr = gs_marc-matnr.           ""物料编号
    gs_stpov-idnrk = gs_marc-matnr.           ""BOM组件
    gs_stpov-qpa1 = 1.                       ""单层QPA
    gs_stpov-ewahr = 1.                       ""以百分比表示的使用概率(备选项目)
    "APPEND gs_stpov TO gt_stpov.
    APPEND gs_stpov TO lt_stpov2.

    gs_dstuf-matnr  = gs_marc-matnr. "初始查询料号
    gs_dstuf-werks = gs_marc-werks.  ""初始查询工厂
    gs_dstuf-dstuf =  1.             "成本阶
    APPEND gs_dstuf TO gt_dstuf.

    "IF gs_marc-matnr = '099-37378AN001A-N' AND gs_marc-werks = 'RMK2'.
    "  BREAK-POINT.  "测试使用
    "ENDIF.

    lv_line  = lv_line + 1.
    lv_result = ( lv_line - 1 ) * 100 / lines( gt_marc ).
    lv_restex = lv_result.
    lv_stxt =  |开始时间:{ lv_str }  第{ lv_line },共{ lines( gt_marc ) }  进度:{ lv_restex } %   料号:{ gs_marc-matnr } 工厂:{ gs_marc-werks }  |.

    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        percentage = lv_result
        text       = lv_stxt.

    PERFORM frm_getdata_zcor0055_bom USING gs_marc. "未实现,并没有优化成本价gt_dstuf 跨工厂的取值
    PERFORM frm_getdata_zcor0055_dstuf.
    PERFORM frm_getdata_zcor0055_qpa2.

    CLEAR:gt_dstuf,lt_marc2. "必要的,避免数据冗余查找

  ENDLOOP.
  CLEAR:wa_marc1,wa_marc2,lt_marc1,lt_marc2,gt_marc,gs_marc,gs_stpov,lt_stpov1,gs_dstuf,lt_dstuf,gt_dstuf.
  CLEAR:gs_matnrs,gt_matnrs,gt_zmatnrs,gt_zmatnrs[].

  lv_line = 0.

  IF gt_stpov_fin IS INITIAL.
    RETURN. "说明没有找到任何BOM
  ENDIF.



  SELECT
      mbew~matnr,           ""物料编号
      mbew~bwkey AS werks,  ""工厂
      mbew~bklas            ""评估类
  FROM mbew
    FOR ALL ENTRIES IN @gt_stpov_fin
 WHERE matnr = @gt_stpov_fin-matnr
   AND bwkey = @gt_stpov_fin-werks
   "AND mbew~bklas = '7920' "只要成品料号
 INTO CORRESPONDING FIELDS OF TABLE @gt_mbew.

  IF gt_mbew IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt_mbew BY matnr werks.

  LOOP AT gt_stpov_fin INTO gs_stpov.
    READ TABLE gt_mbew INTO gs_mbew WITH KEY matnr = gs_stpov-matnr            ""物料编号
                                             werks = gs_stpov-werks            ""工厂
                                             BINARY SEARCH.
    IF sy-subrc = 0.
      IF gs_mbew-bklas = '7900'  OR  gs_mbew-bklas = '7920'.
        APPEND gs_stpov TO lt_stpov1.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_stpov,wa_stpov,gs_mbew,gt_stpov_fin,gt_mbew.

  IF lt_stpov1 IS INITIAL.
    RETURN.
  ENDIF.

  SORT lt_stpov1 BY zmatnr zwerks erfmg1 matnr werks.


ENDFORM.


*&---------------------------------------------------------------------*
*& Form frm_getdata_zcor0055_bom
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> GS_MARC
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0055_bom  USING ls_marc TYPE ty_marc.

  TYPES: BEGIN OF f_ty_marc,
           matnr TYPE matnr,            ""物料
           werks TYPE werks_d,          ""工厂
         END OF f_ty_marc.

  DATA  zgt_matnr TYPE TABLE OF  f_ty_marc.

  DATA  qs_marc TYPE  ty_marc. "临时加的

  DATA lv_isfillin TYPE c. "判断是否填写数据


  "函数的必输参数,虽然有返回值但是没用上。
  DATA:lt_equicat TYPE TABLE OF cscequi,
       lt_kndcat  TYPE TABLE OF cscknd,
       lt_matcat  TYPE TABLE OF cscmat,
       lt_stdcat  TYPE TABLE OF cscstd,
       lt_tplcat  TYPE TABLE OF csctpl,
       lt_prjcat  TYPE TABLE OF cscprj,
       gt_topmat  TYPE TABLE OF mc29s.

  DATA BEGIN OF g_topmat OCCURS 0.
  INCLUDE STRUCTURE mc29s.
  DATA END OF g_topmat.

  "函数输出的内表数据添加些字段方便计算-与ZCOR0055不同
  DATA: lt_wultb TYPE TABLE OF stpov,
        gs_wultb TYPE stpov.


  "STLTY  物料清单类别        M    内表筛选        来源STKO表   M表示物料BOM
  "STLST  物料清单状态        1    内表筛选         " 1 是激活状态 "CS03 显示物料 BOM >> 抬头 >> 物料清单状态
  "STLAN  物料清单用途        1    取消函数写入    “OS20:BOM 用途  1:生产”  例如: 646-00721-069-N  0512 属于 2:工程/设计
  "POSTP  项目类别(物料单)  L    函数写入        来源STPO表的POSTP项目类别(物料单)  L 表示库存项目
  "STALT  备选物料清单       一般是空的,据了解没有用到
  "DELETE lt_wultb WHERE stlty <> 'M' OR  stlst <> '1'. "删除 物料清单类别 & 物料清单状态


  CALL FUNCTION 'CS_WHERE_USED_MAT'
    EXPORTING
      datub                      = lv_datub       "有效期限
      datuv                      = lv_ndate2        "生效日期:当前的期末日期
      matnr                      = ls_marc-matnr  "物料编号
      postp                      = lv_postp       "条目类别
      stlan                      = lv_stlan       "物料清单用途
      werks                      = ls_marc-werks  "工厂
    IMPORTING
      topmat                     = g_topmat
    TABLES
      wultb                      = lt_wultb
      equicat                    = lt_equicat
      kndcat                     = lt_kndcat
      matcat                     = lt_matcat
      stdcat                     = lt_stdcat
      tplcat                     = lt_tplcat
      prjcat                     = lt_prjcat
    EXCEPTIONS
      call_invalid               = 1
      material_not_found         = 2
      no_where_used_rec_found    = 3
      no_where_used_rec_selected = 4
      no_where_used_rec_valid    = 5
      OTHERS                     = 6.

  "存在一料多阶的情况
  "151-18A-0002-N >> 817-07178ZS001A-N >> 817-07178PS001A-N >> 613-22275ST028A-N >> G1CMM038402A-N
  "151-18A-0002-N >> 817-07301ZS002A-N >> 817-07301PS002A-N >> G1CMM038402A-N

  "0511
  "151-18A-0002-N >> 817-05839ZS002A-N >> 817-05839PS002A-N >> 613-19556LW001A-N >> 613-19556ST001A-N >> 677-25606AS002A-N >> 677-25606PB006A-N >> 677-25606CE008A-N >> G1CMM028092A-N  0.000218
  "151-18A-0002-N >> 817-06298ZS002A-N >> 817-06298PS001A-N >>                                                                677-25606PB006A-N >> 677-25606CE008A-N >> G1CMM028092A-N  0.000131
  "151-18A-0002-N >> 817-06298ZS003A-N >> 817-06298PS003A-N >>                                                                677-25606PB006A-N >> 677-25606CE008A-N >> G1CMM028092A-N  0.000135
  "151-18A-0002-N >> 817-07024ZS001A-N >> 817-07024PS001A-N >>                                                                677-25606PB006A-N >> 677-25606CE008A-N >> G1CMM028092A-N  0.000164


  IF lt_wultb IS INITIAL.

    SORT gt_dstuf BY matnr werks. "每次还是要排序

    lv_isfillin = ''.

    IF gt1_ztco0046c IS INITIAL AND gt2_ztco0046c IS INITIAL. "不跨工厂直接取值

      lv_isfillin = 'X'. "确实写入成品料号

    ELSE."跨工厂取值逻辑

      "ztco0046c 数据分开主要是为了区分优先级,物料工厂对应的转出工厂 优先级 要高于  工厂对应的转出工厂,以免二者冲突时计算混淆

      READ TABLE gtz1_ztco0046c INTO DATA(gsz1_ztco0046c) WITH KEY matnr = ls_marc-matnr          ""本次查询的物料
                                                                   werk1 = ls_marc-werks          ""本次查询的工厂
                                                                   BINARY SEARCH."
      IF sy-subrc = 0 .

        LOOP AT gsz1_ztco0046c-datas INTO gs1_ztco0046c.

          SELECT
               marc~matnr,           ""物料编号
               marc~werks           ""工厂
          FROM marc
            WHERE marc~matnr = @ls_marc-matnr
              AND marc~werks = @gs1_ztco0046c-werk2 "转出工厂 要在marc表有值
          INTO TABLE @zgt_matnr. "CORRESPONDING FIELDS OF

          IF sy-subrc = 0 .

            READ TABLE gt_dstuf INTO gs_dstuf WITH KEY matnr = ls_marc-matnr           ""物料编号
                                                       werks = gs1_ztco0046c-werk2     ""转出工厂
                                                       BINARY SEARCH."
            IF sy-subrc = 0.
              lv_isfillin = 'X'. "确实写入成品料号
            ELSE.

              "补物料料号对应的转出工厂 的 成本阶
              READ TABLE gt_dstuf INTO wa_dstuf WITH KEY matnr = ls_marc-matnr           ""物料编号
                                                         werks = ls_marc-werks          ""本次查询的工厂
                                                         BINARY SEARCH."
              IF sy-subrc = 0.
                ls_dstuf-dstuf = wa_dstuf-dstuf + 1.     "成本阶
                ls_dstuf-matnr = ls_marc-matnr.           ""物料编号
                ls_dstuf-werks = gs1_ztco0046c-werk2.     "转出工厂
                APPEND ls_dstuf TO gt_dstuf. "

                wa_stpov-zmatnr = gs_marc-matnr.          ""真正的查询 物料编号 ,不是ls_marc
                wa_stpov-zwerks = gs_marc-werks.          ""真正的查询 工厂 ,不是ls_marc
                wa_stpov-dstuf = wa_dstuf-dstuf + 1.      "成本阶
                wa_stpov-matnr = ls_marc-matnr.           ""物料编号
                wa_stpov-werks = gs1_ztco0046c-werk2.     "转出工厂
                wa_stpov-idnrk = ls_marc-matnr.             ""BOM组件
                wa_stpov-idnrk_werks = ls_marc-werks.       ""本次查询的工厂
                wa_stpov-qpa1 = 1.                       ""单层QPA
                wa_stpov-ewahr = 1.                       ""以百分比表示的使用概率(备选项目)
                "APPEND wa_stpov TO gt_stpov.
                APPEND wa_stpov TO lt_stpov2.
              ENDIF.
              CLEAR:wa_stpov,ls_dstuf,wa_stpov.

              "继续查BOM
              qs_marc-matnr = ls_marc-matnr .
              qs_marc-werks = gs1_ztco0046c-werk2."转出工厂
              PERFORM frm_getdata_zcor0055_bom USING qs_marc. "对转出工厂继续去取BOM
            ENDIF.

          ELSE. "没查到说明这个料号对应的工厂没有建,就不用取BOM
            lv_isfillin = 'X'. "确实写入成品料号
          ENDIF.

        ENDLOOP.
        CLEAR gs1_ztco0046c.

      ELSE. "如果物料、工厂没有维护的话,就只判断工厂

        "例如:C116   半品工厂 ML10    成品工厂 ML00
        READ TABLE gtz2_ztco0046c INTO DATA(gsz2_ztco0046c) WITH KEY werk1 = ls_marc-werks          ""本次查询的工厂 要等于 转入工厂
                                                                     BINARY SEARCH."
        IF sy-subrc = 0 .

          LOOP AT gsz2_ztco0046c-datas INTO gs2_ztco0046c.

            SELECT
                 marc~matnr,           ""物料编号
                 marc~werks           ""工厂
            FROM marc
              WHERE marc~matnr = @ls_marc-matnr
                AND marc~werks = @gs2_ztco0046c-werk2 "转出工厂 要在marc表有值
            INTO TABLE @zgt_matnr." CORRESPONDING FIELDS OF

            IF sy-subrc = 0.

              READ TABLE gt_dstuf INTO gs_dstuf WITH KEY matnr = ls_marc-matnr           ""物料编号
                                                         werks = gs2_ztco0046c-werk2     ""转出工厂
                                                         BINARY SEARCH."
              IF sy-subrc = 0.
                lv_isfillin = 'X'. "确实写入成品料号
              ELSE.

                "补物料料号对应的转出工厂 的 成本阶
                READ TABLE gt_dstuf INTO wa_dstuf WITH KEY matnr = ls_marc-matnr           ""物料编号
                                                           werks = ls_marc-werks          ""本次查询的工厂
                                                           BINARY SEARCH."
                IF sy-subrc = 0.
                  ls_dstuf-dstuf = wa_dstuf-dstuf + 1.     "成本阶
                  ls_dstuf-matnr = ls_marc-matnr.           ""物料编号
                  ls_dstuf-werks = gs2_ztco0046c-werk2.     "转出工厂(有区别)
                  APPEND ls_dstuf TO gt_dstuf. "

                  wa_stpov-zmatnr = gs_marc-matnr.          ""真正的查询 物料编号 ,不是ls_marc
                  wa_stpov-zwerks = gs_marc-werks.          ""真正的查询 工厂 ,不是ls_marc
                  wa_stpov-dstuf = wa_dstuf-dstuf + 1.      "成本阶
                  wa_stpov-matnr = ls_marc-matnr.           ""物料编号
                  wa_stpov-werks = gs2_ztco0046c-werk2.     "转出工厂(有区别)
                  wa_stpov-idnrk = ls_marc-matnr.             ""BOM组件
                  wa_stpov-idnrk_werks = ls_marc-werks.       ""本次查询的工厂
                  wa_stpov-qpa1 = 1.                       ""单层QPA
                  wa_stpov-ewahr = 1.                       ""以百分比表示的使用概率(备选项目)
                  "APPEND wa_stpov TO gt_stpov.
                  APPEND wa_stpov TO lt_stpov2.
                ENDIF.
                CLEAR:wa_stpov,ls_dstuf,wa_stpov.

                qs_marc-matnr = ls_marc-matnr .
                qs_marc-werks = gs2_ztco0046c-werk2."转出工厂
                PERFORM frm_getdata_zcor0055_bom USING qs_marc. "对转出工厂继续去取BOM
              ENDIF.

            ELSE. "没查到说明这个料号对应的工厂没有建,就不用取BOM
              lv_isfillin = 'X'. "确实写入成品料号
            ENDIF.

          ENDLOOP.
          CLEAR gs2_ztco0046c.


        ELSE.
          lv_isfillin = 'X'. "确实写入成品料号
        ENDIF.

      ENDIF.

    ENDIF.
    CLEAR:gs1_ztco0046c,gs2_ztco0046c,gsz1_ztco0046c,gsz2_ztco0046c,qs_marc,zgt_matnr,gs_dstuf.

    IF lv_isfillin = 'X'.
      "填写最后的成品料号
      gs_stpov-zmatnr = gs_marc-matnr.            "真正的查询 物料编号 ,不是ls_marc
      gs_stpov-zwerks = gs_marc-werks.            "真正的查询 工厂 ,不是ls_marc
      gs_stpov-matnr = ls_marc-matnr.            ""本次查询的物料
      gs_stpov-werks = ls_marc-werks.            ""本次查询的工厂
      APPEND gs_stpov TO lt_stpov_fin.
      CLEAR gs_stpov.
    ENDIF.

    lv_isfillin = ''.



  ELSE.


    "筛选查到的BOM料号
    LOOP AT lt_wultb INTO gs_wultb.
      IF gs_wultb-stlty = 'M' AND  gs_wultb-stlst =  '1'. "物料清单类别 & 物料清单状态
        gs_stpov-zmatnr = gs_marc-matnr.            "真正的查询 物料编号 ,不是ls_marc
        gs_stpov-zwerks = gs_marc-werks.            "真正的查询 工厂 ,不是ls_marc
        gs_stpov-werks = gs_wultb-werks.            ""函数输出的 工厂
        gs_stpov-matnr = gs_wultb-matnr.            ""函数输出的 物料编号
        "gs_stpov-bmeng = gs_wultb-bmeng.            ""基本数量
        gs_stpov-idnrk = gs_wultb-idnrk.            ""BOM组件
        "gs_stpov-menge = gs_wultb-menge.            ""组件数量
        gs_stpov-alpgr1 = gs_wultb-alpgr.            ""替代项目:组
        gs_stpov-qpa1 =  gs_wultb-menge / gs_wultb-bmeng.  ""单层QPA
        gs_stpov-ewahr = gs_wultb-ewahr.            ""以百分比表示的使用概率(备选项目)
        "gs_stpov-stlnr = gs_wultb-stlnr.            ""物料清单
        "gs_stpov-datuv = gs_wultb-datuv.            ""有效起始日期
        "gs_stpov-datub = gs_wultb-datub.            ""有效截止日期
        "gs_stpov-posnr = gs_wultb-posnr.            ""BOM项目号
        "gs_stpov-ttidx = gs_wultb-ttidx.            ""在类别表内的索引
        "gs_stpov-alpgr3 = gs_wultb-alpgr.            ""替代项目:组(补充)
        APPEND gs_stpov TO lt_stpov1.
      ENDIF.
    ENDLOOP.
    CLEAR:lt_wultb,gs_wultb,gs_stpov.

    "对查到的料号构造对应关系:查询料号对应BOM主件料号
    LOOP AT lt_stpov1 INTO gs_stpov.
      gs_matnrs-matnr = ls_marc-matnr.            ""当前查询的物料
      gs_matnrs-werks = ls_marc-werks.            ""当前查询的工厂
      gs_matnrs-matnrs = gs_stpov-matnr.          ""BOM主件物料"
      gs_matnrs-werkss = gs_stpov-werks.          ""BOM主件物料的工厂
      COLLECT gs_matnrs INTO gt_matnrs.
    ENDLOOP.
    CLEAR:gs_stpov,gs_matnrs.

    SORT gt_matnrs BY matnr werks matnrs werkss.

    LOOP AT gt_matnrs INTO gs_matnrs
         GROUP BY ( matnr = gs_matnrs-matnr werks = gs_matnrs-werks )
                  ASCENDING ASSIGNING FIELD-SYMBOL(<group_matnrs>).
      LOOP AT GROUP <group_matnrs> ASSIGNING FIELD-SYMBOL(<fs_matnrs>).
        gt_zmatnrs-matnr = <fs_matnrs>-matnr.
        gt_zmatnrs-werks = <fs_matnrs>-werks.
        APPEND <fs_matnrs> TO gt_zmatnrs-matnrs.
      ENDLOOP.
      APPEND gt_zmatnrs.
      CLEAR gt_zmatnrs. "是清除工作区,不是内表
    ENDLOOP.
    CLEAR:gs_matnrs,gt_matnrs.

    "考虑了BOM组件对应多个不同料号的情况,但是没有考虑对应相同料号的情况
    SORT gt_dstuf BY matnr werks. "考虑:跨工厂

    READ TABLE gt_dstuf INTO gs_dstuf WITH KEY matnr = ls_marc-matnr  "查询:本次查询的物料
                                               werks = ls_marc-werks  "查询:本次查询的工厂
                                               BINARY SEARCH.
    IF sy-subrc = 0.
      LOOP AT lt_stpov1 INTO gs_stpov.
        ls_dstuf-dstuf = gs_dstuf-dstuf + 1. "成本阶

        READ TABLE gt_dstuf INTO wa_dstuf WITH KEY matnr = gs_stpov-matnr  "查询:函数输出的物料
                                                   werks = gs_stpov-werks  "查询:函数输出的工厂
                                                   BINARY SEARCH.
        IF sy-subrc = 0.
          IF ls_dstuf-dstuf > wa_dstuf-dstuf. "只有大于的需要改成本阶
            MODIFY gt_dstuf FROM ls_dstuf TRANSPORTING dstuf WHERE matnr = gs_stpov-matnr
                                                               AND werks = gs_stpov-werks.
            PERFORM frm_getdata_zcor0055_matnrs USING gs_stpov-matnr gs_stpov-werks ls_dstuf-dstuf.
          ENDIF.
        ELSE.
          "成本阶一旦被修改说明不需要再去查了
          wa_marc1-zmatnr  = gs_marc-matnr. "真正的查询 物料编号 ,不是ls_marc
          wa_marc1-zwerks  = gs_marc-werks. "真正的查询 工厂 ,不是ls_marc
          wa_marc1-matnr  = gs_stpov-matnr. "函数输出的 物料编号
          wa_marc1-werks  = gs_stpov-werks. "函数输出的 工厂
          COLLECT wa_marc1 INTO lt_marc1.

          ls_dstuf-matnr = gs_stpov-matnr. "函数输出的 物料编号
          ls_dstuf-werks = gs_stpov-werks. "函数输出的 工厂
          APPEND ls_dstuf TO lt_dstuf. "不能是gt_dstuf,否则用BINARY SEARCH有可能查不到数据
        ENDIF.

        IF gs_dstuf-alpgr3 IS NOT INITIAL. "不是wa_dstuf-alpgr3,要继承上阶的替代组
          "替代项目:组(补充)
          MODIFY lt_dstuf FROM gs_dstuf TRANSPORTING alpgr3 WHERE matnr = gs_stpov-matnr
                                                              AND werks = gs_stpov-werks.
        ENDIF.

        "IF gs_marc-matnr = gs_stpov-idnrk  AND gs_marc-werks = gs_stpov-werks. "真正的查询 物料编号 ,不是ls_marc
        " IF gs_stpov-alpgr3 IS NOT INITIAL.
        "   ls_dstuf-alpgr3 = gs_stpov-alpgr3.
        "   MODIFY lt_dstuf FROM ls_dstuf TRANSPORTING alpgr3 WHERE matnr = gs_stpov-matnr
        "                                                       AND werks = gs_stpov-werks. "替代项目:组(补充)
        "ENDIF.
        "ENDIF.

        CLEAR:ls_dstuf. "每次循环ls_dstuf要重置,gs_dstuf不可以做任何变更
      ENDLOOP.
    ENDIF.
    CLEAR:gs_dstuf,ls_dstuf,wa_dstuf,gs_stpov,wa_marc1.

    IF lt_dstuf IS NOT INITIAL.
      APPEND LINES OF lt_dstuf TO gt_dstuf.
      CLEAR lt_dstuf.
    ENDIF.

    "lt_wultb是函数输出结果,筛选到lt_stpov1,查询料号的累计是lt_stpov2,真正的是gt_stpov,不能直接转到gt_stpov,以免料号多次重复计算
    APPEND LINES OF lt_stpov1 TO lt_stpov2.
    CLEAR:lt_stpov1.

  ENDIF.
  CLEAR lt_wultb.



  DO.
    IF lt_marc1 IS NOT INITIAL.
      READ TABLE lt_marc1 INTO wa_marc1 INDEX 1. "每次只读取第一条料号
      DELETE TABLE lt_marc1 FROM wa_marc1. "读取完后立刻删除内表中的第一条
      PERFORM frm_getdata_zcor0055_bom USING wa_marc1. "工作区输入,进行递归
      CLEAR wa_marc1.
    ELSE.
      EXIT. "一定要退出DO循环
    ENDIF.
  ENDDO.



ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOR0055_MATNRS
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> GS_STPOV_MATNR
*&      --> LS_DSTUF_DSTUF
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0055_matnrs USING p_lv_matnr TYPE matnr
                                       p_lv_werks TYPE werks_d
                                       p_lv_dstuf TYPE ttidx.

  DATA: ls_dstuf TYPE ty_dstuf.


  IF p_lv_dstuf > 99. "成本阶过大说明进入了死循环
    lv_recursion = 'X'. "作为提醒标记
    RETURN.
  ENDIF.

  ls_dstuf-dstuf = p_lv_dstuf + 1. "成本阶

  SORT gt_zmatnrs BY matnr werks.

  READ TABLE gt_zmatnrs INTO DATA(wa_zmatnrs) WITH KEY matnr = p_lv_matnr
                                                       werks = p_lv_werks
                                                       BINARY SEARCH.
  IF sy-subrc = 0.
    LOOP AT wa_zmatnrs-matnrs INTO gs_matnrs.
      MODIFY gt_dstuf FROM ls_dstuf TRANSPORTING dstuf WHERE matnr = gs_matnrs-matnrs
                                                         AND werks = gs_matnrs-werks.
      PERFORM frm_getdata_zcor0055_matnrs USING gs_matnrs-matnrs gs_matnrs-werks ls_dstuf-dstuf.
    ENDLOOP.
  ENDIF.
  CLEAR:wa_zmatnrs,gs_matnrs.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOR0055_DSTUF
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0055_dstuf .

  IF gt_dstuf IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt_dstuf BY matnr werks.

  LOOP AT lt_stpov2 INTO gs_stpov.
    READ TABLE gt_dstuf INTO gs_dstuf WITH KEY matnr = gs_stpov-matnr
                                               werks = gs_stpov-werks
                                               BINARY SEARCH.
    IF sy-subrc = 0.
      gs_stpov-dstuf = gs_dstuf-dstuf. "成本阶
      "gs_stpov-alpgr3 = gs_dstuf-alpgr3. ""替代项目:组(补充)
      MODIFY lt_stpov2 FROM gs_stpov TRANSPORTING dstuf ."alpgr3
    ENDIF.
  ENDLOOP.
  CLEAR:gs_stpov,gs_dstuf.

  "APPEND LINES OF lt_stpov2 TO gt_stpov.
  "CLEAR:lt_stpov2.

  CLEAR:gt_dstuf,lt_marc2,gt_zmatnrs,gt_zmatnrs[]. "必要的,避免数据冗余查找

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOR0055_QPA2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0055_qpa2 .


  "CS11 替代项目:组
  TYPES: BEGIN OF ty_alpgr,
           matnr  TYPE matnr,             ""物料编号
           werks  TYPE werks_d,           ""工厂
           zmatnr TYPE matnr,             ""查询的物料
           zwerks TYPE werks_d,           ""查询的工厂
           "alpgr3    TYPE cs_alpgr,              ""替代项目:组(补充)
           "alpgr4(3) TYPE c,                     ""替代项目:组(补充的修订)
         END OF ty_alpgr.

  DATA: gt_alpgr TYPE TABLE OF ty_alpgr,
        gs_alpgr TYPE  ty_alpgr,
        lt_alpgr TYPE TABLE OF ty_alpgr,
        wa_alpgr TYPE  ty_alpgr.


  IF lt_stpov2 IS INITIAL.
    RETURN.
  ENDIF.


  "--------------------------------------------------除重,计算“成本阶”最大的--------------------------------------------------
*  SORT lt_stpov2 BY zmatnr zwerks matnr werks."查询的物料 查询的工厂 物料编号 工厂
*
*  LOOP AT lt_stpov2 INTO gs_stpov.
*    IF gs_stpov-zmatnr && gs_stpov-zwerks && gs_stpov-matnr && gs_stpov-werks <>
*      gs_marc-zmatnr && gs_marc-zwerks && gs_marc-matnr && gs_marc-werks.
*      lv_n = lv_n + 1.
*      gs_marc-zmatnr = gs_stpov-zmatnr.          ""查询的物料
*      gs_marc-zwerks = gs_stpov-zwerks.          ""查询的工厂
*      gs_marc-matnr = gs_stpov-matnr.            ""物料编号
*      gs_marc-werks = gs_stpov-werks.            ""工厂
*      gs_marc-dstuf = gs_stpov-dstuf.            ""成本阶"
*      APPEND gs_marc TO gt_marc.
*    ELSE.
*      IF gs_stpov-dstuf > gs_marc-dstuf. "循环中,成本阶大的就替换
*        gs_marc-dstuf = gs_stpov-dstuf.            ""成本阶"
*        MODIFY gt_marc FROM gs_marc INDEX lv_n TRANSPORTING dstuf. "除了成本阶,其他几个不改应该也可以
*      ENDIF.
*    ENDIF.
*    "gs_stpov-dstuf = 0.
*    "MODIFY lt_stpov2 FROM gs_stpov TRANSPORTING dstuf. "之后好去重
*  ENDLOOP.
*  CLEAR:gs_stpov,gs_marc.
*  lv_n = 0.

  SORT lt_stpov2 BY zmatnr zwerks matnr werks idnrk."查询的物料 查询的工厂 物料编号 工厂 BOM组件
  "正常的反查BOM,如果成本阶不一致,会导致重复
  "查询料号是 806-36221AN001A-N YCH0,MATNR 料号是806-36221LE001A-Y,IDNRK 806-36221NC003A-N 有重复。CS15也是重复,项次不一样
  "YCA0:主件G1604-39522-RT-Z0Y,组件099-33348AS010A-Y 会重复, 查询工单11000078789 发现就是1:1的
  "要先排序再除重,否则还会有重复的部分
  "同主件料号、同组件料号,会出现EWAHR 是0 或100,ALPGR1 是空或者是0L 的情况,不能直接除重
  "DELETE ADJACENT DUPLICATES FROM lt_stpov2 COMPARING ALL FIELDS.

  "去除重复值 "要先排序
  LOOP AT lt_stpov2 INTO gs_stpov.
    IF gs_stpov-zmatnr && gs_stpov-zwerks && gs_stpov-matnr && gs_stpov-werks && gs_stpov-idnrk <>
      wa_stpov-zmatnr && wa_stpov-zwerks && wa_stpov-matnr && wa_stpov-werks && wa_stpov-idnrk.
      lv_n = lv_n + 1.
      wa_stpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
      wa_stpov-zwerks = gs_stpov-zwerks.          ""查询的工厂
      wa_stpov-matnr = gs_stpov-matnr.            ""物料编号
      wa_stpov-werks = gs_stpov-werks.            ""工厂
      wa_stpov-idnrk = gs_stpov-idnrk.            ""BOM组件
      wa_stpov-dstuf = gs_stpov-dstuf.             "成本阶 (本来就是最大的,不需要再处理)

      APPEND gs_stpov TO lt_stpov1. "用 gs_stpov 更简洁
    ELSE.
      IF gs_stpov-alpgr1 IS NOT INITIAL. "替代项目:组 不是空就替换
        MODIFY lt_stpov1 FROM gs_stpov INDEX lv_n TRANSPORTING alpgr1. ""替代项目:组
      ENDIF.
      IF gs_stpov-ewahr <> 0. "以百分比表示的使用概率(备选项目) 不是0 就替换
        MODIFY lt_stpov1 FROM gs_stpov INDEX lv_n TRANSPORTING ewahr. ""以百分比表示的使用概率(备选项目)
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_stpov,wa_stpov,lt_stpov2.
  lv_n = 0.

*  "去重后拉取最大成本阶
*  LOOP AT lt_stpov1 INTO gs_stpov.
*    READ TABLE gt_marc INTO gs_marc WITH KEY zmatnr = gs_stpov-zmatnr          ""查询的物料
*                                             zwerks = gs_stpov-zwerks          ""查询的工厂
*                                             matnr = gs_stpov-matnr            ""物料编号
*                                             werks = gs_stpov-werks            ""工厂
*                                             BINARY SEARCH.
*
*    IF sy-subrc = 0.
*      gs_stpov-dstuf = gs_marc-dstuf.
*      MODIFY lt_stpov1 FROM gs_stpov TRANSPORTING dstuf.
*    ENDIF.
*  ENDLOOP.
*  CLEAR:gs_stpov,gs_marc,gt_marc.



*---------------------------------------------特殊逻辑---------------------------------------------START
  "超级BOM下,虚拟料号空值补替代组都为ZZZ
  "由于昆山立铠用的是可配置的超级BOM,主件料号顺查BOM是通过“MM03 物料需求计划3  可配置物料”特征值进行设定的,
  "逻辑十分复杂,如果通过反查BOM的方式又在跨工厂,来计算QPA难以实现
  "此处只是简单逻辑。根据建BOM时涉及虚拟料号,把虚拟料号 “50 虚无装配” 设置成同组,只计算其中一个的QPA
  "2MULAN00025M-WC ML00  明明是直接物料,也会莫名其妙的设置 sobsl 50
  "当然,也可以通过函数 CS_BOM_EXPL_MAT_V2 ,顺查BOM,计算出 gt_stpox 中的 DUMPS 虚拟项目标识 来判定,但也不完全正确
  "遇到此种情况,CS15反查BOM与CS12顺查BOM的结果是不一样的
  "MLS1_HMD_GROUP ML00 是虚拟料号,对应组件料号:1MLS100005H-LL、1MLS100006H-LL、1MLS100007H-LL
  "CS12 查询结果: 1MLS1000EYW-LL ML00 对应组件 MLS1_HMD_GROUP ML00 仅对应 1MLS100005H-LL
  "                1MLS1000HDW-LL ML00 对应组件 MLS1_HMD_GROUP ML00 仅对应 1MLS100006H-LL
  "参考资料:SAP 变式可配置 BOM 的实现    https://cloud.tencent.com/developer/article/1890680
  "         SAP ABAP 特性相关表取数逻辑  https://blog.csdn.net/tangzhaodong121/article/details/40709575
  CLEAR lt_marc1.

  SELECT
      marc~matnr,          ""物料编号
      marc~werks           ""工厂
  FROM marc
   FOR ALL ENTRIES IN @lt_stpov1
  WHERE marc~matnr = @lt_stpov1-matnr          "物料编号
    AND marc~werks  = @lt_stpov1-werks          "工厂
    AND marc~cuobj IS NOT INITIAL        ""配置(内部对象号)  可配置物料的参数文件
  INTO CORRESPONDING FIELDS OF TABLE @lt_marc1.

  IF lt_marc1 IS NOT INITIAL.

    CLEAR lt_marc1.

    SELECT
        marc~matnr,          ""物料编号
        marc~werks           ""工厂
     FROM marc
      LEFT JOIN mbew ON mbew~matnr = marc~matnr
                    AND mbew~bwkey = marc~werks
     FOR ALL ENTRIES IN @lt_stpov1
    WHERE marc~matnr = @lt_stpov1-matnr          "物料编号
      AND marc~werks  = @lt_stpov1-werks          "工厂
      AND marc~sobsl = '50'        ""特殊采购类型
      AND mbew~bwkey IS NULL "真正的虚拟料号没有评估分类
    INTO CORRESPONDING FIELDS OF TABLE @lt_marc1.


    IF lt_marc1 IS NOT INITIAL.
      SORT lt_marc1 BY matnr werks.

      LOOP AT lt_stpov1 INTO gs_stpov.
        IF gs_stpov-alpgr1 IS INITIAL.
          READ TABLE lt_marc1 INTO gs_marc WITH KEY matnr = gs_stpov-matnr            ""物料编号
                                                   werks = gs_stpov-werks            ""工厂
                                                   BINARY SEARCH.
          IF sy-subrc = 0.
            gs_stpov-alpgr2 = 'ZZZ'.
            MODIFY lt_stpov1 FROM gs_stpov TRANSPORTING alpgr2.
          ENDIF.
        ENDIF.
      ENDLOOP.
      CLEAR:gs_stpov,gs_marc.

    ENDIF.

  ENDIF.

  CLEAR lt_marc1.
*---------------------------------------------特殊逻辑-----------------------------------------------END



  "--------------------------------------------------替代项目:组   补项次--------------------------------------------------
  "以免空白的在一个组里算错比例
  LOOP AT lt_stpov1 INTO gs_stpov.
    IF gs_stpov-zmatnr && gs_stpov-zwerks && gs_stpov-matnr && gs_stpov-werks <>
       wa_stpov-zmatnr && wa_stpov-zwerks && wa_stpov-matnr && wa_stpov-werks.
      wa_stpov-alpgr2 = 100.  "项次从这里编写不会和别的重复
      wa_stpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
      wa_stpov-zwerks = gs_stpov-zwerks.          ""查询的工厂
      wa_stpov-matnr = gs_stpov-matnr.            ""物料编号
      wa_stpov-werks = gs_stpov-werks.            ""工厂
    ENDIF.
    IF gs_stpov-alpgr2 IS INITIAL.
      IF gs_stpov-alpgr1 IS NOT INITIAL.
        gs_stpov-alpgr2 = gs_stpov-alpgr1."有真正的“替代项目:组”那就用原来的
      ELSE.
        wa_stpov-alpgr2 = wa_stpov-alpgr2 + 1.
        gs_stpov-alpgr2 = wa_stpov-alpgr2.
      ENDIF.
      MODIFY lt_stpov1 FROM gs_stpov TRANSPORTING alpgr2.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_stpov,wa_stpov.


  "-------------------------------------------------- gt1_zstpov -------------------------------------------------
  "为了重新排序
  LOOP AT lt_stpov1 INTO gs_stpov.
    gs1_zstpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
    gs1_zstpov-zwerks = gs_stpov-zwerks.          ""查询的工厂
    gs1_zstpov-dstuf = gs_stpov-dstuf.            ""成本阶
    gs1_zstpov-matnr = gs_stpov-matnr.            ""物料编号
    gs1_zstpov-werks = gs_stpov-werks.            ""工厂
    gs1_zstpov-idnrk = gs_stpov-idnrk.            ""BOM组件
    IF gs_stpov-idnrk_werks IS INITIAL.            ""BOM组件的工厂
      gs1_zstpov-idnrk_werks = gs_stpov-werks.            ""BOM组件的工厂   =  工厂
    ELSE.
      gs1_zstpov-idnrk_werks = gs_stpov-idnrk_werks.            ""(如果是跨工厂的话idnrk_werks是有值的)
    ENDIF.
    gs1_zstpov-alpgr2 = gs_stpov-alpgr2.          ""替代项目:组(修订)
    gs1_zstpov-qpa1 = gs_stpov-qpa1.              ""单层QPA"
    gs1_zstpov-ewahr = gs_stpov-ewahr.            ""以百分比表示的使用概率(备选项目)
    "gs1_zstpov-alpgr3 = gs_stpov-alpgr3.          ""替代项目:组(补充)
    APPEND gs1_zstpov TO gt2_zstpov.
  ENDLOOP.
  CLEAR:gs_stpov,gs1_zstpov,lt_stpov1.



  "查询的物料 查询的工厂 成本阶 物料编号 工厂 替代项目:组(修订)  BOM组件  BOM组件的工厂  以百分比表示的使用概率(备选项目)
  "此处的排序对后续计算影响巨大
  SORT gt2_zstpov BY zmatnr zwerks dstuf matnr werks alpgr2 idnrk idnrk_werks ewahr." 加了 idnrk_werks



  "使用概率:EWAHR 以百分比表示的使用概率(备选项目)
  "求同组中,“使用概率”最大的,如果相同则取第一个料号
  "保证同组中只有一个BOM组件,保证领用比例至少有个默认值
  LOOP AT gt2_zstpov INTO gs1_zstpov.
    IF gs1_zstpov-zmatnr && gs1_zstpov-zwerks && gs1_zstpov-matnr && gs1_zstpov-werks && gs1_zstpov-alpgr2 <>
      gs2_zstpov-zmatnr && gs2_zstpov-zwerks && gs2_zstpov-matnr && gs2_zstpov-werks && gs2_zstpov-alpgr2.
      lv_n = lv_n + 1.
      gs2_zstpov-zmatnr = gs1_zstpov-zmatnr.              ""查询的物料
      gs2_zstpov-zwerks = gs1_zstpov-zwerks.              ""查询的工厂
      gs2_zstpov-dstuf = gs1_zstpov-dstuf.                ""成本阶
      gs2_zstpov-matnr = gs1_zstpov-matnr.                ""物料编号
      gs2_zstpov-werks = gs1_zstpov-werks.                ""工厂
      gs2_zstpov-alpgr2 = gs1_zstpov-alpgr2.              ""替代项目:组(修订)
      gs2_zstpov-qpa1 = gs1_zstpov-qpa1.                  ""QPA1    >> 直接算出对应的QPA1
      gs2_zstpov-idnrk = gs1_zstpov-idnrk.                ""BOM组件
      gs2_zstpov-idnrk_werks = gs1_zstpov-idnrk_werks.     ""BOM组件的工厂
      gs2_zstpov-ewahr = gs1_zstpov-ewahr.                ""以百分比表示的使用概率(备选项目)
      "gs2_zstpov-alpgr3 = gs1_zstpov-alpgr3.              ""替代项目:组(补充)
      APPEND gs2_zstpov TO gt1_zstpov.
    ELSE.
      IF gs1_zstpov-ewahr > gs2_zstpov-ewahr. "循环中,一样的组,就要看使用概率,使用概率大的就替换,一样就还保持原样
        gs2_zstpov-idnrk = gs1_zstpov-idnrk.                ""BOM组件
        gs2_zstpov-idnrk_werks = gs1_zstpov-idnrk_werks.     ""BOM组件的工厂
        gs2_zstpov-ewahr = gs1_zstpov-ewahr.                ""以百分比表示的使用概率(备选项目)
        gs2_zstpov-qpa1 = gs1_zstpov-qpa1.                  ""QPA1    >> 直接算出对应的QPA1
        MODIFY gt1_zstpov FROM gs2_zstpov INDEX lv_n TRANSPORTING idnrk idnrk_werks ewahr qpa1.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_zstpov,gs2_zstpov,gt2_zstpov.
  lv_n = 0.





  "-------------------------------------------------------- QPA2--------------------------------------------------------
  LOOP AT gt1_zstpov INTO gs1_zstpov.
    "IF gs1_zstpov-receive1 <> 0.
    "只是为了后面 READ TABLE gt2_zstpov 算的快些,因为用不了 BINARY SEARCH
    IF gs1_zstpov-zmatnr && gs1_zstpov-zwerks <> gs2_zstpov-zmatnr && gs2_zstpov-zwerks.
      gs2_zstpov-zmatnr = gs1_zstpov-zmatnr.          ""查询的物料
      gs2_zstpov-zwerks = gs1_zstpov-zwerks.          ""查询的工厂
      IF gt2_zstpov IS NOT INITIAL.
        APPEND LINES OF gt2_zstpov TO gt3_zstpov.
        CLEAR gt2_zstpov.
        lv_n = 0.
      ENDIF.
    ENDIF.

    "要按成本阶升序,不可以用BINARY SEARCH
    "根据BOM组件取上阶,而不是阶数,因为会有跳阶的情况
    READ TABLE gt2_zstpov INTO gs4_zstpov WITH KEY zmatnr = gs1_zstpov-zmatnr          ""查询的物料
                                                   zwerks = gs1_zstpov-zwerks          ""查询的工厂
                                                   matnr = gs1_zstpov-idnrk            ""查询的BOM组件       匹配 物料编号
                                                   werks = gs1_zstpov-idnrk_werks.     ""查询的BOM组件的工厂 匹配 工厂
    IF NOT sy-subrc = 0.
      gs4_zstpov-qpa2 = 1.          ""上阶的  查询料号QPA  ,取不到默认是1
      " gs4_zstpov-ztransaction = 1.   ""上阶的  关联交易比例 ,取不到默认是1
    ENDIF.

    "关系人的物料占非关系人物料的比例
    IF gs1_zstpov-zmatnr = gs1_zstpov-matnr AND gs1_zstpov-zwerks = gs1_zstpov-werks. "加这个主要是和上面历史取价的不一样,以免逻辑冲突
      "  gs4_zstpov-ztransaction = gs1_zstpov-ztransaction .              "关联交易比例
    ENDIF.

    "保证关联交易料号仅对应一笔库存料号
    IF gs1_zstpov-zmatnr && gs1_zstpov-zwerks && gs1_zstpov-matnr && gs1_zstpov-werks <>
       gs3_zstpov-zmatnr && gs3_zstpov-zwerks && gs3_zstpov-matnr && gs3_zstpov-werks.
      lv_n = lv_n + 1.
      gs3_zstpov-zmatnr = gs1_zstpov-zmatnr.          ""查询的物料
      gs3_zstpov-zwerks = gs1_zstpov-zwerks.          ""查询的工厂
      gs3_zstpov-dstuf = gs1_zstpov-dstuf.            "成本阶
      gs3_zstpov-matnr = gs1_zstpov-matnr.            ""物料编号
      gs3_zstpov-werks = gs1_zstpov-werks.            ""工厂
      "gs3_zstpov-alpgr2 = gs1_zstpov-alpgr2.          ""替代项目:组(修订) ,此处的替代组是库存物料与领用料号的BOM组件,不是查询料号与库存料号的BOM组件
      "gs3_zstpov-alpgr3 = gs1_zstpov-alpgr3.          ""替代项目:组(补充),查询料号与库存料号的BOM组件 的替代组
      " gs5_zstpov-ztransaction = 1 .                    "重置 关联交易比例
      gs6_zstpov-qpa2 = 1.                            "重置 查询料号QPA
      "  gs6_zstpov-zidnrk = ''.                        ""重置 领用料号(复数)
      "gs6_zstpov-receive2 = ''.                      ""重置 领用比例(复数)
      APPEND gs3_zstpov TO gt2_zstpov.
    ENDIF.

    "    "关联交易比例
    "    IF gs1_zstpov-zmatnr && gs1_zstpov-zwerks && gs1_zstpov-matnr && gs1_zstpov-werks && gs1_zstpov-alpgr2 <>
    "       gs5_zstpov-zmatnr && gs5_zstpov-zwerks && gs5_zstpov-matnr && gs5_zstpov-werks && gs5_zstpov-alpgr2.
    "      gs5_zstpov-zmatnr = gs1_zstpov-zmatnr.          ""查询的物料
    "      gs5_zstpov-zwerks = gs1_zstpov-zwerks.          ""查询的工厂
    "      gs5_zstpov-dstuf = gs1_zstpov-dstuf.            "成本阶
    "      gs5_zstpov-matnr = gs1_zstpov-matnr.            ""物料编号
    "      gs5_zstpov-werks = gs1_zstpov-werks.            ""工厂
    "      gs5_zstpov-alpgr2 = gs1_zstpov-alpgr2.          ""替代项目:组(修订)
    "      " gs5_zstpov-alpgr3 = gs1_zstpov-alpgr3.          ""替代项目:组(补充)
    "      "历史关联交易比例 乘 上阶的关联交易比例 乘 本次领用比例
    "      " gs5_zstpov-ztransaction = gs5_zstpov-ztransaction * gs4_zstpov-ztransaction * gs1_zstpov-receive1.
    "    ELSE.
    "      "历史关联交易比例 加 上阶的关联交易比例 乘 本次领用比例
    "      " gs5_zstpov-ztransaction = gs5_zstpov-ztransaction + gs4_zstpov-ztransaction * gs1_zstpov-receive1.
    "    ENDIF.
    "    "  MODIFY gt2_zstpov FROM gs5_zstpov INDEX lv_n TRANSPORTING ztransaction. "同组加,异组乘

    "QPA2
    IF gs1_zstpov-qpa1 <> 0.
      IF gs1_zstpov-zmatnr && gs1_zstpov-zwerks && gs1_zstpov-matnr && gs1_zstpov-werks <>
         gs6_zstpov-zmatnr && gs6_zstpov-zwerks && gs6_zstpov-matnr && gs6_zstpov-werks.
        gs6_zstpov-zmatnr = gs1_zstpov-zmatnr.          ""查询的物料
        gs6_zstpov-zwerks = gs1_zstpov-zwerks.          ""查询的工厂
        gs6_zstpov-dstuf = gs1_zstpov-dstuf.            "成本阶
        gs6_zstpov-matnr = gs1_zstpov-matnr.            ""物料编号
        gs6_zstpov-werks = gs1_zstpov-werks.            ""工厂
        gs6_zstpov-qpa2 = gs1_zstpov-qpa1 * gs4_zstpov-qpa2.      "查询料号QPA = 本次的QPA 乘 上阶的QPA
        " IF NOT gs1_zstpov-zidnrk IS INITIAL.
        "   gs6_zstpov-zidnrk = gs1_zstpov-zidnrk.                    ""领用料号(复数)
        "  gs6_zstpov-receive2 = gs1_zstpov-receive2.                ""领用比例(复数)
        "ENDIF.
      ELSE.
        gs6_zstpov-qpa2 = gs6_zstpov-qpa2 + gs1_zstpov-qpa1 * gs4_zstpov-qpa2.      "查询料号QPA = 同料号不同组的QPA 加 本次的QPA 乘 上阶的QPA
        " IF NOT gs1_zstpov-zidnrk IS INITIAL.
        "  gs6_zstpov-zidnrk = gs6_zstpov-zidnrk && '|' && gs1_zstpov-zidnrk.          ""领用料号(复数)
        " gs6_zstpov-receive2 = gs6_zstpov-receive2 && '|' && gs1_zstpov-receive2.     "领用比例(复数)
        "ENDIF.
      ENDIF.
      "MODIFY gt2_zstpov FROM gs6_zstpov INDEX lv_n TRANSPORTING qpa2 zidnrk receive2. "同组取其一,异组加
      MODIFY gt2_zstpov FROM gs6_zstpov INDEX lv_n TRANSPORTING qpa2 .""同组取其一,异组加
    ENDIF.

    "ENDIF.
  ENDLOOP.
  IF gt2_zstpov IS NOT INITIAL.
    APPEND LINES OF gt2_zstpov TO gt3_zstpov. "扫尾
  ENDIF.
  CLEAR:gs1_zstpov,gs2_zstpov,gs3_zstpov,gs4_zstpov,gs5_zstpov,gs6_zstpov,gt1_zstpov,gt2_zstpov.
  lv_n = 0.


  "去除阶次,以免对排序造成影响
  LOOP AT gt3_zstpov INTO gs1_zstpov.
    gs1_zstpov-dstuf = 0.
    MODIFY gt3_zstpov FROM gs1_zstpov TRANSPORTING dstuf .
  ENDLOOP.
  CLEAR gs1_zstpov.

  "查询的物料 查询的工厂 成本阶 物料编号 工厂
  SORT gt3_zstpov BY zmatnr zwerks dstuf matnr werks.


  LOOP AT lt_stpov_fin INTO gs_stpov.
    READ TABLE gt3_zstpov INTO gs1_zstpov WITH KEY zmatnr = gs_stpov-zmatnr          ""查询的物料
                                                   zwerks = gs_stpov-zwerks          ""查询的工厂
                                                   matnr = gs_stpov-matnr            ""查询的BOM组件 匹配 物料编号
                                                   werks = gs_stpov-werks            ""工厂
                                                   BINARY SEARCH.
    IF sy-subrc = 0.
      wa_stpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
      wa_stpov-zwerks = gs_stpov-zwerks.          ""查询的工厂
      wa_stpov-matnr = gs_stpov-matnr.            ""成品的物料
      wa_stpov-werks = gs_stpov-werks.            ""成品的工厂
      wa_stpov-qpa2 = gs1_zstpov-qpa2.            ""QPA2"
      APPEND wa_stpov TO gt_stpov_fin.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_stpov,wa_stpov,gs1_zstpov,lt_stpov_fin.




ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MATNR_HEAD_1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_matnr_head_1 .

  IF gt_stpov IS INITIAL AND gt_lcm1 IS INITIAL.
    RETURN.
  ENDIF.

  s_zmatnr-sign = 'I'.
  s_zmatnr-option = 'EQ'.
  s_zwerks-sign = 'I'.
  s_zwerks-option = 'EQ'.
  LOOP AT gt_stpov INTO gs_stpov.
    s_zmatnr-low = gs_stpov-matnr.            ""成品物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_stpov-werks.            ""成品物料的工厂
    COLLECT s_zwerks.
  ENDLOOP.
  CLEAR gs_stpov.

  LOOP AT gt_lcm1 INTO gs_lcm1.
    IF ( gs_lcm1-bklas = '7920' AND gs_lcm1-beskz <> 'F' ) OR gs_lcm1-bklas = '3061'. "废料也用成品料号的逻辑
      s_zmatnr-low = gs_lcm1-matnr.          ""物料
      COLLECT s_zmatnr.
      s_zwerks-low = gs_lcm1-werks.           ""工厂
      COLLECT s_zwerks.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_lcm1,gs_marc.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MATNR_HEAD_2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_matnr_head_2 .

  s_zmatnr-sign = 'I'.
  s_zmatnr-option = 'EQ'.
  s_zwerks-sign = 'I'.
  s_zwerks-option = 'EQ'.
  LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.
    IF gs_lcm1-insign = 'A' OR gs_lcm1-insign = 'B'. "成品 或 有成品有入库量的
      s_zmatnr-low = gs_lcm1-matnr_head.          ""成品物料
      COLLECT s_zmatnr.
      s_zwerks-low = gs_lcm1-werks_head.           ""成品工厂
      COLLECT s_zwerks.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_lcm1.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZMMD0023C
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zmmd0023c .


  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  "剔除供应商的逻辑:日铭有委外的,然后采购入库会入加工费,委外入库会入实际的东西,这种情况成品工单入库量要把加工费那个入库踢掉
  "委外工单分为订单收货、科目分配的收货,科目分配的收货是入加工费,需要 剔除

  "物料凭证 5000514332 废料料号 16202001-N :erfmg  以录入单位表示的数量 对应的单位是g, MENGE 数量 对应单位是kg

  "aufm~MBLNR,
  "AUFK~aufnr,
  SELECT
    aufm~matnr,          ""入库物料
    aufm~werks,          ""入库物料的工厂,不是aufk的工厂,可以入无价工厂,与表头的有价工厂不一样
    SUM( CASE aufm~shkzg WHEN 'S' THEN aufm~menge WHEN 'H' THEN - aufm~menge END ) AS erfmg    "以录入项单位表示的数量 改为 数量
  FROM aufm
  LEFT JOIN afpo ON afpo~aufnr = aufm~aufnr  "订单表头数据 PP 订单
  LEFT JOIN aufk ON aufk~aufnr = aufm~aufnr   "订单主数据
  WHERE aufm~budat BETWEEN @lv_fdate1 AND @lv_fdate2 " 针对订单的货物移动 的过账日期,是未来期间,不是当前
      AND aufk~auart <> 'ZPCA' "只剔除拆解工单
      AND aufm~bwart IN ('101','102') "移动类型是入库的
      AND aufm~matnr IN @s_zmatnr  "只筛选入库料号,不能筛选领用料号
      AND aufm~werks IN @s_zwerks
      AND afpo~matnr = aufm~matnr "单头物料等于货物移动的物料
      AND aufm~lifnr IS INITIAL "供应商为空,
  GROUP BY
      aufm~matnr,          "入库物料
      aufm~werks           "入库物料工厂
  INTO CORRESPONDING FIELDS OF TABLE @gt_aufm1.



  IF gt_aufm1 IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt_aufm1 BY matnr werks.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_ALV_LAYOUT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_layout .
  wa_layout-cwidth_opt = 'X'. "最适列宽
  wa_layout-zebra = 'X'. "隔行显示斑马纹   使ALV表格按斑马线间隔条码方式显示
  wa_layout-sel_mode = 'D'. "选择模式 "'D' 单元格的选择,可以多选单元格 多行,多列,任何单元格多选 用户可以使用最左边的选择按钮来选择多行
  wa_layout-stylefname = 'CELLBTN'. "设置单元
ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_ALV_FIELDCAT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_fieldcat .


*----------------------------------------------------------------------*
*                  定义宏
*----------------------------------------------------------------------*
  DEFINE macro_fieldcat.
    CLEAR ls_fieldcat.
    ls_fieldcat-fieldname = &1. "标题列对应的字段名
    ls_fieldcat-coltext = &2. "列标题 列标题,如果字段参考了DDIC,可不设置
    ls_fieldcat-fix_column = &3. "固定列 与KEY字段类似,固定列但颜色不变蓝,必须要在左边才起作用(如果设置固定列的左边包含非固定列,则该列不固定)
    ls_fieldcat-no_zero = &4. "是否隐藏输出为零的字段 当字段为数值为0时,不显示【如0,0.00,则会显示为空】当字段包含前导0时,隐藏前导0,【如0100,则会显示为100】
    "ls_fieldcat-cfieldname = &5. "currency unit field name值为当前输出内表中的货币单位字段的字段名称
    "ls_fieldcat-edit = &6. "准备输入 X:可编辑,space:不可编辑 该控制是在整列的级别上,如果想控制仅仅某一行可编辑,则需要通过style来控制
    ls_fieldcat-ref_field = &5.
    ls_fieldcat-ref_table = &6.

    APPEND ls_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.


  macro_fieldcat:
    'ZN_GJAHR' '当前年度'(t01) '' '' '' '',
    'ZN_MONAT' '当前月份'(t02) '' '' '' '',
    'ZF_GJAHR' '未来年度'(t03) '' '' '' '',
    'ZF_MONAT' '未来月份'(t04) '' '' '' '',
    'BUKRS' '公司代码'(t05) '' '' '' '',
    'ZITEM' '项次'(t06) '' '' '' '',
    'WERKS_HEAD' '成品料号的工厂'(t07) '' '' '' '',
    'MATNR_HEAD' '成品料号'(t08) '' '' '' '',
    'WERKS' '工厂'(t09) '' '' '' '',
    'MATNR' '物料编号'(t10) '' '' 'MATNR' 'MARA',
    'BKLAS' '评估分类'(t11) '' '' '' '',
    'BESKZ' '采购类型'(t12) '' '' '' '',
    'ERFMG' '成品工单未来入库量'(t13) '' '' '' '',
    'ZQM01_QTY' '库存数量'(t14) '' '' '' '',
    'ZQM01_AMOUNT' '料件成本单价'(t15) '' '' '' '',
    'ZQM02_AMOUNT' '成本金额'(t16) '' '' '' '',
    'ZPRO_COST' '成品成本单价'(t17) '' '' '' '',
    'ZPRO_FUT_COST' '成品未来期间成本单价'(t18) '' '' '' '',
    'ZBSALE_PRICE' '成品未来期间售价(CNY)'(t19) '' '' '' '',
    'ZSALE_PRICE' '成品未来期间售价(原币)'(t20) '' '' '' '',
    'ZPRO_WAERK' '成品未来期间售价的币别'(t21) '' '' '' '',
    'ZSALE_RATE' '未来期间销售费用率'(t22) '' '' '' '',
    'ZPRO_GROSS_LOSS' '成品未来毛损'(t23) '' '' '' '',
    'ZHALF_GROSS_LOSS' '库存料毛损'(t24) '' '' '' '',
    'ZLOSS_AMOUNT' '损失金额'(t25) '' '' '' '',
    'ZRAW_WERKS' '原材料号的工厂'(t26) '' '' '' '',
    'ZRAW_MATNR' '原材料号'(t27) '' '' '' '',
    'ZRAW_COST' '原材成本价'(t28) '' '' '' '',
    'ZRAW_PURCHASEP_OC' '原材未来期间采购单价(CNY)'(t29) '' '' '' '',
    'ZRAW_PURCHASEP_HC' '原材未来期间采购单价(原币)'(t30) '' '' '' '',
    'ZRAW_WAERK' '原材未来期间采购单价的币别'(t31) '' '' '' '',
    'MAKTX' '物料描述'(t32) '' '' '' '',
    'LGORT' '库存地点'(t33) '' '' '' '',
    'LGOBE' '库存地点描述'(t34) '' '' '' '',
    'LGORT_P' '仓库属性'(t35) '' '' '' '',
    'CHARG' '批次'(t36) '' '' '' '',
    'HSDAT' '批号生成日期'(t37) '' '' '' '',
    'PRDHA' '产品层次'(t38) '' '' '' '',
    'ZCMCC' '机种'(t39) '' '' '' '',
    'PRCTR' '利润中心'(t40) '' '' '' '',
    'DULL_MONTH' '呆滞月份'(t41) '' '' '' '',
    'STDAY' '库龄天数'(t42) '' '' '' '',
    'QPA2' 'BOM表用量(QPA)'(t43) '' '' '' ''."


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_ALV_OUTPUT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_output_lcm .

  "如果没有选“更新”,ALV报表会显示这个错误“输入的条件找不到数据,请重新输入”,原因是 zmmr1098没有查到数据,如果点了“更新”则看不到这个错误。

  DATA: gs_disvariant TYPE disvariant.

  "gs_disvariant-variant = p2_var.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program = sy-cprog "sy-repid
*     I_INTERFACE_CHECK  = ' '
*     I_BYPASSING_BUFFER =
*     I_BUFFER_ACTIVE    =
*     I_CALLBACK_PROGRAM = ' '
*     I_CALLBACK_PF_STATUS_SET          = ' '
*     I_CALLBACK_USER_COMMAND           = ' '
*     I_CALLBACK_TOP_OF_PAGE            = ' '
*     I_CALLBACK_HTML_TOP_OF_PAGE       = ' '
*     I_CALLBACK_HTML_END_OF_LIST       = ' '
*     I_STRUCTURE_NAME   =
*     I_BACKGROUND_ID    = ' '
*     I_GRID_TITLE       =
*     I_GRID_SETTINGS    =
      is_layout_lvc      = wa_layout
      it_fieldcat_lvc    = lt_fieldcat
*     IT_EXCLUDING       =
*     IT_SPECIAL_GROUPS_LVC             =
"     it_sort_lvc        = lt_sort
*     IT_FILTER_LVC      =
*     IT_HYPERLINK       =
*     IS_SEL_HIDE        =
      i_default          = 'X'
      i_save             = 'A' " 'U'
*     is_variant         = gs_disvariant
"     it_events          = lt_event
*     IT_EVENT_EXIT      =
*     IS_PRINT_LVC       =
*     IS_REPREP_ID_LVC   =
*     I_SCREEN_START_COLUMN             = 0
*     I_SCREEN_START_LINE               = 0
*     I_SCREEN_END_COLUMN               = 0
*     I_SCREEN_END_LINE  = 0
*     I_HTML_HEIGHT_TOP  =
*     I_HTML_HEIGHT_END  =
*     IT_ALV_GRAPHICS    =
*     IT_EXCEPT_QINFO_LVC               =
*     IR_SALV_FULLSCREEN_ADAPTER        =
* IMPORTING
*     E_EXIT_CAUSED_BY_CALLER           =
*     ES_EXIT_CAUSED_BY_USER            =
    TABLES
      t_outtab           = gt_ztco0043b_lcm
    EXCEPTIONS
      program_error      = 1
      OTHERS             = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
    "LEAVE LIST-PROCESSING.
  ENDIF.

ENDFORM.


*&---------------------------------------------------------------------*
*& Form FRM_ALV_OUTPUT_ITEM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_output_item .

  DATA: gs_disvariant TYPE disvariant.

  "gs_disvariant-variant = p2_var.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program = sy-cprog "sy-repid
*     I_INTERFACE_CHECK  = ' '
*     I_BYPASSING_BUFFER =
*     I_BUFFER_ACTIVE    =
*     I_CALLBACK_PROGRAM = ' '
*     I_CALLBACK_PF_STATUS_SET          = ' '
*     I_CALLBACK_USER_COMMAND           = ' '
*     I_CALLBACK_TOP_OF_PAGE            = ' '
*     I_CALLBACK_HTML_TOP_OF_PAGE       = ' '
*     I_CALLBACK_HTML_END_OF_LIST       = ' '
*     I_STRUCTURE_NAME   =
*     I_BACKGROUND_ID    = ' '
*     I_GRID_TITLE       =
*     I_GRID_SETTINGS    =
      is_layout_lvc      = wa_layout
      it_fieldcat_lvc    = lt_fieldcat
*     IT_EXCLUDING       =
*     IT_SPECIAL_GROUPS_LVC             =
"     it_sort_lvc        = lt_sort
*     IT_FILTER_LVC      =
*     IT_HYPERLINK       =
*     IS_SEL_HIDE        =
      i_default          = 'X'
      i_save             = 'A' " 'U'
*     is_variant         = gs_disvariant
"     it_events          = lt_event
*     IT_EVENT_EXIT      =
*     IS_PRINT_LVC       =
*     IS_REPREP_ID_LVC   =
*     I_SCREEN_START_COLUMN             = 0
*     I_SCREEN_START_LINE               = 0
*     I_SCREEN_END_COLUMN               = 0
*     I_SCREEN_END_LINE  = 0
*     I_HTML_HEIGHT_TOP  =
*     I_HTML_HEIGHT_END  =
*     IT_ALV_GRAPHICS    =
*     IT_EXCEPT_QINFO_LVC               =
*     IR_SALV_FULLSCREEN_ADAPTER        =
* IMPORTING
*     E_EXIT_CAUSED_BY_CALLER           =
*     ES_EXIT_CAUSED_BY_USER            =
    TABLES
      t_outtab           = gt_ztco0043b_item
    EXCEPTIONS
      program_error      = 1
      OTHERS             = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
    "LEAVE LIST-PROCESSING.
  ENDIF.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_UPDATE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_update .

  "更新时需要删除当前数据,如果屏幕上加了自选删除按钮则要把此处注释掉
  DELETE FROM ztco0043b_lcm WHERE bukrs = p_bukrs
                              AND zn_gjahr = pn_gjahr "当前年度
                              AND zn_monat = pn_monat "当前月份
                              AND zf_gjahr = pf_gjahr "未来年度
                              AND zf_monat = pf_monat."未来月份


  MODIFY ztco0043b_lcm FROM TABLE gt_ztco0043b_lcm .

  IF sy-subrc = 0.
    COMMIT WORK .
    MESSAGE TEXT-b01 TYPE  'S'. "更新数据成功!
  ELSE.
    ROLLBACK WORK .
    MESSAGE TEXT-b02 TYPE 'S' DISPLAY LIKE 'E' . "更新失败!
  ENDIF.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ztco0043b_lcm_alv
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztco0043b_lcm_alv .

  SELECT *
  FROM ztco0043b_lcm
  WHERE bukrs = @p_bukrs
    AND zn_gjahr = @pn_gjahr "当前年度
    AND zn_monat = @pn_monat "当前月份
    AND zf_gjahr = @pf_gjahr "未来年度
    AND zf_monat = @pf_monat "未来月份
    AND zitem IN @s_zitem "项次
    AND matnr IN @s_matnr "物料
    AND werks IN @s_werks "工厂
    AND bklas IN @s_bklas  "评估分类
    AND beskz IN @s_beskz  "采购类型
  INTO TABLE @gt_ztco0043b_lcm.

  SORT gt_ztco0043b_lcm BY zn_gjahr zn_monat zf_gjahr zf_monat bukrs zitem.

  IF gt_ztco0043b_lcm IS INITIAL. "新表没数据会去取就旧表

    SELECT *
    FROM ztco0043b_item
    WHERE bukrs = @p_bukrs
      AND zn_gjahr = @pn_gjahr "当前年度
      AND zn_monat = @pn_monat "当前月份
      AND zf_gjahr = @pf_gjahr "未来年度
      AND zf_monat = @pf_monat "未来月份
      AND zitem IN @s_zitem "项次
      AND matnr IN @s_matnr "物料
      AND werks IN @s_werks "工厂
      AND bklas IN @s_bklas  "评估分类
      AND beskz IN @s_beskz  "采购类型
    INTO TABLE @gt_ztco0043b_item.

    SORT gt_ztco0043b_item BY zn_gjahr zn_monat zf_gjahr zf_monat bukrs zitem.

  ENDIF.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZTCO0043B_LCM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztco0043b_lcm .



  "不需要考虑呆滞不良等情况
  SELECT *
  FROM ztco0043b_lcm
  WHERE bukrs = @p_bukrs
    AND zn_gjahr = @pn_gjahr "当前年度
    AND zn_monat = @pn_monat "当前月份
    AND zf_gjahr = @pf_gjahr "未来年度
    AND zf_monat = @pf_monat "未来月份
    "如果屏幕不显示就必须清掉 物料、工厂的条件
    "AND matnr IN @s_matnr "物料
    "AND werks IN @s_werks "工厂
  INTO TABLE @gt_ztco0043b_lcm.

  SORT gt_ztco0043b_lcm BY zn_gjahr zn_monat zf_gjahr zf_monat bukrs zitem.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_SALE_RATE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_sale_rate .

  "SUBMIT下ALV
  DATA(lvf_mon) = '0' && pf_monat. "未来月份

  TYPES: BEGIN OF ty_faglb03,
           period      TYPE char3,
           balance_cum TYPE char30,
         END OF ty_faglb03.


  "主营业务收入,销售收入
  DATA: lt_xssr TYPE TABLE OF ty_faglb03,
        ls_xssr TYPE  ty_faglb03.

  DATA: fs_data_xssr TYPE REF TO data.

  FIELD-SYMBOLS:  <fs_table_xssr> TYPE ANY TABLE.

  RANGES: s_hko FOR bsis-hkont.

  "销售费用
  DATA: lt_trange    TYPE TABLE OF rsds_range,
        ls_trange    TYPE rsds_range,
        ls_trange_ft TYPE rsds_frange,
        ls_trange_st TYPE rsdsselopt,
        ls_texpr     TYPE rsds_texpr,
        ls_dyns      TYPE rsds_type,
        lt_seltab    TYPE TABLE OF rsparams,
        ls_seltab    TYPE rsparams.

  CONSTANTS lv_rfarea TYPE faglflext-rfarea VALUE '2000'.

  DATA: lt_xsfy TYPE TABLE OF ty_faglb03,
        ls_xsfy TYPE  ty_faglb03.

  DATA: fs_data_xsfy TYPE REF TO data.

  FIELD-SYMBOLS:  <fs_table_xsfy> TYPE ANY TABLE.




*-------------------------------------------------销售收入--------------------------------------
  s_hko-sign = 'I'.
  s_hko-option = 'EQ'.

  s_hko-low = '0060010101'.          ""销售收入-非关系人-内销-内销收入
  APPEND s_hko.
  s_hko-low = '0060010102'.          ""销售收入-非关系人-内销-加工收入
  APPEND s_hko.
  s_hko-low = '0060010103'.          ""销售收入-非关系人-内销-劳务收入
  APPEND s_hko.
  s_hko-low = '0060010104'.          ""销售收入-非关系人-外销-直接出口
  APPEND s_hko.
  s_hko-low = '0060010105'.          ""销售收入-非关系人-外销-转厂出口
  APPEND s_hko.
  s_hko-low = '0060010207'.          ""销售收入-关系人-内销-内销收入
  APPEND s_hko.
  s_hko-low = '0060010208'.          ""销售收入-关系人-内销-加工收入
  APPEND s_hko.
  s_hko-low = '0060010209'.          ""销售收入-关系人-内销-劳务收入
  APPEND s_hko.
  s_hko-low = '0060010210'.          ""销售收入-关系人-外销-直接出口
  APPEND s_hko.
  s_hko-low = '0060020103'.          ""销售退回-非关系人-预估退货
  APPEND s_hko.
  s_hko-low = '0060030103'.          ""销售折让-非关系人-内销-暂估
  APPEND s_hko."


  cl_salv_bs_runtime_info=>set(
     EXPORTING
       display  = abap_false  "不显示
       metadata = abap_false
       data     = abap_true
    ).

  "调用FAGLB03,如果调取失败,它自己就会报错
  SUBMIT fagl_account_balance
    WITH racct IN s_hko
    WITH rbukrs = p_bukrs
    WITH ryear = pf_gjahr "未来年份
      AND RETURN.


  TRY.
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = fs_data_xssr ).
      ASSIGN fs_data_xssr->* TO <fs_table_xssr>.
      IF <fs_table_xssr> IS ASSIGNED.
        "后续处理逻辑
        MOVE-CORRESPONDING <fs_table_xssr> TO lt_xssr.
*          APPEND LINES OF GT_OUT TO ET_1147BOM.
*           EV_RESPONSE = /ui2/cl_json=>serialize( EXPORTING  data = ET_1147BOM[] ).
      ENDIF.
    CATCH cx_salv_bs_sc_runtime_info.
      MESSAGE '获取数据失败' TYPE 'E' .
  ENDTRY.
  "清除设置的格式
  cl_salv_bs_runtime_info=>clear_all( ).

  IF lt_xssr IS INITIAL.
    MESSAGE s000 WITH TEXT-c02 DISPLAY LIKE 'E'. "“FAGLB03 显示余额”没有主营业务收入!
    "LEAVE LIST-PROCESSING.
  ENDIF.



*-------------------------------------------------销售费用--------------------------------------
  "参考文献:https://zhuanlan.zhihu.com/p/608704979

*&--构建动态选择条件
  CLEAR:ls_trange_st,ls_trange_ft,ls_trange.

  ls_trange_st-sign = 'I'.
  ls_trange_st-option = 'EQ'.
  ls_trange_st-low = lv_rfarea .                            "功能范围2000
  APPEND ls_trange_st TO ls_trange_ft-selopt_t.

  "字段值
  ls_trange_ft-fieldname = 'RFAREA'.
  APPEND ls_trange_ft TO ls_trange-frange_t.

  "表
  ls_trange-tablename = 'ACDOCA'."'FAGLFLEXT'.
  APPEND ls_trange TO lt_trange.

  CALL FUNCTION 'FREE_SELECTIONS_RANGE_2_EX'
    EXPORTING
      field_ranges = lt_trange
    IMPORTING
      expressions  = ls_texpr.

  ls_dyns-texpr = ls_texpr.
  ls_dyns-trange =  lt_trange.


*&--构建选择屏幕条件
  ls_seltab-selname = 'RACCT'.
  ls_seltab-kind = 'S'.
  ls_seltab-sign = 'I'.
  ls_seltab-option = 'CP'.
  ls_seltab-low = '*'. "会计科目输入*
  APPEND ls_seltab TO lt_seltab.
  CLEAR ls_seltab.

  ls_seltab-selname = 'RBUKRS'.
  ls_seltab-kind = 'S'.
  ls_seltab-sign = 'I'.
  ls_seltab-option = 'EQ'.
  ls_seltab-low = p_bukrs. "公司代码
  APPEND ls_seltab TO lt_seltab.
  CLEAR ls_seltab.

  ls_seltab-selname = 'RYEAR'.
  ls_seltab-kind = 'P'.
  ls_seltab-sign = 'I'.
  ls_seltab-option = 'EQ'.
  ls_seltab-low = pf_gjahr. "未来年份
  APPEND ls_seltab TO lt_seltab.
  CLEAR ls_seltab.

  "这个语句可以控制ALV不显示,如果太远了就没用,要紧接着SUBMIT写
  cl_salv_bs_runtime_info=>set(
     EXPORTING
       display  = abap_false  "不显示
       metadata = abap_false
       data     = abap_true
    ).


  "不需要调取屏幕,using selection-screen '2000'
  SUBMIT fagl_account_balance
         WITH fs_dyns = ls_dyns
         WITH SELECTION-TABLE lt_seltab
         "VIA SELECTION-SCREEN      "停留在选择界面
         AND RETURN.               "执行完毕后返回当前程序


  TRY.
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = fs_data_xsfy ).
      ASSIGN fs_data_xsfy->* TO <fs_table_xsfy>.
      IF <fs_table_xsfy> IS ASSIGNED.
        "后续处理逻辑
        MOVE-CORRESPONDING <fs_table_xsfy> TO lt_xsfy.
*          APPEND LINES OF GT_OUT TO ET_1147BOM.
*           EV_RESPONSE = /ui2/cl_json=>serialize( EXPORTING  data = ET_1147BOM[] ).
      ENDIF.
    CATCH cx_salv_bs_sc_runtime_info.
      MESSAGE '获取数据失败' TYPE 'E' .
  ENDTRY.
  "清除设置的格式
  cl_salv_bs_runtime_info=>clear_all( ).


  IF lt_xsfy IS INITIAL.
    MESSAGE s000 WITH TEXT-c11 DISPLAY LIKE 'E'. "“FAGLB03 显示余额”没有销售费用!
    "LEAVE LIST-PROCESSING.
  ENDIF.

  CLEAR:ls_trange_st,ls_trange_ft,ls_trange,lt_trange,ls_texpr,ls_dyns,ls_seltab,lt_seltab.


*------------------------------销售费用计算--------------------------------------------------
  READ TABLE lt_xssr INTO ls_xssr WITH KEY period = lvf_mon.
  IF sy-subrc = 0.
    READ TABLE lt_xsfy INTO ls_xsfy WITH KEY period = lvf_mon.
    IF sy-subrc = 0.
      "未来期间销售费用率 = 销售费用累计 / 主营业务收入累计
      "参考: <fs3>-zsale_rate = lv_xsfy / lv_xsjj.    "销售净额
      IF ls_xssr-balance_cum <> 0.
        lv_zsale_rate = abs( ls_xsfy-balance_cum / ls_xssr-balance_cum ).
      ELSE.
        lv_zsale_rate = 0.
      ENDIF.
    ENDIF.
  ENDIF.
  CLEAR:ls_xssr,ls_xsfy.

  IF lv_zsale_rate IS INITIAL.
    MESSAGE s000 WITH TEXT-c05 DISPLAY LIKE 'E'. "销售费用率缺失!
    "LEAVE LIST-PROCESSING.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_CALCULATE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_calculate .

  IF gt_lcm1 IS INITIAL.
    RETURN.
  ENDIF.

  "7920的成品料号就是它本身
  LOOP AT gt_lcm1 INTO gs_lcm1.
    IF gs_lcm1-bklas = '7920' AND gs_lcm1-beskz <> 'F' . "or gs_lcm1-bklas = '3061' 废料不计算成品入库
      gs_stpov-zmatnr = gs_lcm1-matnr.          ""查询的物料
      gs_stpov-zwerks = gs_lcm1-werks.          ""查询的工厂
      gs_stpov-matnr = gs_lcm1-matnr.           ""物料编号
      gs_stpov-werks = gs_lcm1-werks.           ""工厂"
      COLLECT gs_stpov INTO gt_zstpov1.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_lcm1,gs_stpov.

  IF gt_stpov IS NOT INITIAL.
    APPEND LINES OF gt_stpov TO gt_zstpov1.
    CLEAR gt_stpov.  "gt_stpov 必须清除,变成临时变量!!!
  ENDIF.

  IF gt_zstpov1 IS INITIAL.
    RETURN.
  ENDIF.

  "拉取入库数
  IF gt_aufm1 IS NOT INITIAL.

    LOOP AT gt_zstpov1 INTO gs_stpov.
      READ TABLE gt_aufm1 INTO gs_aufm1 WITH KEY matnr = gs_stpov-matnr          ""物料编号
                                                 werks = gs_stpov-werks          ""工厂
                                                 BINARY SEARCH."
      IF sy-subrc = 0.
        gs_stpov-erfmg1 = gs_aufm1-erfmg .          "工单入库数
        MODIFY gt_zstpov1 FROM gs_stpov TRANSPORTING erfmg1.
      ENDIF.
    ENDLOOP.
    CLEAR:gs_lcm1,gs_stpov.

    "汇总  方法一
    LOOP AT gt_zstpov1 INTO gs_stpov.
      IF gs_stpov-erfmg1 <> 0.
        wa_stpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
        wa_stpov-zwerks = gs_stpov-zwerks.          ""查询的工厂
        wa_stpov-erfmg2 = gs_stpov-erfmg1.            ""工单入库数 的 总数
        COLLECT wa_stpov INTO gt_stpov.
      ENDIF.
    ENDLOOP.
    CLEAR:wa_stpov,gs_stpov.

*    "汇总  方法二
*    WITH +data AS ( SELECT * FROM @gt_zstpov1 AS gt_zstpov1 )
*    SELECT
*       a~zmatnr,
*       a~zwerks,
*       SUM( a~erfmg1 ) AS erfmg2
*    FROM +data AS a
*    GROUP BY
*       zmatnr,
*       zwerks
*    INTO CORRESPONDING FIELDS OF TABLE @gt_stpov.

    DELETE gt_stpov WHERE erfmg2 = 0.

    SORT gt_stpov BY zmatnr zwerks.

    LOOP AT gt_zstpov1 INTO gs_stpov.
      READ TABLE gt_stpov INTO wa_stpov WITH KEY zmatnr = gs_stpov-zmatnr          ""查询的物料
                                                 zwerks = gs_stpov-zwerks          ""查询的工厂
                                                 BINARY SEARCH."
      IF sy-subrc = 0.
        MODIFY gt_zstpov1 FROM wa_stpov TRANSPORTING erfmg2. "工单入库总数
      ELSE.
        "wa_stpov-erfmgsign = 'X'.
        "MODIFY gt_zstpov1 FROM wa_stpov TRANSPORTING erfmgsign. "没有入库量打上标识
      ENDIF.
    ENDLOOP.
    CLEAR:wa_stpov,gs_stpov,gt_stpov.

  ELSE.

    "    wa_stpov-erfmgsign = 'X'.
    "    LOOP AT gt_zstpov1 INTO gs_stpov.
    "      MODIFY gt_zstpov1 FROM wa_stpov TRANSPORTING erfmgsign. "没有入库量打上标识
    "    ENDLOOP.
    "    CLEAR:wa_stpov,gs_stpov.

  ENDIF.


  LOOP AT gt_zstpov1 INTO gs_stpov.
    IF gs_stpov-erfmg2 <> 0."入库总数不等于零
      IF gs_stpov-erfmg1 <> 0."入库数不等于零
        APPEND gs_stpov TO gt_zstpov2. "入库总数不为零有入库的部分
      ENDIF.
    ELSE.
      APPEND gs_stpov TO gt_zstpov3. "入库数为零的部分
    ENDIF.
  ENDLOOP.
  CLEAR gs_stpov.



  "降序:入库数量大的在上面
  SORT gt_zstpov2 DESCENDING BY zmatnr zwerks erfmg1 matnr werks.

  "取前十入库量最大的料号
  IF p_p3 IS NOT INITIAL.
    LOOP AT gt_zstpov2 INTO gs_stpov.
      IF gs_stpov-zmatnr && gs_stpov-zwerks <>
        wa_stpov-zmatnr && wa_stpov-zwerks.
        wa_stpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
        wa_stpov-zwerks = gs_stpov-zwerks.          ""查询的工厂              ""
        lv_n = 0.
      ENDIF.
      lv_n = lv_n + 1.

      IF lv_n < 11.
        APPEND gs_stpov TO gt_stpov.
      ENDIF.
    ENDLOOP.
    CLEAR:wa_stpov,gs_stpov.

    CLEAR gt_zstpov2.
    APPEND LINES OF gt_stpov TO gt_zstpov2.
    lv_n = 0.
    CLEAR gt_stpov.
  ENDIF.

*--------------------------入库总数不为零有入库的部分  方法一 --------------------------
*后续用with + data 的方法,但是还是用不了

*  "方便排序查询
*  MOVE-CORRESPONDING gt_zstpov2 TO gt_erfmg1.
*
*  SORT gt_erfmg1 BY zmatnr zwerks matnr werks erfmg1.


*--------------------------入库总数不为零有入库的部分  方法二 --------------------------

  "查询物料对应的成品料号的入库量
  LOOP AT gt_zstpov2 INTO gs_stpov
       GROUP BY ( zmatnr = gs_stpov-zmatnr zwerks = gs_stpov-zwerks )
                ASCENDING ASSIGNING FIELD-SYMBOL(<group_stpov>).
    LOOP AT GROUP <group_stpov> ASSIGNING FIELD-SYMBOL(<fs_stpov>).
      gtz_stpov-zmatnr = <fs_stpov>-zmatnr. ""查询的物料
      gtz_stpov-zwerks = <fs_stpov>-zwerks.   ""查询的工厂
      APPEND <fs_stpov> TO gtz_stpov-stpov.
    ENDLOOP.
    APPEND gtz_stpov.
    CLEAR gtz_stpov. "是清除工作区,不是内表
  ENDLOOP.
  CLEAR:gs_stpov.

  SORT gtz_stpov BY zmatnr zwerks.



*-----------------------------入库数为零的部分-------------------------
  "入库总数为零排序
  SORT gt_zstpov3 BY zmatnr zwerks erfmg1 matnr werks.

  LOOP AT gt_zstpov3 INTO gs_stpov.

    IF gs_stpov-zmatnr && gs_stpov-zwerks <>
      wa_stpov-zmatnr && wa_stpov-zwerks.
      IF lv_n > 0. "如果在下面写有255的限制
        MODIFY gt_erfmg2 FROM gs_erfmg INDEX lv_n TRANSPORTING matnrs.
      ENDIF.

      lv_n = lv_n + 1.
      lv_i = 1.
      wa_stpov-zmatnr = gs_stpov-zmatnr.          ""查询的物料
      wa_stpov-zwerks = gs_stpov-zwerks.          ""查询的工厂

      gs_erfmg-zmatnr = gs_stpov-zmatnr.          ""查询的物料
      gs_erfmg-zwerks = gs_stpov-zwerks.          ""查询的工厂
      gs_erfmg-matnrs = gs_stpov-matnr.          ""成品料号(复数)
      APPEND gs_erfmg TO gt_erfmg2.
    ELSE.
      lv_i = lv_i + 1.
      "目前料号的编码原则是18位的,加上分隔符算19位,按照最长255来算,最多显示13个料号
      "后来经过商议改为只显示3个料号
      IF lv_i < 4.
        gs_erfmg-matnrs = gs_erfmg-matnrs && '|' && gs_stpov-matnr.          ""成品料号(复数)
      ENDIF.
    ENDIF.
  ENDLOOP.
  IF lv_n > 0.
    MODIFY gt_erfmg2 FROM gs_erfmg INDEX lv_n TRANSPORTING matnrs. "lv_n 为零会报错
  ENDIF.
  CLEAR:wa_stpov,gs_stpov,gs_erfmg.
  lv_i = 0.
  lv_n = 0.

  SORT gt_erfmg2 BY zmatnr zwerks.



ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZSDR0047
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zsdr0047 .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  TYPES: BEGIN OF ty_sdvbeln,
           vbeln  TYPE ztsdr0047-vbeln,          "销售和分销凭证号
           insign TYPE c,                            ""内置分类(用于日期排序)"
         END OF ty_sdvbeln.

  DATA: gt1_sdvbeln TYPE TABLE OF ty_sdvbeln,
        gt2_sdvbeln TYPE TABLE OF ty_sdvbeln,
        gs1_sdvbeln TYPE ty_sdvbeln,
        gs2_sdvbeln TYPE ty_sdvbeln.

  DATA: fs_data_sd47 TYPE REF TO data.
  FIELD-SYMBOLS:  <fs_table_sd47> TYPE ANY TABLE.

  RANGES:s_zvkorg FOR likp-vkorg , "销售组织
  s_zvbeln FOR likp-vbeln. "外向交货


  SELECT DISTINCT "先过账日期
      ztsdr0047~vbeln,              ""销售和分销凭证号
     '1' AS insign                  ""标识
  FROM ztsdr0047
  WHERE ztsdr0047~matnr IN @s_zmatnr
    AND ztsdr0047~vkorg = @p_bukrs
    AND ztsdr0047~lfart NOT IN ( 'ZLF4','ZLR3','NLR2','NLRR','NLR3','NCR1','NCR2','NCR3','NCRR' )    "交货类型:  出货单价不取免费样品及退货订单
    AND ztsdr0047~wadat_ist BETWEEN @lv_fdate1 AND @lv_fdate2
  INTO CORRESPONDING FIELDS OF TABLE @gt1_sdvbeln.

  SELECT DISTINCT "后凭证日期
      ztsdr0047~vbeln,              ""销售和分销凭证号
      '2' AS insign                  ""标识
  FROM ztsdr0047
  WHERE ztsdr0047~matnr IN @s_zmatnr
    AND ztsdr0047~vkorg = @p_bukrs
    AND ztsdr0047~lfart NOT IN ( 'ZLF4','ZLR3','NLR2','NLRR','NLR3','NCR1','NCR2','NCR3','NCRR' )    "交货类型:  出货单价不取免费样品及退货订单
    AND ztsdr0047~bldat BETWEEN @lv_fdate1 AND @lv_fdate2
  APPENDING CORRESPONDING FIELDS OF TABLE @gt1_sdvbeln. "追加

  IF gt1_sdvbeln IS INITIAL.
    RETURN.
  ENDIF.


  s_zvkorg-sign =  'I'.
  s_zvkorg-option = 'EQ'.
  s_zvkorg-low = p_bukrs.
  s_zvkorg-high = ''.
  APPEND s_zvkorg.

  s_zvbeln-sign =  'I'.
  s_zvbeln-option = 'EQ'.
  s_zvbeln-high = ''.
  LOOP AT gt1_sdvbeln INTO gs1_sdvbeln.
    s_zvbeln-low = gs1_sdvbeln-vbeln.
    COLLECT s_zvbeln.
  ENDLOOP.
  CLEAR gs1_sdvbeln.

  "初始设置
  CALL METHOD cl_salv_bs_runtime_info=>set
    EXPORTING
      display  = abap_false
      metadata = abap_false
      data     = abap_true.

  SUBMIT zsdr0047
  WITH s_vkorg IN s_zvkorg
  WITH s_vbeln IN s_zvbeln
  WITH s_matnr IN s_zmatnr
   AND RETURN.


  TRY.
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = fs_data_sd47 ).
      ASSIGN fs_data_sd47->* TO <fs_table_sd47>.
      IF <fs_table_sd47> IS ASSIGNED.
        "后续处理逻辑
        MOVE-CORRESPONDING <fs_table_sd47> TO gt1_ztsdr0047.
      ENDIF.
    CATCH cx_salv_bs_sc_runtime_info.
      MESSAGE '获取数据失败' TYPE 'E' .
  ENDTRY.
  "清除设置的格式
  cl_salv_bs_runtime_info=>clear_all( ).


  IF gt1_ztsdr0047 IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt1_sdvbeln BY vbeln insign.

  LOOP AT gt1_ztsdr0047 INTO gs1_ztsdr0047.
    READ TABLE gt1_sdvbeln INTO gs1_sdvbeln WITH KEY vbeln = gs1_ztsdr0047-vbeln
                                                     BINARY SEARCH.
    IF sy-subrc = 0. "一定要有标识
      gs1_ztsdr0047-insign = gs1_sdvbeln-insign.          "标识
      IF gs1_ztsdr0047-insign = '1'.
        gs1_ztsdr0047-udate = gs1_ztsdr0047-wadat_ist.          ""排序日期 = 实际货物移动日期
      ELSEIF gs1_ztsdr0047-insign = '2'.
        gs1_ztsdr0047-udate = gs1_ztsdr0047-bldat.              ""排序日期 = 凭证中的凭证日期"
      ENDIF.
      APPEND gs1_ztsdr0047 TO gt3_ztsdr0047.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_sdvbeln,gt1_ztsdr0047.

  "升序: 物料 标识 排序日期 实际货物移动日期 凭证中的凭证日期 销售和分销凭证货币 净价值
  "注意:不能像 ZCOD0046 一样 把 DESCENDING 放在最后,否则排序有问题
  "升序 ,取最接近未来月份的月初日期
  SORT gt3_ztsdr0047 BY matnr insign udate wadat_ist bldat waerk netpr2 vbeln." WERKS VKORG YYYYMM

  DELETE ADJACENT DUPLICATES FROM gt3_ztsdr0047 COMPARING ALL FIELDS. "要先排序再去重

  LOOP AT gt3_ztsdr0047 INTO gs1_ztsdr0047.
    IF gs1_ztsdr0047-matnr  <>
      gs2_ztsdr0047-matnr .
      gs2_ztsdr0047-matnr = gs1_ztsdr0047-matnr.                ""物料编号
      APPEND gs1_ztsdr0047 TO gt2_ztsdr0047.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_ztsdr0047,gs2_ztsdr0047,gt3_ztsdr0047.

  SORT gt2_ztsdr0047 BY matnr.

  "此处是直接取报表的值,不考虑转换因子


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZTSDR0047
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztsdr0047 .

  "交货单号8100005376,是日铭出CSG的,价格其实来源于采购单,不直接来源于出货单,内表ZTSDR0047和报表ZSDR0047里的价格是不一样的


  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  "ZCOD0046 是筛选了 ztsdr0047~yyyymm,但是立铠销货单8100016087发生了202310,过账日期是20231101
  "优先取实际扣账日期首次出售价,如料号在未来期间无实际扣账单据但存在未扣账单据可取凭证日期首次出货价。


  SELECT DISTINCT "先过账日期
      ztsdr0047~matnr,              ""物料编号
      "ztsdr0047~werks,              ""工厂
      "ztsdr0047~vkorg,              ""销售组织
     '1' AS insign,                 ""标识
      ztsdr0047~wadat_ist AS udate, ""排序日期
      ztsdr0047~wadat_ist,          ""实际货物移动日期
      ztsdr0047~bldat,              ""凭证中的凭证日期
      "ztsdr0047~yyyymm,             ""年月
      ztsdr0047~waerk,              ""销售和分销凭证货币
      ztsdr0047~netpr2              ""净价值 "
  FROM ztsdr0047
  WHERE "ztsdr0047~werks IN @s_zwerks AND
     ztsdr0047~matnr IN @s_zmatnr
    AND ztsdr0047~vkorg = @p_bukrs
    AND ztsdr0047~lfart NOT IN ( 'ZLF4','ZLR3','NLR2','NLRR','NLR3','NCR1','NCR2','NCR3','NCRR' )    "交货类型:  出货单价不取免费样品及退货订单
    "不能使用日期 的  或 ,后面区分还是有异常的,比如凭证日期是2023年1月,过账日期是2022年12月,这笔过账日期就会排在前面,导致先取了不是当月的扣账日期的价格
    "AND ( ztsdr0047~wadat_ist BETWEEN @lv_fdate1 AND @lv_fdate2
    "       OR ztsdr0047~bldat BETWEEN @lv_fdate1 AND @lv_fdate2
    "       OR ztsdr0047~yyyymm = @lv_frq )  " "此处与ZCOD0046不一样
    AND ztsdr0047~wadat_ist BETWEEN @lv_fdate1 AND @lv_fdate2
    AND ztsdr0047~netpr2 <> 0
  INTO CORRESPONDING FIELDS OF TABLE @gt1_ztsdr0047.

  SELECT DISTINCT "后凭证日期
      ztsdr0047~matnr,              ""物料编号
      "ztsdr0047~werks,              ""工厂
      "ztsdr0047~vkorg,              ""销售组织
      '2' AS insign,                 ""标识
      ztsdr0047~bldat AS udate,      ""排序日期
      ztsdr0047~wadat_ist,          ""实际货物移动日期
      ztsdr0047~bldat,              ""凭证中的凭证日期
      "ztsdr0047~yyyymm,             ""年月
      ztsdr0047~waerk,              ""销售和分销凭证货币
      ztsdr0047~netpr2              ""净价值 "
  FROM ztsdr0047
  WHERE "ztsdr0047~werks IN @s_zwerks AND
     ztsdr0047~matnr IN @s_zmatnr
    AND ztsdr0047~vkorg = @p_bukrs
    AND ztsdr0047~lfart NOT IN ( 'ZLF4','ZLR3','NLR2','NLRR','NLR3','NCR1','NCR2','NCR3','NCRR' )    "交货类型:  出货单价不取免费样品及退货订单
    "AND ( ztsdr0047~wadat_ist BETWEEN @lv_fdate1 AND @lv_fdate2
    "       OR ztsdr0047~bldat BETWEEN @lv_fdate1 AND @lv_fdate2
    "       OR ztsdr0047~yyyymm = @lv_frq )  " "此处与ZCOD0046不一样
    AND ztsdr0047~bldat BETWEEN @lv_fdate1 AND @lv_fdate2
    AND ztsdr0047~netpr2 <> 0
  APPENDING CORRESPONDING FIELDS OF TABLE @gt1_ztsdr0047. "追加

  IF gt1_ztsdr0047 IS INITIAL.
    RETURN.
  ENDIF.

*  LOOP AT gt1_ztsdr0047 INTO gs1_ztsdr0047.
*    "升序,先“实际货物移动日期”后“凭证中的凭证日期”
*    IF gs1_ztsdr0047-wadat_ist IS NOT INITIAL.
*      gs1_ztsdr0047-insign = '1'.
*    ELSE.
*      gs1_ztsdr0047-insign = '2'.
*    ENDIF.
*    MODIFY gt1_ztsdr0047 FROM gs1_ztsdr0047 TRANSPORTING insign.
*  ENDLOOP.
*  CLEAR:gs1_ztsdr0047.

  "升序: 物料 标识 排序日期 实际货物移动日期 凭证中的凭证日期 销售和分销凭证货币 净价值
  "注意:不能像 ZCOD0046 一样 把 DESCENDING 放在最后,否则排序有问题
  "升序 ,取最接近未来月份的月初日期
  SORT gt1_ztsdr0047 BY matnr insign udate wadat_ist bldat waerk netpr2 vbeln." WERKS VKORG YYYYMM

  LOOP AT gt1_ztsdr0047 INTO gs1_ztsdr0047.
    IF gs1_ztsdr0047-matnr  <> "&& gs1_ztsdr0047-werks
      gs2_ztsdr0047-matnr ."&& gs2_ztsdr0047-werks
      gs2_ztsdr0047-matnr = gs1_ztsdr0047-matnr.                ""物料编号
      "gs2_ztsdr0047-werks = gs1_ztsdr0047-werks.                ""工厂
      APPEND gs1_ztsdr0047 TO gt2_ztsdr0047.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_ztsdr0047,gs2_ztsdr0047,gt1_ztsdr0047.

  SORT gt2_ztsdr0047 BY matnr. "werks

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZSDR0051_VBAP
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zsdr0051_vbap .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  SELECT DISTINCT
      vbap~matnr,          ""物料编号
      vbkd~prsdt,          ""定价日期和汇率
      vbap~waerk,          ""销售和分销凭证货币
      vbap~netpr,          ""净价
      vbap~kpein           ""条件定价单位"
 FROM vbkd
    LEFT JOIN vbap ON vbap~vbeln = vbkd~vbeln "采购凭证抬头表
    LEFT JOIN t001w ON t001w~werks = vbap~werks "通过 工厂 链接 公司 进行筛选
  WHERE t001w~vkorg = @p_bukrs
    AND vbap~matnr IN @s_zmatnr
    AND vbkd~prsdt BETWEEN @lv_fdate1 AND @lv_fdate2   ""交货单定价日期计算期间在未来期间
    AND vbap~netpr <> 0        ""净价
    AND vbap~kpein <> 0          ""条件定价单位"
    "AND substring( t001w~werks , 1, 2 ) <> 'NV'   ""不能是无价的
    "AND vbap~netwr > 0 "净值 大于零,不要退货的销售订单
  INTO CORRESPONDING FIELDS OF TABLE @gt1_vbap.


  "升序: 物料编号 定价日期和汇率 销售和分销凭证货币 净价 条件定价单位
  SORT gt1_vbap BY matnr prsdt waerk netpr kpein.

  LOOP AT gt1_vbap INTO gs1_vbap.
    IF gs1_vbap-matnr <>
      gs2_vbap-matnr.
      gs2_vbap-matnr = gs1_vbap-matnr.                ""物料编号
      APPEND gs1_vbap TO gt2_vbap.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_vbap,gs2_vbap,gt1_vbap.

  SORT gt2_vbap BY matnr.


  LOOP AT gt2_vbap INTO gs1_vbap.
    IF gs1_vbap-kpein <> 0.
      "比如说日币的转换因子是1000,单价需要乘转换因子
      CALL FUNCTION 'CURRENCY_CONVERTING_FACTOR'
        EXPORTING
          currency          = gs1_vbap-waerk
        IMPORTING
          factor            = l_factor
        EXCEPTIONS
          too_many_decimals = 1
          OTHERS            = 2.

      gs1_vbap-zzprice = l_factor * gs1_vbap-netpr / gs1_vbap-kpein.

      MODIFY gt2_vbap FROM gs1_vbap TRANSPORTING zzprice.  "原币价格
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_vbap.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZSDR0051_VBKD
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zsdr0051_vbkd .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  SELECT DISTINCT
      ekpo~matnr,          ""物料编号
      vbkd~prsdt,          ""定价日期和汇率
      ekko~waers,          ""货币码
      ekpo~netpr,          ""采购凭证中的净价(以凭证货币计)
      ekpo~peinh           ""价格单位"
  FROM ekpo
    LEFT JOIN ekko ON ekko~ebeln = ekpo~ebeln "采购凭证抬头表
    LEFT JOIN t001w ON t001w~lifnr = ekko~lifnr "通过 供应商链接出货方公司
    LEFT JOIN vbap ON ( vbap~zzsto1 = ekpo~ebeln AND substring( vbap~zzpos1, 2, 5 )  = ekpo~ebelp ) OR
                      ( vbap~zzsto2 = ekpo~ebeln AND substring( vbap~zzpos2, 2, 5 )  = ekpo~ebelp )"退货的
    LEFT JOIN vbkd ON vbkd~vbeln = vbap~vbeln
  WHERE t001w~vkorg = @p_bukrs "供应商对应的公司代码
    AND ekpo~matnr IN @s_zmatnr
     AND ekpo~netpr <> 0 AND ekpo~peinh <> 0 "免费的采购单有时有会计凭证,有时又没有
     AND vbkd~prsdt BETWEEN @lv_fdate1 AND @lv_fdate2   ""交货单定价日期计算期间在未来期间
     "AND substring( ekpo~werks , 1, 2 ) <> 'NV'   ""工厂不是无价的
     "AND vbap~netwr > 0 "净价大于零,不要退货的销售订单
  INTO CORRESPONDING FIELDS OF TABLE @gt1_vbkd.


  "升序: 物料编号 定价日期和汇率 货币码 采购凭证中的净价(以凭证货币计) 价格单位
  SORT gt1_vbkd BY matnr prsdt waers netpr peinh.

  LOOP AT gt1_vbkd INTO gs1_vbkd.
    IF gs1_vbkd-matnr <>
      gs2_vbkd-matnr.
      gs2_vbkd-matnr = gs1_vbkd-matnr.                ""物料编号
      APPEND gs1_vbkd TO gt2_vbkd.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_vbkd,gs2_vbkd,gt1_vbkd.

  SORT gt2_vbkd BY matnr.

  LOOP AT gt2_vbkd INTO gs1_vbkd.
    IF gs1_vbkd-peinh <> 0.
      "比如说日币的转换因子是1000,单价需要乘转换因子
      CALL FUNCTION 'CURRENCY_CONVERTING_FACTOR'
        EXPORTING
          currency          = gs1_vbkd-waers
        IMPORTING
          factor            = l_factor
        EXCEPTIONS
          too_many_decimals = 1
          OTHERS            = 2.

      gs1_vbkd-zzprice = l_factor * gs1_vbkd-netpr / gs1_vbkd-peinh.

      MODIFY gt2_vbkd FROM gs1_vbkd TRANSPORTING zzprice.  "原币价格
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_vbkd.

ENDFORM.


*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZSDR0048
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zsdr0048 .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  DATA: fs_data_sell TYPE REF TO data.
  FIELD-SYMBOLS:  <fs_table_sell> TYPE ANY TABLE.

  RANGES:s_mon FOR bkpf-budat.

  "测试 C121的料号G1KT03724-2-Z1N,发现如果输入20231101,20231130的有效期所有的会有漏,输入20231101,99991231也不太对
  "目前看下来输入'00010101'. 到月末日期是完整的,但是还要进一步筛选
  s_mon-sign =  'I'.
  s_mon-option = 'BT'. "不是EQ
  s_mon-low = '00010101'.
  s_mon-high = lv_fdate2. "应该要输入未来月末日期更合理但是现在取不到
  APPEND s_mon.

  "初始设置
  CALL METHOD cl_salv_bs_runtime_info=>set
    EXPORTING
      display  = abap_false
      metadata = abap_false
      data     = abap_true.

  SUBMIT zsdr0048
  WITH s_vkorg = p_bukrs
  WITH s_matnr IN s_zmatnr
  WITH s_sday IN s_mon
  WITH s_kschl = 'PR00'
  WITH  p_1 = 'X' "最新报价 ,日期一定要输对
  "WITH  p_2 = 'X' "所有报价'
  AND RETURN.


  TRY.
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = fs_data_sell ).
      ASSIGN fs_data_sell->* TO <fs_table_sell>.
      IF <fs_table_sell> IS ASSIGNED.
        "后续处理逻辑
        MOVE-CORRESPONDING <fs_table_sell> TO gt1_ztsdr0048.
      ENDIF.
    CATCH cx_salv_bs_sc_runtime_info.
      MESSAGE '获取数据失败' TYPE 'E' .
  ENDTRY.
  "清除设置的格式
  cl_salv_bs_runtime_info=>clear_all( ).


  IF gt1_ztsdr0048 IS INITIAL.
    RETURN.
  ENDIF.

  "降序:物料编号 销售组织 开始生效日期 有效期截止日期 记录建立日期 年月 条件单位(货币或百分比) 实际单价(单价/基数)
  "(与ZCOD0046不同,它是 erdat 记录建立日期)
  "注意:不能像 ZCOD0046 一样 把 DESCENDING 放在最后,否则排序有问题
  "此处是降序,取最接近未来年月的最后一天的
  "SORT gt1_ztsdr0048 DESCENDING BY matnr vkorg datab datbi erdat yyyymm konwa pc_kbetr.
  "物料编号 开始生效日期 有效期截止日期 条件单位(货币或百分比) 实际单价(单价/基数)
  SORT gt1_ztsdr0048 DESCENDING BY matnr datab datbi konwa pc_kbetr.

  LOOP AT gt1_ztsdr0048 INTO gs1_ztsdr0048.
    "IF gs1_ztsdr0048-datab  <= lv_fdate2 . "有效开始日期必须小于未来月末日期
    IF gs1_ztsdr0048-matnr  <> "&& gs1_ztsdr0048-vkorg
      gs2_ztsdr0048-matnr . "&& gs2_ztsdr0048-vkorg
      gs2_ztsdr0048-matnr = gs1_ztsdr0048-matnr.                ""物料编号
      "gs2_ztsdr0048-vkorg = gs1_ztsdr0048-vkorg.                ""销售组织
      APPEND gs1_ztsdr0048 TO gt2_ztsdr0048.
    ENDIF.
    "ENDIF.
  ENDLOOP.
  CLEAR:gs1_ztsdr0048,gs2_ztsdr0048,gt1_ztsdr0048.

  SORT gt2_ztsdr0048 BY matnr. " vkorg

  "直接取表的,不考虑转换因子
ENDFORM.


*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZTSDR0048
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztsdr0048 .


  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  "这种方法取不到 C121 0000990143 这个单号
  SELECT DISTINCT
      ztsdr0048~matnr,             ""物料编号
      "ztsdr0048~vkorg,             ""销售组织
      ztsdr0048~datab,             ""开始生效日期
      ztsdr0048~datbi,             ""有效期截止日期
      "ztsdr0048~erdat,             ""记录建立日期
      "ztsdr0048~yyyymm,            ""年月
      ztsdr0048~konwa,             ""条件单位(货币或百分比)
      ztsdr0048~pc_kbetr          ""实际单价(单价/基数) "
  FROM ztsdr0048
  WHERE ztsdr0048~vkorg = @p_bukrs "'C311 的数据是最多的
    AND ztsdr0048~matnr IN @s_zmatnr
    AND ztsdr0048~datab <= @lv_fdate2 "生效日期小于未来月底日期
    AND ztsdr0048~datbi >= @lv_fdate1 "截止日期大于未来月初日期
    AND ztsdr0048~kschl = 'PR00'  ""条件类型
  INTO CORRESPONDING FIELDS OF TABLE @gt1_ztsdr0048.

  IF gt1_ztsdr0048 IS INITIAL.
    RETURN.
  ENDIF.

  "降序:物料编号 销售组织 开始生效日期 有效期截止日期 记录建立日期 年月 条件单位(货币或百分比) 实际单价(单价/基数)
  "(与ZCOD0046不同,它是 erdat 记录建立日期)
  "注意:不能像 ZCOD0046 一样 把 DESCENDING 放在最后,否则排序有问题
  "此处是降序,取最接近未来年月的最后一天的
  "SORT gt1_ztsdr0048 DESCENDING BY matnr vkorg datab datbi erdat yyyymm konwa pc_kbetr.
  "物料编号 开始生效日期 有效期截止日期 条件单位(货币或百分比) 实际单价(单价/基数)
  SORT gt1_ztsdr0048 DESCENDING BY matnr datab datbi konwa pc_kbetr.

  LOOP AT gt1_ztsdr0048 INTO gs1_ztsdr0048.
    IF gs1_ztsdr0048-matnr  <> "&& gs1_ztsdr0048-vkorg
      gs2_ztsdr0048-matnr. " && gs2_ztsdr0048-vkorg
      gs2_ztsdr0048-matnr = gs1_ztsdr0048-matnr.                ""物料编号
      "gs2_ztsdr0048-vkorg = gs1_ztsdr0048-vkorg.                ""销售组织
      APPEND gs1_ztsdr0048 TO gt2_ztsdr0048.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_ztsdr0048,gs2_ztsdr0048,gt1_ztsdr0048.

  SORT gt2_ztsdr0048 BY matnr." vkorg


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZMMR1098_SELL
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zmmr1098_sell .


  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  DATA: fs_data_sell TYPE REF TO data.

  FIELD-SYMBOLS: <fs_table_sell> TYPE ANY TABLE.

  RANGES:s_mon FOR bkpf-budat.
  RANGES:s_lif FOR eina-lifnr.

  SELECT
    lifnr
  FROM lfa1
    WHERE vbund = @p_bukrs
   INTO TABLE @DATA(gt_lifnr).

  "没有供应商就不取了
  IF gt_lifnr IS INITIAL.
    RETURN.
  ENDIF.

  s_lif-sign = 'I'.
  s_lif-option = 'EQ'.
  LOOP AT gt_lifnr INTO DATA(gs_lifnr).
    s_lif-low = gs_lifnr-lifnr.            ""供应商
    COLLECT s_lif.
  ENDLOOP.
  CLEAR gs_lifnr.


  cl_salv_bs_runtime_info=>set(
     EXPORTING
       display  = abap_false  "不显示
       metadata = abap_false
       data     = abap_true
    ).

  s_mon-sign =  'I'.
  s_mon-option = 'BT'. "不是EQ
  s_mon-low = lv_fdate1.
  s_mon-high = '99991231'. "lv_fdate2' 应该要输入未来月末日期更合理但是现在取不到
  APPEND s_mon.

  SUBMIT zmmr1098
    WITH s_matnr IN s_zmatnr
    WITH s_lifnr IN s_lif
    WITH s_yxdate IN s_mon
     AND RETURN.

  "ZCOD0046 取值说的是CSG,内表也叫lt_CSG,但是看到并没有筛选CSG,其他厂区的资料也能取到的样子
  "此处的核价是通用的不区分法人
  TRY.
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = fs_data_sell ).
      ASSIGN fs_data_sell->* TO <fs_table_sell>.
      IF <fs_table_sell> IS ASSIGNED.
        "后续处理逻辑
        MOVE-CORRESPONDING <fs_table_sell> TO gts1_ztmmr1098.
*          APPEND LINES OF GT_OUT TO ET_1147BOM.
*           EV_RESPONSE = /ui2/cl_json=>serialize( EXPORTING  data = ET_1147BOM[] ).
      ENDIF.
    CATCH cx_salv_bs_sc_runtime_info.
      MESSAGE '获取数据失败' TYPE 'E' .
  ENDTRY.
  "清除设置的格式
  cl_salv_bs_runtime_info=>clear_all( ).


  IF gts1_ztmmr1098 IS INITIAL.
    RETURN.
  ENDIF.


  "降序:物料编码 有效期开始日期 有效期截止日期 币别 实际单价
  SORT gts1_ztmmr1098 DESCENDING BY matnr datab datbi konwa zzprice.

  LOOP AT gts1_ztmmr1098 INTO gss1_ztmmr1098.
    IF gss1_ztmmr1098-datab <= lv_fdate2 . "有效开始日期必须小于未来月末日期
      IF gss1_ztmmr1098-matnr <>
        gss2_ztmmr1098-matnr .
        gss2_ztmmr1098-matnr = gss1_ztmmr1098-matnr.                ""物料编号
        APPEND gss1_ztmmr1098 TO gts2_ztmmr1098.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gss1_ztmmr1098,gss2_ztmmr1098,gts1_ztmmr1098.

  SORT gts2_ztmmr1098 BY matnr.

  "直接取表的,不考虑转换因子
ENDFORM.


*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOR0011
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0011 .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.


  "-------------------------------------------当前进销存----------------------------------
  SELECT
      ztco0011a~werks,              ""工厂
      ztco0011a~matnr,              ""物料编号
      SUM( ztco0011a~zqm01_qty ) AS zqm01_qty,          ""期末数量
      SUM( ztco0011a~zqm01_amt ) AS zqm02_amount           ""期末金额"
  FROM ztco0011a
  WHERE ztco0011a~bukrs = @p_bukrs
    AND ztco0011a~lfgja = @pn_gjahr "当前年度
    AND ztco0011a~lfmon = @pn_monat "当前月份
    AND ztco0011a~werks IN @s_zwerks
    AND ztco0011a~matnr IN @s_zmatnr
  GROUP BY
      ztco0011a~werks,              ""工厂
      ztco0011a~matnr              ""物料编号
  INTO CORRESPONDING FIELDS OF TABLE @gt1_ztco0011a.


  "没有满足条件的数据,提示信息并终止程序
  IF gt1_ztco0011a IS INITIAL.
    MESSAGE s000 WITH TEXT-c01 DISPLAY LIKE 'E'. "“ZCOR0011  进销存月报”没有当月数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

  SORT gt1_ztco0011a BY werks matnr.


  "-------------------------------------------未来进销存----------------------------------
  SELECT
    ztco0011a~werks,              ""工厂
    ztco0011a~matnr,              ""物料编号
    SUM( ztco0011a~zqm01_qty ) AS zqm01_qty,          ""期末数量
    SUM( ztco0011a~zqm01_amt ) AS zqm02_amount           ""期末金额"
FROM ztco0011a
WHERE ztco0011a~bukrs = @p_bukrs
  AND ztco0011a~lfgja = @pf_gjahr "未来年度
  AND ztco0011a~lfmon = @pf_monat "未来月份
  AND ztco0011a~werks IN @s_zwerks
  AND ztco0011a~matnr IN @s_zmatnr
GROUP BY
    ztco0011a~werks,              ""工厂
    ztco0011a~matnr              ""物料编号
INTO CORRESPONDING FIELDS OF TABLE @gt2_ztco0011a.


  "没有满足条件的数据,提示信息并终止程序
  IF gt2_ztco0011a IS INITIAL.
    MESSAGE s000 WITH TEXT-c06 DISPLAY LIKE 'E'. " “ZCOR0011  进销存月报”没有未来数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

  SORT gt2_ztco0011a BY werks matnr.



ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOR0013
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcor0013 .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.


  "-------------------------------------------当前----------------------------------
  SELECT DISTINCT
      ztco0013~matnr,          ""物料编号
      ztco0013~werks,          ""工厂
      ztco0013~waers,          ""货币码
      ztco0013~pvprs,          ""周期单位价格
      ztco0013~peinh           ""价格单位"
  FROM ztco0013
  WHERE ztco0013~matnr IN @s_zmatnr          "物料编号
    AND ztco0013~werks IN @s_zwerks          "工厂
    AND ztco0013~bdatj = @pn_gjahr           "过账日期 YYYY = 当前年度
    AND ztco0013~poper = @pn_monat           "过账期间   = 当前月份
    AND ztco0013~curtp = '10'                "货币类型
  INTO CORRESPONDING FIELDS OF TABLE @gt1_ztco0013.

  "没有满足条件的数据,提示信息并终止程序
  IF gt1_ztco0013 IS INITIAL.
    MESSAGE s000 WITH TEXT-c07 DISPLAY LIKE 'E'. "“ZCOR13MA 物料成本批量分析”没有当月数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

  SORT gt1_ztco0013 BY matnr werks.


  "-------------------------------------------未来----------------------------------
  SELECT DISTINCT
      ztco0013~matnr,          ""物料编号
      ztco0013~werks,          ""工厂
      ztco0013~waers,          ""货币码
      ztco0013~pvprs,          ""周期单位价格
      ztco0013~peinh           ""价格单位"
  FROM ztco0013
  WHERE ztco0013~matnr IN @s_zmatnr          "物料编号
    AND ztco0013~werks IN @s_zwerks          "工厂
    AND ztco0013~bdatj = @pf_gjahr           "过账日期 YYYY = 未来年度
    AND ztco0013~poper = @pf_monat           "过账期间   = 未来月份
    AND ztco0013~curtp = '10'                "货币类型
  INTO CORRESPONDING FIELDS OF TABLE @gt2_ztco0013.

  "没有满足条件的数据,提示信息并终止程序
  IF gt2_ztco0013 IS INITIAL.
    MESSAGE s000 WITH TEXT-c08 DISPLAY LIKE 'E'. "“ZCOR13MA 物料成本批量分析”没有未来月份数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

  SORT gt2_ztco0013 BY matnr werks.



ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MBEWH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mbewh .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.


  "-------------------------------------------当前----------------------------------
  SELECT
      mbewh~matnr,          ""物料编号
      mbewh~bwkey,          ""估价范围
      mbewh~verpr,          ""移动平均价格/周期单价
      mbewh~peinh          ""价格单位"
  FROM mbewh
  WHERE mbewh~matnr IN @s_zmatnr          "物料编号
    AND mbewh~bwkey IN @s_zwerks          "工厂
    AND mbewh~lfgja = @pn_gjahr           "当前期间的会计年度
    AND mbewh~lfmon = @pn_monat           "当前期间(过账期间)
    AND mbewh~vprsv = 'V'                "价格控制指示符
  INTO CORRESPONDING FIELDS OF TABLE @gt1_mbewh.

  "没有满足条件的数据,提示信息并终止程序
*  IF gt1_mbewh IS INITIAL.
*    MESSAGE s000 WITH TEXT-c09 DISPLAY LIKE 'E'. "当前成本单价没找到!
*    LEAVE LIST-PROCESSING.
*  ENDIF.

  SORT gt1_mbewh BY matnr bwkey.


  "-------------------------------------------未来----------------------------------
  SELECT
      mbewh~matnr,          ""物料编号
      mbewh~bwkey,          ""估价范围
      mbewh~verpr,          ""移动平均价格/周期单价
      mbewh~peinh          ""价格单位"
  FROM mbewh
  WHERE mbewh~matnr IN @s_zmatnr          "物料编号
    AND mbewh~bwkey IN @s_zwerks          "工厂
    AND mbewh~lfgja = @pf_gjahr           "当前期间的会计年度
    AND mbewh~lfmon = @pf_monat           "当前期间(过账期间)
    AND mbewh~vprsv = 'V'                "价格控制指示符
  INTO CORRESPONDING FIELDS OF TABLE @gt2_mbewh.

  "没有满足条件的数据,提示信息并终止程序
*  IF gt2_mbewh IS INITIAL.
*    MESSAGE s000 WITH TEXT-c10 DISPLAY LIKE 'E'. "未来期间成本单价没找到!
*    LEAVE LIST-PROCESSING.
*  ENDIF.

  SORT gt2_mbewh BY matnr bwkey.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MATNR_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_matnr_raw_2 . "方法二,和方法一的内表不一样

  IF gt_lcm1 IS INITIAL.
    RETURN.
  ENDIF.

  s_zmatnr-sign = 'I'.
  s_zmatnr-option = 'EQ'.
  s_zwerks-sign = 'I'.
  s_zwerks-option = 'EQ'.
  LOOP AT gt_lcm1 INTO gs_lcm1.
    "虽然逻辑是这样但也难免以后有变,干脆不卡控,后面根据需要做取值
    "gs_lcm1-bklas = '7920' AND gs_lcm1-beskz = 'F' 其实是7920的E件不找,F件要找
    "gs_lcm1-bklas = '7920' AND gs_lcm1-beskz = 'F' 没有成品料号的要找
    "gs_lcm1-bklas = '3061' 的也没有采购价
    s_zmatnr-low = gs_lcm1-matnr.          ""物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_lcm1-werks.           ""工厂
    COLLECT s_zwerks.
  ENDLOOP.
  CLEAR:gs_lcm1.


  LOOP AT gt_ztco0043b_raw INTO gs_ztco0043b_raw.
    s_zmatnr-low = gs_ztco0043b_raw-matnr.          ""物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_ztco0043b_raw-werks.           ""工厂
    COLLECT s_zwerks.
  ENDLOOP.
  CLEAR:gs_ztco0043b_raw.




ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MATNR_RAW_2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_matnr_raw_1 . "方法一,原来的方法

  IF gt_lcm2 IS INITIAL.
    RETURN.
  ENDIF.

  s_zmatnr-sign = 'I'.
  s_zmatnr-option = 'EQ'.
  s_zwerks-sign = 'I'.
  s_zwerks-option = 'EQ'.
  LOOP AT gt_lcm2 INTO gs_lcm1.
    "虽然逻辑是这样但也难免以后有变,干脆不卡控,后面根据需要做取值
    "gs_lcm1-bklas = '7920' AND gs_lcm1-beskz = 'F' 其实是7920的E件不找,F件要找
    "gs_lcm1-bklas = '7920' AND gs_lcm1-beskz = 'F' 没有成品料号的要找
    "gs_lcm1-bklas = '3061' 的也没有采购价
    s_zmatnr-low = gs_lcm1-matnr.          ""物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_lcm1-werks.           ""工厂
    COLLECT s_zwerks.
  ENDLOOP.
  CLEAR:gs_lcm1.


  LOOP AT gt_ztco0043b_raw INTO gs_ztco0043b_raw.
    s_zmatnr-low = gs_ztco0043b_raw-matnr.          ""物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_ztco0043b_raw-werks.           ""工厂
    COLLECT s_zwerks.
  ENDLOOP.
  CLEAR:gs_ztco0043b_raw.


*  LOOP AT gt1_ckis INTO gs1_ckis.
*    IF gs1_ckis-matnr IS NOT INITIAL.
*      s_zmatnr-low = gs1_ckis-matnr.          ""物料
*      COLLECT s_zmatnr.
*    ENDIF.
*    IF gs1_ckis-werks IS NOT INITIAL.
*      s_zwerks-low = gs1_ckis-werks.           ""工厂
*      COLLECT s_zwerks.
*    ENDIF.
*  ENDLOOP.
*  CLEAR:gs1_ckis.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_EKPO
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ekpo .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  SELECT DISTINCT
      ekpo~matnr,          ""物料编号
      "ekpo~werks,          ""工厂 (不区分工厂取采购价)
      mseg~budat_mkpf,     "物料凭证中的过账日期
      ekko~waers,          ""货币码
      ekpo~netpr,          ""采购凭证中的净价(以凭证货币计) 11长度2小数
      ekpo~peinh          ""价格单位"  5长度
      "这里不能取物料数量
  FROM mseg  "物料凭证
      LEFT JOIN ekpo ON ekpo~ebeln = mseg~ebeln AND ekpo~ebelp = mseg~ebelp AND ekpo~bukrs = mseg~bukrs "采购凭证项目表,通过 采购凭证、项目、公司 链接
      LEFT JOIN ekko ON ekko~ebeln = ekpo~ebeln "采购凭证抬头表
      LEFT JOIN bkpf ON substring( bkpf~awkey, 1, 10 ) = mseg~mblnr AND substring( bkpf~awkey, 11, 4 ) = mseg~mjahr AND bkpf~bukrs = ekko~bukrs "会计核算凭证标题,用“AWKEY 对象键值”链接,取会计凭证等数据
   WHERE bkpf~gjahr = @pf_gjahr AND bkpf~monat = @pf_monat "符合“BKPF 会计核算凭证标题【表】”的年、月
     AND ekko~memory = '' "采购订单未完成
     AND ekpo~netpr <> 0 AND ekpo~peinh <> 0 "免费的采购单有时有会计凭证,有时又没有
     AND mseg~menge <> 0 "物料凭证要有数量
     AND ekpo~matnr IN @s_zmatnr
     AND mseg~bukrs = @p_bukrs
     "AND ekpo~werks IN @s_zwerks(不区分工厂取采购价)
     AND substring( ekpo~werks , 1, 2 ) <> 'NV' ""不是无价的
   INTO CORRESPONDING FIELDS OF TABLE @gt_ekpo1.


  "寄售单价,用金额除以数量算单价
  SELECT DISTINCT
      mseg~matnr,           ""物料编号
      "mseg~werks,           ""工厂 (不区分工厂取采购价)
      mseg~budat_mkpf,      "物料凭证中的过账日期
      t001~waers,           ""本位币
      mseg~dmbtr,           ""以本币计的金额
      mseg~menge            ""数量
  FROM mseg  "物料凭证
     LEFT JOIN t001 ON t001~bukrs = mseg~bukrs
     LEFT JOIN bkpf ON substring( bkpf~awkey, 1, 10 ) = mseg~mblnr AND substring( bkpf~awkey, 11, 4 ) = mseg~mjahr AND bkpf~bukrs = mseg~bukrs "会计核算凭证标题,用“AWKEY 对象键值”链接,取会计凭证等数据
  WHERE bkpf~gjahr = @pf_gjahr AND bkpf~monat = @pf_monat "符合“BKPF 会计核算凭证标题【表】”的年、月
     AND mseg~matnr IN @s_zmatnr  "物料
     AND mseg~bukrs = @p_bukrs
     "and mseg~werks IN @s_zwerks "(不区分工厂取采购价)
     AND substring( mseg~werks , 1, 2 ) <> 'NV' ""不是无价的
     AND mseg~sobkz = 'K'          "特殊库存标识 是寄售
     AND mseg~lifnr IS NOT INITIAL ""供应商帐户号:关系人不会寄售
     AND mseg~ebeln IS INITIAL     ""采购订单号:寄售没有采购单
     AND mseg~dmbtr <> 0            ""以本币计的金额,寄售金额是零的不要
     AND mseg~menge <> 0           "物料凭证要有数量
  APPENDING CORRESPONDING FIELDS OF TABLE @gt_ekpo1.



  IF gt_ekpo1 IS INITIAL.
    RETURN.
  ENDIF.


  LOOP AT gt_ekpo1 INTO gs_ekpo1.

    IF gs_ekpo1-menge = 0. "数量是零说明是正常的,不是零说明是寄售的

      "比如说日币的转换因子是1000,单价需要乘转换因子
      CALL FUNCTION 'CURRENCY_CONVERTING_FACTOR'
        EXPORTING
          currency          = gs_ekpo1-waers
        IMPORTING
          factor            = l_factor
        EXCEPTIONS
          too_many_decimals = 1
          OTHERS            = 2.

      "转换因子 * 采购凭证中的净价  /  价格单位
      gs_ekpo1-zzprice = l_factor * gs_ekpo1-netpr / gs_ekpo1-peinh.

    ELSE.
      gs_ekpo1-zzprice = gs_ekpo1-dmbtr / gs_ekpo1-menge. "寄售采购价 =  本币金额/数量
    ENDIF.

    MODIFY gt_ekpo1 FROM gs_ekpo1 TRANSPORTING zzprice.  "原币价格
    CLEAR:gs_ekpo1.
  ENDLOOP.



  "升序:物料编号 工厂 凭证中的过账日期 货币码 实际价
  "未来期间最接近计算期间的,要升序排
  SORT gt_ekpo1 BY matnr budat_mkpf waers zzprice." WERKS

  LOOP AT gt_ekpo1 INTO gs_ekpo1.
    IF gs_ekpo1-matnr   <> "&& gs_ekpo1-werks
      gs_ekpo2-matnr . "&& gs_ekpo2-werks
      gs_ekpo2-matnr = gs_ekpo1-matnr.          ""物料
      "gs_ekpo2-werks = gs_ekpo1-werks.            ""工厂
      APPEND gs_ekpo1 TO gt_ekpo2.
    ENDIF.
  ENDLOOP.
  CLEAR:gs_ekpo1,gs_ekpo2.
  CLEAR:gt_ekpo1.

  SORT gt_ekpo2 BY matnr ."werks.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZMMR1098_BUY
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zmmr1098_buy .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  DATA: fs_data1 TYPE REF TO data.

  FIELD-SYMBOLS: <fs_table1> TYPE ANY TABLE.

  RANGES:s_mon FOR bkpf-budat.

  cl_salv_bs_runtime_info=>set(
     EXPORTING
       display  = abap_false  "不显示
       metadata = abap_false
       data     = abap_true
    ).

  s_mon-sign =  'I'.
  s_mon-option = 'BT'. "不是EQ
  s_mon-low = lv_fdate1.
  s_mon-high = '99991231'. "lv_fdate2' 应该要输入未来月末日期更合理但是现在取不到
  APPEND s_mon.

  SUBMIT zmmr1098
    WITH s_matnr IN s_zmatnr
    WITH s_yxdate IN s_mon
     AND RETURN.

  "ZCOD0046 取值说的是CSG,内表也叫lt_CSG,但是看到并没有筛选CSG,其他厂区的资料也能取到的样子
  "此处的核价是通用的不区分法人
  TRY.
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = fs_data1 ).
      ASSIGN fs_data1->* TO <fs_table1>.
      IF <fs_table1> IS ASSIGNED.
        "后续处理逻辑
        MOVE-CORRESPONDING <fs_table1> TO gtb1_ztmmr1098.
*          APPEND LINES OF GT_OUT TO ET_1147BOM.
*           EV_RESPONSE = /ui2/cl_json=>serialize( EXPORTING  data = ET_1147BOM[] ).
      ENDIF.
    CATCH cx_salv_bs_sc_runtime_info.
      MESSAGE '获取数据失败' TYPE 'E' .
  ENDTRY.
  "清除设置的格式
  cl_salv_bs_runtime_info=>clear_all( ).


  IF gtb1_ztmmr1098 IS INITIAL.
    RETURN.
  ENDIF.

  "降序:物料编码 有效期开始日期 有效期截止日期 币别 实际单价
  SORT gtb1_ztmmr1098 DESCENDING BY matnr datab datbi konwa zzprice.

  LOOP AT gtb1_ztmmr1098 INTO gsb1_ztmmr1098.
    IF gsb1_ztmmr1098-datab <= lv_fdate2 . "有效开始日期必须小于未来月末日期
      IF gsb1_ztmmr1098-matnr <>
        gsb2_ztmmr1098-matnr .
        gsb2_ztmmr1098-matnr = gsb1_ztmmr1098-matnr.                ""物料编号
        APPEND gsb1_ztmmr1098 TO gtb2_ztmmr1098.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gsb1_ztmmr1098,gsb2_ztmmr1098,gtb1_ztmmr1098.

  SORT gtb2_ztmmr1098 BY matnr.

  "直接取表的,不考虑转换因子

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_REPORT_1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_report_1 .

  "DATA lv_boolean TYPE c.

  IF gt_lcm1 IS INITIAL.
    RETURN.
  ENDIF.

  "lv_boolean = ''.

  LOOP AT gt_lcm1 INTO gs_lcm1.
    "入库总数不为零有入库的部分
    ""READ TABLE gt_erfmg1 INTO gs_erfmg
    READ TABLE gtz_stpov INTO DATA(waz_stpov) WITH KEY zmatnr = gs_lcm1-matnr          ""查询的物料编号
                                                       zwerks = gs_lcm1-werks          ""查询的工厂
                                                       BINARY SEARCH."
    IF sy-subrc = 0.
      APPEND gs_lcm1 TO gt_lcm2.
      "lv_boolean = 'X'.
    ELSE.
      "入库数为零的部分
      READ TABLE gt_erfmg2 INTO wa_erfmg WITH KEY zmatnr = gs_lcm1-matnr          ""查询的物料编号
                                                  zwerks = gs_lcm1-werks          ""查询的工厂
                                                  BINARY SEARCH."
      IF sy-subrc = 0.
        gs_lcm1-werks_head = gs_lcm1-werks.          ""成品料号的工厂  =  查询料号的工厂
        gs_lcm1-matnr_head = wa_erfmg-matnrs.          ""成品料号(复数)
        gs_lcm1-insign = '2'."有成品料号没入库量
        APPEND gs_lcm1 TO gt_ylcm.
      ELSE.
        APPEND gs_lcm1 TO gt_ylcm.
      ENDIF.
    ENDIF.
    CLEAR:gs_lcm1.
  ENDLOOP.
  CLEAR:gs_lcm1,gs_erfmg,wa_erfmg.


  IF gt_lcm2 IS NOT INITIAL.

    SORT gt_lcm2 BY matnr werks.

    LOOP AT gt_lcm2 INTO gs_lcm1.
      lv_n = lv_n + 1.
      gs_lcm1-zitem = lv_n.
      MODIFY gt_lcm2 FROM gs_lcm1 TRANSPORTING zitem.
    ENDLOOP.
    CLEAR gs_lcm1.
    lv_n = 0.

    LOOP AT gt_lcm2 INTO gs_lcm1
         GROUP BY ( matnr = gs_lcm1-matnr werks = gs_lcm1-werks )
                  ASCENDING ASSIGNING FIELD-SYMBOL(<group_lcm>).
      LOOP AT GROUP <group_lcm> ASSIGNING FIELD-SYMBOL(<fsz_lcm>).
        gtz_lcm-matnr = <fsz_lcm>-matnr. ""物料
        gtz_lcm-werks = <fsz_lcm>-werks.   ""工厂
        APPEND <fsz_lcm> TO gtz_lcm-datas.
      ENDLOOP.
      APPEND gtz_lcm.
      CLEAR gtz_lcm. "是清除工作区,不是内表
    ENDLOOP.
    CLEAR:gs_lcm1.

    SORT gtz_lcm BY matnr werks.


    DO.
      IF gtz_lcm[] IS INITIAL.
        EXIT.
      ENDIF.

      READ TABLE gtz_lcm INTO DATA(gsz_lcm) INDEX 1. "每次读取第一条,计算后必须删除

      IF NOT sy-subrc = 0. "读取不成功就退出循环
        EXIT.
      ENDIF.

      "按理说,gtz_lcm 与 gtz_stpov 这两张表的物料、工厂的顺序是一模一样的,笔数也是一样的
      READ TABLE gtz_stpov INTO waz_stpov INDEX 1.

      IF NOT sy-subrc = 0. "读取不成功就退出循环
        EXIT.
      ENDIF.


      LOOP AT gsz_lcm-datas INTO gs_lcm1.

        gs_lcm2-zqm01_qty = gs_lcm1-zqm01_qty.
        gs_lcm2-zqm02_amount = gs_lcm1-zqm02_amount.
        LOOP AT waz_stpov-stpov INTO gs_stpov.
          gs_lcm1-werks_head = gs_stpov-werks.          ""成品料号的工厂
          gs_lcm1-matnr_head = gs_stpov-matnr.          ""成品料号
          gs_lcm1-erfmg = gs_stpov-erfmg1.               ""成品工单入库量
          gs_lcm1-zqm01_qty = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm01_qty.                 ""库存数量"
          gs_lcm1-zqm02_amount = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm02_amount.           ""成本金额
          gs_lcm1-qpa2 = gs_stpov-qpa2. "QPA2
          gs_lcm1-insign = '1'. "有成品料号有入库量
          "一定要进行过度,否则会出现数据溢出错误 No more memory available to add rows to an internal table.
          "APPEND 使用大概两三百万次的时候会出错
          APPEND gs_lcm1 TO gt_lcm3.

          "APPEND LINES OF 能添加的行数是有限的,但是具体有添加多少行还与列数的长度有关,
          "比如说 MATNR_HEAD 这个字段设置了最大的1333,则会报内存错误,字符设置成了255个,则可以继续执行
          "实际并没有测试出具体写多少,预估了个五十万行
          lv_n = lv_n + 1.
          IF lv_n > 500000. "APPEND LINES OF  一直有提示溢出错误
            APPEND LINES OF gt_lcm3 TO gt_ztco0043b_lcm.
            CLEAR gt_lcm3.
            lv_n = 0.
          ENDIF.
        ENDLOOP.
      ENDLOOP.
      CLEAR:gs_lcm1,gs_lcm2,gs_stpov.

      "如果只用循环的话,会因为循环次数太多而报内存错误。
      "APPEND LINES OF 不能用太多次,也不能添加太多行
      IF gt_lcm3 IS NOT INITIAL.
        APPEND LINES OF gt_lcm3 TO gt_ztco0043b_lcm.
        CLEAR gt_lcm3.
      ENDIF.
      lv_n = 0.

      "按理说都会成功删除的
      DELETE TABLE gtz_lcm[] FROM gsz_lcm. "删除第一笔
      DELETE TABLE gtz_stpov[] FROM waz_stpov. "删除第一笔

      CLEAR:gsz_lcm,waz_stpov.
    ENDDO.

    CLEAR:gs_lcm1,gs_lcm2,waz_stpov,gs_stpov,gsz_lcm.
    lv_n = 0.
    lv_line = 0.

*    "排序:zitem项次 是升序  erfmg成品工单未来入库量 是降序
*    格式变量,不方便排序
*    SORT gt_ztco0043b_lcm BY zitem erfmg DESCENDING.

    "计算汇总
    LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.
      IF gs_lcm2-zitem <> gs_lcm1-zitem.
        lv_n = lv_n + 1.
        gs_lcm2-zitem = gs_lcm1-zitem.                        ""项次
        gs_lcm2-zqm01_qty =  gs_lcm1-zqm01_qty.              ""库存数量
        gs_lcm2-zqm02_amount = gs_lcm1-zqm02_amount.           ""成本金额"
        APPEND gs_lcm2 TO gt_lcm5.
      ELSE.
        gs_lcm2-zqm01_qty = gs_lcm2-zqm01_qty + gs_lcm1-zqm01_qty.                ""库存数量
        gs_lcm2-zqm02_amount = gs_lcm2-zqm02_amount + gs_lcm1-zqm02_amount.        ""成本金额"
        MODIFY gt_lcm5 FROM gs_lcm2 INDEX lv_n TRANSPORTING zqm01_qty zqm02_amount.
      ENDIF.
    ENDLOOP.
    CLEAR:gs_lcm1,gs_lcm2.
    lv_n = 0.

    "求尾差
    LOOP AT gt_lcm2 INTO gs_lcm1.
      READ TABLE gt_lcm5 INTO gs_lcm2 WITH KEY zitem = gs_lcm1-zitem  ""项次
                                               BINARY SEARCH."
      IF sy-subrc = 0.
        gs_lcm3-zitem = gs_lcm1-zitem.                                            ""项次
        gs_lcm3-zqm01_qty = gs_lcm1-zqm01_qty - gs_lcm2-zqm01_qty.                ""库存数量
        gs_lcm3-zqm02_amount = gs_lcm1-zqm02_amount - gs_lcm2-zqm02_amount.       "成本金额"
        APPEND gs_lcm3 TO gt_lcm6.
      ENDIF.
    ENDLOOP.
    CLEAR:gs_lcm1,gs_lcm2,gs_lcm3.

    "补尾差
    LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.
      IF gs_lcm2-zitem <> gs_lcm1-zitem.
        gs_lcm2-zitem = gs_lcm1-zitem.      ""项次
        READ TABLE gt_lcm6 INTO gs_lcm3 WITH KEY zitem = gs_lcm1-zitem  ""项次
                                                 BINARY SEARCH."
        IF sy-subrc = 0.
          gs_lcm4-zqm01_qty = gs_lcm1-zqm01_qty + gs_lcm3-zqm01_qty.                ""库存数量
          gs_lcm4-zqm02_amount = gs_lcm1-zqm02_amount + gs_lcm3-zqm02_amount.       "成本金额"
          MODIFY gt_ztco0043b_lcm FROM gs_lcm4 TRANSPORTING zqm01_qty zqm02_amount.
        ENDIF.
      ENDIF.
    ENDLOOP.
    CLEAR:gs_lcm1,gs_lcm2,gs_lcm3,gs_lcm4.

    "测试发现内表有八百多万行数据时出现内存不足的情况
    "APPEND LINES OF gt_lcm4 TO gt_ztco0043b_lcm.

    CLEAR:gt_lcm2,gt_lcm3,gt_lcm4,gt_lcm5,gt_lcm6.

  ENDIF.

  CLEAR:gt_lcm1. "


  APPEND LINES OF gt_ylcm TO gt_ztco0043b_lcm.
  CLEAR gt_ylcm.



*  IF lv_boolean = 'X'.
*
*    LOOP AT gtz_stpov INTO waz_stpov.
*
*      lv_ztime = sy-uzeit.
*      lv_str = |{ lv_ztime+0(2) }:{ lv_ztime+2(2) }:{ lv_ztime+4(2) }|.
*
*      lv_line  = lv_line + 1.
*      lv_result = ( lv_line - 1 ) * 100 / lines( gtz_stpov ).
*      lv_restex = lv_result.
*      lv_stxt =  |开始时间:{ lv_str }  第{ lv_line },共{ lines( gtz_stpov ) }  进度:{ lv_restex } %   料号:{ waz_stpov-zmatnr } 工厂:{ waz_stpov-zwerks }  |.
*
*      WITH +data AS ( SELECT * FROM @waz_stpov-stpov AS lt_stpov )
*         SELECT
*           a~lfgja AS zn_gjahr,                  ""当前年度
*           a~lfmon AS zn_monat,                  ""当前月份
*           @pf_gjahr AS zf_gjahr,                           ""未来年度
*           @pf_monat AS zf_monat,                           ""未来月份
*           a~bukrs,                             ""公司代码
*           a~werks,                             ""工厂
*           a~matnr,                             ""物料编号
*           a~bklas,                             ""评估分类
*           a~beskz,                             ""采购类型
*           a~totqty AS zqm01_qty,               ""库存数量
*           a~salk3 AS zqm02_amount,             ""成本金额
*           a~maktx,                             ""物料描述
*           a~lgort,                             ""库存地点
*           a~lgobe,                             ""库存地点描述
*           a~lgort_p,                           ""仓库属性
*           a~charg,                             ""批次
*           a~hsdat,                             ""批号生成日期"
*           mara~prdha,                                     ""产品层次
*           a~zcmcc,                             ""机种
*           a~prctr,                             ""利润中心
*           a~dull_month,                        ""呆滞月份
*           a~stday,                             ""库龄天数"
*           b~werks AS werks_head,        ""成品料号的工厂
*           b~matnr AS matnr_head        ""成品料号(复数)
*       FROM +data AS b
*         INNER JOIN ztco0043_slm AS a ON a~bukrs = @p_bukrs
*                                AND a~lfgja = @pn_gjahr "当前年度
*         AND a~lfmon = @pn_monat "当前月份
*         AND a~matnr = b~zmatnr "物料
*         AND a~werks = b~zwerks "工厂
*         "AND lgort_p IN @s_lgort_p
*         LEFT JOIN mara AS mara ON mara~matnr = a~matnr
*
*         APPENDING CORRESPONDING FIELDS OF TABLE @gt_ztco0043b_lcm.
*
*    ENDLOOP.
*    CLEAR waz_stpov.
*
*  ENDIF.
*  lv_boolean = ''.


*  IF gt_lcm2 IS NOT INITIAL.
*
*
*    SORT gt_lcm2 BY matnr werks.
*
*    LOOP AT gt_lcm2 INTO gs_lcm1.
*      lv_n = lv_n + 1.
*      gs_lcm1-zitem = lv_n.
*      MODIFY gt_lcm2 FROM gs_lcm1 TRANSPORTING zitem.
*    ENDLOOP.
*    CLEAR gs_lcm1.
*    lv_n = 0.
*
*    LOOP AT gt_lcm2 INTO gs_lcm1
*         GROUP BY ( matnr = gs_lcm1-matnr werks = gs_lcm1-werks )
*                  ASCENDING ASSIGNING FIELD-SYMBOL(<group_lcm>).
*      LOOP AT GROUP <group_lcm> ASSIGNING FIELD-SYMBOL(<fs_lcm>).
*        gtz_lcm-matnr = <fs_lcm>-matnr. ""物料
*        gtz_lcm-werks = <fs_lcm>-werks.   ""工厂
*        APPEND <fs_lcm> TO gtz_lcm-datas.
*      ENDLOOP.
*      APPEND gtz_lcm.
*      CLEAR gtz_lcm. "是清除工作区,不是内表
*    ENDLOOP.
*    CLEAR:gs_lcm1.
*
*    SORT gtz_lcm BY matnr werks.
*
*
*    lv_ztime = sy-uzeit.
*    lv_str = |{ lv_ztime+0(2) }:{ lv_ztime+2(2) }:{ lv_ztime+4(2) }|.
*
*    "按理说,gtz_lcm 与 gtz_stpov 这两张表的物料、工厂的顺序是一模一样的,笔数也是一样的
*
*    DO.
*      IF gtz_lcm[] IS INITIAL.
*        EXIT.
*      ENDIF.
*
*      READ TABLE gtz_lcm INTO DATA(gsz_lcm) INDEX 1. "每次读取第一条,计算后必须删除
*
*      IF NOT sy-subrc = 0. "读取不成功就退出循环
*        EXIT.
*      ENDIF.
*
*      READ TABLE gtz_stpov INTO waz_stpov INDEX 1.
*
*      IF NOT sy-subrc = 0. "读取不成功就退出循环
*        EXIT.
*      ENDIF.
*
*      lv_line  = lv_line + 1.
*      lv_result = ( lv_line - 1 ) * 100 / lines( gt_lcm2 ).
*      lv_restex = lv_result.
*      lv_stxt =  |开始时间:{ lv_str }  第{ lv_line },共{ lines( gt_lcm2 ) }  进度:{ lv_restex } %   料号:{ gsz_lcm-matnr } 工厂:{ gsz_lcm-werks }  |.
*
*      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
*        EXPORTING
*          percentage = lv_result
*          text       = lv_stxt.
*
*      LOOP AT gsz_lcm-datas INTO gs_lcm1.
*
*        gs_lcm2-zqm01_qty = gs_lcm1-zqm01_qty.
*        gs_lcm2-zqm02_amount = gs_lcm1-zqm02_amount.
*        LOOP AT waz_stpov-stpov INTO gs_stpov.
*          gs_lcm1-werks_head = gs_stpov-werks.          ""成品料号的工厂
*          gs_lcm1-matnr_head = gs_stpov-matnr.          ""成品料号
*          gs_lcm1-erfmg = gs_stpov-erfmg1.               ""成品工单入库量
*          gs_lcm1-zqm01_qty = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm01_qty.                 ""库存数量"
*          gs_lcm1-zqm02_amount = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm02_amount.           ""成本金额
*          gs_lcm1-insign = '1'. "有成品料号有入库量
*          "一定要进行过度,否则会出现数据溢出错误 No more memory available to add rows to an internal table.
*          "APPEND 使用大概两三百万次的时候会出错
*          APPEND gs_lcm1 TO gt_lcm3.
*
*          "APPEND LINES OF 能添加的行数是有限的,但是具体有添加多少行还与列数的长度有关,
*          "比如说 MATNR_HEAD 这个字段设置了最大的1333,则会报内存错误,字符设置成了255个,则可以继续执行
*          "没有进行实际测试
*          lv_n = lv_n + 1.
*          IF lv_n > 500000. "APPEND LINES OF  一直有提示溢出错误
*            APPEND LINES OF gt_lcm3 TO gt_ztco0043b_lcm.
*            CLEAR gt_lcm3.
*            lv_n = 0.
*          ENDIF.
*        ENDLOOP.
*      ENDLOOP.
*      CLEAR:gs_lcm1,gs_lcm2,gs_stpov.
*
*      "如果只用循环的话,会因为循环次数太多而报内存错误。
*      "APPEND LINES OF 不能用太多次,也不能添加太多行
*      IF gt_lcm3 IS NOT INITIAL.
*        APPEND LINES OF gt_lcm3 TO gt_ztco0043b_lcm.
*        CLEAR gt_lcm3.
*      ENDIF.
*      lv_n = 0.
*
*      "按理说都会成功删除的
*      DELETE TABLE gtz_lcm[] FROM gsz_lcm. "删除第一笔
*      DELETE TABLE gtz_stpov[] FROM waz_stpov. "删除第一笔
*
*      CLEAR:gsz_lcm,waz_stpov.
*    ENDDO.
*
*    CLEAR:gs_lcm1,gs_lcm2,waz_stpov,gs_stpov,gsz_lcm.
*    lv_n = 0.
*    lv_line = 0.
*
*
**    LOOP AT gt_lcm2 INTO gs_lcm1.
**
**      lv_line  = lv_line + 1.
**      lv_result = ( lv_line - 1 ) * 100 / lines( gt_lcm2 ).
**      lv_restex = lv_result.
**      lv_stxt =  |开始时间:{ lv_str }  第{ lv_line },共{ lines( gt_lcm2 ) }  进度:{ lv_restex } %   料号:{ gs_lcm1-matnr } 工厂:{ gs_lcm1-werks }  |.
**
**      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
**        EXPORTING
**          percentage = lv_result
**          text       = lv_stxt.
**
**      READ TABLE gtz_stpov INTO waz_stpov WITH KEY zmatnr = gs_lcm1-matnr          ""查询的物料编号
**                                                        zwerks = gs_lcm1-werks          ""查询的工厂
**                                                        BINARY SEARCH."
**      IF sy-subrc = 0.
**        gs_lcm2-zqm01_qty = gs_lcm1-zqm01_qty.
**        gs_lcm2-zqm02_amount = gs_lcm1-zqm02_amount.
**        LOOP AT waz_stpov-stpov INTO gs_stpov.
**          gs_lcm1-werks_head = gs_stpov-werks.          ""成品料号的工厂
**          gs_lcm1-matnr_head = gs_stpov-matnr.          ""成品料号
**          gs_lcm1-erfmg = gs_stpov-erfmg1.               ""成品工单入库量
**          gs_lcm1-zqm01_qty = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm01_qty.                 ""库存数量"
**          gs_lcm1-zqm02_amount = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm02_amount.           ""成本金额
**          gs_lcm1-insign = '1'. "有成品料号有入库量
**          "一定要进行过度,否则会出现数据溢出错误 No more memory available to add rows to an internal table.
**          "APPEND 使用大概两三百万次的时候会出错
**          APPEND gs_lcm1 TO gt_lcm3.
**
**          "APPEND LINES OF 能添加的行数是有限的,但是具体有添加多少行还与列数的长度有关,
**          "比如说 MATNR_HEAD 这个字段设置了最大的1333,则会报内存错误,字符设置成了255个,则可以继续执行
**          "这个只是保险装置,测试时并没有一次性添加五十万行的数据的情况,如果数据还是太多的话再做调整
**          lv_n = lv_n + 1.
**          IF lv_n > 500000. "APPEND LINES OF  一直有提示溢出错误
**            APPEND LINES OF gt_lcm3 TO gt_ztco0043b_lcm.
**            CLEAR gt_lcm3.
**            lv_n = 0.
**          ENDIF.
**
**        ENDLOOP.
**
**        IF gt_lcm3 IS NOT INITIAL.
**          APPEND LINES OF gt_lcm3 TO gt_ztco0043b_lcm.
**          CLEAR gt_lcm3.
**        ENDIF.
**        lv_n = 0.
**      ENDIF.
**    ENDLOOP.
**    CLEAR:gs_lcm1,gs_lcm2,waz_stpov,gs_stpov.
**    lv_n = 0.
**    lv_line = 0.
*
**方法一 还是会出错
**    WITH +data AS ( SELECT * FROM @gt_lcm2 AS gt_lcm2 )
**    SELECT
**      a~zn_gjahr,                   ""当前年度
**      a~zn_monat,                   ""当前月份
**      a~zf_gjahr,                   ""未来年度
**      a~zf_monat,                   ""未来月份
**      a~bukrs,                      ""公司代码
**      a~zitem,                      ""项次
**      b~werks AS werks_head,        ""成品料号的工厂
**      b~matnr AS matnr_head,        ""成品料号(复数)
**      a~werks,                      ""工厂
**      a~matnr,                      ""物料编号
**      a~bklas,                      ""评估分类
**      a~beskz,                      ""采购类型
**      a~erfmg,                      ""成品工单未来入库量
**      a~zqm01_qty,                  ""库存数量
**      a~zqm01_amount,               ""料件成本单价
**      a~zqm02_amount,               ""成本金额
**"      a~zpro_cost,                  ""成品成本单价
**"      a~zpro_fut_cost,              ""成品未来期间成本单价
**"      a~zbsale_price,               ""成品未来期间售价(CNY)
**"      a~zsale_price,                ""成品未来期间售价(原币)
**"      a~zpro_waerk,                 ""成品未来期间售价的币别
**"      a~zsale_rate,                 ""未来期间销售费用率
**"      a~zpro_gross_loss,            ""成品未来毛损
**"      a~zhalf_gross_loss,           ""库存料毛损
**"      a~zloss_amount,               ""损失金额
**"      a~zraw_werks,                 ""原材料号的工厂
**"      a~zraw_matnr,                 ""原材料号
**"      a~zraw_cost,                  ""原材成本价
**"      a~zraw_purchasep_oc,          ""原材未来期间采购单价(CNY)
**"      a~zraw_purchasep_hc,          ""原材未来期间采购单价(原币)
**"      a~zraw_waerk,                 ""原材未来期间采购单价的币别
**      a~maktx,                      ""物料描述
**      a~lgort,                      ""库存地点
**      a~lgobe,                      ""库存地点描述
**      a~lgort_p,                    ""仓库属性
**      a~charg,                      ""批次
**      a~hsdat,                      ""批号生成日期
**      a~prdha,                      ""产品层次
**      a~zcmcc,                      ""机种
**      a~prctr,                      ""利润中心
**      a~dull_month,                 ""呆滞月份
**      a~stday                      ""库龄天数
**      "a~insign                      ""内置分类(LCM公式分类)"
**    FROM +data AS a
**    INNER JOIN ztco0043b_bom AS b ON b~bukrs = @p_bukrs
**                                 AND b~gjahr = @pn_gjahr "当前年度
**                                 AND b~monat = @pn_monat "当前月份
**                                 AND b~zmatnr = a~matnr "物料
**                                 AND b~zwerks = a~werks "工厂
**    INTO CORRESPONDING FIELDS OF TABLE @gt_lcm3.
**
**
**    LOOP AT gt_lcm3 INTO gs_lcm1.
**      READ TABLE gt_erfmg1 INTO gs_erfmg WITH KEY zmatnr = gs_lcm1-matnr          ""查询的物料编号
**                                                 zwerks = gs_lcm1-werks          ""查询的工厂
**                                                 matnr = gs_lcm1-matnr_head          ""成品物料编号
**                                                 werks = gs_lcm1-werks_head          ""成品的工厂
**                                                 BINARY SEARCH."
**      IF sy-subrc = 0.
**
**        gs_lcm1-erfmg = gs_erfmg-erfmg1.               ""成品工单入库量
**        gs_lcm1-zqm01_qty = gs_erfmg-erfmg1 / gs_erfmg-erfmg2 * gs_lcm1-zqm01_qty.                 ""库存数量"
**        gs_lcm1-zqm02_amount = gs_erfmg-erfmg1 / gs_erfmg-erfmg2 * gs_lcm1-zqm02_amount.           ""成本金额
**        gs_lcm1-insign = '1'. "有成品料号有入库量
**
**        APPEND gs_lcm1 TO gt_ztco0043b_lcm.
**      ENDIF.
**    ENDLOOP.
**    CLEAR:gs_lcm1,gs_stpov.
*
*
**    "排序:zitem项次 是升序  erfmg成品工单未来入库量 是降序
**    格式变量,不方便排序
**    SORT gt_ztco0043b_lcm BY zitem erfmg DESCENDING.
*
*    "计算汇总
*    LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.
*      IF gs_lcm2-zitem <> gs_lcm1-zitem.
*        lv_n = lv_n + 1.
*        gs_lcm2-zitem = gs_lcm1-zitem.                        ""项次
*        gs_lcm2-zqm01_qty =  gs_lcm1-zqm01_qty.              ""库存数量
*        gs_lcm2-zqm02_amount = gs_lcm1-zqm02_amount.           ""成本金额"
*        APPEND gs_lcm2 TO gt_lcm5.
*      ELSE.
*        gs_lcm2-zqm01_qty = gs_lcm2-zqm01_qty + gs_lcm1-zqm01_qty.                ""库存数量
*        gs_lcm2-zqm02_amount = gs_lcm2-zqm02_amount + gs_lcm1-zqm02_amount.        ""成本金额"
*        MODIFY gt_lcm5 FROM gs_lcm2 INDEX lv_n TRANSPORTING zqm01_qty zqm02_amount.
*      ENDIF.
*    ENDLOOP.
*    CLEAR:gs_lcm1,gs_lcm2.
*    lv_n = 0.
*
*    "求尾差
*    LOOP AT gt_lcm2 INTO gs_lcm1.
*      READ TABLE gt_lcm5 INTO gs_lcm2 WITH KEY zitem = gs_lcm1-zitem  ""项次
*                                               BINARY SEARCH."
*      IF sy-subrc = 0.
*        gs_lcm3-zitem = gs_lcm1-zitem.                                            ""项次
*        gs_lcm3-zqm01_qty = gs_lcm1-zqm01_qty - gs_lcm2-zqm01_qty.                ""库存数量
*        gs_lcm3-zqm02_amount = gs_lcm1-zqm02_amount - gs_lcm2-zqm02_amount.       "成本金额"
*        APPEND gs_lcm3 TO gt_lcm6.
*      ENDIF.
*    ENDLOOP.
*    CLEAR:gs_lcm1,gs_lcm2,gs_lcm3.
*
*    "补尾差
*    LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.
*      IF gs_lcm2-zitem <> gs_lcm1-zitem.
*        gs_lcm2-zitem = gs_lcm1-zitem.      ""项次
*        READ TABLE gt_lcm6 INTO gs_lcm3 WITH KEY zitem = gs_lcm1-zitem  ""项次
*                                                 BINARY SEARCH."
*        IF sy-subrc = 0.
*          gs_lcm4-zqm01_qty = gs_lcm1-zqm01_qty + gs_lcm3-zqm01_qty.                ""库存数量
*          gs_lcm4-zqm02_amount = gs_lcm1-zqm02_amount + gs_lcm3-zqm02_amount.       "成本金额"
*          MODIFY gt_ztco0043b_lcm FROM gs_lcm4 TRANSPORTING zqm01_qty zqm02_amount.
*        ENDIF.
*      ENDIF.
*    ENDLOOP.
*    CLEAR:gs_lcm1,gs_lcm2,gs_lcm3,gs_lcm4.
*
*    "测试发现内表有八百多万行数据时出现内存不足的情况
*    "APPEND LINES OF gt_lcm4 TO gt_ztco0043b_lcm.
*
*    CLEAR:gt_lcm2,gt_lcm3,gt_lcm4,gt_lcm5,gt_lcm6.
*
*  ENDIF.
*
*  CLEAR:gt_lcm1. "


*该方法会由于计算次数过多而会发生溢出错误
*  LOOP AT gtz_stpov INTO DATA(waz_stpov).
*    LOOP AT waz_stpov-stpov INTO gs_stpov.
*      IF waz_stpov-matnrs IS INITIAL.
*        waz_stpov-matnrs =  gs_stpov-matnr.          ""成品料号
*      ELSE.
*        waz_stpov-matnrs = waz_stpov-matnrs && '|' && gs_stpov-matnr.          ""成品料号
*      ENDIF.
*    ENDLOOP.
*    MODIFY gtz_stpov FROM waz_stpov TRANSPORTING matnrs.
*    CLEAR waz_stpov.
*  ENDLOOP.
*  CLEAR:waz_stpov,gs_stpov.
*
*
*  "依据工单入库量分摊库存数量和成本金额
*  LOOP AT gt_lcm1 INTO gs_lcm1.
*
*    READ TABLE gtz_stpov INTO waz_stpov WITH KEY zmatnr = gs_lcm1-matnr          ""查询的物料编号
*                                                 zwerks = gs_lcm1-werks          ""查询的工厂
*                                                 BINARY SEARCH."
*    IF sy-subrc = 0.
*
*      gs_lcm2-zqm01_qty = gs_lcm1-zqm01_qty.
*      gs_lcm2-zqm02_amount = gs_lcm1-zqm02_amount.
*      LOOP AT waz_stpov-stpov INTO gs_stpov.
*        IF gs_stpov-erfmg2 <> 0.
*          IF gs_stpov-erfmg1 <> 0. "入库数不等于零的不要,以免数据过多
*            gs_lcm1-werks_head = gs_stpov-werks.          ""成品料号的工厂
*            gs_lcm1-matnr_head = gs_stpov-matnr.          ""成品料号
*            gs_lcm1-erfmg = gs_stpov-erfmg1.               ""成品工单入库量
*            gs_lcm1-zqm01_qty = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm01_qty.                 ""库存数量"
*            gs_lcm1-zqm02_amount = gs_stpov-erfmg1 / gs_stpov-erfmg2 * gs_lcm2-zqm02_amount.           ""成本金额
*            gs_lcm1-insign = '1'. "有成品料号有入库量
*            APPEND gs_lcm1 TO gt_lcm2.
*          ENDIF.
*        ELSE."入库总量为零,意味着有成品料号,但是没有任何入库量
*          "lv_n = lv_n + 1.
*          "IF lv_n > 1.
*          "  gs_lcm1-zqm01_qty = 0.    ""库存数量"
*          "  gs_lcm1-zqm02_amount = 0. ""成本金额
*          "ENDIF.
*          gs_lcm1-werks_head = waz_stpov-zwerks.          ""成品料号的工厂  =  查询料号的工厂
*          gs_lcm1-matnr_head = waz_stpov-matnrs.          ""成品料号(复数)
*          gs_lcm1-insign = '2'."有成品料号没入库量
*          APPEND gs_lcm1 TO gt_lcm2.
*          EXIT.
*        ENDIF.
*      ENDLOOP.
*      "lv_n = 0.
*      CLEAR:gs_lcm2.
*    ELSE.
*
*      APPEND gs_lcm1 TO gt_lcm2.
*
*    ENDIF.
*    CLEAR:gs_lcm1.
*  ENDLOOP.
*  CLEAR:gs_lcm1,gs_lcm2,waz_stpov,gs_stpov.
*  lv_n = 0.


  APPEND LINES OF gt_ylcm TO gt_ztco0043b_lcm.
  CLEAR gt_ylcm.


  "原币的价格
  LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.
    "料号分类,用于区分不同的公式
    IF ( gs_lcm1-bklas = '7920' AND gs_lcm1-beskz <> 'F' ) OR gs_lcm1-bklas = '3061'.
      gs_lcm1-insign = 'A'. "成品 或 废料
    ELSEIF ( gs_lcm1-bklas = '7920' AND gs_lcm1-beskz = 'F' ) OR gs_lcm1-bklas = '7900' OR gs_lcm1-bklas = '3000'.
      IF gs_lcm1-insign = '1'. "有成品料号有入库量
        gs_lcm1-insign = 'B'. "原材、半品 有成品料号有入库量
      ELSE.
        IF gs_lcm1-beskz <> 'F'. "采购分类,包括E件,X件
          gs_lcm1-insign = 'C'. "原材、半品 有成品料号没入库量 或 没成品料号 是自制件的
        ELSEIF gs_lcm1-beskz = 'F'. "采购分类
          gs_lcm1-insign = 'D'. "原材、半品 有成品料号没入库量 或 没成品料号 是采购件的
        ENDIF.
      ENDIF.
    ELSE.
      gs_lcm1-insign = 'E'. "非存货料号的
    ENDIF.
    MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING insign.

    IF gs_lcm1-insign = 'C'.
      gs1_ckis-zwerks = gs_lcm1-werks.          ""工厂
      gs1_ckis-zmatnr = gs_lcm1-matnr.          ""物料编号"
      COLLECT gs1_ckis INTO gt1_ckis.
    ENDIF.

    CLEAR:gs_lcm1.
  ENDLOOP.
  CLEAR:gs_lcm1,gs1_ztsdr0047,gs1_ztsdr0048,gsb1_ztmmr1098,gs1_ckis.


*改为-单独跑
*  "查询原材料号
*  LOOP AT gt1_ckis INTO gs1_ckis.
*
*    s_zmatnr-sign = 'I'.
*    s_zmatnr-option = 'EQ'.
*    s_zwerks-sign = 'I'.
*    s_zwerks-option = 'EQ'.
*
*    s_zmatnr-low = gs1_ckis-zmatnr.            ""物料
*    COLLECT s_zmatnr.
*    s_zwerks-low = gs1_ckis-zwerks.            ""工厂
*    COLLECT s_zwerks.
*
*    gs_marc-zmatnr = gs1_ckis-zmatnr.            ""物料
*    gs_marc-zwerks = gs1_ckis-zwerks.            ""工厂
*    APPEND gs_marc TO gt_marc.
*
*    PERFORM frm_getdata_ckis.
*
*    IF gt3_ckis IS NOT INITIAL.
*
*      LOOP AT gt3_ckis INTO gs2_ckis.
*        IF gs2_ckis-bklas = '3000'.
*          gs2_ckis-zmatnr = gs_lcm1-matnr.            ""物料
*          gs2_ckis-zwerks = gs_lcm1-werks.            ""工厂
*          gs2_ckis-price = gs2_ckis-wertn ."/ gs2_ckis-peinh.          ""金额 = 控制区域货币的值  / 以控制范围货币记价的单位价格
*          APPEND gs2_ckis TO gt2_ckis.
*        ENDIF.
*      ENDLOOP.
*      CLEAR gs2_ckis.
*
*      IF gt2_ckis IS NOT INITIAL.
*        "降序:查询物料  查询物料的工厂 金额 物料编号 工厂 评估类
*        SORT gt2_ckis DESCENDING BY zmatnr zwerks price matnr werks bklas .
*
*        READ TABLE gt2_ckis INTO gs2_ckis INDEX 1.
*
*        IF sy-subrc = 0.
*          MODIFY gt1_ckis FROM gs2_ckis TRANSPORTING matnr werks.
*        ENDIF.
*
*      ENDIF.
*    ENDIF.
*    CLEAR:gs2_ckis,gt3_ckis,gt2_ckis,gs_marc,gt_marc,lt_marc1.
*  ENDLOOP.
*  CLEAR:gs_marc,gs1_ckis,gs2_ckis,gt3_ckis,gt2_ckis.
*
*  SORT gt1_ckis BY zmatnr zwerks.
*
*
*  CLEAR:s_zmatnr,s_zwerks.
*  REFRESH:s_zmatnr,s_zwerks.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_REPORT_2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_report_2 .

  IF gt_ztco0043b_lcm IS INITIAL.
    RETURN.
  ENDIF.

  "原币的价格,注意,来源不一样,转换因子的考虑是不一样的,此处的原币一律要求是考虑过转换因子的原币
  LOOP AT gt_ztco0043b_lcm INTO gs_lcm1.

    IF gs_lcm1-insign = 'A' OR gs_lcm1-insign = 'B'. "成品 或 有成品有入库量的

      IF gs_lcm1-zpro_waerk IS INITIAL AND gt2_ztsdr0047 IS NOT INITIAL.                ""成品未来期间售价的币别
        READ TABLE gt2_ztsdr0047 INTO gs1_ztsdr0047 WITH KEY matnr = gs_lcm1-matnr_head          ""成品料号
                                                             "werks = gs_lcm1-werks_head          ""成品料号的工厂
                                                             BINARY SEARCH."
        IF sy-subrc = 0.
          gs_lcm1-zpro_waerk = gs1_ztsdr0047-waerk.            ""成品未来期间售价的币别
          gs_lcm1-zsale_price = gs1_ztsdr0047-netpr2.          ""成品未来期间售价(原币)"
        ENDIF.
      ENDIF.

      IF gs_lcm1-zpro_waerk IS INITIAL AND gt2_vbap IS NOT INITIAL.                ""成品未来期间售价的币别
        READ TABLE gt2_vbap INTO gs1_vbap WITH KEY matnr = gs_lcm1-matnr_head          ""成品料号
                                                   BINARY SEARCH."
        IF sy-subrc = 0.
          gs_lcm1-zpro_waerk = gs1_vbap-waerk.            ""成品未来期间售价的币别
          gs_lcm1-zsale_price = gs1_vbap-zzprice.          ""成品未来期间售价(原币)"
        ENDIF.
      ENDIF.

      IF gs_lcm1-zpro_waerk IS INITIAL AND gt2_vbkd IS NOT INITIAL.                ""成品未来期间售价的币别
        READ TABLE gt2_vbkd INTO gs1_vbkd WITH KEY matnr = gs_lcm1-matnr_head          ""成品料号
                                                   BINARY SEARCH."
        IF sy-subrc = 0.
          gs_lcm1-zpro_waerk = gs1_vbkd-waers.            ""成品未来期间售价的币别
          gs_lcm1-zsale_price = gs1_vbkd-zzprice.          ""成品未来期间售价(原币)"
        ENDIF.
      ENDIF.

      IF gs_lcm1-zpro_waerk IS INITIAL AND gt2_ztsdr0048 IS NOT INITIAL.                ""成品未来期间售价的币别
        READ TABLE gt2_ztsdr0048 INTO gs1_ztsdr0048 WITH KEY matnr = gs_lcm1-matnr_head          ""成品料号
                                                             "vkorg = gs_lcm1-bukrs                ""公司代码
                                                             BINARY SEARCH."
        IF sy-subrc = 0.
          gs_lcm1-zpro_waerk = gs1_ztsdr0048-konwa.              ""成品未来期间售价的币别
          gs_lcm1-zsale_price = gs1_ztsdr0048-pc_kbetr.          ""成品未来期间售价(原币)"
        ENDIF.
      ENDIF.

      IF gs_lcm1-zpro_waerk IS INITIAL AND gts2_ztmmr1098 IS NOT INITIAL.                ""成品未来期间售价的币别
        READ TABLE gts2_ztmmr1098 INTO gss1_ztmmr1098 WITH KEY matnr = gs_lcm1-matnr_head          ""成品料号
                                                             BINARY SEARCH."
        IF sy-subrc = 0.
          gs_lcm1-zpro_waerk = gss1_ztmmr1098-konwa.             ""成品未来期间售价的币别
          gs_lcm1-zsale_price = gss1_ztmmr1098-zzprice.          ""成品未来期间售价(原币)"
        ENDIF.
      ENDIF.

      IF gs_lcm1-zpro_waerk IS NOT INITIAL.
        gs_rate1-waerk = gs_lcm1-zpro_waerk.
        COLLECT gs_rate1 INTO gt_rate1.

        MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING zpro_waerk zsale_price.
      ENDIF.

    ELSEIF  gs_lcm1-insign = 'C'.
      "找原材料gt_ztco0043b_raw " 1_ckis >> _ztco0043b_raw
      READ TABLE gt_ztco0043b_raw INTO gs_ztco0043b_raw WITH KEY zwerks = gs_lcm1-werks          ""工厂
                                                                 zmatnr = gs_lcm1-matnr          ""物料编号
                                                                 BINARY SEARCH."
      IF sy-subrc = 0.
        IF gs_ztco0043b_raw-matnr IS NOT INITIAL AND gs_ztco0043b_raw-werks IS NOT INITIAL.
          gs_lcm1-zraw_matnr = gs_ztco0043b_raw-matnr.          ""原材料号
          gs_lcm1-zraw_werks = gs_ztco0043b_raw-werks.          ""原材料号的工厂"
          MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING zraw_matnr zraw_werks.

          "先取采购单的价格,再取采购核价
          "采购凭证价
          READ TABLE gt_ekpo2 INTO gs_ekpo1 WITH KEY matnr = gs_lcm1-zraw_matnr           ""原材料号
                                                     "werks = gs_lcm1-zraw_werks          ""原材料号的工厂"(不取分工厂,法人不能合并运行)
                                                     BINARY SEARCH."
          IF sy-subrc = 0.
            gs_rate1-waerk = gs_ekpo1-waers.
            COLLECT gs_rate1 INTO gt_rate1.

            gs_lcm1-zraw_waerk = gs_ekpo1-waers.                 ""原材未来期间采购单价的币别
            gs_lcm1-zraw_purchasep_hc = gs_ekpo1-zzprice.       ""原材未来期间采购单价(原币)"
            MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING zraw_waerk zraw_purchasep_hc.
          ELSE.

            "采购核价
            READ TABLE gtb2_ztmmr1098 INTO gsb1_ztmmr1098 WITH KEY matnr = gs_lcm1-zraw_matnr           ""原材料号
                                                                   BINARY SEARCH."
            IF sy-subrc = 0.
              gs_rate1-waerk = gsb1_ztmmr1098-konwa.
              COLLECT gs_rate1 INTO gt_rate1.

              gs_lcm1-zraw_waerk = gsb1_ztmmr1098-konwa.             ""原材未来期间采购单价的币别
              gs_lcm1-zraw_purchasep_hc = gsb1_ztmmr1098-zzprice.    ""原材未来期间采购单价(原币)"
              MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING zraw_waerk zraw_purchasep_hc.
            ENDIF.

          ENDIF.

        ENDIF.
      ENDIF.


    ELSEIF gs_lcm1-insign = 'D' OR gs_lcm1-insign = 'E'. "采购的  或   非存货的
      "采购价
      READ TABLE gt_ekpo2 INTO gs_ekpo1 WITH KEY matnr = gs_lcm1-matnr          ""物料编号
                                                 "werks = gs_lcm1-werks          ""工厂(不取分工厂,法人不能合并运行)
                                                 BINARY SEARCH."
      IF sy-subrc = 0.
        gs_rate1-waerk = gs_ekpo1-waers.
        COLLECT gs_rate1 INTO gt_rate1.

        gs_lcm1-zraw_waerk = gs_ekpo1-waers.                 ""原材未来期间采购单价的币别
        gs_lcm1-zraw_purchasep_hc = gs_ekpo1-zzprice.       ""原材未来期间采购单价(原币)"
        MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING zraw_waerk zraw_purchasep_hc.

      ELSE.

        "采购核价
        READ TABLE gtb2_ztmmr1098 INTO gsb1_ztmmr1098 WITH KEY matnr = gs_lcm1-matnr          ""原材料号
                                                               BINARY SEARCH."
        IF sy-subrc = 0.
          gs_rate1-waerk = gsb1_ztmmr1098-konwa.
          COLLECT gs_rate1 INTO gt_rate1.

          gs_lcm1-zraw_waerk = gsb1_ztmmr1098-konwa.             ""原材未来期间采购单价的币别
          gs_lcm1-zraw_purchasep_hc = gsb1_ztmmr1098-zzprice.    ""原材未来期间采购单价(原币)"
          MODIFY gt_ztco0043b_lcm FROM gs_lcm1 TRANSPORTING zraw_waerk zraw_purchasep_hc.
        ENDIF.
      ENDIF.

    ENDIF.

    CLEAR:gs_lcm1.
  ENDLOOP.
  CLEAR:gs_lcm1,gs1_ztsdr0047,gs1_ztsdr0048,gsb1_ztmmr1098,gs1_ckis,gs_ztco0043b_raw.


  SORT gt_rate1 BY waerk.


  LOOP AT gt_rate1 INTO gs_rate1.

    "因为来源过于复杂,必须每个来源考虑转换因子,不能此处写l_factor
*    "比如说日币的转换因子是1000,单价需要乘转换因子
*    CALL FUNCTION 'CURRENCY_CONVERTING_FACTOR'
*      EXPORTING
*        currency          = gs_rate1-waerk
*      IMPORTING
*        factor            = l_factor
*      EXCEPTIONS
*        too_many_decimals = 1
*        OTHERS            = 2.

    "计算原币对本币的汇率
    CALL FUNCTION 'BAPI_EXCHANGERATE_GETDETAIL'
      EXPORTING
        rate_type  = 'M'
        from_curr  = gs_rate1-waerk
        to_currncy = 'CNY'
        date       = lv_fdate1
      IMPORTING
        exch_rate  = cw_rate.

    "汇率
    gs_rate1-rate =  cw_rate-exch_rate * ( cw_rate-to_factor / cw_rate-from_factor ).
    MODIFY gt_rate1 FROM gs_rate1 TRANSPORTING rate.
  ENDLOOP.
  CLEAR:gs_rate1.

*  IF p_p2 IS NOT INITIAL. "删除当前数据
*
*    SELECT zitem
*    FROM ztco0043b_lcm
*    WHERE bukrs = @p_bukrs
*      AND zn_gjahr = @pn_gjahr "当前年度
*      AND zn_monat = @pn_monat "当前月份
*      AND zf_gjahr = @pf_gjahr "未来年度
*      AND zf_monat = @pf_monat "未来月份
*    INTO TABLE @DATA(gt_dat_ls).
*
*    lv_n = lines( gt_dat_ls ).
*
*    CLEAR gt_dat_ls.
*
*  ENDIF.

  lv_n = 0.
  LOOP AT gt_ztco0043b_lcm ASSIGNING FIELD-SYMBOL(<fs_lcm>)." INTO gs_lcm1.
    lv_n = lv_n + 1.
    <fs_lcm>-zitem = lv_n.                    ""重置: 项次

    IF <fs_lcm>-insign = 'A' OR <fs_lcm>-insign = 'B'. "成品 或 有成品有入库量的

      IF <fs_lcm>-insign = 'A'. "成品
        ""成品工单入库量
        READ TABLE gt_aufm1 INTO gs_aufm1 WITH KEY matnr = <fs_lcm>-matnr_head          ""成品料号
                                                   werks = <fs_lcm>-werks_head         ""成品料号的工厂
                                                   BINARY SEARCH."
        IF sy-subrc = 0.
          <fs_lcm>-erfmg = gs_aufm1-erfmg.
        ENDIF.
        "成品成本单价
        <fs_lcm>-zpro_cost = <fs_lcm>-zqm01_amount.                 ""成品成本单价 = 料件成本单价
      ELSE.
        "成品成本单价
        READ TABLE gt1_mbewh INTO gs1_mbewh WITH KEY matnr = <fs_lcm>-matnr_head         ""成品料号
                                                     bwkey = <fs_lcm>-werks_head          ""成品料号的工厂
                                                     BINARY SEARCH."
        IF sy-subrc = 0.
          "IF gs1_ztco0011a-zqm01_qty <> 0 . ""期末数量 不等于零
          "  <fs_lcm>-zpro_cost = gs1_ztco0011a-zqm02_amount / gs1_ztco0011a-zqm01_qty.          ""成品成本单价 = 期末金额" /  期末数量
          "ENDIF.
          <fs_lcm>-zpro_cost = gs1_mbewh-verpr / gs1_mbewh-peinh. "成品成本单价 = 移动平均价格/周期单价  /  价格单位
        ENDIF.
      ENDIF.

      "成品未来期间成本单价
      READ TABLE gt2_mbewh INTO gs2_mbewh WITH KEY matnr = <fs_lcm>-matnr_head         ""成品料号
                                                   bwkey = <fs_lcm>-werks_head          ""成品料号的工厂
                                                   BINARY SEARCH."
      IF sy-subrc = 0.
        "IF gs2_ztco0011a-zqm01_qty <> 0 . ""期末数量 不等于零
        "  <fs_lcm>-zpro_fut_cost  = gs2_ztco0011a-zqm02_amount / gs2_ztco0011a-zqm01_qty.          ""成品未来期间成本单价= 期末金额" /  期末数量
        "ENDIF.
        <fs_lcm>-zpro_fut_cost = gs2_mbewh-verpr / gs2_mbewh-peinh. "成品未来期间成本单价 = 移动平均价格/周期单价  /  价格单位
      ENDIF.

      ""成品未来期间售价(CNY)
      READ TABLE gt_rate1 INTO gs_rate1 WITH KEY waerk = <fs_lcm>-zpro_waerk BINARY SEARCH."
      IF sy-subrc = 0.
        "成品未来期间售价(CNY) = 成品未来期间售价(原币)" * 转换因子 * 汇率
        <fs_lcm>-zbsale_price = <fs_lcm>-zsale_price  * gs_rate1-rate.
      ENDIF.

      ""未来期间销售费用率
      <fs_lcm>-zsale_rate = lv_zsale_rate.

      ""成品未来毛损 = 成品未来期间成本单价 - 成品未来期间售价(CNY) * ( 1 - 销售费用率 )
      <fs_lcm>-zpro_gross_loss = <fs_lcm>-zpro_fut_cost - <fs_lcm>-zbsale_price * ( 1 - <fs_lcm>-zsale_rate ) .


    ELSEIF <fs_lcm>-insign = 'C' OR <fs_lcm>-insign = 'D' OR <fs_lcm>-insign = 'E'.

      IF <fs_lcm>-insign = 'C'.
        "原材成本价
        READ TABLE gt3_mbewh INTO gs3_mbewh WITH KEY matnr = <fs_lcm>-zraw_matnr           ""原材料号
                                                     bwkey =  <fs_lcm>-zraw_werks          ""原材料号的工厂"
                                                     BINARY SEARCH."
        IF sy-subrc = 0.
          <fs_lcm>-zraw_cost = gs3_mbewh-verpr / gs3_mbewh-peinh. "原材成本价 = 移动平均价格/周期单价  /  价格单位
        ENDIF.
      ELSEIF <fs_lcm>-insign = 'D' OR <fs_lcm>-insign = 'E'. "采购的  或   非存货的
        <fs_lcm>-zraw_werks = <fs_lcm>-werks .                 ""原材料号的工厂 =  工厂
        <fs_lcm>-zraw_matnr = <fs_lcm>-matnr.                 ""原材料号        = 物料编号"
        <fs_lcm>-zraw_cost = <fs_lcm>-zqm01_amount.           ""原材成本价      = 料件成本单价"
      ENDIF.

      IF <fs_lcm>-zraw_waerk IS NOT INITIAL.
        READ TABLE gt_rate1 INTO gs_rate1 WITH KEY waerk = <fs_lcm>-zraw_waerk BINARY SEARCH."
        IF sy-subrc = 0.
          "原材未来期间采购单价(CNY) = 原材未来期间采购单价(原币) * 转换因子 * 汇率
          <fs_lcm>-zraw_purchasep_oc = <fs_lcm>-zraw_purchasep_hc  * gs_rate1-rate.
        ENDIF.
      ENDIF.

    ENDIF.


    IF <fs_lcm>-insign = 'A'.
      ""库存料毛损 = 成品成本单价 - 成品未来期间售价(CNY) * ( 1 - 销售费用率 )
      <fs_lcm>-zhalf_gross_loss = <fs_lcm>-zpro_cost - <fs_lcm>-zbsale_price * ( 1 - <fs_lcm>-zsale_rate ) .
    ELSEIF <fs_lcm>-insign = 'B'.
      IF <fs_lcm>-zpro_cost = 0.""成品成本单价
        IF  <fs_lcm>-zpro_fut_cost <> 0. ""成品未来期间成本单价
          ""库存料毛损 = 料件成本单价 /  成品未来期间成本单价  *  成品未来毛损
          <fs_lcm>-zhalf_gross_loss = <fs_lcm>-zqm01_amount / <fs_lcm>-zpro_fut_cost * <fs_lcm>-zpro_gross_loss.
        ENDIF.
      ELSE.
        ""库存料毛损 = 料件成本单价 /  成品成本单价  *  成品未来毛损
        <fs_lcm>-zhalf_gross_loss = <fs_lcm>-zqm01_amount / <fs_lcm>-zpro_cost * <fs_lcm>-zpro_gross_loss.
      ENDIF.
    ELSE.
      ""库存料毛损 = ( 原材成本价 - 原材未来期间采购单价(CNY) ) /  原材成本价  * 料件成本单价
      IF <fs_lcm>-zraw_cost <> 0.
        <fs_lcm>-zhalf_gross_loss = ( <fs_lcm>-zraw_cost - <fs_lcm>-zraw_purchasep_oc ) / <fs_lcm>-zraw_cost * <fs_lcm>-zqm01_amount.
      ENDIF.
    ENDIF.


    ""损失金额 = 库存料毛损 * 库存数量
    <fs_lcm>-zloss_amount = <fs_lcm>-zhalf_gross_loss * <fs_lcm>-zqm01_qty.


    "超过几百万行时会提示内存不足
    "APPEND gs_lcm1 TO gt_lcm1.
    "CLEAR:gs_lcm1.

  ENDLOOP.
  lv_n = 0.
  CLEAR:gs_lcm1,gs1_ztco0011a,gs2_ztco0011a.
  "CLEAR gt_ztco0043b_lcm.


  "MOVE-CORRESPONDING gt_lcm1 TO gt_ztco0043b_lcm.
  "MOVE-CORRESPONDING gt_zlcm TO gt_ztco0043b_lcm.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MBEWH_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mbewh_raw .

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.


  "-------------------------------------------当前----------------------------------
  SELECT
      mbewh~matnr,          ""物料编号
      mbewh~bwkey,          ""估价范围
      mbewh~verpr,          ""移动平均价格/周期单价
      mbewh~peinh          ""价格单位"
  FROM mbewh
  WHERE mbewh~matnr IN @s_zmatnr          "物料编号
    AND mbewh~bwkey IN @s_zwerks          "工厂
    AND mbewh~lfgja = @pn_gjahr           "当前期间的会计年度
    AND mbewh~lfmon = @pn_monat           "当前期间(过账期间)
    AND mbewh~vprsv = 'V'                "价格控制指示符
  INTO CORRESPONDING FIELDS OF TABLE @gt3_mbewh.

  "没有满足条件的数据,提示信息并终止程序
  IF gt3_mbewh IS INITIAL.
    MESSAGE s000 WITH TEXT-c09 DISPLAY LIKE 'E'. "当前成本单价没找到!
    LEAVE LIST-PROCESSING.
  ENDIF.

  SORT gt3_mbewh BY matnr bwkey.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SELECTION_CHECK_P1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_selection_check_p1 .

  IF p_bukrs IS INITIAL.
    MESSAGE s000 WITH '“公司代码”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pn_gjahr IS INITIAL.
    MESSAGE s000 WITH '“当前年份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pn_monat IS INITIAL.
    MESSAGE s000 WITH '“当前月份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pf_gjahr IS INITIAL.
    MESSAGE s000 WITH '“未来年份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pf_monat IS INITIAL.
    MESSAGE s000 WITH '“未来月份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF p_s1 IS INITIAL AND p_s2 IS INITIAL AND p_s3 IS INITIAL.
    MESSAGE s000 WITH '“良品、不良品、呆滞”至少选其一!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  lv_nrq = pn_gjahr && pn_monat.
  lv_ndate1 = pn_gjahr && pn_monat && '01'.

  lv_frq = pf_gjahr && pf_monat.
  lv_fdate1 = pf_gjahr && pf_monat && '01'.

  IF lv_ndate1 > lv_fdate1.
    MESSAGE s000 WITH '当前日期不能大于未来日期!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

*  "如果不设置该卡控,会导致后续“显示”时把以前的数据删除
*  IF s_matnr IS NOT INITIAL OR s_werks IS NOT INITIAL.
*    IF p_p1 IS NOT INITIAL.
*      MESSAGE s000 WITH '“物料”或“工厂”不为空时仅能进行测试,“更新”不能勾选!' DISPLAY LIKE 'E'.
*      LEAVE LIST-PROCESSING.
*    ENDIF.
*  ENDIF.


  "获取当前期末日期
  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = lv_ndate1
    IMPORTING
      last_day_of_month = lv_ndate2.


  "获取未来期末日期
  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = lv_fdate1
    IMPORTING
      last_day_of_month = lv_fdate2.


  s_lgort_p-sign = 'I'.
  s_lgort_p-option = 'EQ'.
  IF p_s1 IS NOT INITIAL.
    s_lgort_p-low = '良品'.
    APPEND s_lgort_p.
  ENDIF.

  IF p_s2 IS NOT INITIAL.
    s_lgort_p-low = '不良品'.
    APPEND s_lgort_p.
  ENDIF.

  IF p_s3 IS NOT INITIAL.
    s_lgort_p-low = '呆滞'.
    APPEND s_lgort_p.
  ENDIF.

  "全选的话就改成*,主要是防止库位缺失没有补到仓库属性的情况
  IF p_s1 IS NOT INITIAL AND p_s2 IS NOT INITIAL AND p_s3 IS NOT INITIAL.
    CLEAR:s_lgort_p,s_lgort_p[].
    s_lgort_p-sign = 'I'.
    s_lgort_p-option = 'CP'. "不是EQ
    s_lgort_p-low = '*'.
    APPEND s_lgort_p.
  ENDIF.

  IF s_lgort_p IS INITIAL."屏幕检查时也有提示
    LEAVE LIST-PROCESSING.
  ENDIF.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SELECTION_CHECK_P2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_selection_check_p2 .

  IF p_bukrs IS INITIAL.
    MESSAGE s000 WITH '“公司代码”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pn_gjahr IS INITIAL.
    MESSAGE s000 WITH '“当前年份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pn_monat IS INITIAL.
    MESSAGE s000 WITH '“当前月份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pf_gjahr IS INITIAL.
    MESSAGE s000 WITH '“未来年份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  IF pf_monat IS INITIAL.
    MESSAGE s000 WITH '“未来月份”为空!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  lv_nrq = pn_gjahr && pn_monat.
  lv_ndate1 = pn_gjahr && pn_monat && '01'.

  lv_frq = pf_gjahr && pf_monat.
  lv_fdate1 = pf_gjahr && pf_monat && '01'.

  IF lv_ndate1 > lv_fdate1.
    MESSAGE s000 WITH '当前日期不能大于未来日期!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  "获取当前期末日期
  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = lv_ndate1
    IMPORTING
      last_day_of_month = lv_ndate2.


  "获取未来期末日期
  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = lv_fdate1
    IMPORTING
      last_day_of_month = lv_fdate2.



ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOD0046_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcod0046_raw .

  SELECT DISTINCT
      ztco0043_slm~werks,                             ""工厂
      ztco0043_slm~matnr                             ""物料编号
  FROM ztco0043_slm
  WHERE bukrs = @p_bukrs
    AND lfgja = @pn_gjahr "当前年度
    AND lfmon = @pn_monat "当前月份
    AND matnr IN @s_matnr "物料
    AND werks IN @s_werks "工厂
    AND substring( werks, 1, 2 ) <> 'NV' "有的料号会从无价厂工单发料,核对 ZMMR0078 ZSFSL 时要注意
    AND bklas IN ('3000','7900') ""评估分类
    AND beskz = 'E' ""采购类型 是 E
    AND matnr IS NOT INITIAL
    AND werks IS NOT INITIAL
  INTO CORRESPONDING FIELDS OF TABLE @gt_lcm1.

  "没有满足条件的数据,提示信息并终止程序
  IF gt_lcm1 IS INITIAL.
    MESSAGE s000 WITH TEXT-c00 DISPLAY LIKE 'E'. "“ZCOD0046 LCM SLM查询报表”没有数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

  lv_ztime = sy-uzeit.
  lv_str = |{ lv_ztime+0(2) }:{ lv_ztime+2(2) }:{ lv_ztime+4(2) }|.


  "查询原材料号
  LOOP AT gt_lcm1 INTO gs_lcm1.

    lv_line  = lv_line + 1.
    lv_result = ( lv_line - 1 ) * 100 / lines( gt_lcm1 ).
    lv_restex = lv_result.
    lv_stxt =  |开始时间:{ lv_str }  第{ lv_line },共{ lines( gt_lcm1 ) }  进度:{ lv_restex } %   料号:{ gs_lcm1-matnr } 工厂:{ gs_lcm1-werks }  |.

    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        percentage = lv_result
        text       = lv_stxt.

    s_zmatnr-sign = 'I'.
    s_zmatnr-option = 'EQ'.
    s_zwerks-sign = 'I'.
    s_zwerks-option = 'EQ'.

    s_zmatnr-low = gs_lcm1-matnr.            ""物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_lcm1-werks.            ""工厂
    COLLECT s_zwerks.

    gs_marc-zmatnr = gs_lcm1-matnr.            ""物料
    gs_marc-zwerks = gs_lcm1-werks.            ""工厂
    APPEND gs_marc TO gt_marc.

    "PERFORM frm_getdata_ckis.
    "PERFORM frm_getdata_ckis_raw.

    PERFORM frm_getdata_mast_sobsl. "特殊采购类型
    PERFORM frm_getdata_mast. "BOM,SQL递归
    PERFORM frm_getdata_mast_raw."计算原材料

  ENDLOOP.
  CLEAR:gs_marc,gs1_ckis,gs2_ckis,gt3_ckis,gt2_ckis.
  lv_line = 0.

  CLEAR:s_zmatnr,s_zwerks.
  REFRESH:s_zmatnr,s_zwerks.

  "PERFORM frm_getdata_raw_ckis_modify.
  PERFORM frm_getdata_mast_raw_modify.



ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_CKIS
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ckis .

  SELECT
      keko~matnr AS zmatnr, ""查询料号
      keko~werks AS zwerks, ""查询料号的工厂
      ckis~matnr,           ""物料编号
      ckis~werks,           ""工厂
      mbew~bklas,           ""评估类
      ckis~wertn,          ""控制区域货币的值
      ckis~peinh            ""以控制范围货币记价的单位价格"
 FROM ckis
      LEFT JOIN keko ON keko~kalnr = ckis~kalnr "没有数量结构的成本估算的成本估算编号
                    AND keko~kalka = ckis~kalka "成本核算类型
                    AND keko~kadky = ckis~kadky"成本核算日期 (码)
      LEFT JOIN mbew ON mbew~matnr = ckis~matnr AND mbew~bwkey = ckis~werks
   WHERE keko~kalka = '01'         "成本核算类型 :PPC1
     AND keko~kadky BETWEEN @lv_ndate1 AND @lv_ndate2          "成本核算日期 (码)
     AND keko~matnr IN @s_zmatnr
     AND keko~werks IN @s_zwerks
     AND mbew~bklas IS NOT NULL
     AND ckis~wertn <> 0
   INTO CORRESPONDING FIELDS OF TABLE @gt2_ckis.

  CLEAR:s_zmatnr,s_zwerks.
  REFRESH:s_zmatnr,s_zwerks.

  IF gt2_ckis IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt_marc BY zmatnr zwerks.


  s_zmatnr-sign = 'I'.
  s_zmatnr-option = 'EQ'.
  s_zwerks-sign = 'I'.
  s_zwerks-option = 'EQ'.
  LOOP AT gt2_ckis INTO gs1_ckis.
    "例如: EC3RY000100HT001-N 0342 20230331 标估金额是自己等于自己
    IF NOT ( gs1_ckis-zmatnr = gs1_ckis-matnr AND gs1_ckis-zwerks = gs1_ckis-werks ).
      READ TABLE gt_marc INTO gs_marc WITH KEY zmatnr = gs1_ckis-zmatnr
                                                   zwerks = gs1_ckis-zwerks
                                                   BINARY SEARCH.
      IF sy-subrc = 0.
        APPEND gs1_ckis TO gt3_ckis.

        IF gs1_ckis-bklas = '7900' OR gs1_ckis-bklas = '7920'.
          gs_marc-zmatnr = gs1_ckis-matnr.            ""物料
          gs_marc-zwerks = gs1_ckis-werks.            ""工厂
          APPEND gs_marc TO lt_marc1.

          s_zmatnr-low = gs1_ckis-matnr.            ""物料
          COLLECT s_zmatnr.
          s_zwerks-low = gs1_ckis-werks.            ""工厂
          COLLECT s_zwerks.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_ckis,gs_marc.
  CLEAR gt2_ckis.

  IF lt_marc1 IS NOT INITIAL.
    APPEND LINES OF lt_marc1 TO gt_marc.
    CLEAR lt_marc1.
  ENDIF.

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  PERFORM frm_getdata_ckis.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MAST
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mast .

  "mbewh不见得能查到原材的价格,要往前推才行,容易出现原材中不值钱的辅料有价格,值钱的原料没有价格
  SELECT
      stas~stlty,          ""物料清单类别
      stas~stlnr,          ""物料清单
      stas~stlal,          ""备选物料清单
      stas~stlkn,          ""BOM 项目节点号 "
      mast~matnr AS zmatnr,          ""查询物料编号
      mast~werks AS zwerks,          ""查询的工厂
      stpo~idnrk AS matnr,           ""物料编号
      mast~werks,                    ""工厂
      mbew~bklas,                    ""评估类
      marc~beskz,                   ""BOM组件的采购类型
      "mbewh~verpr,                   ""移动平均价格/周期单价
      "mbewh~peinh,                   ""价格单位
      stpo~menge,                    ""组件数量"
     ( CASE stas~lkenz WHEN 'X' THEN  stas~datuv ELSE @lv_ndate2 END ) AS datuv    "有效起始日期>>作为截止日期
  FROM stpo
    LEFT JOIN stas "目的是取失效日期
                  ON stas~stlty = stpo~stlty          ""物料清单类别
                  AND stas~stlnr = stpo~stlnr          ""物料清单
                  AND stas~stlkn = stpo~stlkn          ""项目节点"

    LEFT JOIN stko ON stko~stlty = stas~stlty          ""物料清单类别
                  AND stko~stlnr = stas~stlnr          ""物料清单
                  AND stko~stlal = stas~stlal          ""备选物料清单
    LEFT JOIN mast ON mast~stlnr = stko~stlnr          ""物料清单
                  AND mast~stlal = stko~stlal          ""备选物料清单
    LEFT JOIN mbew ON mbew~matnr = stpo~idnrk          ""组件物料
                  AND mbew~bwkey = mast~werks
    "LEFT JOIN mbewh ON mbewh~matnr = stpo~idnrk          ""组件物料
    "               AND mbewh~bwkey = mast~werks
    "               AND mbewh~lfgja = @pn_gjahr           "当前期间的会计年度
    "               AND mbewh~lfmon = @pn_monat           "当前期间(过账期间)
    "              AND mbewh~vprsv = 'V'                "价格控制指示符,料号不一定结算,有可能导致组件缺失
    LEFT JOIN marc ON marc~matnr = stpo~idnrk
                  AND marc~werks = mast~werks
   WHERE mast~matnr IN @s_zmatnr          ""查询物料编号
    AND mast~werks IN @s_zwerks         ""查询的工厂
    AND mast~andat <= @lv_ndate2        ""创建日期小于当前月末日期
    AND stko~stlty =  'M'                    ""物料清单类别
    AND stko~stlst =  '1'                    ""物料清单状态 "
    AND stpo~datuv <= @lv_ndate2        ""有效期自小于当前月末日期
    AND stas~datuv <= @lv_ndate2        ""有效期自小于当前月末日期
    AND stpo~idnrk IS NOT INITIAL
    AND stpo~menge <> 0
    "AND mbew~bklas IN ('3000','7900','7920') "3MULAN00094N-MB 的 ML10 对应的31MULAN00094N-MB-B,31MULAN00094N-MB-T没有评估分类
   INTO CORRESPONDING FIELDS OF TABLE @gt1_zraw.


  CLEAR:s_zmatnr,s_zwerks.
  REFRESH:s_zmatnr,s_zwerks.

  IF gt1_zraw IS INITIAL.
    RETURN.
  ENDIF.

  "查询失效的物料
  LOOP AT gt1_zraw INTO gs1_zraw.
    IF gs1_zraw-datuv < lv_ndate2 .
      APPEND gs1_zraw TO gt2_zraw.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_zraw.

  "物料清单类别 物料清单 备选物料清单 BOM 项目节点号
  SORT gt2_zraw BY stlty stlnr stlal stlkn .

  "删除失效的
  LOOP AT gt1_zraw INTO gs1_zraw.
    READ TABLE gt2_zraw INTO gs2_zraw WITH KEY stlty = gs1_zraw-stlty          ""物料清单类别
                                              stlnr = gs1_zraw-stlnr          ""物料清单
                                              stlal = gs1_zraw-stlal          ""备选物料清单
                                              stlkn = gs1_zraw-stlkn          ""BOM 项目节点号
                                              BINARY SEARCH."
    IF sy-subrc <> 0.
      gs1_raw-zmatnr = gs1_zraw-zmatnr.          ""查询物料编号
      gs1_raw-zwerks = gs1_zraw-zwerks.          ""查询的工厂
      gs1_raw-matnr = gs1_zraw-matnr.            ""物料编号
      gs1_raw-werks = gs1_zraw-werks.            ""工厂
      gs1_raw-bklas = gs1_zraw-bklas.            "评估类
      gs1_raw-beskz = gs1_zraw-beskz.            ""采购类型
      gs1_raw-menge = gs1_zraw-menge.            ""组件数量"
      APPEND gs1_raw TO gt1_raw.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_zraw,gs2_zraw,gs1_raw,gt1_zraw,gt2_zraw.

  IF gt1_raw IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt_marc BY zmatnr zwerks .

  s_zmatnr-sign = 'I'.
  s_zmatnr-option = 'EQ'.
  s_zwerks-sign = 'I'.
  s_zwerks-option = 'EQ'.
  LOOP AT gt1_raw INTO gs1_raw.
    READ TABLE gt_marc INTO gs_marc WITH KEY zmatnr = gs1_raw-zmatnr
                                                zwerks = gs1_raw-zwerks
                                                BINARY SEARCH.
    IF sy-subrc = 0.
      APPEND gs1_raw TO gt2_raw.

      "IF gs1_raw-bklas = '7900' OR gs1_raw-bklas = '7920'. "一般而言只有成品、半品、才有BOM组件,但是发现C116有例外
      READ TABLE gt_marc INTO gs_marc WITH KEY zmatnr = gs1_raw-matnr
                                               zwerks = gs1_raw-werks
                                               BINARY SEARCH.
      IF sy-subrc <> 0.
        gs_marc-zmatnr = gs1_raw-matnr.            ""物料
        gs_marc-zwerks = gs1_raw-werks.            ""工厂
        APPEND gs_marc TO lt_marc1.

        s_zmatnr-low = gs1_raw-matnr.            ""物料
        COLLECT s_zmatnr.
        s_zwerks-low = gs1_raw-werks.            ""工厂
        COLLECT s_zwerks.
        "ENDIF.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_raw,gs_marc.
  CLEAR gt1_raw.

  IF lt_marc1 IS NOT INITIAL.
    APPEND LINES OF lt_marc1 TO gt_marc.
    CLEAR lt_marc1.
  ENDIF.

  IF s_zmatnr[] IS INITIAL OR s_zwerks[] IS INITIAL.
    RETURN.
  ENDIF.

  PERFORM frm_getdata_mast.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MAST_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mast_raw .

  CLEAR:gt1_raw,gt_marc,lt_marc1.

  IF gt2_raw IS INITIAL.
    RETURN.
  ENDIF.

  "所有的BOM料号进行筛选出原材料号
  LOOP AT gt2_raw INTO gs1_raw.
    IF gs1_raw-bklas = '3000' OR gs1_raw-bklas = '7900' .
      IF gs1_raw-beskz = 'F'."评估分类  "gs1_raw-bklas = '3000'.
        gs1_raw-zmatnr = gs_lcm1-matnr.            ""物料
        gs1_raw-zwerks = gs_lcm1-werks.            ""工厂
        "IF gs1_raw-peinh <> 0.
        "  gs1_raw-price = gs1_raw-verpr / gs1_raw-peinh * gs1_raw-menge. ""金额 = 移动平均价格/周期单价  /  价格单位  *  组件数量
        "ENDIF.
        APPEND gs1_raw TO gt1_raw.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR gs1_raw.
  CLEAR gt2_raw.

  IF gt1_raw IS INITIAL.
    RETURN.
  ENDIF.

*  "降序:查询物料  查询物料的工厂 金额 物料编号 工厂 评估类
*  SORT gt1_raw DESCENDING BY zmatnr zwerks price matnr werks bklas .
*
*  READ TABLE gt1_raw INTO gs1_raw INDEX 1.
*
*  IF sy-subrc = 0.
*    IF gs1_raw-price <> 0.
*      APPEND gs1_raw TO gt3_raw.
*    ELSE.
*
*      "PERFORM frm_getdata_mast_raw_mbewh.
*      PERFORM frm_getdata_mast_raw_ckmlcr.
*
*    ENDIF.
*  ENDIF.
*  CLEAR:gs1_raw,gt1_raw.

  IF lines( gt1_raw ) = 1. "如果只有唯一一个原材料号就不比较单价了
    APPEND LINES OF gt1_raw TO gt3_raw.
  ELSE.
    PERFORM frm_getdata_mast_raw_ckmlcr.
  ENDIF.

  CLEAR gt1_raw."要清空

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MAST_RAW_MBEWH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mast_raw_mbewh .

  IF gt1_raw IS INITIAL.
    RETURN.
  ENDIF.

  SELECT
      mbewh~matnr,          ""物料编号
      mbewh~bwkey,          ""估价范围
      mbewh~lfgja,          ""当前期间的会计年度
      mbewh~lfmon,          ""当前期间(过账期间)
      mbewh~verpr,          ""移动平均价格/周期单价
      mbewh~peinh           ""价格单位"
  FROM mbewh
   FOR ALL ENTRIES IN @gt1_raw
  WHERE mbewh~matnr = @gt1_raw-matnr          "物料编号
    AND mbewh~bwkey  = @gt1_raw-werks          "工厂
    "AND mbewh~lfgja = @pn_gjahr           "当前期间的会计年度
    "AND mbewh~lfmon = @pn_monat           "当前期间(过账期间)
    AND mbewh~vprsv = 'V'                "价格控制指示符
    AND mbewh~verpr <> 0
    AND mbewh~peinh <> 0
  INTO CORRESPONDING FIELDS OF TABLE @gt1_zmbewh.

  IF gt1_zmbewh IS INITIAL.
    RETURN.
  ENDIF.

  "降序:物料编号 估价范围 当前期间的会计年度 当前期间(过账期间)
  SORT gt1_zmbewh DESCENDING BY matnr bwkey lfgja lfmon.

  LOOP AT gt1_zmbewh INTO gs1_zmbewh.
    IF gs1_zmbewh-lfgja && gs1_zmbewh-lfmon <= lv_nrq.
      IF gs1_zmbewh-matnr && gs1_zmbewh-bwkey <>
        gs2_zmbewh-matnr && gs2_zmbewh-bwkey.
        gs2_zmbewh-matnr = gs1_zmbewh-matnr.            ""物料编号
        gs2_zmbewh-bwkey = gs1_zmbewh-bwkey.            ""工厂
        APPEND gs1_zmbewh TO gt2_zmbewh.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_zmbewh,gs2_zmbewh.
  CLEAR gt1_zmbewh.

  IF gt2_zmbewh IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt2_zmbewh BY matnr bwkey.

  LOOP AT gt1_raw INTO gs1_raw.
    READ TABLE gt2_zmbewh INTO gs1_zmbewh WITH KEY matnr = gs1_raw-matnr          ""物料编号
                                                   bwkey = gs1_raw-werks          ""估价范围
                                                   BINARY SEARCH."
    IF sy-subrc = 0.
      IF gs1_zmbewh-peinh <> 0.
        gs1_raw-price = gs1_zmbewh-verpr / gs1_zmbewh-peinh * gs1_raw-menge .""金额 = 移动平均价格/周期单价  /  价格单位  *  组件数量
        MODIFY gt1_raw FROM gs1_raw TRANSPORTING price.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_raw,gs1_zmbewh.
  CLEAR gt2_zmbewh.

  SORT gt1_raw DESCENDING BY zmatnr zwerks price matnr werks bklas .

  READ TABLE gt1_raw INTO gs1_raw INDEX 1.

  IF sy-subrc = 0.
    IF gs1_raw-price <> 0.
      APPEND gs1_raw TO gt3_raw.
    ENDIF.
  ENDIF.
  CLEAR:gs1_raw,gt1_raw.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MAST_RAW_CKMLCR
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mast_raw_ckmlcr .

  IF gt1_raw IS INITIAL.
    RETURN.
  ENDIF.

  SELECT
       ckmlhd~matnr,                   ""物料编号
       ckmlhd~bwkey,                   ""估价范围
       ckmlcr~bdatj AS lfgja,          ""过账日期 YYYY
       ckmlcr~poper AS lfmon,          ""过账期间
       ckmlcr~pvprs AS verpr,          ""周期单位价格(实际价)
       ckmlcr~stprs,          "标准价格
       ckmlcr~peinh                    ""价格单位"
   FROM ckmlcr
    LEFT JOIN ckmlhd ON ckmlhd~kalnr = ckmlcr~kalnr
    FOR ALL ENTRIES IN @gt1_raw
   WHERE ckmlhd~kzbws IS INITIAL    "特定库存的评估 ,查看SE16看出来的
      AND ckmlhd~matnr = @gt1_raw-matnr "物料编号
      AND ckmlhd~bwkey  = @gt1_raw-werks  "估价范围
      AND ckmlcr~curtp = '10'          "货币类型
      AND ckmlcr~peinh <> 0 "价格单位不等于零
      AND ( ckmlcr~pvprs <> 0 OR ckmlcr~stprs <> 0 ) "价格其一要不等于零
   INTO CORRESPONDING FIELDS OF TABLE @gt1_ckmlcr.

  IF gt1_ckmlcr IS INITIAL.
    RETURN.
  ENDIF.

  "
  LOOP AT gt1_ckmlcr INTO gs1_ckmlcr.
    "降序:实际价格优先于标准价格
    IF gs1_ckmlcr-verpr <> 0.
      gs1_ckmlcr-insign = '2'.
    ELSE.
      gs1_ckmlcr-insign = '1'.
    ENDIF.
    MODIFY gt1_ckmlcr FROM gs1_ckmlcr TRANSPORTING insign.
  ENDLOOP.
  CLEAR gs1_ckmlcr.


  "降序:物料编号 估价范围 标识 当前期间的会计年度 当前期间(过账期间)
  SORT gt1_ckmlcr DESCENDING BY matnr bwkey insign lfgja lfmon.

  LOOP AT gt1_ckmlcr INTO gs1_ckmlcr.
    IF gs1_ckmlcr-lfgja && gs1_ckmlcr-lfmon <= lv_nrq.
      IF gs1_ckmlcr-matnr && gs1_ckmlcr-bwkey <>
        gs2_ckmlcr-matnr && gs2_ckmlcr-bwkey.
        gs2_ckmlcr-matnr = gs1_ckmlcr-matnr.            ""物料编号
        gs2_ckmlcr-bwkey = gs1_ckmlcr-bwkey.            ""工厂
        APPEND gs1_ckmlcr TO gt2_ckmlcr.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_ckmlcr,gs2_ckmlcr.
  CLEAR gt1_ckmlcr.

  IF gt2_ckmlcr IS INITIAL.
    RETURN.
  ENDIF.

  SORT gt2_ckmlcr BY matnr bwkey.

  LOOP AT gt1_raw INTO gs1_raw.
    READ TABLE gt2_ckmlcr INTO gs1_ckmlcr WITH KEY matnr = gs1_raw-matnr          ""物料编号
                                                   bwkey = gs1_raw-werks          ""估价范围
                                                   BINARY SEARCH."
    IF sy-subrc = 0.
      IF gs1_ckmlcr-peinh <> 0.
        IF gs1_ckmlcr-verpr <> 0.
          gs1_raw-zprice = gs1_ckmlcr-verpr / gs1_ckmlcr-peinh * gs1_raw-menge .""金额 = 移动平均价格/周期单价  /  价格单位  *  组件数量
        ELSE.
          gs1_raw-zprice = gs1_ckmlcr-stprs / gs1_ckmlcr-peinh * gs1_raw-menge .""金额 = 标准价格  /  价格单位  *  组件数量
        ENDIF.
        gs1_raw-price = gs1_raw-zprice.
        MODIFY gt1_raw FROM gs1_raw TRANSPORTING price.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CLEAR:gs1_raw,gs1_ckmlcr.
  CLEAR gt2_ckmlcr.

  SORT gt1_raw DESCENDING BY zmatnr zwerks price matnr werks bklas .

  READ TABLE gt1_raw INTO gs1_raw INDEX 1.

  IF sy-subrc = 0.
    IF gs1_raw-price <> 0.
      APPEND gs1_raw TO gt3_raw.
    ENDIF.
  ENDIF.
  CLEAR:gs1_raw,gt1_raw.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_ALV_FIELDCAT_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_fieldcat_raw .


*----------------------------------------------------------------------*
*                  定义宏
*----------------------------------------------------------------------*
  DEFINE macro_fieldcat.
    CLEAR ls_fieldcat.
    ls_fieldcat-fieldname = &1. "标题列对应的字段名
    ls_fieldcat-coltext = &2. "列标题 列标题,如果字段参考了DDIC,可不设置
    ls_fieldcat-fix_column = &3. "固定列 与KEY字段类似,固定列但颜色不变蓝,必须要在左边才起作用(如果设置固定列的左边包含非固定列,则该列不固定)
    ls_fieldcat-no_zero = &4. "是否隐藏输出为零的字段 当字段为数值为0时,不显示【如0,0.00,则会显示为空】当字段包含前导0时,隐藏前导0,【如0100,则会显示为100】
    "ls_fieldcat-cfieldname = &5. "currency unit field name值为当前输出内表中的货币单位字段的字段名称
    "ls_fieldcat-edit = &6. "准备输入 X:可编辑,space:不可编辑 该控制是在整列的级别上,如果想控制仅仅某一行可编辑,则需要通过style来控制
    ls_fieldcat-ref_field = &5.
    ls_fieldcat-ref_table = &6.

    APPEND ls_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.


  macro_fieldcat:
    'GJAHR' '会计年度'(s01) '' '' '' '',
    'MONAT' '月份'(s02) '' '' '' '',
    'BUKRS' '公司代码'(s03) '' '' '' '',
    'ZWERKS' '工厂'(s04) '' '' '' '',
    'ZMATNR' '物料编号'(s05) '' '' 'MATNR' 'MARA',
    'WERKS' '原材料的工厂'(s06) '' '' '' '',
    'MATNR' '原材料的物料编号'(s07) '' '' 'MATNR' 'MARA'.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_ALV_OUTPUT_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_output_raw .

  DATA: gs_disvariant TYPE disvariant.

  "gs_disvariant-variant = p2_var.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program = sy-cprog "sy-repid
*     I_INTERFACE_CHECK  = ' '
*     I_BYPASSING_BUFFER =
*     I_BUFFER_ACTIVE    =
*     I_CALLBACK_PROGRAM = ' '
*     I_CALLBACK_PF_STATUS_SET          = ' '
*     I_CALLBACK_USER_COMMAND           = ' '
*     I_CALLBACK_TOP_OF_PAGE            = ' '
*     I_CALLBACK_HTML_TOP_OF_PAGE       = ' '
*     I_CALLBACK_HTML_END_OF_LIST       = ' '
*     I_STRUCTURE_NAME   =
*     I_BACKGROUND_ID    = ' '
*     I_GRID_TITLE       =
*     I_GRID_SETTINGS    =
      is_layout_lvc      = wa_layout
      it_fieldcat_lvc    = lt_fieldcat
*     IT_EXCLUDING       =
*     IT_SPECIAL_GROUPS_LVC             =
"     it_sort_lvc        = lt_sort
*     IT_FILTER_LVC      =
*     IT_HYPERLINK       =
*     IS_SEL_HIDE        =
      i_default          = 'X'
      i_save             = 'A' " 'U'
*     is_variant         = gs_disvariant
"     it_events          = lt_event
*     IT_EVENT_EXIT      =
*     IS_PRINT_LVC       =
*     IS_REPREP_ID_LVC   =
*     I_SCREEN_START_COLUMN             = 0
*     I_SCREEN_START_LINE               = 0
*     I_SCREEN_END_COLUMN               = 0
*     I_SCREEN_END_LINE  = 0
*     I_HTML_HEIGHT_TOP  =
*     I_HTML_HEIGHT_END  =
*     IT_ALV_GRAPHICS    =
*     IT_EXCEPT_QINFO_LVC               =
*     IR_SALV_FULLSCREEN_ADAPTER        =
* IMPORTING
*     E_EXIT_CAUSED_BY_CALLER           =
*     ES_EXIT_CAUSED_BY_USER            =
    TABLES
      t_outtab           = gt_ztco0043b_raw
    EXCEPTIONS
      program_error      = 1
      OTHERS             = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
    "LEAVE LIST-PROCESSING.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZTCO0043B_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztco0043b_raw .

  "不能下物料、工厂的条件

  SELECT
      "ZTCO0043B_RAW~GJAHR,           ""会计年度
      "ZTCO0043B_RAW~MONAT,           ""月份
      "ZTCO0043B_RAW~BUKRS,           ""公司代码
      ztco0043b_raw~zwerks,          ""工厂
      ztco0043b_raw~zmatnr,          ""物料编号
      ztco0043b_raw~werks,           ""原材料的工厂
      ztco0043b_raw~matnr            ""原材料的物料编号"
  FROM ztco0043b_raw
   WHERE bukrs = @p_bukrs
    AND gjahr = @pn_gjahr "当前年度
    AND monat = @pn_monat "当前月份
    "AND zmatnr IN @s_matnr "物料
    "AND zwerks IN @s_werks "工厂
  INTO CORRESPONDING FIELDS OF TABLE @gt_ztco0043b_raw.

  SORT gt_ztco0043b_raw BY gjahr monat bukrs zwerks zmatnr.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA2_ZTCO0043B_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata2_ztco0043b_raw .

  SELECT *
  FROM ztco0043b_raw
  WHERE bukrs = @p_bukrs
    AND gjahr = @pn_gjahr "当前年度
    AND monat = @pn_monat "当前月份
    AND zmatnr IN @s_matnr "物料
    AND zwerks IN @s_werks "工厂
  INTO TABLE @gt_ztco0043b_raw.

  SORT gt_ztco0043b_raw BY gjahr monat bukrs zwerks zmatnr.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOD0046_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcod0046_bom .

  "注意:LCM的数量来源于SLM,金额不来源于,料号单价来源于进销存
  SELECT DISTINCT
      ztco0043_slm~werks,                             ""工厂
      ztco0043_slm~matnr,                             ""物料编号
      ztco0043_slm~bklas,                             ""评估分类
      ztco0043_slm~beskz                             ""采购类型
  FROM ztco0043_slm
   WHERE bukrs = @p_bukrs
    AND lfgja = @pn_gjahr "当前年度
    AND lfmon = @pn_monat "当前月份
    AND substring( werks, 1, 2 ) <> 'NV' "
    AND bklas IN ('3000','7900','7920')                     ",'7920'
    AND matnr IN @s_matnr "物料
    AND werks IN @s_werks "工厂
    AND matnr IS NOT INITIAL
    AND werks IS NOT INITIAL
  INTO CORRESPONDING FIELDS OF TABLE @gt_lcm2.

  IF gt_lcm2 IS NOT INITIAL.
    LOOP AT gt_lcm2 INTO gs_lcm1.
      IF gs_lcm1-bklas = '7920' AND gs_lcm1-beskz = 'F'.
        APPEND gs_lcm1 TO gt_lcm1.
      ELSEIF gs_lcm1-bklas = '3000' OR gs_lcm1-bklas = '7900'.
        APPEND gs_lcm1 TO gt_lcm1.
      ENDIF.
    ENDLOOP.
    CLEAR:gs_lcm1,gt_lcm2.
  ENDIF.


  "没有满足条件的数据,提示信息并终止程序
  IF gt_lcm1 IS INITIAL.
    MESSAGE s000 WITH TEXT-c00 DISPLAY LIKE 'E'. "“ZCOD0046 LCM SLM查询报表”没有数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOD0046C
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcod0046c .

  "跨工厂,考虑物料编号
  SELECT
      ztco0046c~matnr,                               ""物料编号
      ztco0046c~werk1,                               ""转出工厂
      ztco0046c~werk2                               ""转入工厂
  FROM ztco0046c
    LEFT JOIN t001w ON t001w~werks = ztco0046c~werk1
  WHERE t001w~vkorg  = @p_bukrs              ""公司代码
    AND ztco0046c~z_delete IS INITIAL
    AND ztco0046c~matnr IS NOT INITIAL
  INTO CORRESPONDING FIELDS OF TABLE @gt1_ztco0046c.

  SORT gt1_ztco0046c BY matnr werk1 werk2.

  IF gt1_ztco0046c IS NOT INITIAL.

    LOOP AT gt1_ztco0046c INTO gs1_ztco0046c
       GROUP BY ( matnr = gs1_ztco0046c-matnr werk1 = gs1_ztco0046c-werk1 )
                ASCENDING ASSIGNING FIELD-SYMBOL(<group1_ztco0046c>).
      LOOP AT GROUP <group1_ztco0046c> ASSIGNING FIELD-SYMBOL(<fs1_ztco0046c>).
        gtz1_ztco0046c-matnr = <fs1_ztco0046c>-matnr. ""物料
        gtz1_ztco0046c-werk1 = <fs1_ztco0046c>-werk1.   ""工厂
        APPEND <fs1_ztco0046c> TO gtz1_ztco0046c-datas.
      ENDLOOP.
      APPEND gtz1_ztco0046c.
      CLEAR gtz1_ztco0046c. "是清除工作区,不是内表
    ENDLOOP.
    CLEAR:gs1_ztco0046c.

    SORT gtz1_ztco0046c BY matnr werk1.

  ENDIF.


  "跨工厂,不考虑物料编号
  SELECT
      ztco0046c~werk1,                               ""转出工厂
      ztco0046c~werk2                               ""转入工厂
  FROM ztco0046c
    LEFT JOIN t001w ON t001w~werks = ztco0046c~werk1
  WHERE t001w~vkorg  = @p_bukrs              ""公司代码
    AND ztco0046c~z_delete IS INITIAL
    AND ztco0046c~matnr IS INITIAL
  INTO CORRESPONDING FIELDS OF TABLE @gt2_ztco0046c.

  SORT gt2_ztco0046c BY matnr werk1 werk2.

  IF gt2_ztco0046c IS NOT INITIAL.

    LOOP AT gt2_ztco0046c INTO gs2_ztco0046c
       GROUP BY ( matnr = gs2_ztco0046c-matnr werk1 = gs2_ztco0046c-werk1 )
                ASCENDING ASSIGNING FIELD-SYMBOL(<group2_ztco0046c>).
      LOOP AT GROUP <group2_ztco0046c> ASSIGNING FIELD-SYMBOL(<fs2_ztco0046c>).
        gtz2_ztco0046c-werk1 = <fs2_ztco0046c>-werk1.   ""工厂
        APPEND <fs2_ztco0046c> TO gtz2_ztco0046c-datas.
      ENDLOOP.
      APPEND gtz2_ztco0046c.
      CLEAR gtz2_ztco0046c. "是清除工作区,不是内表
    ENDLOOP.
    CLEAR:gs2_ztco0046c.

    SORT gtz2_ztco0046c BY werk1.

  ENDIF.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_UPDATE_ZTCO0043B_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_update_ztco0043b_bom .

  IF lt_stpov1 IS INITIAL.
    RETURN.
  ENDIF.

  "删除三年前的数据
  DELETE FROM ztco0043b_bom WHERE bukrs = p_bukrs "公司
                              AND gjahr = lv_del_gjahr "年
                              AND monat = lv_del_monat. "月


  MOVE-CORRESPONDING lt_stpov1 TO lt_ztco0043b_bom.


  LOOP AT lt_ztco0043b_bom INTO ls_ztco0043b_bom.
    ls_ztco0043b_bom-gjahr = pn_gjahr.          ""当前期间的会计年度
    ls_ztco0043b_bom-monat = pn_monat.          ""当前期间(过账期间)
    ls_ztco0043b_bom-bukrs = p_bukrs.          ""公司代码"
    MODIFY lt_ztco0043b_bom FROM ls_ztco0043b_bom TRANSPORTING gjahr monat bukrs.
  ENDLOOP.
  CLEAR ls_ztco0043b_bom.

  IF s_matnr IS INITIAL AND s_werks IS INITIAL."如果没下物料工厂的条件

    DELETE FROM ztco0043b_bom WHERE bukrs = p_bukrs "公司
                              AND gjahr = pn_gjahr "当前年度
                              AND monat = pn_monat. "当前月份

  ELSE.

    LOOP AT lt_ztco0043b_bom INTO ls_ztco0043b_bom.
      DELETE FROM ztco0043b_bom WHERE bukrs = p_bukrs "公司
                                AND gjahr = pn_gjahr "当前年度
                                AND monat = pn_monat "当前月份
                                AND zwerks = ls_ztco0043b_bom-zwerks "工厂
                                AND zmatnr = ls_ztco0043b_bom-zmatnr."物料
    ENDLOOP.
    CLEAR ls_ztco0043b_bom.

  ENDIF.


  INSERT ztco0043b_bom FROM TABLE lt_ztco0043b_bom.

  IF sy-subrc = 0.
    COMMIT WORK .
    MESSAGE TEXT-b01 TYPE  'S'. "更新数据成功!
  ELSE.
    ROLLBACK WORK .
    MESSAGE TEXT-b02 TYPE 'S' DISPLAY LIKE 'E' . "更新失败!
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZTCO0043B_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztco0043b_bom .

  "如果LCM计算全部运行的话,则不应该取物料、工厂
  SELECT
      ztco0043b_bom~zmatnr,          ""物料编号
      ztco0043b_bom~zwerks,          ""工厂
      ztco0043b_bom~matnr,           ""成品料的物料编号
      ztco0043b_bom~werks,           ""成品料的工厂
      ztco0043b_bom~qpa2            ""成品料的工厂
      "mbew~bklas                     ""成品料的评估类 "
  FROM ztco0043b_bom
     LEFT JOIN mbew ON mbew~matnr = ztco0043b_bom~matnr AND mbew~bwkey = ztco0043b_bom~werks
  WHERE bukrs = @p_bukrs
    AND gjahr = @pn_gjahr "当前年度
    AND monat = @pn_monat "当前月份
    "AND zmatnr IN @s_matnr "物料
    "AND zwerks IN @s_werks "工厂
  INTO CORRESPONDING FIELDS OF TABLE @gt_stpov.

  "SORT gt_ztco0043b_bom BY gjahr monat bukrs zwerks zmatnr werks matnr.

  SORT gt_stpov BY zmatnr zwerks erfmg1 matnr werks.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA2_ZTCO0043B_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata2_ztco0043b_bom .

  "要下物料、工厂的条件
  SELECT
      ztco0043b_bom~gjahr,           ""当前年度
      ztco0043b_bom~monat,           ""当前月份
      ztco0043b_bom~bukrs,           ""公司代码
      ztco0043b_bom~zwerks,          ""工厂
      ztco0043b_bom~zmatnr,          ""物料编号
      ztco0043b_bom~werks,           ""成品料的工厂
      ztco0043b_bom~matnr,           ""成品料的物料编号
      mbew~bklas,                     ""成品料的评估类 "
      ztco0043b_bom~qpa2            ""BOM表用量(QPA)
  FROM ztco0043b_bom
     LEFT JOIN mbew ON mbew~matnr = ztco0043b_bom~matnr AND mbew~bwkey = ztco0043b_bom~werks
  WHERE bukrs = @p_bukrs
    AND gjahr = @pn_gjahr "当前年度
    AND monat = @pn_monat "当前月份
    AND zmatnr IN @s_matnr "物料
    AND zwerks IN @s_werks "工厂
  INTO TABLE @gt_ztco0043b_bom.


  SORT gt_ztco0043b_bom BY gjahr monat bukrs zwerks zmatnr werks matnr.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_ALV_FIELDCAT_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_fieldcat_bom .

*----------------------------------------------------------------------*
*                  定义宏
*----------------------------------------------------------------------*
  DEFINE macro_fieldcat.
    CLEAR ls_fieldcat.
    ls_fieldcat-fieldname = &1. "标题列对应的字段名
    ls_fieldcat-coltext = &2. "列标题 列标题,如果字段参考了DDIC,可不设置
    ls_fieldcat-fix_column = &3. "固定列 与KEY字段类似,固定列但颜色不变蓝,必须要在左边才起作用(如果设置固定列的左边包含非固定列,则该列不固定)
    ls_fieldcat-no_zero = &4. "是否隐藏输出为零的字段 当字段为数值为0时,不显示【如0,0.00,则会显示为空】当字段包含前导0时,隐藏前导0,【如0100,则会显示为100】
    "ls_fieldcat-cfieldname = &5. "currency unit field name值为当前输出内表中的货币单位字段的字段名称
    "ls_fieldcat-edit = &6. "准备输入 X:可编辑,space:不可编辑 该控制是在整列的级别上,如果想控制仅仅某一行可编辑,则需要通过style来控制
    ls_fieldcat-ref_field = &5.
    ls_fieldcat-ref_table = &6.

    APPEND ls_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.


  macro_fieldcat:
    'GJAHR' '当前年度'(r01) '' '' '' '',
    'MONAT' '当前月份'(r02) '' '' '' '',
    'BUKRS' '公司代码'(r03) '' '' '' '',
    'ZWERKS' '工厂'(r04) '' '' '' '',
    'ZMATNR' '物料编号'(r05) '' '' 'MATNR' 'MARA',
    'WERKS' '成品料的工厂'(r06) '' '' '' '',
    'MATNR' '成品料的物料编号'(r07) '' '' 'MATNR' 'MARA',
    'BKLAS' '成品料的评估类 '(r08) '' '' '' '',
    'QPA2' 'BOM表用量(QPA) '(r09) '' '' '' ''."

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_ALV_OUTPUT_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_alv_output_bom .

  DATA: gs_disvariant TYPE disvariant.

  "gs_disvariant-variant = p2_var.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program = sy-cprog "sy-repid
*     I_INTERFACE_CHECK  = ' '
*     I_BYPASSING_BUFFER =
*     I_BUFFER_ACTIVE    =
*     I_CALLBACK_PROGRAM = ' '
*     I_CALLBACK_PF_STATUS_SET          = ' '
*     I_CALLBACK_USER_COMMAND           = ' '
*     I_CALLBACK_TOP_OF_PAGE            = ' '
*     I_CALLBACK_HTML_TOP_OF_PAGE       = ' '
*     I_CALLBACK_HTML_END_OF_LIST       = ' '
*     I_STRUCTURE_NAME   =
*     I_BACKGROUND_ID    = ' '
*     I_GRID_TITLE       =
*     I_GRID_SETTINGS    =
      is_layout_lvc      = wa_layout
      it_fieldcat_lvc    = lt_fieldcat
*     IT_EXCLUDING       =
*     IT_SPECIAL_GROUPS_LVC             =
"     it_sort_lvc        = lt_sort
*     IT_FILTER_LVC      =
*     IT_HYPERLINK       =
*     IS_SEL_HIDE        =
      i_default          = 'X'
      i_save             = 'A' " 'U'
*     is_variant         = gs_disvariant
"     it_events          = lt_event
*     IT_EVENT_EXIT      =
*     IS_PRINT_LVC       =
*     IS_REPREP_ID_LVC   =
*     I_SCREEN_START_COLUMN             = 0
*     I_SCREEN_START_LINE               = 0
*     I_SCREEN_END_COLUMN               = 0
*     I_SCREEN_END_LINE  = 0
*     I_HTML_HEIGHT_TOP  =
*     I_HTML_HEIGHT_END  =
*     IT_ALV_GRAPHICS    =
*     IT_EXCEPT_QINFO_LVC               =
*     IR_SALV_FULLSCREEN_ADAPTER        =
* IMPORTING
*     E_EXIT_CAUSED_BY_CALLER           =
*     ES_EXIT_CAUSED_BY_USER            =
    TABLES
      t_outtab           = gt_ztco0043b_bom
    EXCEPTIONS
      program_error      = 1
      OTHERS             = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
    "LEAVE LIST-PROCESSING.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ztco0043b_lcm_N
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztco0043b_lcm_n .

  DATA: lv_i TYPE i.


  SELECT COUNT(*)
  FROM ztco0043b_lcm "新表
  WHERE bukrs = @p_bukrs
    AND zn_gjahr = @pn_gjahr "当前年度
    AND zn_monat = @pn_monat "当前月份
    AND zf_gjahr = @pf_gjahr "未来年度
    AND zf_monat = @pf_monat "未来月份
    AND zitem IN @s_zitem "项次
    AND matnr IN @s_matnr "物料
    AND werks IN @s_werks "工厂
    AND bklas IN @s_bklas  "评估分类
    AND beskz IN @s_beskz  "采购类型
  INTO @lv_i.

  IF lv_i = 0. "如果新表没数据就查旧表

    SELECT COUNT(*)
    FROM ztco0043b_item  "旧表
    WHERE bukrs = @p_bukrs
      AND zn_gjahr = @pn_gjahr "当前年度
      AND zn_monat = @pn_monat "当前月份
      AND zf_gjahr = @pf_gjahr "未来年度
      AND zf_monat = @pf_monat "未来月份
      AND zitem IN @s_zitem "项次
      AND matnr IN @s_matnr "物料
      AND werks IN @s_werks "工厂
      AND bklas IN @s_bklas  "评估分类
      AND beskz IN @s_beskz  "采购类型
    INTO @lv_i.

  ENDIF.

  lv_content = '当前条目:'  && lv_i .
  MESSAGE lv_content TYPE 'S'  .

  lv_i = 0.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZTCO0043B_BOM_N
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ztco0043b_bom_n .

  DATA lv_i TYPE i.

  "要下物料、工厂的条件
  SELECT COUNT(*)
  FROM ztco0043b_bom
     LEFT JOIN mbew ON mbew~matnr = ztco0043b_bom~matnr AND mbew~bwkey = ztco0043b_bom~werks
  WHERE bukrs = @p_bukrs
    AND gjahr = @pn_gjahr "当前年度
    AND monat = @pn_monat "当前月份
    AND zmatnr IN @s_matnr "物料
    AND zwerks IN @s_werks "工厂
  INTO @lv_i.


  lv_content = '当前条目:'  && lv_i .
  MESSAGE lv_content TYPE 'S'  .

  lv_i = 0.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_CKIS_RAW
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_ckis_raw .
  IF gt3_ckis IS NOT INITIAL.

    LOOP AT gt3_ckis INTO gs2_ckis.
      IF gs2_ckis-bklas = '3000'.
        gs2_ckis-zmatnr = gs_lcm1-matnr.            ""物料
        gs2_ckis-zwerks = gs_lcm1-werks.            ""工厂
        gs2_ckis-price = gs2_ckis-wertn ."/ gs2_ckis-peinh.          ""金额 = 控制区域货币的值  / 以控制范围货币记价的单位价格
        APPEND gs2_ckis TO gt2_ckis.
      ENDIF.
    ENDLOOP.
    CLEAR gs2_ckis.

    IF gt2_ckis IS NOT INITIAL.
      "降序:查询物料  查询物料的工厂 金额 物料编号 工厂 评估类
      SORT gt2_ckis DESCENDING BY zmatnr zwerks price matnr werks bklas .

      READ TABLE gt2_ckis INTO gs2_ckis INDEX 1.

      IF sy-subrc = 0.
        APPEND gs2_ckis TO gt1_ckis.
      ENDIF.

    ENDIF.
  ENDIF.
  CLEAR:gs2_ckis,gt3_ckis,gt2_ckis,gs_marc,gt_marc,lt_marc1.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_RAW_CKIS_MODIFY
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_raw_ckis_modify .

  IF gt1_ckis IS NOT INITIAL.
    SORT gt1_ckis BY zmatnr zwerks.

    MOVE-CORRESPONDING gt1_ckis TO gt_ztco0043b_raw.

    LOOP AT gt_ztco0043b_raw INTO gs_ztco0043b_raw.
      gs_ztco0043b_raw-gjahr = pn_gjahr.          ""当前期间的会计年度
      gs_ztco0043b_raw-monat = pn_monat.          ""当前期间(过账期间)
      gs_ztco0043b_raw-bukrs = p_bukrs.          ""公司代码"
      MODIFY gt_ztco0043b_raw FROM gs_ztco0043b_raw TRANSPORTING gjahr monat bukrs.
    ENDLOOP.

    MODIFY ztco0043b_raw FROM TABLE gt_ztco0043b_raw.

    IF sy-subrc = 0.
      COMMIT WORK .
      MESSAGE TEXT-b01 TYPE  'S'. "更新数据成功!
    ELSE.
      ROLLBACK WORK .
      MESSAGE TEXT-b02 TYPE 'S' DISPLAY LIKE 'E' . "更新失败!
    ENDIF.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MAST_RAW_MODIFY
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mast_raw_modify .

  IF gt3_raw IS INITIAL.
    RETURN.
  ENDIF.

  "删除三年前的数据
  DELETE FROM ztco0043b_raw WHERE bukrs = p_bukrs "公司
                              AND gjahr = lv_del_gjahr "年
                              AND monat = lv_del_monat. "月

  SORT gt3_raw BY zmatnr zwerks.

  MOVE-CORRESPONDING gt3_raw TO gt_ztco0043b_raw.

  LOOP AT gt_ztco0043b_raw INTO gs_ztco0043b_raw.
    gs_ztco0043b_raw-gjahr = pn_gjahr.          ""当前期间的会计年度
    gs_ztco0043b_raw-monat = pn_monat.          ""当前期间(过账期间)
    gs_ztco0043b_raw-bukrs = p_bukrs.          ""公司代码"
    MODIFY gt_ztco0043b_raw FROM gs_ztco0043b_raw TRANSPORTING gjahr monat bukrs.
  ENDLOOP.

  IF s_matnr IS INITIAL AND s_werks IS INITIAL."如果没下物料工厂的条件
    DELETE FROM ztco0043b_raw WHERE bukrs = p_bukrs "公司
                                AND gjahr = pn_gjahr "当前年度
                                AND monat = pn_monat. "当前月份
  ENDIF.

  MODIFY ztco0043b_raw FROM TABLE gt_ztco0043b_raw.

  IF sy-subrc = 0.
    COMMIT WORK .
    MESSAGE TEXT-b01 TYPE  'S'. "更新数据成功!
  ELSE.
    ROLLBACK WORK .
    MESSAGE TEXT-b02 TYPE 'S' DISPLAY LIKE 'E' . "更新失败!
  ENDIF.



ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_MAST_SOBSL
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_mast_sobsl .
  "SPRO ->生产-> 物料需求计划-> 主数据-> 定义特殊采购类型


  SELECT
      marc~matnr AS zmatnr,           ""物料
      t460a~wrk02 AS zwerks          ""工厂"
  FROM marc
    LEFT JOIN t460a ON t460a~werks = marc~werks         ""特殊采购类型
                   AND t460a~sobsl = marc~sobsl         ""特殊采购类型
   WHERE marc~matnr IN @s_zmatnr          ""查询物料编号
     AND marc~werks IN @s_zwerks         ""查询的工厂
     AND t460a~wrk02 IS NOT INITIAL
  INTO CORRESPONDING FIELDS OF TABLE @lt_marc1.

  IF lt_marc1 IS INITIAL.
    RETURN.
  ENDIF.

  LOOP AT lt_marc1 INTO gs_marc.
    s_zmatnr-sign = 'I'.
    s_zmatnr-option = 'EQ'.
    s_zwerks-sign = 'I'.
    s_zwerks-option = 'EQ'.

    s_zmatnr-low = gs_marc-zmatnr.            ""物料
    COLLECT s_zmatnr.
    s_zwerks-low = gs_marc-zwerks.            ""工厂
    COLLECT s_zwerks.
  ENDLOOP.
  CLEAR gs_marc.

  APPEND LINES OF lt_marc1 TO gt_marc.
  CLEAR lt_marc1.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_SALES_EXPENSES
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_sales_expenses .

  "销售费用
  TYPES: BEGIN OF ty_xsfy,
           mm1          TYPE zmonth_e,            ""期间
           ori_this_amt TYPE zori_amt_e,          ""金额(本币)"
         END OF ty_xsfy.

  DATA: gt_xsfy1 TYPE TABLE OF ty_xsfy,
        gt_xsfy2 TYPE TABLE OF ty_xsfy,
        gs_xsfy1 TYPE ty_xsfy,
        gs_xsfy2 TYPE ty_xsfy.


  "ZTFRD0019 境内厂区损益表
  "   ZFR0019         财务报表(中国)
  "作业名称 ZFR0019-C131
  "每月2号到8号凌晨4点执行


  SELECT
      ztfrd0019~mm1,                   ""期间
      ztfrd0019~ori_this_amt          ""金额(本币)"
  FROM ztfrd0019 "境内厂区损益表
   WHERE bukrs = @p_bukrs
   AND  subject LIKE '%销售费用%'
   AND  yyyy  = @pf_gjahr
   AND  mm1 = @pf_monat "检查未来月份有没有数据
   INTO CORRESPONDING FIELDS OF TABLE @gt_xsfy1.

  IF gt_xsfy1 IS INITIAL.
    MESSAGE s000 WITH TEXT-c04 DISPLAY LIKE 'E'. "“ZFR0019 财务报表(中国)”没有未来月份的销售费用!
    LEAVE LIST-PROCESSING.
  ENDIF.
  CLEAR gt_xsfy1.


  SELECT
      ztfrd0019~mm1,                   ""期间
      ztfrd0019~ori_this_amt          ""金额(本币)"
  FROM ztfrd0019 "境内厂区损益表
   WHERE bukrs = @p_bukrs
   AND  subject LIKE '%销售费用%'
   AND  yyyy  = @pf_gjahr
   AND  mm1 <= @pf_monat
   INTO CORRESPONDING FIELDS OF TABLE @gt_xsfy1 .

  IF gt_xsfy1 IS INITIAL.
    MESSAGE s000 WITH TEXT-c03 DISPLAY LIKE 'E'. "“ZFR0019 财务报表(中国)”没有销售费用!
    LEAVE LIST-PROCESSING.
  ENDIF.


  LOOP AT gt_xsfy1 INTO gs_xsfy1. "只保留一条累计金额
    gs_xsfy2-ori_this_amt = gs_xsfy1-ori_this_amt.          "金额(本币)
    COLLECT gs_xsfy2 INTO gt_xsfy2.
  ENDLOOP.
  CLEAR:gs_xsfy1,gs_xsfy2.


  READ TABLE gt_xsfy2 INTO gs_xsfy2 INDEX 1.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DELETE_ztco0043b_lcm
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_delete_ztco0043b_lcm . "删除当前数据

  "IF p_p2 IS NOT INITIAL.

  DELETE FROM ztco0043b_lcm WHERE bukrs = p_bukrs
                            AND zn_gjahr = pn_gjahr "当前年度
                            AND zn_monat = pn_monat "当前月份
                            AND zf_gjahr = pf_gjahr "未来年度
                            AND zf_monat = pf_monat."未来月份

  IF sy-subrc = 0.
    COMMIT WORK .
    MESSAGE '删除成功' TYPE  'S'.
  ELSE.
    ROLLBACK WORK .
    MESSAGE '删除失败' TYPE 'S' DISPLAY LIKE 'E' .
  ENDIF.

  "LEAVE LIST-PROCESSING.

  " ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GETDATA_ZCOD0046D
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_getdata_zcod0046d .

  "DATA lv_id(30) TYPE c.

  "lv_id = 'ZCOD0046D' && p_bukrs .


  "注意:LCM的数量来源于SLM,金额不来源于,料号单价来源于进销存
  SELECT DISTINCT
*      ztco0043_slm~lfgja AS zn_gjahr,                  ""当前年度
*      ztco0043_slm~lfmon AS zn_monat,                  ""当前月份
*      @pf_gjahr AS zf_gjahr,                           ""未来年度
*      @pf_monat AS zf_monat,                           ""未来月份
*      ztco0043_slm~bukrs,                             ""公司代码
      ztco0043_slm~werks,                             ""工厂
      ztco0043_slm~matnr                             ""物料编号
*      ztco0043_slm~bklas,                             ""评估分类
*      ztco0043_slm~beskz,                             ""采购类型
*      ztco0043_slm~totqty AS zqm01_qty,               ""库存数量
*      ztco0043_slm~salk3 AS zqm02_amount,             ""成本金额
*      ztco0043_slm~maktx,                             ""物料描述
*      ztco0043_slm~lgort,                             ""库存地点
*      ztco0043_slm~lgobe,                             ""库存地点描述
*      ztco0043_slm~lgort_p,                           ""仓库属性
*      ztco0043_slm~charg,                             ""批次
*      ztco0043_slm~hsdat,                             ""批号生成日期"
*      mara~prdha,                                     ""产品层次
*      ztco0043_slm~zcmcc,                             ""机种
*      ztco0043_slm~prctr,                             ""利润中心
*      ztco0043_slm~dull_month,                        ""呆滞月份
*      ztco0043_slm~stday                             ""库龄天数"
  FROM ztco0043_slm
  "  LEFT JOIN mara AS mara ON mara~matnr = ztco0043_slm~matnr
  WHERE bukrs = @p_bukrs
    AND lfgja = @pn_gjahr "当前年度
    AND lfmon = @pn_monat "当前月份
    "如果屏幕不显示就必须清掉 物料、工厂的条件
    "AND ztco0043_slm~matnr IN @s_matnr "物料
    "AND ztco0043_slm~werks IN @s_werks "工厂
    AND substring( werks, 1, 2 ) <> 'NV'
    "AND bklas IN ('3000','7900','7920')
    AND lgort_p IN  @s_lgort_p
  INTO CORRESPONDING FIELDS OF TABLE @gt_lcm1.

  "没有满足条件的数据,提示信息并终止程序
  IF gt_lcm1 IS INITIAL.
    MESSAGE s000 WITH TEXT-c00 DISPLAY LIKE 'E'. "“ZCOD0046 LCM SLM查询报表”没有数据!
    LEAVE LIST-PROCESSING.
  ENDIF.

  SORT gt_lcm1 BY matnr werks .

  "经过测试发现,八百九十万行的数据时还是可以运行下去,但是运行数据结果有一千七百行的时候还是运行不了

  "FREE MEMORY ID: lv_id.

  lv_ztime = sy-uzeit.
  lv_str = |{ lv_ztime+0(2) }:{ lv_ztime+2(2) }:{ lv_ztime+4(2) }|.

  LOOP AT gt_lcm1 INTO gs_lcm1.

    lv_line  = lv_line + 1.
    lv_result = ( lv_line - 1 ) * 100 / lines( gt_lcm1 ).
    lv_restex = lv_result.
    lv_stxt =  |开始时间:{ lv_str }  第{ lv_line },共{ lines( gt_lcm1 ) }  进度:{ lv_restex } %   料号:{ gs_lcm1-matnr } 工厂:{ gs_lcm1-werks }  |.

    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        percentage = lv_result
        text       = lv_stxt.

    SUBMIT zcod0046d
    WITH p_bukrs = p_bukrs
    WITH pn_gjahr = pn_gjahr
    WITH pn_monat = pn_monat
    WITH pf_gjahr = pf_gjahr
    WITH pf_monat = pf_monat
    WITH s_matnr = gs_lcm1-matnr "ZCOD0046D 的 s_matnr 和 本重新命名一样,实际不太一样的,这里是单选的
    WITH s_werks = gs_lcm1-werks
    WITH p_s1 = p_s1
    WITH p_s2 = p_s2
    WITH p_s3 = p_s3
    WITH p_p1 = 'X' "追加数据
    WITH p_p3 = p_p3
    AND RETURN.

    "两种方法花的时间差不太多
    "lt_ztco0043b_lcm要与EXPORT写入时的变量保持一致
    "IMPORT lt_ztco0043b_lcm = lt_ztco0043b_lcm[] FROM MEMORY ID  lv_id.
    "APPEND LINES OF lt_ztco0043b_lcm TO gt_ztco0043b_lcm.
    "CLEAR lt_ztco0043b_lcm.
    "FREE MEMORY ID: lv_id.

  ENDLOOP.
  CLEAR:gs_lcm1.
  lv_line = 0.
  "CLEAR lt_ztco0043b_lcm.
  "FREE MEMORY ID: lv_id.

ENDFORM.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值