HermesSQL zakupy i łańcuch dokumentów

Zamówienie do dostawcy

Zakup w systemie ERP nie jest jednym dokumentem, lecz sekwencją kilku zapisów o różnym skutku. Zamówienie do dostawcy deklaruje zamiar i nie zmienia stanu magazynu. Przyjęcie zwiększa stan ilościowy, a faktura zakupu zwiększa zobowiązanie i trafia do rejestru VAT. Tak wygląda mechanizm ogólny. Dla HermesSQL potwierdzają go opisy modułu na stronie o zakupach towarów oraz kosztów i usług: zamówienia do dostawców i rejestracja faktur zakupowych.

Zamówienie powstaje ręcznie albo z propozycji wyliczonej wcześniej. Źródłem propozycji bywa bilans zamówień i rezerwacji albo harmonogram opisany w tekście o planowaniu zakupów materiałowych. Ta strona zaczyna dopiero od momentu, gdy decyzja o zakupie już zapadła i trzeba ją zapisać w dokumentach.

DokumentSkutek magazynowySkutek finansowy
Zamówienie do dostawcyBrak zmiany stanu, rośnie ilość oczekiwanaBrak zapisu księgowego
Przyjęcie towaruWzrost stanu ilościowego i wartościowegoWartość przyjęcia do rozliczenia z fakturą
Faktura zakupuBez zmiany ilościZobowiązanie wobec dostawcy i wpis do rejestru VAT
Korekta fakturyZmiana ilości albo wartości pozycjiZmniejszenie lub zwiększenie zobowiązania

Przyjęcie towaru na magazyn

Przyjęcie zewnętrzne rejestruje faktyczną ilość, która weszła na magazyn, niezależnie od tego, co dostawca zapisał na liście przewozowym. Przebieg fizyczny opisuje tekst o przyjęciu do magazynu i dokumentach dostawy, a rodzaje dokumentów porządkuje strona o dokumentach magazynowych. Dostawę awizowaną poprzedza ustalenie terminu i rampy w kalendarzu awizacji, a przyjęcie porównuje ilość rzeczywistą z zapowiedzianą.

Reguła: faktura zakupu nie zastępuje przyjęcia. Dokument finansowy i dokument magazynowy mają osobne cykle życia, a ich powiązanie wynika z relacji między pozycjami, nie z numeru wpisanego w pole tekstowe.

Faktura zakupu

Faktura dostawcy trafia do systemu po przyjęciu albo równolegle z nim. Rejestracja porównuje pozycje faktury z pozycjami przyjęcia i zamówienia. Rozbieżność w cenie lub ilości zatrzymuje dokument przed zatwierdzeniem, bo dopiero zatwierdzona faktura zapisuje się do rejestru VAT i do rozrachunków.

Statusy dokumentu zakupu

Dokument przechodzi kilka statusów, a każdy z nich odbiera część uprawnień do edycji. W buforze pozycje można dowolnie zmieniać, bo system nie wykonał jeszcze żadnego ruchu. Po zatwierdzeniu powstaje ruch magazynowy i wpis do rejestru, więc dalsze zmiany wymagają korekty.

StatusEdycja pozycjiSkutek w systemie
BuforDozwolonaBrak ruchu magazynowego i wpisu do rejestru
ZatwierdzonyZablokowanaRuch magazynowy i zapis w rejestrze VAT
ZaksięgowanyZablokowanaDekretacja przekazana do modułu finansowego
AnulowanyZablokowanaDokument wyłączony z rozliczeń, ślad zostaje w historii

Rozdzielenie ról wzmacnia kontrolę. Osoba, która rejestruje fakturę, nie powinna jej zatwierdzać, a uprawnienie do zatwierdzania przypisuje się rolą, nie pojedynczym użytkownikom. Przy większej liczbie dostawców taki podział ogranicza błędy wynikające z pośpiechu.

Pola dokumentu zakupu i dekretacja

Nagłówek z danymi dostawcy

Opis rejestracji zakupu w HermesSQL zaczyna się od utworzenia nowego dokumentu i wpisania podstawowych danych. Chodzi o datę zakupu i dostawcę, a dalej o numer faktury oraz listę produktów z cenami i ilościami. Każde z tych pól pełni w bazie inną funkcję.

  • Dostawca - odwołanie do kartoteki kontrahentów, z którego biorą się termin płatności i domyślne konta.
  • Numer faktury dostawcy - identyfikator z dokumentu źródłowego, wpisywany bez zmian, bo służy do wykrywania duplikatów.
  • Data zakupu - data, od której dokument wpływa na rejestr VAT i na wycenę magazynu.
  • Pozycje - towary lub usługi wraz z ilością i ceną jednostkową.

