diff --git a/cmd/ntech/main.go b/cmd/ntech/main.go index 237d65d..0314090 100644 --- a/cmd/ntech/main.go +++ b/cmd/ntech/main.go @@ -312,6 +312,7 @@ func main() { r.With(modul("pdv"), doz("pdv.dodaj")).Post("/pdv/kir/nova", h.SacuvajPdvKir) r.With(modul("pdv"), doz("pdv.obrisi")).Post("/pdv/kir/obrisi/{id}", h.ObrisiPdvKir) r.With(modul("pdv"), doz("pdv.dodaj")).Post("/pdv/kir/backfill-prodaje", h.KirBackfillProdaje) + r.With(modul("pdv"), doz("pdv.dodaj")).Post("/pdv/kir/backfill-servisa", h.KirBackfillServisa) r.With(modul("pdv"), doz("pdv.dodaj")).Get("/pdv/kir/dnevni-pazar", h.DnevniPazarKir) r.With(modul("pdv"), doz("pdv.dodaj")).Post("/pdv/kir/dnevni-pazar", h.SacuvajDnevniPazarKir) r.With(modul("pdv")).Get("/pdv/kpr", h.PdvKpr) diff --git a/internal/handler/pdv_kir.go b/internal/handler/pdv_kir.go index f34459b..ed3736b 100644 --- a/internal/handler/pdv_kir.go +++ b/internal/handler/pdv_kir.go @@ -296,6 +296,75 @@ func (h *Handler) KirBackfillProdaje(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/pdv/kir", http.StatusSeeOther) } +// KirBackfillServisa kreira KIR zapise za sve preuzete servisne naloge sa +// identifikovanim kupcem koji ih nemaju. Namenjen za jednokratno popunjavanje. +func (h *Handler) KirBackfillServisa(w http.ResponseWriter, r *http.Request) { + if _, ok := h.zahtevajDozvolu(w, r, "pdv.dodaj"); !ok { + return + } + ctx := r.Context() + sada := time.Now() + + nalozi, postojiMap, kandidati, err := h.kirKandidatiServisa(ctx) + if err != nil { + http.Error(w, "Greška pri učitavanju servisa", http.StatusInternalServerError) + return + } + duplikati := sumnjiviDuplikati(kandidati) + + var kreirano, preskoceno, sumnjivo int + for _, sn := range nalozi { + if postojiMap[sn.ID] { + preskoceno++ + continue + } + if duplikati[sn.ID] { + sumnjivo++ + continue + } + radovi, err := h.ServisniRadoviRepo.DohvatiZaNalog(ctx, sn.ID) + if err != nil { + slog.Error("backfill KIR: greška pri čitanju radova", "servis_id", sn.ID, "error", err) + continue + } + delovi, err := h.ServisniDeloviRepo.DohvatiZaNalog(ctx, sn.ID) + if err != nil { + slog.Error("backfill KIR: greška pri čitanju delova", "servis_id", sn.ID, "error", err) + continue + } + klijent, err := h.KlijentiRepo.DohvatiID(ctx, *sn.KlijentID) + if err != nil { + slog.Error("backfill KIR: greška pri čitanju klijenta", "servis_id", sn.ID, "error", err) + continue + } + pib := klijent.PIB + if klijent.Tip != "pravno" { + pib = klijent.JMBG + } + datumPrometa := sn.DatumPrijema + if sn.DatumZavrsetka != nil { + datumPrometa = *sn.DatumZavrsetka + } + kir := model.KirIzServisa(sn.ServisniNalog, radovi, delovi, klijent.PunoIme(), pib, klijent.Mesto, datumPrometa, sada) + if kir.Ukupno <= 0 { + preskoceno++ + continue + } + if _, e := h.PdvKirRepo.Kreiraj(ctx, &kir); e != nil { + slog.Error("backfill KIR: greška pri kreiranju zapisa", "servis_id", sn.ID, "error", e) + continue + } + kreirano++ + } + + poruka := fmt.Sprintf("Backfill završen: %d novih KIR zapisa, %d preskočeno.", kreirano, preskoceno) + if sumnjivo > 0 { + poruka += fmt.Sprintf(" %d sumnjivih duplikata NIJE upisano — proveri ručno.", sumnjivo) + } + middleware.SetFlash(w, r, h.DB, "uspeh", poruka) + http.Redirect(w, r, "/pdv/kir", http.StatusSeeOther) +} + // PodaciDnevniPazar su podaci za formu zbirnog KIR unosa (maloprodaja) type PodaciDnevniPazar struct { model.PodaciStranice diff --git a/internal/handler/uskladjivanje.go b/internal/handler/uskladjivanje.go index c418f9d..d9a27be 100644 --- a/internal/handler/uskladjivanje.go +++ b/internal/handler/uskladjivanje.go @@ -139,6 +139,36 @@ func (h *Handler) kpoKandidatiServisa(ctx context.Context) (naplaceni []model.Se return naplaceni, postojiMap, kandidati, nenaplaceniBroj, nil } +// kirKandidatiServisa vraća sve preuzete servisne naloge sa identifikovanim kupcem +// (KlijentID != nil, isti kriterijum kao u Prodaji — B2B/identifikovan kupac) sa +// mapom postojećih KIR upisa i kandidatima za detekciju duplikata. +func (h *Handler) kirKandidatiServisa(ctx context.Context) ([]model.ServisniNalogSaKlijentom, map[int64]bool, []kandidatUskladjivanja, error) { + svi, err := h.ServisRepo.Lista(ctx, "", "") + if err != nil { + return nil, nil, nil, err + } + var kandidatNalozi []model.ServisniNalogSaKlijentom + for _, sn := range svi { + if sn.Status == model.StatusPreuzeto && !sn.Stornirano && !sn.PopravkaOdbijena && sn.KlijentID != nil { + kandidatNalozi = append(kandidatNalozi, sn) + } + } + postojiMap := make(map[int64]bool, len(kandidatNalozi)) + var kandidati []kandidatUskladjivanja + for _, sn := range kandidatNalozi { + postoji, _ := h.PdvKirRepo.PostojiZaIzvor(ctx, "servis", sn.ID) + postojiMap[sn.ID] = postoji + datum := sn.DatumPrijema + if sn.DatumZavrsetka != nil { + datum = *sn.DatumZavrsetka + } + kandidati = append(kandidati, kandidatUskladjivanja{ + ID: sn.ID, KlijentID: sn.KlijentID, Iznos: sn.Naplaceno, Datum: datum, ImaUpis: postoji, + }) + } + return kandidatNalozi, postojiMap, kandidati, nil +} + // PraznineKnjigovodstva broji naloge (prodaja + servis) koji čekaju KIR/KPO/fiskalni // upis prema TRENUTNO aktivnim modulima firme, i naloge koji su sumnjivi duplikati // (double-submit) pa ih automatski backfill preskače. @@ -146,16 +176,31 @@ func (h *Handler) PraznineKnjigovodstva(ctx context.Context) (model.PrazninaKnji var p model.PrazninaKnjigovodstva if h.modulUkljucen(ctx, "pdv") { - _, postojiMap, kandidati, err := h.kirKandidatiProdaje(ctx) + _, postojiMapP, kandidatiP, err := h.kirKandidatiProdaje(ctx) if err != nil { return p, err } - duplikati := sumnjiviDuplikati(kandidati) - for id, postoji := range postojiMap { + _, postojiMapS, kandidatiS, err := h.kirKandidatiServisa(ctx) + if err != nil { + return p, err + } + duplikatiP := sumnjiviDuplikati(kandidatiP) + duplikatiS := sumnjiviDuplikati(kandidatiS) + for id, postoji := range postojiMapP { if postoji { continue } - if duplikati[id] { + if duplikatiP[id] { + p.SumnjiviDupli++ + continue + } + p.BezKir++ + } + for id, postoji := range postojiMapS { + if postoji { + continue + } + if duplikatiS[id] { p.SumnjiviDupli++ continue } diff --git a/web/templates/stranice/pdv_kir.html b/web/templates/stranice/pdv_kir.html index cfcefc0..4e95cc1 100644 --- a/web/templates/stranice/pdv_kir.html +++ b/web/templates/stranice/pdv_kir.html @@ -33,6 +33,13 @@ Uvezi iz prodaje +
{{end}} + Nov izlazni račun