PDV KIR: dnevni pazar se ažurira (zamenjuje) umesto tvrde blokade

Prethodna zaštita od duplog unosa (77320d2) je trajno onemogućavala ispravku
zbirnog KIR zapisa jednom kad bi bio sačuvan — a taj zapis nema vezu nazad ka
pojedinačnim nalozima, pa naknadni storno ili nova prodaja istog dana ne mogu da
ga koriguju kroz postojeće mehanizme (ObrisiPoIzvoru radi samo za B2B auto-KIR).

Sad se ponovni upis za isti dan tretira kao ažuriranje: stari zapis (po broju
dokumenta FISK-YYYYMMDD) se briše i zamenjuje trenutno tačnim iznosima. Forma i
dalje upozorava da zapis već postoji, ali dugme dozvoljava svesno ažuriranje
umesto da bude trajno sakriveno.
This commit is contained in:
2026-07-01 11:59:37 +02:00
parent b99f465ec5
commit 1adf49e8cc
4 changed files with 26 additions and 8 deletions
+3 -1
View File
@@ -71,8 +71,10 @@ type PdvKirRepository interface {
// PostojiZaIzvor vraća true ako postoji bar jedan zapis za dati izvor i izvorID // PostojiZaIzvor vraća true ako postoji bar jedan zapis za dati izvor i izvorID
PostojiZaIzvor(ctx context.Context, izvor string, izvorID int64) (bool, error) PostojiZaIzvor(ctx context.Context, izvor string, izvorID int64) (bool, error)
// PostojiPoBrojuDokumenta vraća true ako postoji zapis sa datim brojem dokumenta // PostojiPoBrojuDokumenta vraća true ako postoji zapis sa datim brojem dokumenta
// (npr. zaštita od duplog unosa dnevnog pazara "FISK-YYYYMMDD") // (npr. za prikaz upozorenja da je dnevni pazar "FISK-YYYYMMDD" već upisan)
PostojiPoBrojuDokumenta(ctx context.Context, brojDokumenta string) (bool, error) PostojiPoBrojuDokumenta(ctx context.Context, brojDokumenta string) (bool, error)
// ObrisiPoBrojuDokumenta briše zapis(e) sa datim brojem dokumenta (zamena pri ažuriranju)
ObrisiPoBrojuDokumenta(ctx context.Context, brojDokumenta string) error
} }
// PdvKprRepository definiše operacije nad knjigom primljenih računa (KPR) // PdvKprRepository definiše operacije nad knjigom primljenih računa (KPR)
+9
View File
@@ -148,6 +148,15 @@ func (r *PdvKirRepo) PostojiZaIzvor(ctx context.Context, izvor string, izvorID i
return n > 0, nil return n > 0, nil
} }
// ObrisiPoBrojuDokumenta briše KIR zapis(e) sa datim brojem dokumenta (za zamenu
// zbirnog dnevnog pazara ažuriranim iznosima).
func (r *PdvKirRepo) ObrisiPoBrojuDokumenta(ctx context.Context, brojDokumenta string) error {
if _, err := r.db.ExecContext(ctx, "DELETE FROM pdv_kir WHERE broj_dokumenta = ?", brojDokumenta); err != nil {
return fmt.Errorf("ntech: PdvKirRepo.ObrisiPoBrojuDokumenta: %w", err)
}
return nil
}
// PostojiPoBrojuDokumenta vraća true ako postoji KIR zapis sa datim brojem dokumenta // PostojiPoBrojuDokumenta vraća true ako postoji KIR zapis sa datim brojem dokumenta
func (r *PdvKirRepo) PostojiPoBrojuDokumenta(ctx context.Context, brojDokumenta string) (bool, error) { func (r *PdvKirRepo) PostojiPoBrojuDokumenta(ctx context.Context, brojDokumenta string) (bool, error) {
var n int var n int
+4 -4
View File
@@ -327,11 +327,11 @@ func (h *Handler) SacuvajDnevniPazarKir(w http.ResponseWriter, r *http.Request)
return return
} }
// ako za ovaj dan već postoji zbirni zapis, zameni ga ažuriranim iznosima
// (npr. naknadni storno ili prodaja posle prethodnog upisa promenili su promet tog dana)
brojDokumenta := fmt.Sprintf("FISK-%s", datum.Format("20060102")) brojDokumenta := fmt.Sprintf("FISK-%s", datum.Format("20060102"))
if postoji, _ := h.PdvKirRepo.PostojiPoBrojuDokumenta(r.Context(), brojDokumenta); postoji { if err := h.PdvKirRepo.ObrisiPoBrojuDokumenta(r.Context(), brojDokumenta); err != nil {
middleware.SetFlash(w, r, h.DB, "greska", fmt.Sprintf("Dnevni pazar za %s je već upisan u KIR.", datum.Format("02.01.2006."))) slog.Error("brisanje starog dnevnog pazara nije uspelo", "datum", datum, "error", err)
http.Redirect(w, r, "/pdv/kir/dnevni-pazar?datum="+datumStr, http.StatusSeeOther)
return
} }
z := model.PdvKir{ z := model.PdvKir{
@@ -82,13 +82,13 @@
<div class="kartica animiraj" style="margin-bottom:16px;border:1.5px solid #f59e0b;background:color-mix(in srgb,#fef3c7 60%,var(--pozadina));"> <div class="kartica animiraj" style="margin-bottom:16px;border:1.5px solid #f59e0b;background:color-mix(in srgb,#fef3c7 60%,var(--pozadina));">
<div style="padding:16px;"> <div style="padding:16px;">
<div style="font-size:14px;font-weight:600;color:#92400e;margin-bottom:4px;">⚠ Već upisano</div> <div style="font-size:14px;font-weight:600;color:#92400e;margin-bottom:4px;">⚠ Već upisano</div>
<div style="font-size:13px;color:#78350f;">Dnevni pazar za {{.Datum}} je već upisan u KIR. Ponovni upis bi duplirao promet za ovaj dan.</div> <div style="font-size:13px;color:#78350f;">Dnevni pazar za {{.Datum}} je već upisan u KIR. Ako je promet tog dana naknadno promenjen (storno ili nova prodaja), ažuriranjem se stari zapis zamenjuje trenutnim iznosima.</div>
</div> </div>
</div> </div>
{{end}} {{end}}
{{if and (gt .Promet.BrojNaloga 0) (not .VecUpisano)}} {{if gt .Promet.BrojNaloga 0}}
<!-- forma za upis --> <!-- forma za upis/ažuriranje -->
<form method="POST" action="/pdv/kir/dnevni-pazar"> <form method="POST" action="/pdv/kir/dnevni-pazar">
<input type="hidden" name="_csrf" value="{{.CsrfToken}}"> <input type="hidden" name="_csrf" value="{{.CsrfToken}}">
<input type="hidden" name="datum" value="{{.Datum}}"> <input type="hidden" name="datum" value="{{.Datum}}">
@@ -99,10 +99,17 @@
<div class="kartica animiraj"> <div class="kartica animiraj">
<div style="padding:16px;display:flex;justify-content:flex-end;gap:12px;"> <div style="padding:16px;display:flex;justify-content:flex-end;gap:12px;">
<a href="/pdv/kir" class="btn-sekundarno" hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML">Odustani</a> <a href="/pdv/kir" class="btn-sekundarno" hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML">Odustani</a>
{{if .VecUpisano}}
<button type="submit" class="btn-primarno"
data-potvrda="Dnevni pazar za {{.Datum}} je već upisan. Zameniti stari zapis trenutnim iznosima?">
Ažuriraj KIR za ovaj dan
</button>
{{else}}
<button type="submit" class="btn-primarno" <button type="submit" class="btn-primarno"
data-potvrda="Upisati dnevni pazar za {{.Datum}} u KIR?"> data-potvrda="Upisati dnevni pazar za {{.Datum}} u KIR?">
Upiši u KIR Upiši u KIR
</button> </button>
{{end}}
</div> </div>
</div> </div>
</form> </form>