Faktury i rachunki mają to samo wejście. Jak uniknąć mieszania obu struktur?

W jednym interfejsie odbierane są zarówno faktury, jak i paragony, a pisanie dużych obiektów jest łatwe, gdy „wszystkie pola są opcjonalne”. Taki przedmiot może pomieścić wszystko, ale trudno powiedzieć, co dokładnie jest odbierane. Bardziej przejrzystym byłoby zachowanie dwóch oddzielnych umów i wybranie jednej z nich z jawnym polem typu.

Faktury i rachunki są często umieszczane w tym samym interfejsie w celu ich przetwarzania, ale jeśli do ich otrzymania zostanie użyty tylko szeroki obiekt z „wszystkimi polami opcjonalnymi", może on pomieścić dowolne dane wejściowe, ale nie będzie w stanie stwierdzić, jakiego rodzaju dokument został otrzymany. Ten artykuł jest przeznaczony dla programistów i personelu biznesowego, którzy muszą zaprojektować interfejs odbierania dokumentów lub utrzymywać reguły sprawdzania poprawności schematu JSON. Po przeczytaniu tego dowiesz się, jak zachować dwie niezależne umowy, wybrać jedną z jawnym polem typu oraz radzić sobie z konfliktami gałęzi i nieznanymi typami.

W przykładach w tym artykule wykorzystano próbki syntetyczne w celu zademonstrowania metod przetwarzania. Kod został sprawdzony na przykładach w izolowanym środowisku, ale nie gwarantuje to działania wszystkich rzeczywistych plików ani produktu. Przed przystąpieniem do przetwarzania ważnych dokumentów prosimy o zachowanie oryginałów i zapoznanie się z nimi zgodnie z granicami i pozycjami akceptacji w tekście.

Jak sobie poradzić ze wspólnym wprowadzaniem faktur i paragonów? Wniosek w jednym zdaniu

W przypadku otrzymania dwóch dokumentów z tego samego portalu wygodniej jest zachować dwie oddzielne umowy i wybrać jedną z nich za pomocą wymaganego polakind, zamiast używać szerokiego obiektu, w którym zmieści się wszystko.

twoja sytuacjaZalecane praktykipowód
Ten sam interfejs musi odbierać faktury i paragonyZachowaj dwie oddzielne umowy, wybrane za pomocą wymaganego pola rodzajuDuży obiekt z opcjonalnymi wszystkimi polami może pomieścić wszystko, ale trudno wyjaśnić, co jest odbierane.
Organizuj oddziały za pomocą oneOfKażda gałąź używa const do ustalenia rodzajuoneOf wymaga dopasowania dokładnie jednej gałęzi. Nakładające się pola gałęzi spowodują niepowodzenie poprawnego wprowadzania danych.
Wprowadź brakujący typ lub konflikt pólZwróć wyraźny komunikat o błędzie pokazujący sprzeczne pola i źródłaSamo wyświetlenie komunikatu „brak dopasowania"nie może pomóc w zlokalizowaniu problemu
Klasyfikator nie potrafi rozróżnić typów dokumentówZachowaj status nieznany i wejdź do niezależnej kolejki do klasyfikacjiLosowy wybór oddziału przyniesie jedynie fałszywy „sukces"
Weryfikacja konstrukcji zaliczonaNie oznacza to, że klasyfikacja jest prawidłowa ani że dokumenty są autentyczne.Pewność klasyfikacji, weryfikacja struktury i autentyczność biznesowa to trzy różne poziomy

Dlaczego nie możesz użyć szerokiego obiektu?

Ryzyko, że wszystkie pola staną się opcjonalne

Gdy interfejs akceptuje zarówno faktury, jak i paragony, łatwo jest pisać duże obiekty, korzystając z opcji „wszystkie pola opcjonalne". Taki obiekt może rzeczywiście otrzymywać różnorodne dane wejściowe, ale kosztem:

  • Ze struktury nie można stwierdzić, który dokument został otrzymany.
  • Pozycje wymagane i opcjonalne obu dokumentów są ze sobą pomieszane, a zasady weryfikacji stają się coraz bardziej niejasne.
  • Kiedy pojawia się błąd, trudno jest dokładnie wyjaśnić, gdzie dane wejściowe nie są zgodne z oczekiwaniami.

