XL017 – Wykorzystanie API ERP XL

Wprowadzenie

System Comarch ERP XL może pracować jako serwer aplikacji udostępniając innym aplikacjom swoje funkcje. Dzięki zaimplementowaniu funkcji API (Application Programming Interface) dowolna aplikacja może w prosty sposób korzystać z mechanizmów, którymi dysponuje Comarch ERP XL. Daje to niespotykaną w rozwiązaniach konkurencyjnych otwartość systemu, pozwalając zarówno na integrację ze standardowymi narzędziami programistycznymi, (np. Microsoft Office i Visual Basic) jak i możliwość integracji z dowolnym systemem informatycznym eksploatowanym w firmie.

System Comarch ERP XL oferuje kilkadziesiąt funkcji pozwalających na zdalną pracę w systemie. Funkcje te są zgromadzone w bibliotece CDN_API.DLL, która jest instalowana łącznie z całym systemem Comarch ERP XL.

Uwaga
Aby aplikacja wykorzystująca XL API mogła być łatwo przenoszona pomiędzy komputerami, wskazane jest, aby folder, w którym jest zainstalowany program Comarch ERP XL, był umieszczony w ścieżce dostępu systemu Windows. Umożliwi to aplikacji zewnętrznej odszukanie odpowiednich bibliotek DLL. W przypadku, gdy aplikacja zewnętrzna jest umieszczona w kartotece z bibliotekami programu Comarch ERP XL, powyższy warunek nie jest konieczny.

Hermetyczność

Duży nacisk przy tworzeniu funkcji  XL API położony został na bezpieczeństwo i integralność danych wprowadzanych poprzez te funkcje. Wynikiem tego jest funkcja weryfikująca Użytkownika (XLLogin) oraz wewnętrzny mechanizm Comarch ERP XL kontrolujący poprawność zakończenia działania funkcji API.

Program Comarch ERP XL bardzo dokładnie śledzi wszelkie zmiany w bazie, dokonywane przy pomocy funkcji API. Jeżeli wystąpi błąd, który spowoduje niepoprawne przerwanie działania aplikacji wykorzystującej API, to wszystkie zmiany przez nią wprowadzone, które nie zostały poprawnie zakończone, zostają bezwzględnie wycofane. Warunkiem poprawności zmian wprowadzanych przez API jest albo zakończenie wprowadzania obiektu, który stanowi logiczną całość albo wylogowanie się z systemu funkcją XLLogout.

Przyklad
Obiektem, który tworzy logiczną całość jest np. faktura. Tworzenie takiego obiektu z poziomu funkcji API ograniczają funkcje XLNowyDokument oraz XLZamknijDokument. Jeżeli przerwanie działania aplikacji nastąpi po wywołaniu pierwszej z nich, a przed zamknięciem dokumentu, to dokument taki zostanie wycofany z bazy danych. Jeżeli natomiast zostanie poprawnie zakończone wywołanie funkcji XLZamknijDokument, to dokument taki jest zapisywany na stałe w bazie danych nawet, jeżeli błąd aplikacji wystąpi przed wylogowaniem się poprzez funkcję XLLogout (dokument jako logiczna całość został wprowadzony poprawnie).

Wersjonowanie

Ponieważ zakładamy, iż funkcjonalność  XL API będzie stale rozszerzana, funkcje te zostały wyposażone w mechanizm wersjonowania. Zapewni on kompatybilność z poprzednimi wersjami API, czyli pozwoli na uniknięcie sytuacji, w których po zmodyfikowaniu (rozszerzeniu) funkcji API Użytkownicy i Integratorzy byliby zmuszeni do wprowadzania odpowiednich zmian w napisanych przez siebie aplikacjach wspomagających.

Ponieważ Comarch ERP XL musi zawsze działać na najnowszych strukturach danych, mechanizm wersjonowania będzie pełnił rolę translatora pomiędzy strukturami API przekazanymi z zewnętrznej aplikacji, a strukturami wykorzystywanymi wewnątrz Comarch ERP XL. Po wartości przekazanej w polu: Wersja, zostanie rozpoznana struktura przekazana do funkcji i dokonane zostanie odpowiednie przepisanie wartości do struktury wewnętrznie wykorzystywanej przez Comarch ERP XL. W momencie, gdy struktury wewnętrzne i zewnętrzne są różne, pola niewykorzystywane zostaną wypełnione domyślnymi wartościami.

Ponieważ struktury danych wykorzystywane przez API służą również do zwracania danych z programu Comarch ERP XL, mechanizm wersjonowania jest mechanizmem działającym w obie strony (dokonana zostanie odpowiednia translacja danych wewnętrznych do struktury przekazywanej na zewnątrz).

Dzięki temu aplikacje napisane w aktualnej wersji API będą działały poprawnie również w kolejnych wersjach Comarch ERP XL, bez potrzeby dokonywania w nich przeróbek (z wyjątkiem sytuacji, w której chcemy rozszerzyć funkcjonalność aplikacji o nowe możliwości Comarch ERP XL API).

Przyklad
Zestaw funkcji jest jeden. Różne są zestawy parametrów tych funkcji (z sufixami _1, … , _12) w bibliotece dynamicznej CDN_API.DLL są funkcje bez sufiksów. Rozpoznanie wersji jest realizowane w ten sposób, że każda struktura ma pole: Wersja, które jest sprawdzane przy wywołaniu poszczególnych funkcji i w zależności od tej wartości, wewnętrznie wołane są funkcje z odpowiednimi sufiksami. Użycie jednocześnie 2 wersji API nie jest polecane, jeśli chodzi o funkcje dotyczące tego samego obszaru, tzn. nie powinno się stosować funkcji dodającej nagłówek w wersji 1 a funkcji dodającej pozycje w wersji 5. Choć możliwe jest działanie w takich przypadkach funkcji, to nie polecamy takiego rozwiązania. Natomiast stosowanie różnych wersji w różnych obszarach Comarch ERP XL jest jak najbardziej dopuszczalne. Tzn. można wystawić zamówienie zestawem funkcji w wersji 1, a fakturę zestawem funkcji w wersji np. 5.

Po każdorazowej zmianie struktur, publikowana będzie nowa wersja XL API oznaczona kolejnym numerem. Numer ten będzie nadawany równolegle dla wszystkich struktur API niezależnie od tego, czy została ona zmieniona (np. zmiana tylko w strukturze XLLoginInfo spowoduje zmianę numeru wersji dla wszystkich pozostałych struktur API).

Algorytm postępowania

Typowy scenariusz wykorzystujący funkcje XL-API najprościej jest prześledzić na przykładzie faktury sprzedaży.

Kolejność wywoływanych funkcji jest następująca:

  • XLLogin - inicjalizacja bibliotek Comarch ERP XL, login operatora do bazy danych;
  • XLNowyDokument – otwarcie nagłówka nowego dokumentu; powoduje zapisanie w bazie danych otwartego nagłówka dokumentu (w omawianym przypadku jest to faktura sprzedaży);
  • XLDodajPozycje – dodanie pozycji do faktury; wywołanie tej funkcji może nastąpić wielokrotnie, jeżeli do dokumentu chcemy dopisać więcej niż jedną pozycję;
  • XLDodajPlatnosc – zapis płatności do tworzonej faktury; wywołanie tej funkcji jest opcjonalne – jeżeli nie zostanie wywołana, system automatycznie wygeneruje płatność domyślną przy zamykaniu faktury; funkcja może być wołana wielokrotnie – np. w przypadku specyfikacji płatności ratalnej;
  • XLZamknijDokument – zakończenie edycji i zamknięcie dokumentu; dokument może być zamykany w trybie normalnym (zapis bez możliwości późniejszej modyfikacji) lub w trybie „do bufora";
  • XLLogout – w obrębie jednej sesji otwartej funkcją XLLogin możemy wystawić dowolną ilość dokumentów. Wystawienie każdego z nich powinno zaczynać się wywołaniem funkcji XLNowyDokument i kończyć wywołaniem funkcji XLZamknijDokument.

Przykłady zastosowań

Import dokumentu z pliku .TXT

Jest to szczególnie istotne dla firm wprowadzających bardzo długie transakcje zakupu. Często wraz z towarem jego dostawca dostarcza dyskietkę ze specyfikacją dostawy. Korzystając np. z programu Microsoft Excel można napisać prosty program wczytujący taki plik tekstowy do arkusza, a następnie łączący się poprzez XL API z systemem Comarch ERP XL i generujący odpowiedni dokument zakupu.

