VOFM、Copy Control与合并开票 (ZT)

问题的提出:

很多企业在晚上运行后台作业来开具到期发票。问题是这些自动运行的到期清单,是以怎样的逻辑被拆分、合并的?本文档将解释标准系统的工作逻辑并提供事例来说明怎样对标准逻辑作自定义增强。

发票(Billing Documents)是用功能函数RV_INVOICE_CREATE来创建的,这个函数将被VF01/SAPMV60A、VF04/SDBILLDL等事务码调用。在此函数运行之前,会有一个内含一条或者多条数据的内表传入。这些数据将以客户、销售组织、开票类型等字段排序,排序的结果是这些数据被分成了几个小组。对每一个小组,系统逻辑试图合并他们从而开除一张发票。在发票创建的过程中,系统将从上述内表中提取出抬头和行项目数据,填充至带开票的内存数据中。

r3中包含了一种用于数据传输控制的可配置的函数逻辑(Routines),叫Data Transfer Routine,它可以更改数据从源凭证到目的凭证的传递方式。本例中将对发票凭证进行讨论。

一旦待开票的数据(内存数据)被填充,系统逻辑将循环对照次行数据与前行数据,如果基本字段一致,两者将被合并。如果不同,新的发票将被创建。发票里有几个特殊的字段,他们不能作为拆分依据。下一节将说明标准合并规则(Standard Combination Criteria),里面列举了这些不能作为拆分依局的字段。

标准合并规则(Standard Combination Criteria)

程序SAPMV60A/MV60ATOP中,有如下定义:

DATA: BEGIN OF AUSNAHME_TAB,
        FELD1(5)  VALUE 'VBELN',
        FELD2(5)  VALUE 'NETWR',
        FELD3(5)  VALUE 'KNUMV',
        FELD4(5)  VALUE 'VBELN',
        FELD5(5)  VALUE 'ERNAM',
        FELD6(5)  VALUE 'ERDAT',
        FELD7(5)  VALUE 'ERZET',
        FELD8(5)  VALUE 'AEDAT',
        FELD9(5)  VALUE 'BELNR',
        FELD10(5) VALUE 'RFBSK',
        FELD12(5) VALUE 'SFAKN',
        FELD13(5) VALUE 'MWSBK',
        FELD14(5) VALUE 'FKTYP',
      END OF AUSNAHME_TAB.

存在于AUSNAHME_TAB结构中的字段将不会作为拆分依据。具体判断逻辑在函数SPLIT_TREE_LIST_DISPLAY、子例程SPLIT_EXAMINE中:

        IF I_HEADER_EXCEPTION_FIELDS NS GT_HEADER_NAMETAB-FIELDNAME.
          GT_HEADER_FIELD_SPLIT-VBELN_F  = LS_VBRK_F-VBELN.
          GT_HEADER_FIELD_SPLIT-VBELN_S  = LS_VBRK_S-VBELN.
          GT_HEADER_FIELD_SPLIT-FIELD    = GT_HEADER_NAMETAB-FIELDTEXT.
          GT_HEADER_FIELD_SPLIT-VALUE_F  = .
          GT_HEADER_FIELD_SPLIT-VALUE_S  = .
          APPEND GT_HEADER_FIELD_SPLIT.
        ENDIF.

数据传输例程(Data Transfer Routine)

正确的控制合并和拆分的方法是采用数据传输例程(Data Transfer Routines)。数据传输例程的主要目的是将前导文件数据传到待创建的后续文件的内存结构中。我们可以在VOFM中找到系统标准的例程。

在VOFM里定义自己的逻辑后,再在发票拷贝关系(TCode:VTFL)中分配给相关的单据。

1、强制拆分

在发票抬头中有一个用来强制拆分开票的特殊字段:VBRK-ZUKRI。如001例程中,SPART字段和VTWEG字段分别代表产品组合分销渠道。所以,001例程的含义就是,不同的产品组、不同的分销渠道,要出具不同的发票!

FORM. DATEN_KOPIEREN_900.
  DATA: BEGIN OF ZUK,
          MODUL(3) VALUE '001',
          VTWEG LIKE VBAK-VTWEG,
          SPART LIKE VBAK-SPART,
          WERKS LIKE LIPS-WERKS,
        END OF ZUK.
  ZUK-SPART = VBAK-SPART.
  ZUK-VTWEG = VBAK-VTWEG.
  ZUK-WERKS = LIPS-WERKS. ‘新增工厂控制
  VBRK-ZUKRI = ZUK.
ENDFORM.

如果新增一行对工厂的限制(ZUK-WERKS = LIPS-WERKS),那么不同的工厂也要开出不同的发票。

2、阻止拆分

为了阻止拆分,可以将影响拆分的字段设置成相同的内容。例如,两个含有不同装运条件的交货单将被拆分开票,因为装运条件被拷贝到了发票抬头(VBRK)中。如果这个字段被清空了,那么拆分将不再发生。示例例程如下:

FORM. DATEN_KOPIEREN_900.
  DATA: BEGIN OF ZUK,
          MODUL(3) VALUE '001',
          VTWEG LIKE VBAK-VTWEG,
          SPART LIKE VBAK-SPART,
        END OF ZUK.
  ZUK-SPART = VBAK-SPART.
  ZUK-VTWEG = VBAK-VTWEG.
  VBRK-ZUKRI = ZUK.
  CLEAR VBRK-VSBED. ‘ 清空装运条件字段
ENDFORM.

新增一行:Clear VBRK-VSBED清空发票抬头(内存临时数据)的装运条件字段。激活后分配给到发票的复制控制,开票时,装运条件不再作为拆分依据了。

3、用自定义字段合并、拆分

如果客户每天发生多笔业务,那么每天就会有很多发货过账和发票。有些客户希望同一天同一个工厂开具一张发票,另一些客户希望为每一笔到达货物出具发票。

为满足上述需求,我们将创建一个自定义的数据传输例程,此例程基于一个自定义的客户数据字段(例如KNA1-KATR7)来决定交货单是否应该被合并或拆分到发票。为了实现它,订单号码将被添加到VBRK-ZUKRI字段中。

(1)本例中将使用KNA1-KATR7,将其描述更改为“Consolidated Invoice”。
(2)在SM30中,定义KATR7只允许有2个值:“”代表拆分、“X”代表合并。
(3)使KATR7字段在数据传输例程中生效。将KATR7添加到结构KUAGV中的字结构KUAGVZ中,激活。
(4)在数据传输例程中添加如下代码:

FORM. DATEN_KOPIEREN_900.
  DATA: BEGIN OF ZUK,
          MODUL(3) VALUE '001',
          VTWEG LIKE VBAK-VTWEG,
          SPART LIKE VBAK-SPART,
          WERKS LIKE LIPS-WERKS,
          VBELN LIKE VBAK-VBELN,
        END OF ZUK.
  ZUK-SPART = VBAK-SPART.
  ZUK-VTWEG = VBAK-VTWEG.
  ZUK-WERKS = LIPS-WERKS. ‘新增工厂控制
  IF VBAK-KATR7 IS INITIAL.
    ZUK-VBELN = VBAK-VBELN.
  ENDIF.
  VBRK-ZUKRI = ZUK.
ENDFORM.

如果在客户数据中维护了客户组7(KNA1-KATR7)为“X”,将集中出具发票。

猜你喜欢

转载自blog.csdn.net/champaignwolf/article/details/80098909