Typowy błąd polega na wpisaniu numeru faktury z dodatkowymi spacjami albo w innej wielkości liter. Baza traktuje wtedy dwa zapisy jako różne dokumenty, mimo że dotyczą tej samej dostawy. Kontrola unikalności w parze dostawca i numer eliminuje ten problem, jeżeli numer jest wcześniej znormalizowany.

Schemat nagłówka i pozycji

Poniższy schemat jest przykładem, a nie opisem rzeczywistej struktury HermesSQL. Pokazuje, jak zapisać nagłówek i pozycje tak, aby baza sama pilnowała integralności.

CREATE TABLE dbo.ZakupNaglowek (
    Id             INT IDENTITY(1,1) PRIMARY KEY,
    DostawcaId     INT          NOT NULL,
    NrFakturyDost  NVARCHAR(50) NOT NULL,
    DataZakupu     DATE         NOT NULL,
    Status         TINYINT      NOT NULL DEFAULT 0,
    CONSTRAINT UQ_Zakup_Dostawca_Nr UNIQUE (DostawcaId, NrFakturyDost)
);

CREATE TABLE dbo.ZakupPozycja (
    Id               INT IDENTITY(1,1) PRIMARY KEY,
    NaglowekId       INT           NOT NULL
        REFERENCES dbo.ZakupNaglowek (Id),
    ZamowieniePozId  INT           NULL,
    TowarId          INT           NOT NULL,
    Ilosc            DECIMAL(18,3) NOT NULL CHECK (Ilosc <> 0),
    CenaNetto        DECIMAL(18,4) NOT NULL
);

Ograniczenie CHECK dopuszcza ilość ujemną, bo korekty często zapisuje się jako pozycje z przeciwnym znakiem. Kolumna ZamowieniePozId jest opcjonalna, ponieważ zakup może wystąpić bez wcześniejszego zamówienia. Dokumentacja o kluczach głównych i obcych w SQL Server opisuje zachowanie ograniczeń przy usuwaniu i aktualizacji wierszy.

Konta księgowe i kategorie kosztowe

Zgodnie z opisem systemu zakup przypisuje się do właściwych kont księgowych, dzięki czemu dane trafiają do systemu finansowego bez ponownego wpisywania. Ten sam dokument można zaklasyfikować kategorią kosztową i centrum budżetowym. System podpowiada wtedy opcje wybierane najczęściej w poprzednich transakcjach, co skraca rejestrację powtarzalnych zakupów.

Dekretacja jest w istocie tabelą reguł: rodzaj towaru albo usługi wskazuje konto kosztu, a stawka podatku wskazuje konto VAT naliczonego. Przy zakupach usług i kosztów, takich jak transport czy media, ta sama reguła wybiera dodatkowo projekt lub dział. Szersze zasady organizacji zaopatrzenia zbiera tekst o zarządzaniu zakupami w firmie.

Wartość przyjęcia a koszty dodatkowe

Cena z faktury dostawcy nie zawsze jest pełnym kosztem nabycia. Transport i cło doliczone na osobnej fakturze zwiększają wartość towaru tylko wtedy, gdy firma tak zdecyduje w polityce rachunkowej. Zakupy usług i kosztów strona o zakupach towarów oraz kosztów i usług opisuje jako osobną ścieżkę rejestracji, z przypisaniem do projektu lub działu.

Od tej decyzji zależy metoda wyceny rozchodu. Przy FIFO koszt dodatkowy trafia do najstarszej partii, przy średniej ważonej rozkłada się na cały stan. Wybór metody wpływa na marżę w raportach, choć nie zmienia ilości na magazynie.

Powiązania dokumentów i rozliczanie ilości

Klucz obcy między pozycjami

Powiązanie zamówienia z przyjęciem i fakturą realizuje się na poziomie pozycji. Pozycja przyjęcia wskazuje pozycję zamówienia, a pozycja faktury wskazuje pozycję przyjęcia. Dzięki temu jedna faktura obejmuje kilka przyjęć, a jedno zamówienie dzieli się na kilka dostaw. Relację wiele do wielu zapisuje się w osobnej tabeli powiązań z ilością rozliczoną w każdym połączeniu.

