Sekwencyjny numer faktury restartowany z nowym rokiem

0
Panczo napisał(a):

Rozważ co zajmie Ci więcej czasu i będzie mniej kłopotliwe w utrzymaniu. Częste przypadki z praktyki

Klient zaczyna z system i stwierdza, że koszty będzie wprowadzał jednym rejestrem numerowanym w ramach roku. Więc luz tworzysz sekwencje i jedziesz w ramach roku od 1.
Gdzieś pod koniec roku, stwierdza, że numerowanie roczne jest bez sensu, bo faktury nie spływają na czas i często zdarza mu się że faktura z wyższym numerem jest starsza od wcześniejszych.
Postanawia, że od nowego roku zmienia numerację na miesięczną.
Teraz sytuacja się zmienia i kupuje coraz więcej z UE w eur. Więc postanawia dodać nowy symbol do wyróżnienia tych faktur.
I wspomniany tu już case z przełomem roku, idą już faktury z nowego, ale ciągle jest wprowadzany poprzedni.

Jeżeli uważasz, że sekwencja jest na tyle elastyczna, że to ogarnie to ok. IMO to się nie sprawdzi.

Troche nie rozumiem co polecasz? Moim zdaniem rozwiazanie z sekwencje jest wystarczajace. Jezeli format ulegnie zmianie to nie ma problemu. Dlatego w tabeli faktry trzymany jest caly juz sformatowany numer. Logike zawsze mozna zmienic, ktora jest odseparowana. Na razie na 100% nie potrzebuje miesiecy, to po cholere tracic czas i to implemoentowac oraz testowac. Cos co nie bedzie uzyte?

2

Troche nie rozumiem co polecasz?

Zrezygnować z sekwencji

Moim zdaniem rozwiazanie z sekwencje jest wystarczajace. Jezeli format ulegnie zmianie to nie ma problemu. Dlatego w tabeli faktry trzymany jest caly juz sformatowany numer. Logike zawsze mozna zmienic, ktora jest odseparowana. Na razie na 100% nie potrzebuje miesiecy, to po cholere tracic czas i to implemoentowac oraz testowac. Cos co nie bedzie uzyte?

To, że czegoś teraz nie potrzebujesz, nie znaczy, że tego nie będziesz potrzebował. Nawet jeżeli faktycznie tego nie będziesz potrzebował to skutecznie pomijasz argument o przełomie roku, którego raczej nie unikniesz. Więc jak przy pomocy sekwencji rozwiążesz wprowadzanie danych do 2 osobnych lat?

4

Sekwencje

  1. sekwencji powinieneś mieć tyle ile masz numerów startujących od jeden - resetowanie sekwencji to najgorsze co możesz zrobić. Jak masz faktury vat i korekty to MUSISZ mieć przynajmniej dwie sekwencje.
  2. jak się pani Krysi przypomni drugiego stycznie, że ma jeszcze fakturę, którą trzeba do grudnia dopisać (a już dodała 10 styczniowych) to jesteś w bardzo czarnej dupie - zresetowałeś sekwencję.
  3. jak podczas zapisu faktury cokolwiek się wywali i zrobisz rollback to NUMER JUŻ SIĘ ZWIĘKSZYŁ i masz dziurę w numeracji i jesteś w czarnej dupie.

Wszystko to można ogarnąć i się na to przygotować, tylko że nakład pracy będzie kosmiczny w porównaniu do dodatkowej tabeli z dwiema kolumnami - typ i numer, gdzie do pola typ wpiszesz cokolwiek co jednoznacznie identyfikuje numerator (np. rok, miesiąc, typ dokumentu i magazyn)

0
abrakadaber napisał(a):

Sekwencje

  1. sekwencji powinieneś mieć tyle ile masz numerów startujących od jeden - resetowanie sekwencji to najgorsze co możesz zrobić. Jak masz faktury vat i korekty to MUSISZ mieć przynajmniej dwie sekwencje.
  2. jak się pani Krysi przypomni drugiego stycznie, że ma jeszcze fakturę, którą trzeba do grudnia dopisać (a już dodała 10 styczniowych) to jesteś w bardzo czarnej dupie - zresetowałeś sekwencję.
  3. jak podczas zapisu faktury cokolwiek się wywali i zrobisz rollback to NUMER JUŻ SIĘ ZWIĘKSZYŁ i masz dziurę w numeracji i jesteś w czarnej dupie.

