W aplikacji umożliwiono usuwanie, dodawanie oraz edycję raportów z poziomu serwera synchronizacji. Definicje raportów znajdują się w katalogu: C:\Program Files (x86)\Comarch Mobile\Serwer synchronizacji/Reports.
Aby dodać nowy raport należy utworzyć jego definicję, a następnie zapisać go w formacie xml.
Uwaga
W przypadku zapisu definicji raportu w Notatniku należy wybrać kodowanie UTF-8.
Aby usunąć istniejący raport należy zmienić jego ID na ujemne, następnie zmienić datę modyfikacji (np. wystarczy zapisać ponownie plik z raportem) i wykonać synchronizację.
Uwaga
Podczas synchronizacji definicji raportów na urządzenie brana jest pod uwagę data modyfikacji pliku. W celu wymuszenia synchronizacji raportu należy wykonać dowolną modyfikację.
Zmiana ID raportu na ujemne
Istnieje możliwość zmiany języka raportu.
Przyklad
W przypadku, gdy w wersji polskojęzycznej chcemy mieć raport w języku niemieckim, to należy zmodyfikować ostatni człon nazwy z deu na pol, następnie należy zmienić datę modyfikacji.
Przykład modyfikacji raportu
W celu opisania przykładowej modyfikacji raportu wykorzystany zostanie Raport dobowy przedstawiciela. Do tegoż raportu zostanie dodany argument za pomocą którego możliwe będzie wybranie dnia, z którego dany raport zostanie zaprezentowany.
W tym celu należy wyedytować definicję raportu o nazwie 53#DailyReport#pol.xml znajdującą się w domyślnej lokalizacji C:\Program Files (x86)\Comarch Mobile\Serwer synchronizacji\Reports\ i katalogu odpowiednim dla systemu ERP. W pliku tym należy przed sekcją elements dodać sekcję zawierającą argumenty raportu oraz argument o typie daty (typeId = 0) według następującego przykładu:
Kolejnym krokiem dla lepszej czytelności raportu będzie usunięcie godziny z nagłówka raportu znajdującego się na zielonej belce. Dla pierwszego elementu raportu (id = 1) należy wyedytować sekcję sql w pozostawiając następujące polecenie:
Następnie w całym pliku należy wyszukać wszystkie fragmenty kodu odnoszące się do aktualnej daty i zamienić je na odnoszące się do wcześniej zdefiniowanego argumentu. Wobec tego należy fragmenty:
date('now','localtime')
Zamienić na następujące:
date(@data@/1000, 'unixepoch', 'localtime')
Po wykonaniu tych kroków zmodyfikowany raport będzie wymagał wyboru daty:
Widok okna z wyborem parametru
I będzie prezentował dane o stanach magazynów mobilnych oraz wystawionych dokumentach, zapisach kasowych i obrotu kaucjami z wybranego dnia.
Widok raportu z różnymi danymi
Elementy składowe
Definicja raportu składa się z danych sekcji xml. Główną sekcją raportu jest sekcja report. W niej zaś zawarte są następujące:
reportHeader
reportType
onListVisibillity
arguments
elements
W celu opisania elementów składowych raportów jako przykład wykorzystany zostanie standardowy raport dostępny w aplikacji Comarch Mobile - Podsumowanie dnia, którego definicja znajduje się w pliku 2#SummaryOfTheDay#pol.xml.
Nagłówek
Nagłówek raportu opisany jest sekcją reportHeader, w niej zaś znajdują się poniższe:
Nazwa
name
Opis
Nazwa raportu.
Parametry
wartość tekstowa
Nazwa
description
Opis
Opis raportu.
Parametry
wartość tekstowa
Przyklad
<reportHeader>
<name>Podsumowanie dnia</name><description>Podsumowanie wykonanych w dniu operacji. Sprzedaż wg grup. Udział grup w sprzedaży dnia.</description>
</reportHeader>
Widok raportu w kaflu Raporty
Typ raportu
Sekcja oznaczająca typ raportu: reportType. Musi zawierać następującą sekcję:
Nazwa
value
Opis
Wartość typu raportu. Np. jeżeli użytkownik nie posiada praw do dokumentów zakupowych, to nie wykona raportu o typie 1 oraz 0.
Parametry
0 - wszystkie typy
1 - raport sprzedażowy
2 - raport zakupowy
3 - raport serwisowy
Przyklad
<reportType>
<value>0</value>
</reportType>
Widoczność raportu
Sekcja onListVisibillity określa miejsca w aplikacji mobilnej poza kaflem Raporty, z których dostępny jest raport. Musi zawierać następującą sekcję:
Nazwa
value
Opis
Wartość występowania raportu. Możliwe wartości łączone np. 129 = 128+1 - raport widoczny zarówno na liście kontrahentów jak i karcie kontrahenta.
Parametry
0 - tylko lista raportów
1 - lista kontrahentów
2 - lista towarów
4 - element wizyty "Inny"
8 - listy pozycji dokumentów
16 - duża kalkulacja podczas dodawania pozycji na dokument
Dostępność raportu z poziomu dodawania pozycji na dokumencie
Argumenty
Raport może wykorzystywać podane przez użytkownika aplikacji po kliknięciu w ikonę ołówka argumenty (parametry). Argumenty znajdują się w sekcji arguments definicji raportu, zaś poszczególne argumenty opatrzone są sekcją argumentwedług następującego przykładu:
Przyklad
<arguments>
<argument>...</argument>
</arguments>
Parametry raportu Podsumowanie dnia
Wskazówka
Aby wstawiane polecenia SQL działały poprawnie należy umieścić je w znaczniku <![CDATA[polecenieSQL ]> w celu wyłączenia spod analizy deserializatora XML.
Argument może zawierać następujące sekcje:
Nazwa
id
Opis
Identyfikator argumentu.
Parametry
wartość liczbowa
Nazwa
typeId
Opis
Typ argumentu.
Parametry
0 - wybór daty
1 - pole tekstowe
2 - lista z parametrami zdefiniowanymi w sekcji posibleSQL
3 - pole liczbowe
4 - wybór kontrahenta
5 - wybór towaru
6 - wybór typu check
Wskazówka
Jeżeli typ argumentu został wybrany jako 0 (wybór daty), to element defaultSQL należy ustawić jako:
<![CDATA[select date('now','localtime')]]>
zaś posibleSQL zostawić puste wstawiając:
<![CDATA[]]>
Przyklad
Przykład argumentu wybranego jako typ 6 (typ check) w raporcie Prezentacja partii towaru (45#ItemLots#pol.xml) dostępnym przy współpracy z systemem ERP Altum:
<argument>
<id>3</id><typeId>6</typeId><name>mag</name><visibleName>Magazyn</visibleName><defaultSQL><![CDATA[SELECT '(' || group_concat(id, ',') || ')' AS Conc, 'Wszystkie' AS ValueFROM WarehousesWHERE IsActive = 1 AND Id > 0GROUP BY Value ]]></defaultSQL><posibleSQL><![CDATA[SELECT id || ' [' || code || '] ' , name FROM Warehouses WHERE IsActive = 1 AND Id > 0 ]]></posibleSQL>
</argument>
Widok wyboru parametru o typie check
Nazwa
name
Opis
Nazwa argumentu używana w poleceniach SQL.
Parametry
wartość tekstowa
Nazwa
visibleName
Opis
Nazwa argumentu widoczna w aplikacji.
Parametry
wartość tekstowa
Nazwa
defaultSQL
Opis
Wartość parametru ustawiana domyślnie. Jeżeli wartość pozostanie pusta (ustawiona na <![CDATA[]]>) to wartość parametru w aplikacji ustawi się na 'Wybierz wartość' i konieczny będzie wybór tego parametru przed otwarciem raportu.
Parametry
polecenie SQL
Nazwa
posibleSQL
Opis
Wartości parametru możliwe do wyboru.
Parametry
polecenie SQL
Nazwa
isErpSQL
Opis
Znacznik decydujący czy polecenie SQL ma być wykonywane na bazie systemu ERP. Używany w raportach online.
Parametry
brak sekcji - polecenie wykonywane na bazie mobilnej
0 - polecenie wykonywane na bazie mobilnej
1 - polecenie wykonywane na bazie systemu ERP
Nazwa
validationRule
Opis
Znacznik definiujący sposób walidacji argumentu (tylko dla typu data).
Parametry
Trzy cyfry oddzielone kropkami np. 2.0.1:
Pierwsza cyfra:
0 - brak walidacji
1 - sprawdzenie, czy data jest przyszła
2 - sprawdzenie, która data jest późniejsza
Druga cyfra - określa pary argumentów (np. argument dataOd 2.1.1 a dataDo 2.1.2)
Trzecia cyfra - określa która data ma być wcześniejszą (wartość 1), a która późniejszą (wartość 2)
Przyklad
<argument>
<id>2</id><typeId>2</typeId><name>grupowanie</name><visibleName>Sposób grupowania</visibleName><defaultSQL><![CDATA[select 0,'Brak']]></defaultSQL><posibleSQL><![CDATA[select 0,'Brak' union all select 1,'Kategoria' union all select 2,'Marka' union all select 3,'Producent' union all select 4,'Grupa']]></posibleSQL>
</argument>
Zdefiniowany w powyższym przykładzie argument widoczny jest w aplikacji w następujący sposób:
Parametr Sposób grupowania
Elementy
Elementy raportu składają się na jego wygląd w aplikacji mobilnej. Poszczególne elementy raportu znajdują się w sekcji elements definicji raportu, zaś każda z poniżej opisanych sekcji może znajdować się w sekcji element, która jest definicją jednego elementu.
Przyklad
<elements>
<element>...</element>
</elements>
Nazwa
id
Opis
Identyfikator elementu.
Parametry
wartość liczbowa
Nazwa
typeId
Opis
Typ elementu.
Parametry
0 – nagłówek raportu, który w aplikacji widoczny jest w raporcie na zielonej belce.
1 – tabela1
2 – tabela2
3 – wykres słupkowy
4 – wykres kołowy
5 – wykres liniowy
6 – wartość tekstowa
Nazwa
sql
Opis
Polecenie SQL wykonywane na bazie SQL, które tworzy tabelę wynikową. Podanie argumentu odbywa się poprzez umieszczenie jego nazwy w znakach @ np. @grupowanie@.
Parametry
polecenie SQL/polecenie wywołujące procedurę
Nazwa
header
Opis
Nagłówek elementu.
Parametry
wartość tekstowa/polecenie SQL
Nazwa
headerType
Opis
Typ nagłówka raportu.
Parametry
0 - tekst
1 - polecenie SQL
Nazwa
isSummary
Opis
Znacznik czy element zawiera podsumowanie zwartości tabeli. W przypadku jego użycia w sekcji sql należy umieścić polecenia sumujące wybrane kolumny tabeli.
Parametry
brak sekcji - brak podsumowania
0 - brak podsumowania
1 - podsumowanie
polecenie SQL zwracające jedną z powyższych wartości
Nazwa
isSummaryType
Opis
Typ znacznika podsumowania.
Parametry
brak sekcji - wartość liczbowa
0 - wartość liczbowa
1 - polecenie SQL
Nazwa
isErpSQL
Opis
Znacznik czy polecenie ma być wykonane na bazie systemu ERP. Używany w raportach online.
Parametry
brak sekcji - polecenie wykonywane na bazie mobilnej
0 - polecenie wykonywane na bazie mobilnej
1 - polecenie wykonywane na bazie systemu ERP
Nazwa
reportTypeVisibility
Opis
Widoczność elementu w zależności od rodzaju raportu.
Parametry
0 - wszystkie typy
1 - raport sprzedażowy
2 - raport zakupowy
3 - raport serwisowy
Nazwa
showNumberOfRows
Opis
Wyświetla liczbę zwróconych rekordów w tabeli jako ostatni wiersz tabeli. Używane tylko gdy sekcja isSummary przyjmuje wartość 1.
Parametry
brak sekcji - nie wyświetlaj
0 - nie wyświetlaj
1 - wyświetl
Nazwa
isExecute
Opis
Znacznik czy wykonać dany element.
Parametry
0 - brak wykonania
1 - wykonanie
polecenie SQL zwracające jedną z powyższych wartości
Nazwa
isExecuteType
Opis
Typ znacznika wykonania elementu.
Parametry
brak sekcji - wartość liczbowa
0 - wartość liczbowa
1 - polecenie SQL
Przyklad
<element>
<id>8</id><typeId>3</typeId><sql><![CDATA[selectcoalesce(categories.name, 'Brak kategorii') as Kategoria,sum(DocumentsPositions.GrossValueInSystemCurrency) as NetValuefrom documentsjoin documentspositionson documentspositions.documentid = documents.idAND DocumentsPositions.DocumentIsLocal = Documents.DocumentIsLocaland DocumentsPositions.IsItemsSetVirtualPosition = 0and DocumentsPositions.RelatedItemsSetOrdinal is nulljoin items on items.id = documentspositions.itemidleft join categories on items.categoryid = categories.idwhere Documents.DocumentIsLocal = 1 AND documents.NumeratorId IN (16,17) AND datetime(DocumentDate/1000, 'unixepoch','localtime') >datetime(date(@data@/1000, 'unixepoch', 'localtime'),'start of day') and datetime(DocumentDate/1000, 'unixepoch','localtime') <datetime(date(@data@/1000, 'unixepoch','localtime'),'start of day','+1 day', '-1 seconds') and 1 = @grupowanie@ group by categories.nameunion allselectcoalesce(brands.name, 'brak marki') as Marka,sum(DocumentsPositions.GrossValueInSystemCurrency) as NetValuefrom documentsjoin documentspositions on documentspositions.documentid = documents.id AND DocumentsPositions.DocumentIsLocal = Documents.DocumentIsLocal and DocumentsPositions.IsItemsSetVirtualPosition = 0 and DocumentsPositions.RelatedItemsSetOrdinal is nulljoin items on items.id = documentspositions.itemidleft join brands on items.brandid = brands.idwhere Documents.DocumentIsLocal = 1 AND documents.NumeratorId IN (16,17) AND datetime(DocumentDate/1000, 'unixepoch','localtime') >datetime(date(@data@/1000, 'unixepoch', 'localtime'),'start of day') and datetime(DocumentDate/1000, 'unixepoch','localtime') <datetime(date(@data@/1000, 'unixepoch','localtime'),'start of day','+1 day', '-1 seconds') and 2 = @grupowanie@ group by brands.nameunion allselectcoalesce(Producers.name, 'brak producenta') as Grouping,sum(DocumentsPositions.GrossValueInSystemCurrency) as NetValuefrom documentsjoin documentspositions on documentspositions.documentid = documents.idAND DocumentsPositions.DocumentIsLocal = Documents.DocumentIsLocaland DocumentsPositions.IsItemsSetVirtualPosition = 0and DocumentsPositions.RelatedItemsSetOrdinal is nulljoin items on items.id = documentspositions.itemidleft join Producers on items.producerid = Producers.idwhere Documents.DocumentIsLocal = 1 AND documents.NumeratorId IN (16,17) AND datetime(DocumentDate/1000, 'unixepoch','localtime') >datetime(date(@data@/1000, 'unixepoch', 'localtime'),'start of day') and datetime(DocumentDate/1000, 'unixepoch') <datetime(date(@data@/1000, 'unixepoch','localtime'),'start of day','+1 day', '-1 seconds') and 3 = @grupowanie@ group by Producers.nameunion allselectcoalesce(ig.name , 'brak grupy towaru') as Grupa ,sum(DocumentsPositions.GrossValueInSystemCurrency) as GrossValuefrom documentsjoin documentspositionson documentspositions.documentid = documents.idAND DocumentsPositions.DocumentIsLocal = Documents.DocumentIsLocaland DocumentsPositions.IsItemsSetVirtualPosition = 0and DocumentsPositions.RelatedItemsSetOrdinal is nulljoin items on items.id = documentspositions.itemidjoin itemsgroupslinks igl on items.id = igl.itemidjoin itemsgroups ig on groupid = ig.idwhere Documents.DocumentIsLocal = 1 AND documents.NumeratorId IN (16,17) AND (select count(*) from itemsgroups join itemsgroupslinks on itemsgroupslinks.itemid = igl.itemid and itemsgroups.id = itemsgroupslinks.groupid where parentid = ig.id) = 0 and datetime(DocumentDate/1000, 'unixepoch','localtime') >datetime(date(@data@/1000, 'unixepoch', 'localtime'),'start of day') and datetime(DocumentDate/1000, 'unixepoch','localtime') <datetime(date(@data@/1000, 'unixepoch','localtime'),'start of day','+1 day', '-1 seconds') and @grupowanie@=4 group by ig.name]]></sql><header>Wykres zakupu wg grupowania</header><isSummary>0</isSummary><reportTypeVisibility>2</reportTypeVisibility>
</element>
Widok standardowego raportu Podsumowanie dnia
Przykłady modyfikacji raportów
Dodanie argumentu
W celu opisania przykładowej modyfikacji raportu wykorzystany zostanie Raport dobowy przedstawiciela. Do raportu zostanie dodany argument za pomocą którego możliwe będzie wybranie dnia, z którego dany raport zostanie zaprezentowany.
W tym celu należy wyedytować definicję raportu o nazwie 53#DailyReport#pol.xml znajdującą się w domyślnej lokalizacji C:\Program Files (x86)\Comarch Mobile\Serwer synchronizacji\Reports\ i katalogu odpowiednim dla systemu ERP. W pliku tym należy przed sekcją elements dodać sekcję zawierającą argumenty raportu oraz argument o typie daty (typeId = 0) według następującego przykładu:
Kolejnym krokiem dla lepszej czytelności raportu będzie usunięcie godziny z nagłówka raportu znajdującego się na zielonej belce. Dla pierwszego elementu raportu (id = 1) należy wyedytować sekcję sql w pozostawiając następujące polecenie:
Następnie w całym pliku należy wyszukać wszystkie fragmenty kodu odnoszące się do aktualnej daty i zamienić je na odnoszące się do wcześniej zdefiniowanego argumentu. Wobec tego należy fragmenty:
date('now','localtime')
Zamienić na następujące:
date(@data@/1000, 'unixepoch', 'localtime')
Po wykonaniu tych kroków zmodyfikowany raport będzie wymagał wyboru daty:
Widok okna z wyborem parametru
I będzie prezentował dane o stanach magazynów mobilnych oraz wystawionych dokumentach, zapisach kasowych i obrotu kaucjami z wybranego dnia.
Widok raportu z różnymi danymi
Dodanie nowej kolumny w tabeli
W celu opisania modyfikacji wykorzystany zostanie raport Sprzedaż SKU. Modyfikacja dotyczyć będzie dodania nowej kolumny z kodem EAN w tabeli Towary.
Standardowy raport Sprzedaż SKU
W tym celu należy wyedytować definicję raportu o nazwie 1#SalesSKU#pol.xml znajdującą się w domyślnej lokalizacji C:\Program Files (x86)\Comarch Mobile\Serwer synchronizacji\Reports\.
Wskazówka
Poprawność modyfikowanych zapytań SQL można zweryfikować wykonując je na bazie mobilnej (plik data.db na urządzeniu mobilnym) np. za pomocą narzędzia SQLite Studio.
W pliku należy wyedytować zapytanie SQL dla elementu o id = 3 dodając do niego pole zwracające kod EAN dla danego towaru w poleceniu select wraz z funkcją IFNULL, która w przypadku braku kodu EAN dla towaru zwróci pustą wartość w wierszu tabeli. Następnie należy do zapytania dołączyć tabelę ItemsBarcodes używając polecenia LEFT JOIN oraz odpowiednich aliasów. Dodane linijki zostały oznaczone kolorem żółtym.
<id>3</id>
<typeId>1</typeId>
<sql>
<![CDATA[
Select
Items.Name as '[l]Nazwa',
IFNULL(bar.Barcode, '') AS EAN,
(sum(DocumentsPositions.Quantity/DocumentsPositions.Denominator*DocumentsPositions.Nominator)) as '[d4]Ilość',
DocumentsPositions.UnitName as JM,
cast(ROUND(sum(DocumentsPositions.NetValueInSystemCurrency), 2) as Varchar) || ' ' || c.Symbol as 'Netto',
cast(ROUND(sum(DocumentsPositions.GrossValueInSystemCurrency), 2) as varchar) || ' ' || c.Symbol as 'Brutto',
sum(DocumentsPositions.Quantity) as '[d4]Ilość(podst.)',
DocumentsPositions.BaseUnitName as 'JM(podst.)'
from Documents d
join DocumentsPositions
on d.Id = DocumentsPositions.DocumentId
AND d.DocumentIsLocal = DocumentsPositions.DocumentIsLocal
and DocumentsPositions.IsItemsSetVirtualPosition = 0
and DocumentsPositions.RelatedItemsSetOrdinal is null
join Items on Items.Id = DocumentsPositions.ItemId
left JOIN ItemsBarcodes bar ON bar.ItemId = DocumentsPositions.ItemId
join Currencies c ON c.e = 1 AND c.IsSystem = 1
where d.DocumentIsLocal = 1 AND NumeratorId IN (1,2,3,4,5) AND datetime(d.DocumentDate/1000, 'unixepoch','localtime') >datetime(date(@dataOd@/1000, 'unixepoch','localtime'),'start of day')
and datetime(d.DocumentDate/1000, 'unixepoch','localtime') <datetime(date(@dataDo@/1000, 'unixepoch','localtime'),'start of day','+1 day', '-1 seconds')
group by DocumentsPositions.ItemId,unitname order by items.name
]]>
</sql>
Zmodyfikowany w ten sposób raport będzie prezentował się następująco:
Raport Sprzedaż SKU z dodatkową kolumną EAN
Usunięcie kolumny z tabeli
W celu opisania modyfikacji wykorzystany zostanie raport Ranking kontrahentów kupujących towar, w którym to usunięte zostaną dwie kolumny z tabeli: Marża (kwotowo) i Marża (procentowo).
Standardowy raport: Ranking kontrahentów kupujących towar
W tym celu należy wyedytować definicję raportu o nazwie 38#CustomersPurchasingItems#pol.xml znajdującą się w domyślnej lokalizacji C:\Program Files (x86)\Comarch Mobile\Serwer synchronizacji\Reports\.
Wskazówka
Poprawność modyfikowanych zapytań SQL można zweryfikować wykonując je na bazie mobilnej (plik data.db na urządzeniu mobilnym) np. za pomocą narzędzia SQLite Studio.
Z pliku należy usunąć część zapytania SQL dla elementu o id = 2, która odpowiada za zwrócenie wartości danych kolumn Marża (kwotowo) i Marża (procentowo). Będzie to poniższy fragment, który dla tego elementu występuje dwa razy:
CASE
WHEN SUBSTR(ROUND(SUM(Case when d.IsVatFromNetValue == 1 THEN dp.MarginValueInSystemCurrency ELSE dp.MarginValueInSystemCurrency*100/(100+dp.VatRateValue) END), 2), LENGTH(ROUND(SUM(Case when d.IsVatFromNetValue == 1 THEN dp.MarginValueInSystemCurrency ELSE dp.MarginValueInSystemCurrency*100/(100+dp.VatRateValue) END), 2))-1,1) = "."
THEN ROUND(SUM(Case when d.IsVatFromNetValue == 1 THEN dp.MarginValueInSystemCurrency ELSE dp.MarginValueInSystemCurrency*100/(100+dp.VatRateValue) END), 2) || "0" || "<br/>" || (Select Value From Configuration Where Key == 'Currency')
ELSE ROUND(SUM(Case when d.IsVatFromNetValue == 1 THEN dp.MarginValueInSystemCurrency ELSE dp.MarginValueInSystemCurrency*100/(100+dp.VatRateValue) END), 2) || "<br/>" || (Select Value From Configuration Where Key == 'Currency')
END AS '[c]Marża<br/>(kwotowo)',
CASE
WHEN (Select Value From Configuration Where Key == 'MarginCountType') == 1
THEN IFNULL(ROUND(ROUND(SUM(Case when d.IsVatFromNetValue == 1 THEN dp.MarginValueInSystemCurrency ELSE dp.MarginValueInSystemCurrency*100/(100+dp.VatRateValue) END), 2)/SUM(dp.EndNetPriceInSystemCurrency * dp.Quantity)*100, 2), 0.00) || " %"
ELSE IFNULL(ROUND(ROUND(SUM(Case when d.IsVatFromNetValue == 1 THEN dp.MarginValueInSystemCurrency ELSE dp.MarginValueInSystemCurrency*100/(100+dp.VatRateValue) END), 2)/SUM(dp.BaseNetPriceInSystemCurrency * dp.Quantity)*100, 2), 0.00) || " %"
END AS '[c]Marża<br/>(procentowo)'
Dodatkowo należy usunąć możliwość wyboru sortowania danych po usuniętych kolumnach. W tym celu dla argumentu o id = 4 z sekcji posibleSQL należy usunąć następujące wartości:
UNION ALL
SELECT 3, 'Marża(kwotowo)'
UNION ALL
SELECT 4, 'Marża(procentowo)'
Po wykonaniu powyższych kroków raport powinien wyglądać następująco:
Raport: Ranking kontrahentów kupujących towar po modyfikacji
Społeczność Comarch
Dzięki społeczności Comarch ERP rozwiązujemy problemy, dzielimy się pomysłami oraz informujemy o różnych nowościach.