Bardziej przejrzystym byłoby zachowanie dwóch oddzielnych umów i wybranie jednej z nich z wyraźnym polem typu.

oneOf nie jest byle jakim

Nakładające się gałęzie spowodują niepowodzenie wprowadzania poprawnych danych.

oneOf wymaga, aby dane wejściowe odpowiadały dokładnie jednej gałęzi. Jeśli obie gałęzie przejdą pomyślnie w tym samym czasie, ogólna weryfikacja zakończy się niepowodzeniem.

Jeśli gałęzie zawierają tylko kilka opcjonalnych pól, prawdopodobnie w znacznym stopniu będą się na siebie nakładać. W tej chwili legalne dane wejściowe nie przechodzą weryfikacji.

Użyj rodzaju i stałej, aby wyeliminować nakładanie się

Użycie wymaganego pola kind plus stałej wartości const może ustalić wyraźne granice pomiędzy gałęziami i z wyprzedzeniem wyeliminować takie nakładanie się.

Więcej szczegółów na temat zasad kombinacji można znaleźć w Reguły kombinacji schematu JSON.

Wykonywalny protokół odciążający

from jsonschema import Draft202012Validator

def branch(kind, identity):
    return {
        "type": "object", "additionalProperties": False,
        "required": ["kind", identity],
        "properties": {"kind": {"const": kind},
                       identity: {"type": "string", "minLength": 1}}
    }

schema = {"oneOf": [branch("invoice", "invoice_number"),
                    branch("receipt", "receipt_number")]}
v = Draft202012Validator(schema)
valid = lambda x: not list(v.iter_errors(x))
assert valid({"kind": "invoice", "invoice_number": "I-1"})
assert valid({"kind": "receipt", "receipt_number": "R-1"})
assert not valid({"kind": "invoice", "receipt_number": "R-1"})
assert not valid({"kind": "receipt", "receipt_number": ""})
assert not valid({"kind": "invoice", "invoice_number": "I-1",
                  "receipt_number": "R-1"})
assert not valid({"kind": "unknown"})

Jest to uproszczony przykładowy rekord i nie stanowi pełnego modelu polowego prawdziwej faktury. Kod demonstruje wybór gałęzi i odrzucanie zbędnych pól. Stawkę podatku, nagłówek i kwotę należy określić osobno.

Jeśli firma dopuszcza dodatkowe pola, przestrzenie nazw dla tych pól powinny być wyraźnie określone, a nie po cichu anulować wszystkie ograniczenia.

Nie wyświetlaj po prostu „brak dopasowania"w komunikacie o błędzie

Wyświetlana jest tylko „niezgodność"i ani użytkownicy, ani opiekunowie nie wiedzą, gdzie leży problem. W poniższej tabeli wymieniono kilka typowych funkcji wejściowych i odpowiadające im metody przesyłania informacji zwrotnych:

Funkcje wejścioweRzeczywiste wątpliwościSugestie i opinie
rodzaju brakujeNie można wybrać protokołuProszę podać typ dokumentu
Typ koliduje z polem liczbowymObie struktury są mieszanePokaż sprzeczne pola i źródła
Numer pusty ciągKlucz istnieje, ale nie ma wartościSpójrz ponownie na ponumerowany obszar
nieznany typNieobjęte obecną umowąWejdź do niezależnej kolejki oczekujących

Nieokreślone typy również potrzebują ujścia

Jeśli klasyfikator nie jest w stanie rozróżnić faktur i paragonów, powinien pozostawić nieznany stan, zamiast wybierać losową gałąź w celu odgadnięcia „sukcesu".

Istnieją trzy różne poziomy, które należy rozpatrywać oddzielnie:

  • Poufność klasyfikacji: Jak pewny jest system w ocenie typu dokumentu.
  • Weryfikacja struktury: Czy dane wejściowe są zgodne z wybraną umową.
  • Autentyczność biznesowa: Czy sam dokument jest autentyczny i ważny.