Wsadowy import transakcji

Firmy wielooddziałowe często importują poprzez łącza modemowe transakcje ze swoich oddziałów do centrali, gdzie mają one być następnie wprowadzone do bazy danych. Program importujący transakcje może za pośrednictwem  XL API połączyć się z systemem Comarch ERP XL i zapisywać w jego bazie danych zaimportowane z oddziałów dokumenty.

Przykładowe kody

Poniżej przedstawione zostały przykładowe kody wykorzystujące  XL API.

Uwaga
W przypadku wielokrotnego wywoływania tej samej funkcji API (np. dodawanie wielu pozycji do FS) konieczne jest czyszczenie struktury (zmienne typu Long należy wypełnić 0, zmienne typu String - pustym ciągiem ””) wykorzystywanej w funkcji każdorazowo po jej użyciu. Jest to konieczne, ponieważ w niektórych polach struktury zwracane są wartości, które w przypadku nie wyczyszczenia ich, będą użyte przy ponownym wykorzystaniu struktury.

Dadanie ZS z jednym elementem (VBA)

Sub Dodaj_Zamowienie()

Dim Sesja As Long

Dim Wynik As Long

Dim Login As XLLoginInfo_12

Dim IDDokumentu As Long

Dim Naglowek As XLDokumentZamNagInfo_12

Dim Element As XLDokumentZamElemInfo_12

Dim Zamkniecie As XLZamkniecieDokumentuZamInfo_12

Sesja = 0

IDDokumentu = 0

With Login

.Wersja = 12

.programID = "TestXL"

.Baza = "CDNXL_Test"

.OpeIdent = "ADMIN"

.OpeHaslo = ""

End With

Wynik = XLlogin_12(Login, Sesja)

If Wynik <> 0 Then

MsgBox("Błąd logowania: " & Wynik)

End If

With Naglowek

.Wersja = 12

.Typ = 6

.Akronim = "Test"

End With

Wynik = XLNowyDokumentZam_12(Sesja, IDDokumentu, Naglowek)

If Wynik <> 0 Then

MsgBox("Błąd dodawania nagłówka: " & Wynik)

End If

With Element

.Wersja = 12

.Ilosc = 10

.CenaKatalogowa = 1

.Towar = "Test"

End With

Wynik = XLDodajPozycjeZam_12(IDDokumentu, Element)

If Wynik <> 0 Then

MsgBox("Błąd dodawania pozycji: " & Wynik)

End If

With Zamkniecie

.Wersja = 12

.TrybZamkniecia = 2

End With

Wynik = XLZamknijDokumentZam_12(IDDokumentu, Zamkniecie)

If Wynik <> 0 Then

MsgBox("Błąd zamykania nagłówka: " & Wynik)

End If

Wynik = XLlogout_12(Sesja)

If Wynik <> 0 Then

MsgBox("Błąd wylogowania: " & Wynik)

End If

End Sub

Przekształcenie ZS do FS (VBA)

Public Sesja As Long

Public IDDokumentu As Long

Public Wynik As Long

Public ElemInfo As XLDokumentElemInfo_12

Sub Zaloguj()

Dim Login As XLLoginInfo_12

Sesja = 0

Wynik = 0

With Login

.Wersja = 12

.ProgramId = "X:VBA"

.Baza = "CDN_XL_Test"

.OpeIdent = ""

.OpeHaslo = ""

End With

Wynik = XLLogin_12(Login, Sesja)

If Wynik <> 0 Then

Wynik = MsgBox("Błąd logowania: " & Wynik)

Exit Sub

End If

End Sub

Sub DodajNaglowek()

Dim NagInfo As XLDokumentNagInfo_12

Worksheets("Nagłówek ZS").Select

Wersja = 12

With NagInfo

.Wersja = 12

.Typ = 4

.ZamFirma = Range("b2").Value

.ZamNumer = Range("c2").Value

.ZamTyp = Range("a2").Value

End With

Wynik = 0

Wynik = XLNowyDokument_12(Sesja, IDDokumentu, NagInfo)

If Wynik <> 0 Then

