Servis: KIR backfill i detekcija praznina (kao Prodaja)
Servisni KIR upis nije imao nijedan mehanizam oporavka — ako auto-upis pri preuzimanju padne, B2B servisni promet tiho ispadne iz PDV evidencije bez traga za korisnika. Dodato po uzoru na Prodaju: - kirKandidatiServisa (preuzeti nalozi sa identifikovanim kupcem) - KirBackfillServisa ruta + dugme "Uvezi iz servisa" na KIR stranici - PraznineKnjigovodstva sad broji i servisne KIR praznine (dashboard upozorenje)
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user