Przejście weryfikacji strukturalnej nie może udowodnić prawidłowości klasyfikacji ani autentyczności dokumentu.

Typ dokumentu również musi zostać zachowany w procesie tłumaczenia

W tym samym polu może być konieczne użycie różnych terminów w różnych dokumentach. W przypadku korzystania z terminologii OmniDoc i dwujęzycznych przepływów pracy recenzji podanie typu dokumentu wraz z listą dostaw pomaga recenzentom zrozumieć kontekst liczb i kwot.

Nie pozwól, aby szeroki obiekt JSON wymazał te różnice.

📊 Porównanie rdzeni

praktykaCzy możesz określić typ dokumentu?Zachowanie, gdy gałęzie zachodzą na siebieObsługa nieznanych typów
Szeroki obiekt ze wszystkimi polami opcjonalnymiTrudno opisać to, co otrzymałem.Nie dotyczy, brak granic gałęzi pomiędzy polamiŁatwo połknięty przez szeroką gamę obiektów i trudny do wykrycia
Dwie niezależne umowy + wymagany rodzajJawny wybór poprzez pole rodzajuUżyj const, aby naprawić wartość i zmniejszyć nakładanie sięZachowaj status nieznany i wejdź do kolejki do klasyfikacji

🎯 Która metoda jest dla Ciebie odpowiednia?

Jeśli chcesz otrzymywać zarówno faktury, jak i rachunki

Zachowaj dwie oddzielne umowy i ustaw kind jako pole wymagane.

Jeśli pola oddziałów często się pokrywają

Napraw kind za pomocą const w każdej gałęzi, aby uniknąć dopasowania prawidłowych danych wejściowych do wielu gałęzi jednocześnie.

Jeśli Twój system pozwala na dodatkowe pola

Najpierw wyjaśnij przestrzeń nazw dodatkowych pól, a następnie zdecyduj, jak złagodzić ograniczenia.

Jeśli Twój klasyfikator nie jest wystarczająco pewny

Pozostaw status nieznany, wyślij dokument do kolejki do posortowania i nie wybieraj na siłę oddziału.

❓ Często zadawane pytania (FAQ)

1. Dlaczego po prostu nie użyć obiektu, w którym wszystkie pola są opcjonalne?

Taki przedmiot może pomieścić wszystko, ale trudno powiedzieć, co dokładnie jest odbierane.

2. Dlaczego oneOf nie wprowadza prawidłowych danych?

oneOf wymaga dopasowania dokładnie jednej gałęzi. Jeśli obie gałęzie przejdą pomyślnie w tym samym czasie, ogólna weryfikacja zakończy się niepowodzeniem. Taka sytuacja może łatwo wystąpić, gdy pola gałęzi w dużym stopniu nakładają się na siebie.

3. Na co należy zwrócić uwagę dopuszczając dodatkowe pola?

Przestrzeń nazw dodatkowych pól powinna być wyraźnie określona, a nie dyskretnie anulować wszystkie ograniczenia.

4. Co zrobić, jeśli klasyfikator nie jest w stanie określić typu dokumentu?

Zachowaj stan nieznany i wejdź do niezależnej kolejki do klasyfikacji. Nie wybieraj losowo oddziału, aby osiągnąć sukces.

5. Czy pozytywny wynik weryfikacji konstrukcji oznacza, że dokument jest autentyczny?

nie mogę. Pewność klasyfikacji, weryfikacja struktury i autentyczność biznesowa to trzy różne poziomy. Przejście przez obiekt nie może udowodnić autentyczności dokumentu.

📝 Podsumowanie

Umieszczając faktury i paragony w tym samym zapisie należy zachować dwie osobne umowy i zaznaczyć je z wymaganym polem kind tak, aby rodzaj wprowadzanego dokumentu był wyraźnie widoczny. Weryfikację oddziałów, informację zwrotną o błędach i wyjścia nieznanego typu należy również projektować wspólnie.

Wypróbuj teraz: prześlij dokument, aby rozpocząć tłumaczenie, zachowując oryginalny układ

Zaktualizowano 2026-11-15