Wynik = MsgBox("Błąd dodawania nagłówka: " & Wynik)

Exit Sub

End If

End Sub

Sub ZamknijNaglowek()

Dim ZamkniecieInfo As XLZamkniecieDokumentuInfo_12

ZamkniecieInfo.Wersja = 12

ZamkniecieInfo.Tryb = 0

Wynik = 0

Wynik = XLZamknijDokument_12(IDDokumentu, ZamkniecieInfo)

If Wynik <> 0 Then

Wynik = MsgBox("Błąd zamykania nagłówka: " & Wynik)

Exit Sub

Else

Wynik = MsgBox("Poprawnie dodano dokument WZ.")

End If

End Sub

Function Pierwszy_wolny_rekord() As Integer

Dim licznik As Long

licznik = 2

Do

If Range("A" & licznik).Value = "" Then

Pierwszy_wolny_rekord = licznik

Exit Function

Else

licznik = licznik + 1

End If

Loop

Stop

End Function

Sub DodajPozycje()

Worksheets("Pozycja ZS").Select

licznik = Pierwszy_wolny_rekord()

For x = 2 To licznik - 1

With ElemInfo

.Wersja = 12

.ZamFirma = Range("b" & x).Value

.ZamTyp = Range("a" & x).Value

.ZamNumer = Range("c" & x).Value

.ZamLp = Range("d" & x).Value

End With

Wynik = 0

Wynik = XLDodajPozycje_12(IDDokumentu, ElemInfo)

If Wynik <> 0 Then

Wynik = MsgBox("Błąd dodawania pozycji: " & Wynik)

Exit Sub

End If

Next x

End Sub

Sub Wyloguj()

Wynik = 0

Wynik = XLLogout_12(Sesja)

If Wynik <> 0 Then

Wynik = MsgBox("Błąd wylogowywania: " & Wynik)

Exit Sub

End If

End Sub

Sub Przeksztalc_ZS()

Zaloguj

DodajNaglowek

DodajPozycje

ZamknijNaglowek

Wyloguj

End Sub

Dodaj Kontrahenta (.NET)

Dla programistów wykorzystujących platformę MS .NET został przygotowany plik assembly, zawierający deklaracje struktur oraz funkcji używanych w XL API. Plik jest dostępny na stronie Comarch (w zasobach Comarch ERP XL). Obecna wersja jest wersją testową, ciągle rozwijaną. Plik należy dołączyć w referencjach projektu (w Microsoft Visual Studio .NET można to zrobić wybierając w menu Project/Add Reference).

using System;

using cdn_api;

namespace XLNowyKontrahent

{

class APIDodajKontrahenta

{

[STAThread]

static void Main(string[] args)

{

XLLoginInfo_12 Login = new XLLoginInfo_12();

Login.Wersja = 12;

Login.ProgramID = "API.NET";

Login.Baza = "maciek4n";

Login.OpeIdent = "ADMIN";

Login.OpeHaslo = "";

Int32 SesjaID = 0;

Int32 KontrahentID = 0;

int LoginResult = cdn_api.cdn_api.XLLogin(Login, ref

SesjaID);

if (LoginResult == 0)

{

XLKontrahentInfo_12 Kontrahent = new XLKontrahentInfo_12();

Kontrahent.Wersja = 12;

Kontrahent.Akronim = "Nowy Kontrahent";

int KontrahentResult =

cdn_api.cdn_api.XLNowyKontrahent(SesjaID,ref KontrahentID,Kontrahent);

}

cdn_api.cdn_api.XLLogout(SesjaID);

}

}

}

Wskazówki do API w C8

Ogólne wytyczne w zakresie konfiguracji

1. Do sprawdzenia są elementy związane z wymogami systemowymi.

  • Zainstalowany i włączony .NET 4.0.

2. Warunki związane z samym systemem ERP XL dla wszystkich systemów operacyjnych:

  • Baza systemu ERP XL musi być podpięta dla wszystkich użytkowników komputera

(wpis o bazie musi być w rejestrze w gałęzi HKEY_LOCAL_MACHINE:

[HKEY_LOCAL_MACHINE\SOFTWARE\CDN\CDNXL\MSSQL\Bazy] – 32bit

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\CDN\CDNXL\MSSQL\Bazy] 64 bit)
  • Musi być wpisany klucz HASP
