Autor Zpráva
tonda13
Profil
Chystám se udělat si nějaký systém na správu faktur, ale při návrh jsem narazil na drobný problém.

Mám tabulky Osoba, Faktura a Položka. Problém je s trvalým uložením informací o osobě.
Standardně jsem uvažoval, že bych do tabulky Faktura umístil cizí klíč z tabulky Osoba. A tady je ten problém, když totiž vystavím/vytvořím fakturu, tak už se údaje na ní nesmí měnit, ale mám-li tam informace o osobě jako cizí klíč, tak pokud změním v tabulce Osoba nějaké údaje změní se i na všech vystavených fakturách. Stejný problém je ji s položkami.

Tak jsem se chtěl zeptat jak by se to dalo řešit, případně jak to řešíte sami?
Díky všem co pomohou
abc
Profil
U nás v práci to řešíme tak, že si ke každé faktuře uložíme i všechny informace o položkách, tak jak byly v době vystavení (název, DPH, NC, PC apod.).
Odběratele neřešíme, ten se prostě vždycky "natáhne" aktuální z Adresáře, řekl bych není potřeba ukládat k faktuře
tonda13
Profil
abc:
To uložení přímo k faktuře mě také napadlo, ale když se v něčem spletu, ještě než fakturu odešlu, tak bych musel celou fakturu vygenerovat znovu a zase jí uložit. A navíc obrovská redundance dat. Je to ovšem kompromis, myslel jsem, že se to dá řešit lépe.

Odběratele neřešíme, ten se prostě vždycky "natáhne"
To je právě to, co nemůžu mít. Protože na konci roku potřebuji všechny uložené faktury vytisknout znovu a pokud by se mezi tím změnily nějaké údaje, tak by došlo k problémům.
juriad
Profil
Ještě existuje jedna zběsilá možnost, každá editace neprovádí UPDATE, ale INSERT se zneplatněním předchozí verze.
Jinak řečeno, tabulka uživatel bude mít ještě sloupečky verze (celočíselný) a aktuální (boolean = 0/1).
Při ukládání záznamu se provede v transakci:
SELECT verze FROM uzivatel WHERE id = $id AND aktualni = 1 # uloz do promenne $verze
INSERT INTO uzivatel (id, verze, aktualni, jmeno, adresa) VALUES ($id, $verze+1, 1, $nove_jmeno, $nova_adresa)
UPDATE uzivatel SET aktualni = 0 WHERE id = $id AND verze = $verze # uz neni aktualni
A všechny SELECTy používající uživatele budou mít navíc podmínku: AND uzivatel.aktualni = 1
Ve faktuře se budeš odkazovat na dvojici uzivatel.id, uzivatel.verze.

Stejně budou řešeny produkty, při každé změně produktu, ať už je to popis nebo cena, vytvoříš pro produkt nový záznam.
Některé cizí klíče se budou odkazovat jen na id s podmínkou na aktualni = 1, jiné cizí klíče se budou odkazovat na dvojici id, verze.

Jelikož nikdy neprovádíš UPDATE dat (ale jen příznaku aktualni) v tabulkách, nestane se ti, že se ti změní hodnoty na faktuře.
Zároveň tím získáš "zálohu" všech údajů a historii změn: využitelné například pro generování grafu pohybu cen (SELECT cena FROM produkt WHERE id = $id ORDER BY verze ASC).
Joker
Profil
juriad:
Proč „zběsilá možnost“?
To je celkem standardní postup v případě, kdy potřebuji evidovat historii nějakého záznamu.
Ale asi bych to udělal trochu jinak, oddělil bych do jiné tabulky jen ty údaje, které se dají měnit a jejichž historii chci uchovávat. (Například údaj typu rodné číslo nebo IČO asi nebudu chtít verzovat, protože snad jediná možná změna je oprava chyby, kterou budu chtít promítnout do všech verzí záznamu. Dál jsou údaje, které sice měnit lze, ale historii změn evidovat nechci, případně je to dokonce nežádoucí. To může být třeba uživatelovo heslo -repektive hash hesla-, nebo když si eviduji třeba čas poslední aktivity, je asi nesmysl při každém načtení stránky založit novou verzi uživatele.)
aDAm
Profil
tonda13: proč mazat při editaci? Jednoduše, zakládáš novou fakturu, tak si odběratele a položky načteš z aktuální tabulek kde je máš, když to uložíš tak si ty data uložíš k fa třeba do speciálních tabulek (já osobně adresu uložím jako json string přímo k záznamu fa) a když jdeš na editaci tak netaháš odběratele a položky z aktuálních tabulek ale z těch co jsou u faktury a cizí klíče či tam budou taky fungovat.
abc
Profil
To uložení přímo k faktuře mě také napadlo, ale když se v něčem spletu, ještě než fakturu odešlu, tak bych musel celou fakturu vygenerovat znovu a zase jí uložit.
To už je přeci jen jeden update v DB.

A navíc obrovská redundance dat. Je to ovšem kompromis, myslel jsem, že se to dá řešit lépe.
Plánuješ vyrobit systém, který bude dělat stovky faktur denně? Budeš mít daleko jiné starosti.
Uvažuj i o různých nadstavbách - např. nějaký přehled prodeje nebo tabulkové zobrazení dokladů a jejich položek

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: