08 апреля 2019 Интеграция с SAP ERP

Интеграция с SAP ERP. Реализация мобильного прайс-чекера в магазине.

В рассматриваемом нами примере интеграции SAP ERP со сторонним ПО мы будем использовать SAP Connector for Microsoft .NET для получения данных из SAP ERP. Программное обеспечение для терминала сбора данных (ТСД) будет состоять из Microsotf Internet Information Server (IIS) на сервере и клиентского ПО Internet Explorer, технология используемая для разработки компоненты - asp.net на языке программирования C#.

При разработке FM в SAP указываем настройку "Дистанционный модуль"

Функция принимает значение завод I_WERKS и возвращает таблицу TAB

  1. FUNCTION Y_GET_MATNR_PRICE
  2.   IMPORTING
  3.     VALUE(I_WERKS) TYPE WERKS_D
  4.   TABLES
  5.     TAB LIKE YSOUT_PRICE
  6.   EXCEPTIONS
  7.     NO_DATA
  8.     NO_VKORG.

Настройка для IIS в базе данных SQL Server

asp.net часть на C# используем SAP Connector for Microsoft .NET

Настройка SAP Connector

  1.     public class MyBackendConfig : IDestinationConfiguration
  2.     {
  3.         SaalutDataClasses1DataContext context;
  4.  
  5.         public RfcConfigParameters GetParameters(String destinationName)
  6.         {
  7.             if (context == null)
  8.                 context = new SaalutDataClasses1DataContext();
  9.  
  10.             if ("AEP".Equals(destinationName))
  11.             {
  12.                 var settingsSP = (from s in context.SettingsSAPERPTbls
  13.                                   select s).FirstOrDefault();
  14.  
  15.                 RfcConfigParameters parms = new RfcConfigParameters();
  16.                 parms.Add(RfcConfigParameters.Name, settingsSP.SystemID);
  17.                 parms.Add(RfcConfigParameters.AppServerHost, settingsSP.MessageServerHost);
  18.                 if (settingsSP.LogonGroup != null || settingsSP.LogonGroup != "")
  19.                     parms.Add(RfcConfigParameters.LogonGroup, settingsSP.LogonGroup);
  20.                 parms.Add(RfcConfigParameters.SystemID, settingsSP.SystemID);
  21.                 parms.Add(RfcConfigParameters.SystemNumber, settingsSP.SystemNumber);
  22.                 if (settingsSP.SAPRouter != null || settingsSP.SAPRouter != "")
  23.                     parms.Add(RfcConfigParameters.SAPRouter, settingsSP.SAPRouter);
  24.                 parms.Add(RfcConfigParameters.User, settingsSP.SAPUser);
  25.                 parms.Add(RfcConfigParameters.Password, settingsSP.SAPPassword);
  26.                 parms.Add(RfcConfigParameters.Client, settingsSP.Client);
  27.                 parms.Add(RfcConfigParameters.Language"en");
  28.                 parms.Add(RfcConfigParameters.PoolSize"5");
  29.                 parms.Add(RfcConfigParameters.MaxPoolSize"10");
  30.                 parms.Add(RfcConfigParameters.IdleTimeout"600");
  31.                 return parms;
  32.             }
  33.             else return null;
  34.         }
  35.  
  36.         public bool ChangeEventsSupported()
  37.         { return false; }
  38.         public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
  39.     }

Загрузка данных:

  1.                 RfcDestinationManager.RegisterDestinationConfiguration(cfg);//1             
  2.                 RfcDestination prd = RfcDestinationManager.GetDestination("AEP");//2  
  3.  
  4.  
  5.                 RfcRepository repo = prd.Repository;//3                                     
  6.                 IRfcFunction pricesBapi =
  7.                     repo.CreateFunction("Y_GET_MATNR_PRICE");//4                               
  8.                 pricesBapi.SetValue("I_WERKS", werk); //5                 
  9.                 pricesBapi.Invoke(prd); //6                 
  10.                 IRfcTable detail = pricesBapi.GetTable("TAB");