[HKEY_LOCAL_MACHINE\SOFTWARE\CDN\HASPXL]

Lub

[HKEY_LOCAL_MACHINE\SOFTWARE\CDN\HASP]

“Serwer”=”Tu nazwa serwera HASP”

  • Ścieżka do systemu ERP XL musi być w globalnej zmiennej środowiskowej PATH -widzianej przez wszystkich użytkowników systemu, a w szczególności przez ASPNET
  • Operator, na którego jest logowanie przez API nie może mieć pustego hasła
  • Wymagania związane z użytkownikami Windowsów:

Użytkownik ASPNET musi być w grupie użytkownicy, użytkownik na którym działa

IIS i ASP musi mieć prawa do katalogu z systemem ERP XL - chodzi o to żeby ten

użytkownik miał uprawnienia do uruchomienia ERP XL. [/su_list]

3. Na systemach serwerowych (2003,2008, 2012) i VISTA, Win 7, 8 najlepiej utworzyć dla takiej aplikacji osobną pulę aplikacji. Użytkownik, na którym działa pula (domyślnie Usługa Sieciowa) musi mieć prawo do katalogu z systemem Comarch ERP XL, aby miał uprawnienia do uruchomienia systemu.

4. Dodatkowo funkcje API powinny być wołane w trybie wsadowym.

5. Na C8 – nowy interfejs – przed logowaniem do API trzeba zawołać poniższy kod.

//jeśli C8 wołana jest metoda z ClaRUN.dll

public class Cdnsys

{

[DllImport(“ClaRUN.dll”)]

static extern void AttachThreadToClarion(int _flag);

public void AttachThread()

{

try

{

AttachThreadToClarion(1);

}

catch (Exception){}

}

}

Powyższe AttachThreadToClarion trzeba wołać przy każdym podnoszeniu nowego wątku.

6. W zmiennej środowiskowej Path powinno być wskazanie w ścieżce na jeden folder z systemem ERP XL (jeżeli jest zawarte odwołanie do innych folderów z wcześniejszymi wersjami należy je usunąć a następnie zapisać zmiany i zrestartować komputer).

7. Trzeba wołać attachthread wg wskazań w dokumentacji (lub jak powyżej) do każdego

nowego wątku i nie używać async’a. Jeżeli XLLogin jest wołane w innym wątku niż

pozostałe funkcje API to ten wątek musi pozostać aktywny tak długo jak wołamy funkcje

API – nie można po jego zakończeniu wołać funkcji API.

8. AttachThreadToClarion woła się 1 raz po utworzeniu wątku .net ( w tymże utworzonym wątku) – czyli 1 raz na wątek (teoretycznie nie ma ograniczenia na ilość wywołań AttachThread). Po wywołaniu AttachThreadToClarion wątek .net i wątek Clariona to jest jeden i ten sam wątek, nie ma więc operacji odwrotnej do AttachThreadToClarion. Jak zakończy się wątek utworzony w .net to zakończy się również w Clarionie i obiekty wątkowe zostaną zwolnione.

Plik Konfiguracyjny

Plik konfiguracyjny aplikacji nie pojawia się automatycznie po stworzeniu projektu i należy go dodać samodzielnie. Wystarczy kliknąć prawym przyciskiem myszy na projekt, do którego chcemy dodać plik z konfiguracjami, następnie wybrać opcję “Add New Item” i w oknie wyboru typu pliku zaznaczyć “Application Configuration File”. Dalej podaje się jego nazwę – standardowo App.config i potwierdza wybór.

Logowanie do API poprzez usługę

Podczas startowania usługi ( np. realizacja zamówienia ZS dokumentem WZ) wołany jest XLLogin, czyli są ustawiane obiekty globalne m.in. kolekcje rodzajów kontrahentów, definicje dokumentów itd. (wszystkie rzeczy konfiguracyjne XL’a). Potem startuje nowy wątek, w którym są wystawiane dokumenty np. WZ. Podczas gdy startuje nowy wątek to część danych konfiguracyjnych kopiuje z wątku głównego (robiona jest kopia żeby wątki się nie blokowały na czas dostępu do danych w wątku głównym). Należy zwrócić uwagę na specyficzne zachowanie usług (jeżeli usługa zawiera metody OnStart, OnStop, AutoResetEvent, WaitOne) – przy jej uruchamianiu wołana jest metoda OnStart (jeśli w niej byłoby umieszczone logowanie do API) to wątek w którym OnStart został wywołany może być za chwilę zakończony, co pociąga za sobą zwolnienie obiektów globalnych ładowanych przy XLLogin. Od tego momentu nowo tworzone wątki generujące np. WZ nie mają skąd skopiować danych konfiguracyjnych.

