From 3817ba4cbd20e2eb2c77a512fed997c03d25ba63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Markovi=C4=87?= Date: Sat, 13 Jun 2026 19:38:54 +0200 Subject: [PATCH] =?UTF-8?q?feat(config):=20helper=20ModulUkljucen=20?= =?UTF-8?q?=E2=80=94=20uklju=C4=8Denost=20modula=20po=20profilu=20firme=20?= =?UTF-8?q?(Faza=200)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Čista funkcija izvodi iz profila firme (podesavanja) koji su zakonski moduli aktivni. Režim „samo evidencija" gasi sve. Pravila: pdv prema prekidaču obveznika, fiskalizacija zaseban prekidač, kpo za paušalce, dvojno za doo. Table-driven test sa 18 slučajeva. --- internal/config/moduli.go | 56 ++++++++++++++++++++++++++++ internal/config/moduli_test.go | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 internal/config/moduli.go create mode 100644 internal/config/moduli_test.go diff --git a/internal/config/moduli.go b/internal/config/moduli.go new file mode 100644 index 0000000..dcf5fcd --- /dev/null +++ b/internal/config/moduli.go @@ -0,0 +1,56 @@ +package config + +// Ovaj fajl izvodi iz profila firme (vidi Project.md §2, §4) koji su zakonski +// moduli uključeni za datu firmu. Profil se čuva kao key-value u tabeli +// `podesavanja`, pa helper prima već učitanu mapu (čista funkcija — lako se +// testira bez baze). Ovo je sloj IZNAD RBAC-a: „da li firma uopšte koristi +// modul", nezavisno od „da li korisnik sme". + +// Ključevi profila firme u tabeli `podesavanja`. +const ( + KljucPravniOblik = "firma_pravni_oblik" + KljucPdvObveznik = "firma_pdv_obveznik" + KljucFiskalizacija = "firma_fiskalizacija" + KljucRezim = "firma_rezim" +) + +// Nazivi modula koje program pali/gasi prema profilu firme. +const ( + ModulPdv = "pdv" + ModulFiskalizacija = "fiskalizacija" + ModulKpo = "kpo" + ModulDvojno = "dvojno" +) + +// ModulUkljucen vraća da li je dati zakonski modul aktivan za firmu, na osnovu +// profila firme. Režim „samo evidencija" gasi ceo zakonski sloj — tada nijedan +// modul nije uključen, bez obzira na ostale prekidače. +func ModulUkljucen(podesavanja map[string]string, modul string) bool { + // podrazumevano (ključ još ne postoji) je „samo evidencija" — najbezbednije + // stanje: stara instalacija ne počinje da se ponaša kao poreski obveznik. + rezim := podesavanja[KljucRezim] + if rezim == "" { + rezim = "samo_evidencija" + } + if rezim != "pun" { + return false + } + + switch modul { + case ModulFiskalizacija: + // fiskalizacija je nezavisna od pravnog oblika — zaseban prekidač + // „izdaje li račune građanima" (Project.md §3, napomena *). + return podesavanja[KljucFiskalizacija] == "da" + case ModulPdv: + // PDV evidencija se vodi kad je firma u sistemu PDV-a. + return podesavanja[KljucPdvObveznik] == "da" + case ModulKpo: + // KPO (knjiga o ostvarenom prometu) je samo za paušalce. + return podesavanja[KljucPravniOblik] == "pausalac" + case ModulDvojno: + // dvojno knjigovodstvo je za DOO (za preduzetnike je buduća podela, Project.md §8). + return podesavanja[KljucPravniOblik] == "doo" + default: + return false + } +} diff --git a/internal/config/moduli_test.go b/internal/config/moduli_test.go new file mode 100644 index 0000000..f90dae2 --- /dev/null +++ b/internal/config/moduli_test.go @@ -0,0 +1,68 @@ +package config + +import ( + "maps" + "testing" +) + +func TestModulUkljucen(t *testing.T) { + // pun je profil punog režima sa svim prekidačima upaljenim i pravnim oblikom doo; + // pojedinačni testovi ga prepravljaju po potrebi preko pomoćne funkcije izmeni. + pun := map[string]string{ + KljucRezim: "pun", + KljucPdvObveznik: "da", + KljucFiskalizacija: "da", + KljucPravniOblik: "doo", + } + // izmeni vraća kopiju mape sa promenjenim/dodatim ključem (da testovi ne dele stanje) + izmeni := func(osnova map[string]string, kljuc, vrednost string) map[string]string { + kopija := make(map[string]string, len(osnova)+1) + maps.Copy(kopija, osnova) + kopija[kljuc] = vrednost + return kopija + } + + testovi := []struct { + naziv string + podesavanja map[string]string + modul string + ocekivano bool + }{ + // master prekidač: režim „samo evidencija" gasi sve + {"prazna mapa — pdv ugašen (default samo_evidencija)", map[string]string{}, ModulPdv, false}, + {"prazna mapa — fiskalizacija ugašena", map[string]string{}, ModulFiskalizacija, false}, + {"prazna mapa — kpo ugašen", map[string]string{}, ModulKpo, false}, + {"prazna mapa — dvojno ugašeno", map[string]string{}, ModulDvojno, false}, + {"samo evidencija gasi pdv iako je obveznik", izmeni(pun, KljucRezim, "samo_evidencija"), ModulPdv, false}, + {"samo evidencija gasi fiskalizaciju iako je upaljena", izmeni(pun, KljucRezim, "samo_evidencija"), ModulFiskalizacija, false}, + + // fiskalizacija — zaseban prekidač, nezavisan od oblika + {"pun + fiskalizacija da", pun, ModulFiskalizacija, true}, + {"pun + fiskalizacija ne", izmeni(pun, KljucFiskalizacija, "ne"), ModulFiskalizacija, false}, + + // pdv — vezan isključivo za prekidač obveznika + {"pun + obveznik da", pun, ModulPdv, true}, + {"pun + obveznik ne (čak i doo)", izmeni(pun, KljucPdvObveznik, "ne"), ModulPdv, false}, + + // kpo — samo paušalac + {"pun + paušalac → kpo", izmeni(pun, KljucPravniOblik, "pausalac"), ModulKpo, true}, + {"pun + doo → nema kpo", pun, ModulKpo, false}, + {"pun + preduzetnik → nema kpo", izmeni(pun, KljucPravniOblik, "preduzetnik_knjige"), ModulKpo, false}, + + // dvojno — samo doo + {"pun + doo → dvojno", pun, ModulDvojno, true}, + {"pun + paušalac → nema dvojno", izmeni(pun, KljucPravniOblik, "pausalac"), ModulDvojno, false}, + {"pun + preduzetnik → nema dvojno (buduća podela)", izmeni(pun, KljucPravniOblik, "preduzetnik_knjige"), ModulDvojno, false}, + + // nepoznat modul + {"nepoznat modul → false", pun, "nepostojeci", false}, + } + + for _, tt := range testovi { + t.Run(tt.naziv, func(t *testing.T) { + if got := ModulUkljucen(tt.podesavanja, tt.modul); got != tt.ocekivano { + t.Errorf("ModulUkljucen(%q) = %v, očekivano %v", tt.modul, got, tt.ocekivano) + } + }) + } +}