Zastosowanie
Głównym celem konfiguracji jest automatyzacja procesu wprowadzania pozycji faktur zakupu pobranych z Krajowego Systemu e-Faktur (KSeF) bezpośrednio do systemu Comarch BPM zintegrowanego z Comarch ERP Optima. Dzięki zastosowaniu zaawansowanej logiki SQL, proces ten:
- Eliminuje ręczne przepisywanie danych: Pozycje z pliku XML KSeF automatycznie wypełniają tabelę na karcie obiegu.
- Zapewnia spójność stawek VAT: Logika mapuje tekstowe oznaczenia stawek z KSeF na wartości liczbowe z konfiguracji Optimy.
- Automatyzuje kalkulacje: System przelicza ceny i wartości netto/brutto w czasie rzeczywistym przy zmianie ilości, ceny lub stawki VAT.
Przykład jest oparty o definicję typu obiegu dostępną na stronach walidowanych w sekcji ERP 5.0->Comarch BPM (dawniej DMS)->Przykłady->ERP Optima
Zawartość przykładu
- Definicja Typu Obiegu (Workflow): Wzorcowa ścieżka obiegu dokumentu zakupu z krokami akceptacji, konfiguracją kontrolki Dane tabelaryczne i wygenerowaniem dokumentu do Comarch Optima
- Punkt konfiguracyjny ACD: Wzorcowa konfiguracja, która jest odpowiedzialna za pobranie ID dokumentu KSeF, Załącznika oraz wszystkich kluczowych danych nagłówkowych (Numer dokumentu, Kontrahent, Data zakupu, Data wystawienia, Data wpływu Termin płatności, Forma płatności, Waluta, Wartość Netto, Wartość Brutto, Numer KSeF, Data przyjęcia z KSeF) oraz utworzenie dokumentu obiegowego.
W przypadku kontrolki Kontrahent w zapytaniu przed nazwą tabeli CDN.Kontrahenci należy wskazać właściwą nazwę bazy Comarch Optima.
Kliknij tutaj, aby pobrać przykład
Zasada działania
Mechanizm opiera się na dwóch trybach pracy zintegrowanych w kontrolce Dane Tabelaryczne (Elementy):
- Tryb Inicjowania (Pobieranie z KSeF): Wyzwalany, gdy kontrolka ID_KSeF zostanie uzupełniona. System pobiera dane z tabeli do.KS_DocumentItems z bazy BPM i łączy je ze stawkami VAT z bazy konfiguracyjnej Comarch ERP Optima.
- Konfiguracja wykorzystuje ID dokumentu KSeF (zapisane w dedykowanej kontrolce typu Liczba całkowita o nazwie np. ID_KSeF) jako identyfikator do pobrania danych.
- Kontrolka tabelaryczna obserwuje pole ID_KSeF, reagując na jego wypełnienie.
- Kluczowym elementem jest zapytanie SQL umieszczone na zakładce Inicjowanie Wartości kontrolki tabelarycznej.
- Zapytanie jest filtrowane za pomocą parametru @ID_KSeF@, dzięki czemu pobiera ono wiersze z właściwego dokumentu KSeF z tabeli do.KS_DocumentItems w bazie BPM.
- Tryb Edycji (Interaktywny): Kontrolka Dane Tabelaryczne (Elementy) obserwuje sama siebie (@^SenderControlName@ = ’Elementy’), co aktywuje logikę automatycznego przeliczania wartości w trybie edycji. Pozwala to na ręczne dopasowanie towaru z kartoteki ERP, pobranie jednostki miary i przypisanie stawki VAT oraz przeliczenie pozostałych wartości.
Konfiguracja przykładu
1. Utworzono kontrolkę ID_KSeF: Na karcie obiegu dodano kontrolkę typu Liczba całkowita o nazwie (identyfikatorze) ID_KSeF, do której będzie zapisywane ID dokumentu KSeF.

2. Utworzono kontrolkę Tabelaryczną: Dodano kontrolkę typu Dane tabelaryczne o nazwie (identyfikatorze) Elementy i skonfigurowano w niej następujące kolumny:
- ”Kod Towaru” (identyfikator kolumny: Kod) – typ Lista
- ”Towar” (identyfikator kolumny: Towar) – typ Towar
- ”Ilość” (identyfikator kolumny: Ilosc) – typ Liczba stałoprzecinkowa
- ”Jm” (identyfikator kolumny: Jm) – typ Tekst
- ”Stawka” (identyfikator kolumny: Stawka) – typ Liczba stałoprzecinkowa
- ”Cena netto” (identyfikator kolumny: Cena_Netto) – typ Liczba stałoprzecinkowa
- ”Cena brutto” (identyfikator kolumny: Cena_Brutto) – typ Liczba stałoprzecinkowa
- ”Wartość netto” (identyfikator kolumny: Wartosc_Netto) – typ Liczba stałoprzecinkowa
- ”Wartość brutto” (identyfikator kolumny: Wartosc_Brutto) – typ Liczba stałoprzecinkowa