Rozwiązaniem jest w metodzie OnStart uruchomienie nowego wątku, w którym jest logowanie do API i ustawienie po zalogowaniu aby wątek nie zakończył się. Można to zrobić za pomocą statycznego obiektu klasy AutoResetEvent i metody WaitOne. W metodzie OnStop usługi trzeba wtedy zawołać metodę Set na tym obiekcie (po wylogowaniu z API).

API a aplikacje działające w oparciu o webserwis

W architekturze serwera opartego o WCF i klienta, problemem dla clariona jest kończenie wątku głównego gdy proces się nie kończy – czyli z punktu widzenia systemu operacyjnego wszystko jest poprawnie, jest wątek główny samej usługi. Wątek ten nie jest jednak związany z clarionem, więc w clarionie dopiero wątek w którym następuje logowanie do API jest wątkiem głównym – po wylogowaniu wątek ten się kończy mimo iż proces nadal działa – czy z punktu widzenia clariona sytuacja niemożliwa do uzyskania – nie ma czegoś takiego jak proces bez żadnego wątku, dlatego tez z tego powodu co jakiś czas zgłaszane mogą być wyjątki.

Rozwiązaniem będzie przy starcie usługi wydzielenie jednego wątku, związanie go z clarionem (AttachThread…) i pozostawieniem aktywnym przez cały czas działania usługi. W wątku tym trzeba wywołać od razu XLLogin. I teraz można zrobić od razu XLLogout, lub pozostawić tą sesję aktywną i w niej wystawiać dokumenty z wątków tworzonych na żądanie klientów – będzie szybciej działać. Czyli teraz nie byłoby już wołania XLLogin,XLNowyDokument…, XLLogout za każdym razem, ale jedynie XLNowyDokument z ID sesji ustalonym w wątku pierwszym.

Trzeba tak zmodyfikować dodatek, żeby choć jeden wątek procesu był podłączony do wątku clarionowego, tak aby nie było sytuacji, w której proces jest aktywny a żaden wątek nie jest połączony z clarionem. To wymaganie nie dotyczy okresu aktywności przed pierwszym wywołaniem AttachThreadToClarion.

Możliwe problemy do weryfikacji:

  • czy IIS po wylogowaniu z API od razu zamknie wątek czy zostawi w puli na pewien czas
  • czy podczas pracy w innym wątku na API IIS nie zamknie takiego zużytego wątku z puli, bo już tam długo tkwił (wtedy zwolnione zostaną obiekty globalne z których może chcieć korzystać pracujący wątek – one pracują w ramach jednego procesu w3wp)

Connection string

Po zmianach w API XLPolaczenie nie zwraca automatycznie danych odnośnie połączenia. Funkcja API zwraca niezbędne dane do połączeń w aplikacji uzupełnione w tabeli cdn.Konfig i Kon_Numer = -137, Kon_Komentarz = ‘ConnectionString’.

Od wersji 2019.0 XLPolaczenie zwraca dane z funkcji skalarnej CDN.PodajDodatokwyConnectString – co pozwala na dynamiczną weryfikację połączenia, w przeciwieństwie do stałej danej wpisanej w CDN.Konfig.

 

Debugowanie od wersji XL 2021

Od wersji 2021.0 podłączenie się pod procesy XL debugerem zostało standardowo zablokowane ze względu na zalecenia działu bezpieczeństwa.  W celu debugowania należy zastosować pakiet deweloperski dostępny na stronach walidowanych dla partnerów w sekcji dodatki dla wersji XL 2021 ( pliki z pakietu należy wgrać do katalogu XL następnie uruchomić rejestr.bat).

Czy ten artykuł był pomocny?