Полученные данные вставляем в таблицу SQL Server:

  1.                 int i = 0;
  2.                 foreach (IRfcStructure elem in detail)
  3.                 {
  4.                     string matnr = elem[0].GetString();
  5.                     double kbetr = elem[1].GetDouble();
  6.                     string kschl = elem[2].GetString();
  7.                     string assort = elem[3].GetString();
  8.  
  9.                     SAPPriceTbl np = new SAPPriceTbl();
  10.                     np.MATNR = matnr;
  11.                     np.KBETR = kbetr;
  12.                     np.KSCHL = kschl;
  13.                     np.ASSORT = assort;
  14.                     context.SAPPriceTbls.InsertOnSubmit(np);
  15.  
  16.                     if (== 100)
  17.                     {
  18.                         context.SubmitChanges();
  19.                         i = 0;
  20.                     }
  21.                     i++;
  22.                 }
  23.                 context.SubmitChanges();

Рисуем интерфейс в Visual Studio для ТСД. Осуществляем поиск по штрихкоду, визуально сопостовляем цену в ТСД с ценой на ценнике и в случае расхождений добавляем в журнал:

Полный код C# на GitHub

Полный код функционального модуля SAP в качестве примера:

  1. FUNCTION Y_GET_MATNR_PRICE
  2.   IMPORTING
  3.     VALUE(I_WERKS) TYPE WERKS_D
  4.   TABLES
  5.     TAB LIKE YSOUT_PRICE
  6.   EXCEPTIONS
  7.     NO_DATA
  8.     NO_VKORG.
  9.  
  10.  
  11.   DATA: lv_vkorg TYPE vkorg,
  12.         lt_rec TYPE TABLE OF t_line,
  13.         ls_rec TYPE t_line,
  14.         lr_kschl TYPE ycl_common=>ty_t_kschl_range.
  15.  
  16.   SELECT SINGLE vkorg FROM t001w
  17.     INTO lv_vkorg
  18.     WHERE werks EQ i_werks.
  19.   IF sy-subrc NE 0 OR lv_vkorg IS INITIAL.
  20.     RAISE no_vkorg.
  21.   ENDIF.
  22.  
  23.   lr_kschl = ycl_common=>get_kschl_range( iv_call_prog = sy-repid iv_call_index = 1 ).
  24.  
  25.   IF tab[] IS INITIAL.
  26.  
  27.     SELECT a971~kschl a971~matnr a971~vrkme a971~datbi a971~datab a971~knumh
  28.            konp~kopos konp~kbetr konp~konwa AS waers konp~loevm_ko
  29.       INTO CORRESPONDING FIELDS OF TABLE lt_rec
  30.       FROM a971 INNER JOIN mara
  31.         ON mara~matnr = a971~matnr
  32.        AND mara~meins = a971~vrkme
  33.       LEFT JOIN konp
  34.         ON konp~knumh EQ a971~knumh
  35.       WHERE a971~kappl EQ 'V'  
  36.         AND a971~kschl IN lr_kschl
  37.         AND a971~vkorg EQ lv_vkorg
  38.         AND a971~vtweg EQ '01'
  39.         AND a971~werks EQ i_werks
  40.         AND a971~datbi GE sy-datum
  41.         AND a971~datab LE sy-datum.
  42.  
  43.   ELSEIF tab[] IS NOT INITIAL.
  44.  
  45.     SELECT a971~kschl a971~matnr a971~vrkme a971~datbi a971~datab a971~knumh
  46.            konp~kopos konp~kbetr konp~konwa AS waers  konp~loevm_ko
  47.       INTO CORRESPONDING FIELDS OF TABLE lt_rec
  48.       FROM a971 INNER JOIN mara
  49.         ON mara~matnr = a971~matnr
  50.        AND mara~meins = a971~vrkme
  51.       LEFT JOIN konp
  52.         ON konp~knumh EQ a971~knumh
  53.       FOR ALL ENTRIES IN tab
  54.       WHERE a971~kappl EQ 'V'  
  55.         AND a971~kschl IN lr_kschl
  56.         AND a971~vkorg EQ lv_vkorg
  57.         AND a971~vtweg EQ '01'
  58.         AND a971~werks EQ i_werks
  59.         AND a971~matnr EQ tab-matnr
  60.         AND a971~datbi GE sy-datum
  61.         AND a971~datab LE sy-datum.
  62.  
  63.   ENDIF.
  64.   DELETE lt_rec WHERE  loevm_ko EQ 'X'.
  65.   IF lt_rec IS INITIAL.
  66.     RAISE no_data.
  67.   ENDIF.
  68.   ls_rec-sort_order = 1.
  69.   MODIFY lt_rec FROM ls_rec TRANSPORTING sort_order WHERE kschl EQ ycl_common=>c_vka0.
  70.   ls_rec-sort_order = 2.
  71.   MODIFY lt_rec FROM ls_rec TRANSPORTING sort_order WHERE kschl EQ ycl_common=>c_yvk3.
  72.   ls_rec-sort_order = 3.
  73.   MODIFY lt_rec FROM ls_rec TRANSPORTING sort_order WHERE kschl EQ ycl_common=>c_vkp0.
  74.   SORT lt_rec BY matnr ASCENDING
  75.                  sort_order ASCENDING
  76.                  kopos ASCENDING.
  77.   FIELD-SYMBOLS: <fs_rec> TYPE t_line,
  78.                  <fs_line> TYPE ysout_price.
  79.   DATA: lv_find TYPE flag.
  80.   CLEAR lv_find.
  81.   CLEAR tab[].
  82.   LOOP AT lt_rec ASSIGNING <fs_rec>.
  83.     AT NEW matnr.
  84.       CLEAR lv_find.
  85.     ENDAT.
  86.     CHECK lv_find NE 'X'.
  87.     IF <fs_rec>-kbetr > 0.
  88.       APPEND INITIAL LINE TO tab ASSIGNING <fs_line>.
  89.       CHECK <fs_line> IS ASSIGNED.
  90.  
  91.       CALL FUNCTION 'BAPI_CURRENCY_CONV_TO_EXTERNAL'
  92.         EXPORTING
  93.           currency        = <fs_rec>-waers
  94.           amount_internal = <fs_rec>-kbetr
  95.         IMPORTING
  96.           amount_external = <fs_line>-kbetr.
  97.  
  98.       CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
  99.         EXPORTING
  100.           input  = <fs_rec>-matnr
  101.         IMPORTING
  102.           output = <fs_line>-matnr.
  103.  
  104.       <fs_line>-kschl = <fs_rec>-kschl.
  105.  
  106.       CALL FUNCTION 'WLK1_CHECK'
  107.         EXPORTING
  108.           DATE                        = sy-datum
  109.           item                        = <fs_rec>-matnr
  110.           shop_werks                  = i_werks
  111.           component_check             = 'X'
  112.         EXCEPTIONS
  113.           no_listing                  = 1
  114.           no_listing_in_time          = 2
  115.           existing_exclusion_listing  = 3
  116.           wrong_parameters            = 4
  117.           no_open_time_shop_in_time   = 5
  118.           no_listing_for_promotion    = 6
  119.           wrong_location              = 7
  120.           no_complete_listing_in_time = 8
  121.           wrong_rackjobber            = 9
  122.           listing_only_as_component   = 10
  123.           no_assignment               = 11
  124.           OTHERS                      = 12.
  125.       IF sy-subrc EQ 0.
  126.         <fs_line>-assort = 'X'.
  127.       ENDIF.
  128.  
  129.  
  130.       lv_find = 'X'.
  131.     ENDIF.
  132.  
  133.   ENDLOOP.
  134. ENDFUNCTION.

Функционал SAP Connector for Microsoft .NET и C# позволяет получать данные простым и удобным способом из SAP ERP.