Wszystko to można ogarnąć i się na to przygotować, tylko że nakład pracy będzie kosmiczny w porównaniu do dodatkowej tabeli z dwiema kolumnami - typ i numer, gdzie do pola typ wpiszesz cokolwiek co jednoznacznie identyfikuje numerator (np. rok, miesiąc, typ dokumentu i magazyn)

To jest bardzo wartosciowa odpowiedz oraz argumenty przeciw sekwencji. 1 i 2 punkt w sumie w moim przypadku nie dotycza sie, ale bardzo, mega sluszne uwagi. Dziki Ci za nie. Za 3 punkt, rozwalil mnie, nie pomyslalem zupelnie o rollback'u. :facepalm. Super post. Powaznie, szacun @abrakadaber !

Jeszcze, zeby tylko podsumowac. Tabela, ktora sugerujesz ma wygladac jak ponizej?

Invoice_numbers
year
sequency

Wszystko dalej bedzie w SQL transaki oraz lock na invoice_numbers. Cos pominalem? Nie potrzebuje typu dokumentu i brak korekt. To sa pardziej takie paragony, troche dlugo to tlumaczyc, ale sam case jest znacznie prosty niz faktury.

W sumie to jak tak mysle, to chyba pierwszy pomysl byl jednak najlepiszy. Czyli w tej samej tabeli invoice trzymac kolumne rok , sekwencje oraz numer. Pozniej lock na tablie, pobieram max(sekwencja) na dany rok i od co. Duzo faktu nie bedzie, tylko kilka na caly miesiac.

edtit

Albo w ogole 2 kolumny, bez roku, bo jest invoice_date. Nastepnie w SQL mozna pobrac invoice_date BETWEEN concat(current_year, '-01-01')::DATE AND concat(current_year, '-12-31')::DATE. Jezeli cos zwroci to git jak nie ma nic to 1 i na koniec +1.

0

sugerowałem tabelkę z 2 polami - wyroznik (differentiator??) typu varchar oraz number (current_namber, last_number) jako int. Jak założysz indeks na oba pola (w kolejności wyróżnik, numer) to cały odczyt będzie leciał po indeksie.
Teraz dla Twojego AKTUALNEGO :p przypadku do pola wyroznik wstawiasz 4-znakowy ROK. Jak Ci dojdzie konieczność numeracji miesięcznej to NIC NIE ZMIENIASZ poza podawaniem nie samego roku ale rok (4 znaki) + miesiąc (2 znaki). Jak Ci się zmieni z rok/miesiąc na rok/typ to dalej NIC NIE ZMIENIASZ w logice tylko podajesz rok + typ i t odziała bez żadnych zmian.

Takie jest moje zdanie na ten temat. Co więcej takie coś działa u kilkudziesięciu klientów w PL od 25-30 lat i problemu nie ma. Niektórzy mają dzienny przyrost dokumentów idący w dziesiątki tysięcy (oczywiście z różnymi wyróżnikami).

0
abrakadaber napisał(a):

sugerowałem tabelkę z 2 polami - wyroznik (differentiator??) typu varchar oraz number (current_namber, last_number) jako int. Jak założysz indeks na oba pola (w kolejności wyróżnik, numer) to cały odczyt będzie leciał po indeksie.
Teraz dla Twojego AKTUALNEGO :p przypadku do pola wyroznik wstawiasz 4-znakowy ROK. Jak Ci dojdzie konieczność numeracji miesięcznej to NIC NIE ZMIENIASZ poza podawaniem nie samego roku ale rok (4 znaki) + miesiąc (2 znaki). Jak Ci się zmieni z rok/miesiąc na rok/typ to dalej NIC NIE ZMIENIASZ w logice tylko podajesz rok + typ i t odziała bez żadnych zmian.

Takie jest moje zdanie na ten temat. Co więcej takie coś działa u kilkudziesięciu klientów w PL od 25-30 lat i problemu nie ma. Niektórzy mają dzienny przyrost dokumentów idący w dziesiątki tysięcy (oczywiście z różnymi wyróżnikami).

Rozumiem, ze w invoice tabelce, bedzie number. Numer moze drastycznie sie zminic, zeby nie robic kombinacji w przyszlosci to najprosciej wydaje sie zapisac sformatowany numer.

Teraz musze zapisac, gdzies sekwencje (int) i moze rok, nie wiem czy zapis roku tak naprawde bedzie potrzebny. Jezeli cos sie zmieni to sekwencja kolumna moze byc usunieta albo zastopiona przy czym nie trace spojnosci z numerem faktury.