Ilustracja bazy danych SQL Server przechowującej powiązane dokumenty zakupu i ich pozycje
Relacje pozycji zamówienia z pozycjami przyjęcia zapisane w bazie zamiast w polach opisowych

Niezrealizowane pozycje zamówień

Rozliczenie ilości sprowadza się do porównania sumy przyjęć z ilością zamówioną. Przykładowe zapytanie zwraca pozycje, które czekają na dostawę lub dostały ją tylko częściowo.

SELECT z.Id            AS PozycjaZamowienia,
       z.Ilosc         AS Zamowiono,
       ISNULL(SUM(p.Ilosc), 0) AS Przyjeto,
       z.Ilosc - ISNULL(SUM(p.Ilosc), 0) AS Pozostalo
FROM dbo.ZamowieniePozycja AS z
LEFT JOIN dbo.PrzyjeciePozycja AS p
       ON p.ZamowieniePozId = z.Id
GROUP BY z.Id, z.Ilosc
HAVING z.Ilosc - ISNULL(SUM(p.Ilosc), 0) > 0;

LEFT JOIN zachowuje pozycje bez żadnego przyjęcia, które przy zwykłym INNER JOIN zniknęłyby z wyniku. Ta sama zasada leży u podstaw pola ilości oczekiwanej, o którym mowa w tekście o stanach magazynowych.

Transakcja przy zapisie przyjęcia

Zapis przyjęcia dotyka kilku tabel naraz. Zmieniają się nagłówek z pozycjami oraz stan magazynowy. Do tego dochodzi ilość rozliczona na zamówieniu. Jeżeli któryś zapis się nie powiedzie, pozostałe muszą zostać cofnięte, inaczej stan magazynu rozjedzie się z dokumentami. Zapewnia to jedna transakcja z ustawionym XACT_ABORT.

SET XACT_ABORT ON;
BEGIN TRANSACTION;

INSERT INTO dbo.Przyjecie (DostawcaId, DataPrzyjecia)
VALUES (@DostawcaId, CAST(GETDATE() AS DATE));

DECLARE @PzId INT = SCOPE_IDENTITY();

INSERT INTO dbo.PrzyjeciePozycja (PrzyjecieId, TowarId, Ilosc, ZamowieniePozId)
SELECT @PzId, TowarId, Ilosc, ZamowieniePozId
FROM @Pozycje;

UPDATE s
SET    s.Ilosc = s.Ilosc + p.Ilosc
FROM   dbo.StanMagazynowy AS s
JOIN   @Pozycje AS p ON p.TowarId = s.TowarId;

COMMIT TRANSACTION;

Przy domyślnym poziomie READ COMMITTED inna sesja nie zobaczy stanu przed zatwierdzeniem całej transakcji. Szczegóły blokad i wersjonowania wierszy opisuje przewodnik po blokowaniu transakcji w SQL Server. Zmienna tabelaryczna @Pozycje w przykładzie oznacza parametr procedury z listą pozycji przyjęcia.

Dostawy częściowe i nadwyżki

Dostawca rzadko realizuje zamówienie jednym transportem. Status zamówienia wynika więc z porównania ilości i zmienia się po każdym przyjęciu. Nadwyżka ponad zamówienie wymaga reguły: pozycję można odrzucić albo przyjąć w granicach tolerancji.

Status zamówieniaWarunekNastępny krok
OtwarteBrak przyjęć powiązanych z pozycjamiOczekiwanie na dostawę
Częściowo zrealizowaneSuma przyjęć mniejsza od zamówionejKolejna dostawa albo zamknięcie reszty
ZrealizowaneSuma przyjęć równa zamówionejRozliczenie z fakturą
Zamknięte z nadwyżkąSuma przyjęć większa od zamówionejDecyzja o tolerancji lub zwrocie

Korekty dokumentów zakupu

Korekta ilości i ceny

Zatwierdzonego dokumentu zakupu nie edytuje się w miejscu, bo zmieniłoby to stan magazynu i rejestr VAT wstecz. Poprawka przyjmuje formę osobnego dokumentu korygującego, który odwołuje się do oryginału. Korekta ilości cofa część przyjęcia, a korekta ceny zmienia wartość pozycji bez ruchu ilościowego.