3. W kontrolce typu Dane tabelaryczne na zakładce Listy zdefiniowano zapytanie pobierające:
- Kod towaru:
select Twr_TwrId, Twr_Kod from cdn.Towary

4. Dodano obserwację kontrolki: W kontrolce Dane tabelaryczne, na zakładce Inicjowanie wartości, dodano powiązanie do kontrolki ID_KSeF oraz do samej siebie.

5. Dodano zapytanie SQL: W kontrolce Dane tabelaryczne, na zakładce Inicjowanie wartości w sekcji Wzór na wartość SQL ERP dodano zapytanie, które pobiera dane z tabeli do.KS_DocumentItems na podstawie przekazanego parametru @ID_KSeF@ (ID dokumentu KSeF). Zapytanie inicjuje kolumnę Kod Towaru i Towar jako wartość NULL, którą użytkownik powinien uzupełnić ręcznie.
- Ta sekcja jest wywoływana tylko raz, podczas inicjowania obiegu:
If
@^SenderControlName@ ='ID_KSeF'
WITH ProcessedDocumentItems AS (
/* CTE 1: Ujednolicenie stawek VAT z KSeF i ujęcie kluczowych kolumn */
SELECT
di.KSI_DocumentId,
di.KSI_ElementNazwa,
di.KSI_ElementWartoscNetto AS KSI_ElementWartoscNetto,
-- **NOWE KOLUMNY:** Dane szczegółowe pozycji
di.KSI_ElementIlosc,
di.KSI_ElementJm,
di.KSI_ElementCenaNetto,
di.KSI_ElementCenaBrutto,
-- Istniejąca kolumna stawki VAT (jako tekst)
di.KSI_ElementStawkaVAT,
-- **Puste pola:** Kod towaru
CAST(NULL AS VARCHAR(50)) AS KSI_ElementKodTowaru,
/* Ustandaryzowanie stawki KSeF do formatu liczbowego/ZW/NP ('23', '8', 'ZW', itp.) */
CASE
WHEN di.KSI_ElementStawkaVAT LIKE 'Stawka%' THEN LTRIM(RTRIM(SUBSTRING(di.KSI_ElementStawkaVAT, 7, LEN(di.KSI_ElementStawkaVAT) - 6)))
WHEN di.KSI_ElementStawkaVAT IN ('zw', 'np', 'oo', 'np') THEN UPPER(di.KSI_ElementStawkaVAT)
ELSE di.KSI_ElementStawkaVAT
END AS StandardizedKSeFVAT_Text
FROM
[BAZA_COMARCH_BPM].do.KS_DocumentItems AS di /* Należy wskazać właściwą nazwę bazy Comarch BPM */
WHERE KSI_DocumentId = @ID_KSeF@
),
OptimaVATRates AS (
/* CTE 2: Przygotowanie stawek VAT z Konfiguracji Optima */
SELECT
Kon_KonId,
Kon_Wartosc,
/* Ekstrakcja wartości liczbowej stawki - Ta wartość to 23.00, 8.00 itd. */
ISNULL(CAST(REPLACE(RTRIM(SUBSTRING(Kon_Wartosc, 1, CHARINDEX(' ', Kon_Wartosc, 2))), ',', '.') AS REAL), 1) AS StawkaVatValue,
/* NORMALIZACJA: Konwersja stawki Optima ('23.00') na format KSeF ('23') dla poprawnego JOIN */
CASE
WHEN Kon_Wartosc LIKE '%ZW%' THEN 'ZW'
WHEN Kon_Wartosc LIKE '%NP%' THEN 'NP'
WHEN Kon_Wartosc LIKE '%OO%' THEN 'OO'
WHEN Kon_Wartosc LIKE '%NP%' THEN 'NP'
ELSE CAST(ISNULL(CAST(REPLACE(RTRIM(SUBSTRING(Kon_Wartosc, 1, CHARINDEX(' ', Kon_Wartosc, 2))), ',', '.') AS REAL), 0) AS VARCHAR(10))
END AS StandardizedOptimaVAT_Text
FROM
[CDN_KNF_Konfiguracja].cdn.Konfig
WHERE Kon_Numer = 301 AND Kon_Wartosc LIKE '%PL'
)
---
/* Końcowy SELECT: Zwraca żądany zestaw kolumn */
SELECT
-- POLA TOWAROWE (Kod Towaru i Towar są puste)
pi.KSI_ElementKodTowaru AS 'Kod Towaru',
CAST(NULL AS VARCHAR(255)) AS 'Towar',
-- Dane szczegółowe pozycji
CAST(pi.KSI_ElementIlosc AS DECIMAL(18, 4)) AS 'Ilość',
CAST(pi.KSI_ElementJm AS VARCHAR(10)) AS 'Jednostka',
-- Stawka VAT jako wartość liczbowa (23.00, 8.00 lub NULL)
CASE
WHEN pi.StandardizedKSeFVAT_Text IN ('ZW', 'NP', 'OO') THEN CAST(NULL AS DECIMAL(18, 2))
ELSE CAST(ovr.StawkaVatValue AS DECIMAL(18, 2))
END AS 'Stawka',
-- Wartości
CAST(pi.KSI_ElementCenaNetto AS DECIMAL(18, 4)) AS 'Cena Netto',
-- WYELICZANIE CENY BRUTTO W PRZYPADKU BRAKU DANYCH ŹRÓDŁOWYCH (POPRAWKA)
CAST(
ISNULL(
pi.KSI_ElementCenaBrutto, -- Użyj wartości z bazy, jeśli jest
pi.KSI_ElementCenaNetto * (1 + ovr.StawkaVatValue / 100.0) -- W przeciwnym razie, wylicz
)
AS DECIMAL(18, 4)) AS 'Cena Brutto',
CAST(pi.KSI_ElementWartoscNetto AS DECIMAL(18, 2)) AS 'Wartość Netto',
-- Pola wyliczone
pi.KSI_ElementWartoscNetto * (ovr.StawkaVatValue / 100.0) AS 'VAT',
pi.KSI_ElementWartoscNetto * (1 + ovr.StawkaVatValue / 100.0) AS 'Brutto'
FROM
ProcessedDocumentItems AS pi
LEFT JOIN
OptimaVATRates AS ovr
ON
pi.StandardizedKSeFVAT_Text = ovr.StandardizedOptimaVAT_Text;
- Ta sekcja jest wywoływana przy każdej modyfikacji danych w kontrolce „Elementy” i wymaga użycia ELSE po sekcji KSeF:
ELSE if @^SenderControlName@ ='Elementy' Begin IF @Elementy_Column@=1 /* Inicjowanie pozycji wiersza po wpisaniu kodu towaru */ BEGIN UPDATE @Elementy@ set [Towar]= kod, [Jm]=(select Twr_JM from cdn.Towary where Twr_TwrID= [Kod]), [Stawka]=(select twr_StawkaZak from cdn.Towary where Twr_TwrID = [Kod]) where POS=@Elementy_Row@ END IF @Elementy_Column@=2 /* Inicjowanie pozycji wiersza po wskazaniu towaru na kontrolce Towar */ BEGIN UPDATE @Elementy@ set [Kod]= towar, [Jm]=(select Twr_JM from cdn.Towary where Twr_TwrID= TOWAR), [Stawka]=(select twr_StawkaZak from cdn.Towary where Twr_TwrID = [Kod]) where POS=@Elementy_Row@ end IF @Elementy_Column@ in (1,2) begin UPDATE @Elementy@ set [Cena_Netto]=Wartosc_Netto / ilosc, [Cena_Brutto]=((Wartosc_Netto / ilosc) + ((Wartosc_Netto / ilosc)*(Stawka/100))), [Wartosc_Brutto]=Wartosc_Netto + (Wartosc_Netto*(Stawka/100)) where POS=@Elementy_Row@ END IF @Elementy_Column@=3 or @Elementy_Column@=6 /* Przeliczanie ceny brutto i wartości netto i brutto po wskazaniu ilości i ceny netto*/ BEGIN UPDATE @Elementy@ set [Cena_Brutto]=(Cena_netto + (Cena_Netto*(Stawka/100))), [Wartosc_Netto]=(Cena_Netto * ilosc), [Wartosc_Brutto]=((Cena_Netto * ilosc)+(Cena_Netto * ilosc)*(Stawka/100)) where POS=@Elementy_Row@ END IF @Elementy_Column@=3 or @Elementy_Column@=7 /* Przeliczanie ceny netto i wartości netto i brutto po wskazaniu ilości i ceny brutto*/ BEGIN UPDATE @Elementy@ set [Cena_Netto]=Cena_Brutto / ((Stawka/100)+1), [Wartosc_Netto]=(Cena_Brutto / ((Stawka/100)+1) * ilosc), [Wartosc_Brutto]=(((Cena_Brutto / ((Stawka/100)+1)) * ilosc)+((Cena_Brutto / ((Stawka/100)+1)) * ilosc)*(Stawka/100)) where POS=@Elementy_Row@ END IF @Elementy_Column@=3 or @Elementy_Column@=8 /* Przeliczanie wartości brutto oraz ceny netto i brutto po wskazaniu ilości i wartości netto*/ BEGIN UPDATE @Elementy@ set [Cena_Netto]=Wartosc_Netto / ilosc, [Cena_Brutto]=((Wartosc_Netto / ilosc) + ((Wartosc_Netto / ilosc)*(Stawka/100))), [Wartosc_Brutto]=Wartosc_Netto + (Wartosc_Netto*(Stawka/100)) where POS=@Elementy_Row@ END IF @Elementy_Column@=3 or @Elementy_Column@=9 /* Przeliczanie wartości netto oraz ceny netto i brutto po wskazaniu ilości i wartości brutto*/ BEGIN UPDATE @Elementy@ set [Cena_Netto]=(Wartosc_brutto / ((Stawka/100)+1)) / ilosc, [Cena_Brutto]=Wartosc_brutto / ilosc, [Wartosc_netto]=Wartosc_brutto / ((Stawka/100)+1) where POS=@Elementy_Row@ END SELECT * FROM @Elementy@ END


