Как получить последнее значение MBEWH ~ LBKUM?

Эта программа фактически используется для расчета общего запаса с лимитом от даты проводки (MATDOC-BUDAT). Но у меня проблема с определением начального запаса. Первоначальный запас (MBEWH-LBKUM) берется с месяца, предшествующего месяцу, когда была проведена дата проводки. Но в программе, которую я сделал, появившиеся исходные стоковые данные (MBEWH-LBKUM) не обновлялись должным образом. Между тем, если говорить о дате публикации (matdoc-budat / запрос, который я присоединил к таблице matdoc), исходные данные о запасах, которые должны появиться, совсем не такие.

Но если я выберу дату публикации только за короткий промежуток времени, результаты будут правильными.

Мой запрос:

FORM F_GETDT .

  REFRESH: IT_ZVBR.

    SELECT DISTINCT MARA~MATNR
                    MATDOC~BUDAT
                    MATDOC~BWART
                    MATDOC~SHKZG
                    MATDOC~WERKS
                    MATDOC~MENGE AS TOTAL
    FROM MARA
    INNER JOIN MATDOC ON MARA~MATNR = MATDOC~MATNR
    INTO CORRESPONDING FIELDS OF TABLE IT_ZVBR
    WHERE MATDOC~WERKS = P_WERKS AND
          MATDOC~BUDAT IN P_BUDAT AND
          MARA~MATKL IN ('E001', 'E002', 'E003', 'E005', 'E006', 'E007', 'E008', 'E009', 'E010', 'E011', 'E012', 'E014').
ENDFORM.

Это мой код для заполнения внутренней таблицы IT_PRINT, которая отображается позже:

FORM F_LSTDT.

  CLEAR: WA_ZVBR, WA_PRINT, V_TEMP, V_DATE, V_MONTH, V_MONTHMIN, V_YEAR.

  SORT IT_ZVBR BY MATNR.
  IT_TEMP = IT_ZVBR.
  DELETE ADJACENT DUPLICATES FROM IT_ZVBR COMPARING MATNR.

  LOOP AT IT_ZVBR INTO WA_ZVBR.

    WA_PRINT-PSTAR = P_BUDAT-LOW.
    WA_PRINT-PFINS = P_BUDAT-HIGH.
    WA_PRINT-MATNR = WA_ZVBR-MATNR.

    SELECT SINGLE MAKTX FROM MAKT
    INTO WA_PRINT-MAKTX
    WHERE MATNR = WA_PRINT-MATNR.

    LOOP AT IT_TEMP INTO WA_TEMP WHERE MATNR = WA_ZVBR-MATNR.

      CLEAR: V_TEMP.
      V_TEMP = WA_TEMP-BUDAT+6(2).
      V_DATE = V_TEMP.

      CLEAR: V_TEMP.
      V_TEMP = WA_TEMP-BUDAT+4(2).
      V_MONTH = V_TEMP.
      V_MONTHMIN = V_MONTH - 1.

      CLEAR: V_TEMP.
      V_TEMP = WA_TEMP-BUDAT+0(4).
      V_YEAR = V_TEMP.

      BLN_SBLM = 12.
      THN_SBLM = V_YEAR - 1.

      IF V_MONTH = 1.
        SELECT SINGLE LBKUM FROM MBEWH
          INTO WA_PRINT-LBKUM
          WHERE MATNR = WA_PRINT-MATNR AND
            LFMON = BLN_SBLM AND
            LFGJA = THN_SBLM AND
            BWKEY = WA_ZVBR-WERKS.
      ELSE.
        SELECT SINGLE LBKUM FROM MBEWH
          INTO WA_PRINT-LBKUM
          WHERE MATNR = WA_PRINT-MATNR AND
            LFMON = V_MONTHMIN AND
            LFGJA =  V_YEAR AND
            BWKEY = WA_ZVBR-WERKS.
      ENDIF.

     //Logic to swap to the latest value  
      IF WA_PRINT-LBKUM = WA_PRINT-TEMP.
          WA_PRINT-TEMP = WA_PRINT-LBKUM.
      ELSEIF WA_PRINT-LBKUM <> WA_PRINT-TEMP AND WA_PRINT-LBKUM > 0.
          CLEAR: WA_PRINT-TEMP.
          WA_PRINT-TEMP = WA_PRINT-LBKUM.
      ENDIF.

  WA_PRINT-LBKUM = WA_PRINT-TEMP.

    ENDLOOP.
    APPEND WA_PRINT TO IT_PRINT.
    SORT IT_PRINT BY MATNR.
    CLEAR: WA_ZVBR, WA_PRINT, WA_TEMP, V_TEMP, V_DATE, V_MONTH, V_MONTHMIN, V_YEAR.
  ENDLOOP.
ENDFORM.

Предполагалось получить данные, которые изображены на картинке ниже (tcode se16n):

Данные, которые должны быть выходными

Потому что в таблице matdoc есть последняя транзакция по дате проводки (BUDAT).

