Servis: garantni list, radovi na otpremnici, selektivno prihvatanje predloga po stavkama

This commit is contained in:
2026-06-25 01:39:56 +02:00
parent a7ec5e9aa9
commit e50fe660b1
9 changed files with 404 additions and 18 deletions
+6
View File
@@ -232,6 +232,9 @@ type ServisniDeloviRepository interface {
PrihvatiPredlozene(ctx context.Context, nalogID int64) error
// ObrisiPredlozene briše sve predložene delove sa naloga (klijent odbio predlog)
ObrisiPredlozene(ctx context.Context, nalogID int64) error
// PrihvatiOdabranePoArtiklu selektivno prihvata predlozene delove po artikal_id;
// prihvaćeni idu kroz normalnu ugradnju (skidaju sa lagera), ostali se odbacuju.
PrihvatiOdabranePoArtiklu(ctx context.Context, nalogID int64, artikalIDs []int64) error
}
// ServisniPotrazivaniDeloviRepository definiše operacije nad delovima koji nedostaju
@@ -255,6 +258,9 @@ type ServisniRadoviRepository interface {
PrihvatiPredlozene(ctx context.Context, nalogID int64) error
// ObrisiPredlozene briše sve predložene radove sa naloga (klijent odbio predlog)
ObrisiPredlozene(ctx context.Context, nalogID int64) error
// PrihvatiOdabrane selektivno prihvata predlozene radove po ID-u;
// prihvaćeni dobijaju predlozeno=0, ostali predlozeni se brišu.
PrihvatiOdabrane(ctx context.Context, nalogID int64, ids []int64) error
}
// MagacinskePromeneRepository definiše operacije nad revizijskim tragom magacina
+68
View File
@@ -315,6 +315,74 @@ func (r *ServisniDeloviRepo) ObrisiPredlozene(ctx context.Context, nalogID int64
return nil
}
// PrihvatiOdabranePoArtiklu prihvata selektivno predložene delove: artikalIDs su prihvaćeni
// (idu kroz normalnu ugradnju/lager), svi ostali predlozeni se brišu bez povraćaja lagera.
func (r *ServisniDeloviRepo) PrihvatiOdabranePoArtiklu(ctx context.Context, nalogID int64, artikalIDs []int64) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: begin tx: %w", err)
}
defer tx.Rollback()
// Dohvati sve predložene potraživane
redovi, err := tx.QueryContext(ctx,
"SELECT id, artikal_id, kolicina, cena_komada FROM servisni_potrazivani_delovi WHERE nalog_id = ? AND predlozeno = 1",
nalogID,
)
if err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: dohvati: %w", err)
}
type stavka struct {
id int64
artikalID int64
kolicina int
cena float64
}
var sve []stavka
for redovi.Next() {
var s stavka
if err := redovi.Scan(&s.id, &s.artikalID, &s.kolicina, &s.cena); err != nil {
redovi.Close()
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: scan: %w", err)
}
sve = append(sve, s)
}
redovi.Close()
if err := redovi.Err(); err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: rows: %w", err)
}
prihvaceni := make(map[int64]bool, len(artikalIDs))
for _, id := range artikalIDs {
prihvaceni[id] = true
}
for _, s := range sve {
if prihvaceni[s.artikalID] {
if _, _, err := ugradiIliPotrazujTx(ctx, tx, nalogID, s.artikalID, s.kolicina, s.cena, nil, false); err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: ugradi: %w", err)
}
}
}
// Briši sve predlozene potraživane (prihvaćeni su prebačeni, odbijeni se odbacuju)
if _, err := tx.ExecContext(ctx,
"DELETE FROM servisni_potrazivani_delovi WHERE nalog_id = ? AND predlozeno = 1", nalogID,
); err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: obrisi: %w", err)
}
if _, err := tx.ExecContext(ctx,
"DELETE FROM servisni_delovi WHERE nalog_id = ? AND predlozeno = 1", nalogID,
); err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: obrisi delove: %w", err)
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("ntech: ServisniDeloviRepo.PrihvatiOdabranePoArtiklu: commit: %w", err)
}
return nil
}
// DohvatiArtikalID vraća artikal_id za dati servisni deo (pre brisanja)
func (r *ServisniDeloviRepo) DohvatiArtikalID(ctx context.Context, deoID int64) (int64, error) {
var artikalID int64
+48
View File
@@ -89,6 +89,54 @@ func (r *ServisniRadoviRepo) ObrisiPredlozene(ctx context.Context, nalogID int64
return nil
}
// PrihvatiOdabrane prihvata selektivno predložene radove: ids su prihvaćeni (predlozeno→0),
// ostali predlozeni se brišu.
func (r *ServisniRadoviRepo) PrihvatiOdabrane(ctx context.Context, nalogID int64, ids []int64) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiOdabrane: begin tx: %w", err)
}
defer tx.Rollback()
prihvaceni := make(map[int64]bool, len(ids))
for _, id := range ids {
prihvaceni[id] = true
}
// Dohvati sve predlozene radove
redovi, err := tx.QueryContext(ctx, "SELECT id FROM servis_radovi WHERE nalog_id = ? AND predlozeno = 1", nalogID)
if err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiOdabrane: dohvati: %w", err)
}
var sviIDs []int64
for redovi.Next() {
var id int64
if err := redovi.Scan(&id); err != nil {
redovi.Close()
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiOdabrane: scan: %w", err)
}
sviIDs = append(sviIDs, id)
}
redovi.Close()
for _, id := range sviIDs {
if prihvaceni[id] {
if _, err := tx.ExecContext(ctx, "UPDATE servis_radovi SET predlozeno = 0 WHERE id = ?", id); err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiOdabrane: update: %w", err)
}
} else {
if _, err := tx.ExecContext(ctx, "DELETE FROM servis_radovi WHERE id = ?", id); err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiOdabrane: delete: %w", err)
}
}
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiOdabrane: commit: %w", err)
}
return nil
}
// Obrisi uklanja jednu stavku rada sa naloga
func (r *ServisniRadoviRepo) Obrisi(ctx context.Context, id int64) error {
if _, err := r.db.ExecContext(ctx, "DELETE FROM servis_radovi WHERE id = ?", id); err != nil {