Knjigovodstvo: storno prodaje/nabavke više ne briše KIR/KPR/KPO
Storno je fizički brisao vezani KIR/KPR/KPO zapis — zakon o računovodstvu ne dozvoljava brisanje poslovnih knjiga (KPO dodatno ima redni broj bez prekida). Sad se original čuva, a storno se dograđuje kao poništavajuća stavka (negirani iznosi, referenca na original) — model.KirStorno/KprStorno/KpoStorno. Usput ispravljen i pravi uzrok prijavljenog bug-a: kirKandidatiProdaje je filtrirala samo internu mapu, ne i listu naloga koju obilazi KirBackfillProdaje — stornirani nalozi su zbog toga dobijali ponovni (pogrešan) KIR upis.
This commit is contained in:
@@ -22,3 +22,24 @@ type KpoSume struct {
|
||||
Prihod float64
|
||||
Broj int
|
||||
}
|
||||
|
||||
// KpoStorno gradi storno zapis za dati KPO red: negiran prihod, upisan pod istim
|
||||
// izvorom/izvor_id kao original. Knjiga o ostvarenom prometu paušalaca vodi redni
|
||||
// broj bez prekida (Pravilnik) — original se nikad ne briše, storno se dodaje kao
|
||||
// poništavajuća stavka koja upućuje na original.
|
||||
func KpoStorno(original KpoZapis, razlog string, datumStorna time.Time) KpoZapis {
|
||||
napomena := "Storno naloga " + original.BrojDokumenta
|
||||
if razlog != "" {
|
||||
napomena += ": " + razlog
|
||||
}
|
||||
return KpoZapis{
|
||||
DatumPrometa: datumStorna,
|
||||
BrojDokumenta: "STORNO-" + original.BrojDokumenta,
|
||||
Opis: original.Opis,
|
||||
Prihod: -original.Prihod,
|
||||
NacinPlacanja: original.NacinPlacanja,
|
||||
Napomena: napomena,
|
||||
Izvor: original.Izvor,
|
||||
IzvorID: original.IzvorID,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,36 @@ func KirIzProdaje(nalog ProdajniNalog, stavke []StavkaProdaje, kupacNaziv, kupac
|
||||
return k
|
||||
}
|
||||
|
||||
// KirStorno gradi storno (knjižno odobrenje) zapis za dati KIR red: iznosi su
|
||||
// negirani original, upisan pod istim izvorom/izvor_id tako da PostojiZaIzvor
|
||||
// ostane tačan i backfill ne pokuša ponovni upis. Zakon o računovodstvu ne
|
||||
// dozvoljava brisanje knjigovodstvenih evidencija — storno se knjiži kao
|
||||
// poništavajuća stavka koja upućuje na original, a ne kao brisanje reda.
|
||||
func KirStorno(original PdvKir, razlog string, datumStorna time.Time) PdvKir {
|
||||
napomena := "Storno računa " + original.BrojDokumenta
|
||||
if razlog != "" {
|
||||
napomena += ": " + razlog
|
||||
}
|
||||
return PdvKir{
|
||||
DatumPrometa: datumStorna,
|
||||
DatumKnjizenja: datumStorna,
|
||||
BrojDokumenta: "STORNO-" + original.BrojDokumenta,
|
||||
KupacNaziv: original.KupacNaziv,
|
||||
KupacPib: original.KupacPib,
|
||||
KupacMesto: original.KupacMesto,
|
||||
OsnovicaOpsta: -original.OsnovicaOpsta,
|
||||
PdvOpsta: -original.PdvOpsta,
|
||||
OsnovicaPosebna: -original.OsnovicaPosebna,
|
||||
PdvPosebna: -original.PdvPosebna,
|
||||
OslobodenSaPravom: -original.OslobodenSaPravom,
|
||||
OslobodenBezPrava: -original.OslobodenBezPrava,
|
||||
Ukupno: -original.Ukupno,
|
||||
Napomena: napomena,
|
||||
Izvor: original.Izvor,
|
||||
IzvorID: original.IzvorID,
|
||||
}
|
||||
}
|
||||
|
||||
// PdvKpr je jedan zapis u knjizi primljenih računa (ulazni PDV).
|
||||
type PdvKpr struct {
|
||||
ID int64
|
||||
@@ -153,6 +183,33 @@ type PdvKpr struct {
|
||||
DatumUnosa time.Time
|
||||
}
|
||||
|
||||
// KprStorno gradi storno zapis za dati KPR red — vidi KirStorno.
|
||||
func KprStorno(original PdvKpr, razlog string, datumStorna time.Time) PdvKpr {
|
||||
napomena := "Storno dokumenta " + original.BrojDokumenta
|
||||
if razlog != "" {
|
||||
napomena += ": " + razlog
|
||||
}
|
||||
return PdvKpr{
|
||||
DatumPrometa: datumStorna,
|
||||
DatumKnjizenja: datumStorna,
|
||||
BrojDokumenta: "STORNO-" + original.BrojDokumenta,
|
||||
DobavljacNaziv: original.DobavljacNaziv,
|
||||
DobavljacPib: original.DobavljacPib,
|
||||
DobavljacMesto: original.DobavljacMesto,
|
||||
OsnovicaOpsta: -original.OsnovicaOpsta,
|
||||
PdvOpsta: -original.PdvOpsta,
|
||||
OsnovicaPosebna: -original.OsnovicaPosebna,
|
||||
PdvPosebna: -original.PdvPosebna,
|
||||
PdvBezOdbitka: -original.PdvBezOdbitka,
|
||||
OslobodenNabavka: -original.OslobodenNabavka,
|
||||
Ukupno: -original.Ukupno,
|
||||
Napomena: napomena,
|
||||
Izvor: original.Izvor,
|
||||
IzvorID: original.IzvorID,
|
||||
Uvoz: original.Uvoz,
|
||||
}
|
||||
}
|
||||
|
||||
// OznakaPoreskogBroja vraća „JMBG" za 13-cifreni broj, inače „PIB" (dobavljači su obično firme).
|
||||
func (k PdvKpr) OznakaPoreskogBroja() string {
|
||||
cifre := 0
|
||||
|
||||
@@ -70,6 +70,38 @@ func TestPdvKirDodajNeto(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestKirStorno: storno stavka negira sve kolone originala, čuva izvor/izvor_id
|
||||
// (da PostojiZaIzvor ostane tačan i backfill ne pokuša ponovni upis) i original
|
||||
// se ne dira — storno se samo dograđuje kao novi red.
|
||||
func TestKirStorno(t *testing.T) {
|
||||
izvorID := int64(18)
|
||||
original := PdvKir{
|
||||
BrojDokumenta: "PR-2607-0013", KupacNaziv: "Kupac doo", KupacPib: "123456789",
|
||||
OsnovicaOpsta: 1000, PdvOpsta: 200, OsnovicaPosebna: 100, PdvPosebna: 10,
|
||||
OslobodenSaPravom: 50, OslobodenBezPrava: 20, Ukupno: 1380,
|
||||
Izvor: "prodaja", IzvorID: &izvorID,
|
||||
}
|
||||
datumStorna := time.Date(2026, 7, 2, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
s := KirStorno(original, "kupac odustao", datumStorna)
|
||||
|
||||
if s.BrojDokumenta != "STORNO-PR-2607-0013" {
|
||||
t.Errorf("broj_dokumenta=%q, očekivano STORNO-PR-2607-0013", s.BrojDokumenta)
|
||||
}
|
||||
if s.Izvor != "prodaja" || s.IzvorID == nil || *s.IzvorID != 18 {
|
||||
t.Errorf("izvor=%q izvor_id=%v, očekivano prodaja/18 (isto kao original)", s.Izvor, s.IzvorID)
|
||||
}
|
||||
if !blizu(s.OsnovicaOpsta, -1000) || !blizu(s.PdvOpsta, -200) {
|
||||
t.Errorf("opšta: osnovica=%v pdv=%v, očekivano -1000/-200", s.OsnovicaOpsta, s.PdvOpsta)
|
||||
}
|
||||
if !blizu(s.Ukupno, -1380) {
|
||||
t.Errorf("ukupno=%v, očekivano -1380", s.Ukupno)
|
||||
}
|
||||
if original.Ukupno != 1380 {
|
||||
t.Errorf("original izmenjen: ukupno=%v, očekivano da ostane 1380", original.Ukupno)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKprIzNabavke(t *testing.T) {
|
||||
nabavka := Nabavka{ID: 3, Napomena: "test", Datum: time.Date(2026, 6, 2, 0, 0, 0, 0, time.UTC)}
|
||||
stavke := []NabavkaStavkaPdv{
|
||||
|
||||
Reference in New Issue
Block a user