Javno odobravanje predloga: Prihvati/Odbij sa komentarom

- Dodati handleri za prihvatanje i odbijanje predloga sa mobilnog
- Prihvatanje: predložene stavke prelaze u ugrađene (predlozeno 1→0)
- Odbijanje: brišu se predložene stavke
- Komentar klijenta uz odluku (textarea na mobilnom, prikaz u detaljima)
- Oznaka na kanbanu za naloge sa predlozima (narandžasta tačka + leva ivica)
- Oznaka na kanbanu za poruku klijenta (💬 dugme, tap za prikaz)
- Spojene kartice Radovi/Predložene usluge i Delovi/Predloženi delovi
- Auto-detekcija predlozeno=1 kad status != Primljeno
- Obrisana Otključaj/Zaključaj dugmad
- Ukupno sa predlogom na javnoj status stranici
- CSRF middleware premešten u zaštićenu grupu
- Migracija 078: komentar_klijenta
- Repo metode: ObrisiPredlozene, AzurirajKomentarKlijenta
- Popravljeno: 405 na odbij, duple rute, razmak između kartica
This commit is contained in:
2026-06-24 02:41:06 +02:00
parent 3c6b0376b8
commit f61b3bd5ca
19 changed files with 699 additions and 148 deletions
+33 -7
View File
@@ -21,7 +21,7 @@ func NoviServisniRadoviRepo(baza *sql.DB) *ServisniRadoviRepo {
// DohvatiZaNalog vraća sve radove (usluge) jednog naloga, redom unosa
func (r *ServisniRadoviRepo) DohvatiZaNalog(ctx context.Context, nalogID int64) ([]model.ServisniRad, error) {
redovi, err := r.db.QueryContext(ctx, `
SELECT id, nalog_id, COALESCE(usluga_id, 0), naziv, kolicina, cena_komada, datum
SELECT id, nalog_id, COALESCE(usluga_id, 0), naziv, kolicina, cena_komada, datum, predlozeno
FROM servis_radovi WHERE nalog_id = ? ORDER BY id`, nalogID)
if err != nil {
return nil, fmt.Errorf("ntech: ServisniRadoviRepo.DohvatiZaNalog: %w", err)
@@ -31,7 +31,7 @@ func (r *ServisniRadoviRepo) DohvatiZaNalog(ctx context.Context, nalogID int64)
var radovi []model.ServisniRad
for redovi.Next() {
var rad model.ServisniRad
if err := redovi.Scan(&rad.ID, &rad.NalogID, &rad.UslugaID, &rad.Naziv, &rad.Kolicina, &rad.CenaKomada, &rad.Datum); err != nil {
if err := redovi.Scan(&rad.ID, &rad.NalogID, &rad.UslugaID, &rad.Naziv, &rad.Kolicina, &rad.CenaKomada, &rad.Datum, &rad.Predlozeno); err != nil {
return nil, fmt.Errorf("ntech: ServisniRadoviRepo.DohvatiZaNalog: %w", err)
}
radovi = append(radovi, rad)
@@ -39,16 +39,21 @@ func (r *ServisniRadoviRepo) DohvatiZaNalog(ctx context.Context, nalogID int64)
return radovi, redovi.Err()
}
// Dodaj upisuje jednu stavku rada na nalog (radovi ne diraju lager)
func (r *ServisniRadoviRepo) Dodaj(ctx context.Context, nalogID, uslugaID int64, naziv string, kolicina, cenaKomada float64) (int64, error) {
// Dodaj upisuje jednu stavku rada na nalog (radovi ne diraju lager).
// predlozeno=true označava uslugu koju serviser predlaže posle dijagnostike.
func (r *ServisniRadoviRepo) Dodaj(ctx context.Context, nalogID, uslugaID int64, naziv string, kolicina, cenaKomada float64, predlozeno bool) (int64, error) {
var uid any
if uslugaID > 0 {
uid = uslugaID
}
predInt := 0
if predlozeno {
predInt = 1
}
rez, err := r.db.ExecContext(ctx, `
INSERT INTO servis_radovi (nalog_id, usluga_id, naziv, kolicina, cena_komada)
VALUES (?, ?, ?, ?, ?)`,
nalogID, uid, naziv, kolicina, cenaKomada,
INSERT INTO servis_radovi (nalog_id, usluga_id, naziv, kolicina, cena_komada, predlozeno)
VALUES (?, ?, ?, ?, ?, ?)`,
nalogID, uid, naziv, kolicina, cenaKomada, predInt,
)
if err != nil {
return 0, fmt.Errorf("ntech: ServisniRadoviRepo.Dodaj: %w", err)
@@ -60,6 +65,27 @@ func (r *ServisniRadoviRepo) Dodaj(ctx context.Context, nalogID, uslugaID int64,
return id, nil
}
// PrihvatiPredlozene prebacuje sve predložene radove naloga u redovne (predlozeno → 0)
func (r *ServisniRadoviRepo) PrihvatiPredlozene(ctx context.Context, nalogID int64) error {
if _, err := r.db.ExecContext(ctx,
"UPDATE servis_radovi SET predlozeno = 0 WHERE nalog_id = ? AND predlozeno = 1", nalogID,
); err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.PrihvatiPredlozene: %w", err)
}
return nil
}
// ObrisiPredlozene briše sve predložene radove sa naloga (klijent odbio predlog)
func (r *ServisniRadoviRepo) ObrisiPredlozene(ctx context.Context, nalogID int64) error {
_, err := r.db.ExecContext(ctx,
"DELETE FROM servis_radovi WHERE nalog_id = ? AND predlozeno = 1", nalogID,
)
if err != nil {
return fmt.Errorf("ntech: ServisniRadoviRepo.ObrisiPredlozene: %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 {