Korekta ceny po wydaniu towaru z magazynu jest trudniejsza, ponieważ część partii już opuściła stan. Wartość różnicy dzieli się wtedy między towar, który został na magazynie, i towar wydany, co zależy od metody wyceny przyjętej w firmie.

Zwrot towaru do dostawcy

Zwrot dokumentuje się jako ruch wychodzący z odniesieniem do przyjęcia i faktury, a dopiero potem jako korektę finansową. Kolejność ma znaczenie: przy odwrotnej faktura korygująca istnieje wcześniej niż fizyczny zwrot i zobowiązanie jest niższe, choć towar nadal leży na magazynie.

Reguła: korekta zawsze wskazuje dokument źródłowy. Korekta bez odniesienia zostawia w rejestrze VAT zapis, którego nie da się powiązać z pierwotnym zakupem podczas kontroli.

Załączniki oraz raportowanie zakupów

Załączniki do dokumentu

Opis systemu wspomina o dołączaniu do dokumentu załączników, takich jak faktury i specyfikacje techniczne, oraz o własnych notatkach przy transakcji. Plik skanu faktury przechowuje się zwykle poza tabelą dokumentu, a w bazie zostaje tylko odwołanie z metadanymi. Opis producenta wspomina też o skanowaniu dokumentów i rozpoznawaniu tekstu, więc zakres tej funkcji trzeba sprawdzić w aktualnej dokumentacji HermesSQL.

Ilustracja załączników dołączanych do dokumentu zakupu, takich jak faktura i specyfikacja techniczna
Załączniki przypisane do dokumentu zakupu pozostają dostępne przy kontroli i audycie

Historia zmian dokumentu

System zachowuje historię operacji na dokumencie, co według opisu ułatwia późniejsze kontrole i audyty. Rejestr zmian zapisuje, kto i kiedy zmienił status, a także jaka była poprzednia wartość. Bez takiego zapisu nie da się ustalić, czy pozycja zmieniła cenę przed zatwierdzeniem, czy po nim.

Raporty zakupowe i eksport

Opis modułu wymienia raporty zakupowe w postaci zestawień i wykresów oraz eksport danych do Excela i PDF. Zestawienia budowane na widokach SQL opisuje strona o raportowaniu HermesSQL. Dokumenty zakupu wchodzą tam jako jedno ze źródeł danych obok sprzedaży i magazynu.

Kontrola spójności zapisów zakupu

Przyjęcia bez faktury

Towar przyjęty na magazyn bez zarejestrowanej faktury zawyża zapasy w ujęciu wartościowym, a zobowiązanie nie istnieje w księgach. Zapytanie kontrolne wyszukuje takie przyjęcia po upływie ustalonego okresu.

SELECT pz.Id, pz.DostawcaId, pz.DataPrzyjecia
FROM dbo.Przyjecie AS pz
WHERE pz.DataPrzyjecia < DATEADD(DAY, -14, CAST(GETDATE() AS DATE))
  AND NOT EXISTS (
        SELECT 1
        FROM dbo.ZakupPozycja AS zp
        WHERE zp.PrzyjeciePozId IN (
              SELECT Id FROM dbo.PrzyjeciePozycja WHERE PrzyjecieId = pz.Id));

Faktury bez przyjęcia

W przypadku odwrotnym faktura zostaje zarejestrowana przed dostawą albo dla towaru, który nigdy nie dotarł. Dokument taki pozostaje w statusie nierozliczonym i nie powinien być płatny, zanim magazyn potwierdzi ilość. Oba zapytania uruchamia się cyklicznie, na przykład jako zadanie SQL Agent, a wynik trafia do osoby odpowiedzialnej za zaopatrzenie.

Częstotliwość kontroli i odpowiedzialność

Kontrola wykonywana raz na kwartał wykrywa problemy zbyt późno, bo dostawca zdąży już wystawić noty odsetkowe. Tygodniowy przebieg zadania, z listą wysyłaną do właściciela procesu zakupowego, skraca ten czas do kilku dni. Lista musi zawierać numer dokumentu oraz nazwę dostawcy, aby osoba kontrolująca nie musiała szukać danych w kilku oknach. Zapisy starsze niż ustalony próg eskaluje się do kierownika działu, a wynik kontroli dopisuje do historii dokumentu.

Pełny obraz łańcucha dostaw ERP pokazuje strona o systemie HermesSQL dla firm. Rozróżnienie dokumentów PZ i WZ wyjaśnia z kolei opracowanie SoftwareStudio o dokumentach magazynowych.