6. Utworzono kontrolkę liczbową: Dodano kontrolkę typu Liczba stałoprzecinkowa o identyfikatorze Razem_netto, w której dodano powiązanie do kontrolki Elementy i skonfigurowano w niej zapytanie, które zlicza wartość z kolumny Wartość netto z kontrolki tabelarycznej:
select sum (Wartosc_Netto) from @Elementy@

7. Utworzono kontrolkę liczbową: Dodano kontrolkę typu Liczba stałoprzecinkowa o identyfikatorze Razem_brutto, w której dodano powiązanie do kontrolki Elementy i skonfigurowano w niej zapytanie, które zlicza wartość z kolumny Brutto z kontrolki tabelarycznej:
select sum (Wartosc_Brutto) from @Elementy@

8. Punkt ACD: W punkcie konfiguracyjnym ACD (Współpraca z KSeF), na zakładce Kontrolki, dodano kontrolkę ID_KSeF i przypisano jej zapytanie, które pobiera ID dokumentu KSeF:
select @Id1@
9. Zdefiniowano również odpowiednie zapytania SQL do poszczególnych kontrolek, do których będą pobierane dane z KSeF.

Uzupełnione dane w punkcie ACD
Po pomyślnym pobraniu dokumentu z KSeF w punkcie ACD (Import dokumentów zakupu z KSeF), dane nagłówkowe oraz identyfikator dokumentu uzupełniły się automatycznie w kontrolkach na podstawie danych odczytanych z pliku XML.

Uzupełniona Kontrolka Dane Tabelaryczne
Po pomyślnym zainicjowaniu dokumentu z punktu ACD, kontrolka tabelaryczna Elementy zostaje automatycznie wypełniona pozycjami odczytanymi bezpośrednio z systemu KSeF. Mechanizm ten zapewnia pełną zgodność danych z fakturą źródłową. System automatycznie przenosi dane dotyczące ilości, jednostki miary, stawek oraz wartości dla każdego wiersza faktury. Kolumna Jm oraz Stawka jest zablokowana do ręcznej edycji (tryb „Do odczytu”), co gwarantuje poprawność danych. Kontrolka Razem netto wyświetla poprawną sumę końcową z kolumny Wartość netto kontrolki Dane tabelaryczne. Kontrolka Razem brutto wyświetla poprawną sumę końcową z kolumny Wartość brutto kontrolki Dane tabelaryczne.

Pozostałe dane uzupełnione na karcie obiegu
Po pomyślnym zainicjowaniu dokumentu z punktu ACD, pozostałe dane na karcie obiegu zostały prawidłowo uzupełnione.





