- Tabela rozszerzenia: dane klienta leżą w osobnej tabeli w osobnym schemacie, powiązanej z awizacją numerem referencyjnym.
- Przejęte kolumny: część pojęć klienta nie dostała własnej kolumny i weszła do istniejących kolumn standardowych.
- Skutek: zapytanie czytające te kolumny po nazwach daje nieprawdę, także gdy stoi za raportem albo eksportem.
- Zasada: opis pola musi mówić o jego funkcji, a nie o nazwie kolumny.
Opisujemy dostosowanie systemu awizacji Studio VSS.net do potrzeb jednego klienta. To przypadek jednego wdrożenia, a nie opis standardu produktu. Artykuł pokazuje koszt pewnego wyboru, a nie wzorzec do powtórzenia. Kod napisaliśmy od nowa na podstawie opisu schematu, z nazwami przykładowymi, takimi jak rozszerzenie.tabela_rozszerzenia i widok_awizacji.
Nazwy kolumn standardowych pojawiają się tu wyłącznie jako opis funkcji pola. W przykładowym kodzie kolumny mają uproszczone nazwy, więc kod służy do pokazania mechanizmu, a nie do skopiowania.
Tabela rozszerzenia w osobnym schemacie
Dane specyficzne dla klienta leżą w osobnej tabeli rozszerzenia, w osobnym schemacie bazy. Tabela zbiera cztery grupy pól.
- Ilości: kartony i sztuki.
- Towar: kategorie produktów i sposób pakowania.
- Dokumenty: dokumenty eksportowe i miejsce uznane.
- Dostawa: rodzaj dostawy i wymiary palety.
Powiązanie z awizacją idzie przez numer referencyjny, czyli wartość wydawaną jako unikalna w skali całej bazy, którą opisuje strona o tabeli _refno. Relacja jeden do jednego wynika ze sposobu zapisu, a nie z ograniczenia bazy, więc sama baza nie wymusza jednego wiersza na numer.
CREATE SCHEMA rozszerzenie;
GO
CREATE TABLE rozszerzenie.tabela_rozszerzenia (
numer_ref bigint NOT NULL,
kartony int NULL,
sztuki int NULL,
pakowanie nvarchar(30) NULL,
rodzaj_dostawy nvarchar(30) NULL,
miejsce_uznane bit NULL
);
Przykład ilustracyjny, skrócony do kilku pól. Nie ma tu klucza obcego ani ograniczenia unikalności, bo powiązanie pilnuje sposób zapisu.
W jednej ze standardowych tabel poszerzono kolumnę tekstową. Kolumna z numerami zamówień urosła ze 100 do 1000 znaków, żeby mieścić listę kilku numerów rozdzielonych średnikiem. Zmianę typu kolumny opisuje dokumentacja ALTER TABLE.
Widoki jako warstwa opisów
Obok tabeli rozszerzenia klient ma kilkanaście widoków, które zamieniają kody na opisy ze słowników. Widoki korzystają z sześciu słowników: rodzaj awizacji, typ transportu, rodzaj kontenera, magazyn, oddział i rampa. Odbiorca zapytania widzi dzięki nim opis zamiast kodu, a treść słownika zmienia się w jednym miejscu.
Widoki rozróżniają też dostawy i wysyłki. Awizacje mają pole kierunku: dostawy mają kierunek IN, a wysyłki kierunek OUT, i widoki filtrują po tym polu. Widoki dostaw przyjmują dodatkowo puste pole kierunku. Zwroty oznacza rodzaj awizacji oraz cecha dokumentu, z jedną wartością dla zwrotu towarowego i drugą dla paletowego.
Zestawienia platformy czytają dane z takich widoków, a ich definicje opisuje strona o tabeli x_zestawienia. Treść zapytań ekranów platforma przechowuje w repozytorium zapytań. Przykład widoku zasilającego odpowiedzi API pokazujemy w artykule o API awizacji na procedurach SQL i JSON. Składnię widoku opisuje dokumentacja CREATE VIEW.
Kolumny, które przejęły nowe pojęcia
Część pojęć klienta nie dostała własnej kolumny. Weszła do kolumny standardowej, która w tej samej tabeli ma nadal swoją pierwotną funkcję. Tabela zestawia sześć takich przypadków.
| Kolumna standardowa | Znaczenie w standardzie | Znaczenie u klienta |
|---|---|---|
| Kolumna dokumentu tożsamości kierowcy | Dokument tożsamości kierowcy | Numer kontenera. W zwrotach kolumna zachowuje znaczenie standardowe. |
| Kolumna zdjęcia tablicy rejestracyjnej | Odnośnik do zdjęcia tablicy rejestracyjnej, a nie numer tablicy | Numer dokumentu odprawy. |
| DDP | Awizacja bezpośrednio od dostawcy z pominięciem działu transportu | W dostawach importowych dane do uzupełnienia. W wysyłkach CMR zatwierdzony przez rolę Eksport. |
| Piętrowanie | Piętrowanie palet | Znacznik korekty danych kierowcy, a od statusu 4 znacznik kontenera oclonego w całości. |
| Waga wyjazdowa | Waga przy wyjeździe | Odprawa zakończona. |
| Waga wjazdowa (wysyłki) | Waga przy wjeździe | Dokumenty EUR1 lub CO dołączone. |
Sześć kolumn standardowych z nowym znaczeniem w opisywanym wdrożeniu.
Numer kontenera leży w kolumnie dokumentu tożsamości kierowcy. W zwrotach ta kolumna zachowuje znaczenie standardowe, więc o jej treści decyduje rodzaj awizacji. Numer dokumentu odprawy leży w kolumnie, która w standardzie przechowuje odnośnik do zdjęcia tablicy rejestracyjnej. Procesy, w których te numery występują, opisują artykuły o agencji celnej w statusie magazynowym kontenera oraz o danych kierowcy uzupełnianych przez tego, kto je zna.
Flaga DDP znaczy w standardzie awizację przyjmowaną bezpośrednio od dostawcy z pominięciem działu transportu. W dostawach importowych oznacza u klienta dane do uzupełnienia. Ustawia się ją przy założeniu awizacji importowej, a zdejmuje po uzupełnieniu danych transportu i kierowcy. W zestawieniach nosi podpis Wymagana korekta. W wysyłkach ta sama kolumna znaczy, że CMR zatwierdziła rola Eksport, o czym piszemy w artykule o wysyłce eksportowej i bramkach między rolami.
Kolumny wag przejęto na flagi. Waga wyjazdowa znaczy odprawa zakończona. W wysyłkach waga wjazdowa znaczy dokumenty EUR1 lub CO dołączone, a flagę wagi wjazdowej kasuje krok końca odprawy.
Jedna kolumna, trzy znaczenia
Najwięcej znaczeń niesie kolumna piętrowania. W standardzie oznacza piętrowanie palet. U klienta ma jeszcze dwa znaczenia zależne od statusu: znacznik korekty danych kierowcy w statusach 1 i 2 oraz, od statusu 4, znacznik kontenera oclonego w całości. Korekta danych kierowcy po kontroli bramy korzysta więc z innej kolumny niż flaga DDP.
Wartość tej kolumny ustawiają i zerują różne zdarzenia. Zestawiamy je w tabeli.
| Zdarzenie | Skutek dla kolumny |
|---|---|
| Zaznaczenie korekty przy potwierdzeniu przybycia | Ustawia znacznik korekty danych kierowcy |
| Korekta danych kierowcy | Zeruje znacznik |
| Dostawy: przejście z weryfikacji do rampy | Zeruje znacznik |
| Dostawy: wyjazd | Zeruje znacznik |
| Wysyłki: zgoda na odprawę | Zeruje znacznik |
| Wysyłki: koniec odprawy | Zeruje znacznik |
| Wysyłki: wyjazd | Zeruje znacznik |
| Od statusu 4: krok agencji celnej z wynikiem kontener oclony w całości | Ustawia znacznik kontenera oclonego |
Zdarzenia według opisu wdrożenia. Wartość niezerowa blokuje ekran zmiany statusu do czasu korekty.
Blokada dotyczy w dostawach statusów 1 i 2. Dopóki dane kierowcy nie zostaną skorygowane, ekran zmiany statusu nie przepuści awizacji dalej. Ta sama kolumna ma więc inne znaczenie w statusie 2 i po odprawie, a zerują ją także zwykłe przejścia statusów, oprócz samej korekty danych.
Dlaczego odczyt po nazwie kolumny daje fałsz
Zapytanie, które czyta te kolumny po nazwach, daje nieprawdę, także gdy stoi za raportem albo eksportem. Pierwsze z poniższych zapytań wygląda jak lista awizacji przyjmowanych bezpośrednio od dostawcy.
SELECT a.numer_awizacji, a.kierunek
FROM dbo.awizacje AS a
WHERE a.ddp = 1;
SELECT SUM(a.waga_wjazdowa) AS laczna_waga
FROM dbo.awizacje AS a
WHERE a.kierunek = 'OUT';
Przykład ilustracyjny. Zakładamy, że flaga to wartość 1.
Pierwsze zapytanie zwróci między innymi dostawy importowe, które czekają na uzupełnienie danych, oraz wysyłki z CMR zatwierdzonym przez rolę Eksport. Awizacje z tych dwóch grup nie są przyjmowane bezpośrednio od dostawcy w znaczeniu standardu. Drugie zapytanie zwróci liczbę, która wygląda jak łączna waga, a w wysyłkach liczy flagi dokumentów EUR1 lub CO. Żadne z nich nie zgłosi błędu, bo składniowo oba są poprawne.
Opis pola musi mówić o jego funkcji, a nie o nazwie kolumny.
Widok nazywa kolumnę według funkcji i zależnie od rodzaju oraz statusu awizacji. W przykładzie przyjmujemy reguły wymyślone, które pokazują wzorzec, a nie odtwarzają wdrożenia.
CREATE VIEW dbo.widok_awizacji
AS
SELECT a.numer_awizacji,
a.kierunek,
CASE WHEN a.rodzaj <> 'ZWR' THEN a.dok_tozsamosci END AS numer_kontenera,
CASE WHEN a.rodzaj = 'ZWR' THEN a.dok_tozsamosci END AS dokument_kierowcy,
CASE WHEN a.kierunek = 'IN' THEN a.ddp END AS dane_do_uzupelnienia,
CASE WHEN a.kierunek = 'OUT' THEN a.ddp END AS cmr_zatwierdzony,
CASE WHEN a.kierunek = 'OUT' THEN a.waga_wjazdowa END AS dokumenty_eur1_co,
CASE WHEN a.status IN (1, 2) THEN a.pietrowanie END AS korekta_danych_kierowcy,
CASE WHEN a.status >= 4 THEN a.pietrowanie END AS kontener_oclony_w_calosci
FROM dbo.awizacje AS a;
Przykład ilustracyjny. Nazwy kolumn i reguły CASE są wymyślone, a widok ma inne kolumny niż w artykule o API.
Odczyt przez taki widok nie pomyli już funkcji pól. Koszt widać jednak od drugiej strony: każdy, kto czyta tabelę bezpośrednio, a nie przez widok, musi znać te reguły z dokumentacji, bo sama baza ich nie zdradza.
Podobny problem dotyczy podpisów. Zestawienia platformy zamieniają nazwy kolumn na podpisy, a w opisywanym wdrożeniu przemianowano podpisy na pojęcia klienta: numer kontenera, numer dokumentu odprawy, wymagana korekta i oclony cały kontener.
Podpis Wymagana korekta jest przypisany do kolumny DDP w zestawieniach dostaw. Podpis oclony cały kontener istnieje w definicjach zestawień, ale kolumna jest w nich ukryta. W zestawieniach zwrotów kolumna dokumentu tożsamości kierowcy zachowuje swój podpis. Definicje podpisów opisuje strona o tabeli x_zestawienia_kolumny.
Pytania przed przejęciem kolumny
Artykuł opisuje koszt tej decyzji w jednym wdrożeniu i nie traktujemy go jako wzorca. Przed podobnym wyborem w innym systemie odpowiedz na cztery pytania.
- Odczyt po nazwie: kto czyta kolumnę po nazwie: raport, eksport, integracja albo ekran standardowy.
- Zależność od statusu: czy znaczenie zmienia się wraz ze statusem lub rodzajem awizacji i gdzie to zapisano.
- Podpisy: czy podpis kolumny w zestawieniach mówi o funkcji pola, czy o jego pierwotnej nazwie.
- Własna kolumna: co zmieniłoby się w odczytach, gdyby pojęcie dostało własną kolumnę w tabeli rozszerzenia.