вторник, 12 февраля 2013 г.

Заполнение LIKP-TDDAT при создании поставки

Создаем поставки с помощью ФМ BAPI_DELIVERYPROCESSING_EXEC.
Кроме всего прочего пытаемся прописать в поставке дату планирования транспортировки LIKP-TDDAT. В параметрах ФМ она лежит в поле TRANSP_PLAN_DATE в таблице, которая передается как параметр REQUEST.
Проблема в том, что ФМ отрабатывает, поставка создается, но  поле TDDAT пустое.

Исследования показали, что проблема комплексная, и нужно обратить внимание как минимум на две вещи:

  1. Кроме заполнения поля TRANSP_PLAN_DATE, которое потом запишется в LIKP-TDDAT, при вызове ФМ необходимо заполнять также поля MAT_AVAILABIL_DATE, LOADING_DATE, GOODS_ISSUE_DATE, DELIVERY_DATE. В принципе есть и другие варианты - например когда заполняются TIMESTAMPы (подробнее можно посмотреть по исходному коду в form MATCH_INTERFACE_DATES_MM в include LV50R_CREAF30). Как альтернативу можно использовать user-exit EXIT_SAPLV50R_CREA_003 и дописать там нужное.
  2. В таблице TVCPL по виду поставки LFART, виду заказа AUART (определяется по виду поставки из таблицы TVLK)  и пустому типу позиции образца (поле PSTYV) выбирается поле GRUAK "Групповое условие копирования данных VBAK". Значение этого поля используется при формировании имени подпрограммы, которая будет вызвана из программы SAPLV50S по шаблону DATEN_KOPIEREN_<GRUAK> для копирования данных в поставку. Таким образом, если в GRUAK было 201, то вызовется подпрограмма  DATEN_KOPIEREN_201. От подпрограммы зависит то, какие поля будут скопированы в поставку. В частности, копирование TDDAT поддерживают только 301 и 311 подпрограммы. 


понедельник, 11 февраля 2013 г.

BOPF Determination

Если не отрабатывает ваш Determination, поиск причин можно начинать из метода DO_DETERMINATIONS класса /BOBF/CL_FRW. Внешние точки остановки там срабатывают.

понедельник, 4 февраля 2013 г.

Конфигурация BOPF

Для конфигурации объектов и ваших расширений в в Business Object Processing Framework служит транзакция /BOBF/CONF_UI. Но по умолчанию она открывается в режиме просмотра, и любые кнопки для изменения, в том числе переключения режима, недоступны. Чтобы их активировать необходимо в окне команд ввести DEBUG и затем во всплывшем окне подтвердить свое намерение.

четверг, 24 января 2013 г.

Отправка EMAIL. Подтверждения доставки и прочтения

Программно Email из SAP удобно создавать и отправлять с помощью  Business Communication Service. Примеры можно найти в программах BCS_EXAMPLE_*.

По умолчанию к письмам почему-то добавляются запросы о доставке и прочтении. Иногда это совсем не нужно. Отменить их можно так:

lo_request->SET_STATUS_ATTRIBUTES( I_REQUESTED_STATUS = 'E'  ). ,
где lo_request - экземпляр класса CL_BCS.


Wait

Команда wait up to N seconds в ABAP  теоретически может принимать в качестве N вещественные числа. Например, так:
wait up to '0.1' seconds.

Но на практике оказывается, что она  их округляет. Таким образом, wait up to '0.5' seconds соответствует 1 секунде, а wait up to '0.4' seconds - 0 секунд. С одной и более секунд понятно, а вот 0 секунд на первый взгляд бессмысленны, но это не так. Например, если вы запустили новую задачу с помощью CALL FUNCTION '...' STARTING NEW TASK и в цикле ожидаете ее завершения, чтобы получить результаты, то пока вы не вызовите wait, у вас не отработает та форма или метод класса, которую/который вы назначили как callback для вашей задачи. Поэтому в цикле ожидания имеет смысл вызывать именно wait up to 0 seconds, потому что даже целая секунда в данном случае  - это много.

пятница, 28 сентября 2012 г.

понедельник, 6 августа 2012 г.

Встраивание своего обработчика в процесс вывода BSP приложения.

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

Вначале была идея написать свой HTTP Request Handler  и встроить его в систему. Но выяснились следующие вещи. Во-первых, просто присвоить свой обработчик  в транзакции SICF к своему Z-BSP-приложению  не получится, потому что все Z-BSP-приложения находятся на уровне /default_host/sap/bc/bsp/sap/*, а на раздел BSP уже назначен обработчик CL_HTTP_EXT_BSP, и все обработчике ниже этого узла работать не будут. Можно бы было добавить свой обработчик к узлу  /default_host/sap/bc/bsp/, либо  вообще его заменить своим, из которого уже вызывать изначальный. Но как показывает чужой опыт (вот, например) это может привести к тому, что сервис будет деактивирован после переноса запроса в целевую систему. Хотя его потом можно активировать вручную, хотелось бы избежать лишних телодвижений и дерганья базисников. И это - во-вторых.

Тогда был найден другой способ. Каждому BSP приложению можно назначить Класс приложения на вкладке Свойства. Этому классу (либо его родительскому классу) можно назначить интерфейс IF_BSP_APPLICATION_EVENTS и реализовать его. Реализовать нужно 4 метода   (ON_REQUEST, ON_RESPONSE,  ON_START и ON_STOP). Причем реализация может быть пустой - главное чтобы метод был.
Методы ON_START и ON_STOP вызываются при запуске и завершении всего BSP-приложения. Методы ON_REQUEST и ON_RESPONSE вызываются для каждого запроса, перед и после стандартного обработчика, соответственно.

В моем случае мне подходил ON_RESPONSE, так как мне нужно было менять готовый ответ. Текущую отдаваемую страницу можно было получить с помощью RESPONSE->GET_CDATA( ), а установить новую с помощью RESPONSE->SET_CDATA(), где RESPONSE - параметр метода ON_RESPONSE типа IF_HTTP_RESPONSE.