Latniej bylo by na przykladzie. Bo z tabelka sa juz dwie rozne wersje. 1 byla, zeby tylko trzymac jeden wiersz i podbijak sekwencje. Druga, zeby zapisywac wszystkie sekwencje. Czasem sa faktury bez sekwencji.

edit

create table invoice_number
(
    id          serial primary key,
    type        varchar(3) not null, -- invoice, receipt itd
    last_year   integer not null,
    last_number integer not null
);

create unique index invoice_number_unique_inx
    on payment_advance_repayments (last_year, last_number);

W tabeli jest zapisywany 1 rekord na caly typ faktury, paragonu itd.

W tym samamym momencie dwoch userow moze pobrac last_number, wiec trzeba dodac lock na tej tabelce. I wydaje sie, ze to wszystko?

0
poniatowski napisał(a):

Rozumiem, ze w invoice tabelce, bedzie number. Numer moze drastycznie sie zminic, zeby nie robic kombinacji w przyszlosci to najprosciej wydaje sie zapisac sformatowany numer.

Nie no, cały sformatowany numer tekstowy tak jak występuje na drukowanym dokumencie. Dodatkowo możesz trzymać sam numer do szybszego wyszukiwania

Teraz musze zapisac, gdzies sekwencje (int) i moze rok, nie wiem czy zapis roku tak naprawde bedzie potrzebny. Jezeli cos sie zmieni to sekwencja kolumna moze byc usunieta albo zastopiona przy czym nie trace spojnosci z numerem faktury.

Nie mam pojęcia o co tu chodzi

Latniej bylo by na przykladzie. Bo z tabelka sa juz dwie rozne wersje. 1 byla, zeby tylko trzymac jeden wiersz i podbijak sekwencje. Druga, zeby zapisywac wszystkie sekwencje. Czasem sa faktury bez sekwencji.

edit

create table invoice_number
(
    id          serial primary key,
    type        varchar(3) not null, -- invoice, receipt itd
    last_year   integer not null,
    last_number integer not null
);
  1. id w tym przypadku jest całkowicie zbędny - równie dobrze możesz założyć PK na trzech pozostałych polach
  2. pole nie jest last_year tylko year bo jego nie zmieniasz jak zacznie się nowy rok tylko dodajesz kolejny rekord z nowym rokiem i numerem = 0 (albo 1 w zależności jaki numer będziesz trzymał)
  3. nic nie stoi na przeszkodzie połączyć type i last_year w jednym polu a dostajesz większą elastyczność

create unique index invoice_number_unique_inx
on payment_advance_repayments (last_year, last_number);

nie możesz mieć unique na tych dwóch polach bo one nie identyfikują numeru - unique musisz mieć przede wszystkim na type year

W tabeli jest zapisywany 1 rekord na caly typ faktury, paragonu itd.

nie - zapisywany jest jeden rekord na typ i rok

W tym samamym momencie dwoch userow moze pobrac last_number, wiec trzeba dodac lock na tej tabelce. I wydaje sie, ze to wszystko?

nie na TABELĘ ale na rekord - najprościej przez SELECT 1 FROM tab WHERE rok = x AND typ = 'y' FOR UPDATE - lock jest automatycznie zdejmowany jak zrobisz rollback albo commit transakcji

0

Problem rozwiazany :) Poszedlem z nowa tabelka. Rozwiazanie proste w implementacji. Latwo zmienic format. Latwo dodwac nowe typy. Z lock na tabeli idzie ladnie zapanowac nad race condition. Potestowalem rozwiazanie, smiga bardzo dobrze, bez zarzutow. Dziki Pany!

0

@abrakadaber: Dzieki za sluszne uwagi.

create table invoice_number
(
    type        varchar(3) not null,
    year        integer not null,
    last_number integer not null
);

create unique index invoice_number_unique_inx
    on payment_advance_repayments (type, year);
2

Tak w ogóle jeśli zajmujesz się takimi rzeczami, to warto spotkać się z osobą, która obsługuje system do faktur w praktyce. Powie ci o wielu rzeczach, o których byś nawet nie pomyślał. Wydaje mi się, że próbujesz ponownie wynaleźć koło i na siłę sam kombinujesz nie znając specyfiki tematu.
Jeśli ma to być realny system, a nie jakaś wprawka programistyczna, to nie pomijaj etapu analizy - oszczędzisz sobie bólu głowy później (albo wk* klientów dzwoniących 31 grudnia, że czegoś nie mogą zrobić).

1 użytkowników online, w tym zalogowanych: 0, gości: 1