From 2388d413f17c3728b945918674c1b47d9b2e89da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Markovi=C4=87?= Date: Mon, 22 Jun 2026 15:26:12 +0200 Subject: [PATCH] =?UTF-8?q?Servis:=20nabavka=20automatski=20vra=C4=87a=20n?= =?UTF-8?q?alog=20iz=20=C4=8Ceka=20delove=20na=20Primljeno?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/db/repository.go | 3 +- .../db/sqlite/servisni_potrazivani_delovi.go | 38 ++++++++++++++----- internal/handler/nabavka.go | 11 +++++- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/internal/db/repository.go b/internal/db/repository.go index f8ee9ad..8c9a630 100644 --- a/internal/db/repository.go +++ b/internal/db/repository.go @@ -223,7 +223,8 @@ type ServisniPotrazivaniDeloviRepository interface { ObrisiZaArtikal(ctx context.Context, nalogID, artikalID int64) error // ProveriIPocistiZaArtikal proverava potraživane redove za dati artikal nakon // povećanja stanja i briše/smanjuje redove koji se mogu pokriti (FIFO). - ProveriIPocistiZaArtikal(ctx context.Context, artikalID int64) error + // Vraća ID-eve naloga čiji je poslednji potraživani red obrisan. + ProveriIPocistiZaArtikal(ctx context.Context, artikalID int64) ([]int64, error) } // ServisniRadoviRepository definiše operacije nad radovima (uslugama) na nalogu diff --git a/internal/db/sqlite/servisni_potrazivani_delovi.go b/internal/db/sqlite/servisni_potrazivani_delovi.go index c6c0614..be5a830 100644 --- a/internal/db/sqlite/servisni_potrazivani_delovi.go +++ b/internal/db/sqlite/servisni_potrazivani_delovi.go @@ -109,39 +109,44 @@ func (r *ServisniPotrazivaniDeloviRepo) ObrisiZaArtikal(ctx context.Context, nal // ProveriIPocistiZaArtikal poziva se nakon što stanje artikla poraste (nabavka) // i čisti potraživane redove koji se sada mogu pokriti dostupnim stanjem (FIFO). // Delimično pokrivanje smanjuje traženu količinu umesto brisanja. -func (r *ServisniPotrazivaniDeloviRepo) ProveriIPocistiZaArtikal(ctx context.Context, artikalID int64) error { +// Vraća ID-eve naloga čiji su svi potraživani redovi obrisani (nalog može da se otključa). +func (r *ServisniPotrazivaniDeloviRepo) ProveriIPocistiZaArtikal(ctx context.Context, artikalID int64) ([]int64, error) { var stanje int err := r.db.QueryRowContext(ctx, "SELECT kolicina FROM artikli WHERE id = ?", artikalID).Scan(&stanje) if err != nil { - return fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: stanje: %w", err) + return nil, fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: stanje: %w", err) } if stanje <= 0 { - return nil + return nil, nil } redovi, err := r.db.QueryContext(ctx, - "SELECT id, kolicina FROM servisni_potrazivani_delovi WHERE artikal_id = ? ORDER BY datum", + "SELECT id, nalog_id, kolicina FROM servisni_potrazivani_delovi WHERE artikal_id = ? ORDER BY datum", artikalID, ) if err != nil { - return fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: query: %w", err) + return nil, fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: query: %w", err) } defer redovi.Close() type red struct { id int64 + nalogID int64 kolicina int } var lista []red for redovi.Next() { var p red - if err := redovi.Scan(&p.id, &p.kolicina); err != nil { - return fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: scan: %w", err) + if err := redovi.Scan(&p.id, &p.nalogID, &p.kolicina); err != nil { + return nil, fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: scan: %w", err) } lista = append(lista, p) } redovi.Close() + // prati naloge iz kojih smo obrisali red + obrisaniNalozi := map[int64]struct{}{} + dostupno := stanje for _, p := range lista { if dostupno <= 0 { @@ -149,16 +154,29 @@ func (r *ServisniPotrazivaniDeloviRepo) ProveriIPocistiZaArtikal(ctx context.Con } if dostupno >= p.kolicina { if _, err := r.db.ExecContext(ctx, "DELETE FROM servisni_potrazivani_delovi WHERE id = ?", p.id); err != nil { - return fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: delete: %w", err) + return nil, fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: delete: %w", err) } + obrisaniNalozi[p.nalogID] = struct{}{} dostupno -= p.kolicina } else { novaKol := p.kolicina - dostupno if _, err := r.db.ExecContext(ctx, "UPDATE servisni_potrazivani_delovi SET kolicina = ? WHERE id = ?", novaKol, p.id); err != nil { - return fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: update: %w", err) + return nil, fmt.Errorf("ntech: ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal: update: %w", err) } dostupno = 0 } } - return nil + + // vrati samo one naloge koji NEMAJU više nijedan potraživani red + var otkljucani []int64 + for nalogID := range obrisaniNalozi { + var preostalo int + _ = r.db.QueryRowContext(ctx, + "SELECT COUNT(*) FROM servisni_potrazivani_delovi WHERE nalog_id = ?", nalogID, + ).Scan(&preostalo) + if preostalo == 0 { + otkljucani = append(otkljucani, nalogID) + } + } + return otkljucani, nil } diff --git a/internal/handler/nabavka.go b/internal/handler/nabavka.go index a2a4e3c..3ad51c5 100644 --- a/internal/handler/nabavka.go +++ b/internal/handler/nabavka.go @@ -261,10 +261,17 @@ func (h *Handler) SacuvajNabavku(w http.ResponseWriter, r *http.Request) { } } - // nakon povećanja stanja proveri da li se potraživani delovi u servisu mogu pokriti + // nakon povećanja stanja: počisti potraživane delove i vrati otključane naloge na Primljeno for _, s := range stavke { - if err := h.ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal(r.Context(), s.ArtikalID); err != nil { + otkljucani, err := h.ServisniPotrazivaniDeloviRepo.ProveriIPocistiZaArtikal(r.Context(), s.ArtikalID) + if err != nil { slog.Error("provera potraživanih delova nije uspela", "artikal_id", s.ArtikalID, "error", err) + continue + } + for _, nalogID := range otkljucani { + if err := h.ServisRepo.AzurirajStatus(r.Context(), nalogID, model.StatusPrimljeno); err != nil { + slog.Error("automatski reset statusa naloga nije uspeo", "nalog_id", nalogID, "error", err) + } } }