Данные на основе даты публикации в matdoc

И данные, которые я действительно получил, - это предыдущие данные.

Данные подчеркнуты синим цветом

Как решить эту проблему? Я так долго зацикливался на этой проблеме. Спасибо раньше.


person Cybits    schedule 08.04.2020    source источник
comment
Пожалуйста, объясните, что вы хотите сделать, простыми словами, не позволяйте людям выводить это из кода. Вкратце, позвольте мне сделать это за вас: я думаю, ваше требование - прочитать стандартный MBEW за месяц до даты в MATDOC. В вашем случае проблема в том, что дата - февраль 2020 года, но ваша программа рассчитана с 2019 года. Поэтому, пожалуйста, отредактируйте свой вопрос. Кроме того, вы должны предоставить минимальный воспроизводимый пример. В настоящее время это не так.   -  person Sandra Rossi    schedule 08.04.2020
comment
Да, ваш вывод верен, Сандра. Вы можете мне помочь? Пожалуйста ... Спасибо раньше   -  person Cybits    schedule 09.04.2020
comment
Я меняю логику на замену lbkum с этого //Logic to swap to the latest value IF WA_PRINT-LBKUM = WA_PRINT-TEMP. WA_PRINT-TEMP = WA_PRINT-LBKUM. ELSEIF WA_PRINT-LBKUM <> WA_PRINT-TEMP AND WA_PRINT-LBKUM > 0. CLEAR: WA_PRINT-TEMP. WA_PRINT-TEMP = WA_PRINT-LBKUM. ENDIF. на это: MODIFY IT_PRINT FROM WA_PRINT TRANSPORTING LBKUM WHERE MATNR = WA_TEMP-MATNR. Он все еще не работает, как я надеюсь   -  person Cybits    schedule 09.04.2020
comment
В вашем коде так много проблем, что я даже не могу сообщить о них здесь (попросите опытного разработчика помочь вам). Тем не менее, если вы отлаживаете, вы можете видеть, что вы читаете соответствующий запас для всех дат MATDOC, и, наконец, вы учитываете только последнее чтение. Но порядок чтения произвольный по датам, поэтому вы, наконец, получаете запас случайной даты. Кстати, будьте осторожны, после каждого SELECT проверяйте SY-SUBRC, чтобы продолжить, если строка не найдена.   -  person Sandra Rossi    schedule 09.04.2020


Ответы (1)


В вашем ужасающем фрагменте вы делаете сортировку, которая полностью портит вашу идею:

SORT it_zvbr BY matnr.
it_temp = it_zvbr.

Это заставляет BUDAT сортировать по убыванию в каждой группе MATNR и нарушает вашу идею с LBKUM, SELECT LBKUM после ELSE становится перезаписанным с каждой итерацией цикла, поэтому он всегда сохраняет последнее значение в порядке сортировки itab, поэтому самое раннее приходит последним.

Чтобы исправить это, замените и поместите SORT после назначения it_temp = it_zvbr.

В целом, весь этот кусок представляет собой беспорядок, и его следует переписать заново. Просто порассуждайте, что вам здесь нужно:

Если вам нужен общий запас из значений MATDOC, чтобы добавить его к начальному запасу из MBEWH до месяца BUDAT, то вам, вероятно, понадобится следующее:

SELECT DISTINCT m~matnr,
                x~maktx,
                ew~lfgja AS initial_year,
                ew~lfmon AS initial_month,
                SUM( lp~menge ) AS total,
                MAX( ew~lbkum ) AS initial_stock
    FROM mara AS m
   INNER JOIN makt AS x
      ON m~matnr = x~matnr
   INNER JOIN matdoc AS mdoc
      ON lp~matnr = m~matnr
    LEFT OUTER JOIN mbewh AS ew
      ON ew~matnr = m~matnr
    INTO TABLE @DATA(it_stock)

   WHERE mdoc~WERKS = p_werks
     AND mdoc~budat IN p_budat 
     AND m~matkl IN ('E001', 'E002', 'E003', 'E005', 'E006', 'E007', 'E008', 'E009', 'E010', 'E011', 'E012', 'E014').
     AND ew~lfmon = ( SELECT MAX( lfmon ) 
                        FROM mbewh AS h 
                       WHERE h~matnr = m~matnr 
                         AND h~lfgja = mdoc~mjahr 
                         AND h~lfmon <> ( SELECT MAX( lfmon ) 
                                            FROM mbewh 
                                           WHERE matnr = h~matnr 
                                             AND lfgja = h~lfgja ) )
   GROUP BY mara~matnr, makt~maktx, ew~lfgja, ew~lfmon.

Я использую MJAHR для подзапроса, поскольку он обычно равен BUDAT первым 4 символам.

Это решение использует вложенные подзапросы MBEWH, чтобы найти предыдущее и последнее значение в каждом периоде оценки, и это тоже выглядит некрасиво, но в любом случае короче, чем ваш исходный фрагмент.

person Suncatcher    schedule 09.04.2020