- PDV uslovi (Moduli.pdv) na: predračun, otpremnica, garantni list, prodaja_stampa - Modal za preuzimanje: jedna cena (sa/bez PDV), ne duplo - Javna status stranica: PDV uslovi za cene, predlog, checkbox-ove - Svi print templejti: viewport=device-width+min-width, bez responsive - JavniToken generisan za postojeće naloge bez tokena (QR popravka) - UkupnoSaPdv() metode na ServisniRad i ServisniDeoSaArtiklom - UkupnoBezPdv() na StavkaProdaje
148 lines
5.0 KiB
Go
148 lines
5.0 KiB
Go
package sqlite
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
"ntech/internal/model"
|
|
)
|
|
|
|
// ServisniRadoviRepo je SQLite implementacija db.ServisniRadoviRepository
|
|
type ServisniRadoviRepo struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
// NoviServisniRadoviRepo kreira repozitorijum radova nad datom bazom
|
|
func NoviServisniRadoviRepo(baza *sql.DB) *ServisniRadoviRepo {
|
|
return &ServisniRadoviRepo{db: baza}
|
|
}
|
|
|
|
// 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 sr.id, sr.nalog_id, COALESCE(sr.usluga_id, 0), sr.naziv, sr.kolicina, sr.cena_komada, sr.datum, sr.predlozeno,
|
|
COALESCE(u.sifra, ''), COALESCE(u.pdv_stopa, 20.0)
|
|
FROM servis_radovi sr
|
|
LEFT JOIN usluge u ON u.id = sr.usluga_id
|
|
WHERE sr.nalog_id = ? ORDER BY sr.id`, nalogID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ntech: ServisniRadoviRepo.DohvatiZaNalog: %w", err)
|
|
}
|
|
defer redovi.Close()
|
|
|
|
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, &rad.Predlozeno, &rad.Sifra, &rad.PdvStopa); err != nil {
|
|
return nil, fmt.Errorf("ntech: ServisniRadoviRepo.DohvatiZaNalog: %w", err)
|
|
}
|
|
rad.CenaSaPdv = rad.CenaKomada * (1 + rad.PdvStopa/100)
|
|
radovi = append(radovi, rad)
|
|
}
|
|
return radovi, redovi.Err()
|
|
}
|
|
|
|
// 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, predlozeno)
|
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
nalogID, uid, naziv, kolicina, cenaKomada, predInt,
|
|
)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("ntech: ServisniRadoviRepo.Dodaj: %w", err)
|
|
}
|
|
id, err := rez.LastInsertId()
|
|
if err != nil {
|
|
return 0, fmt.Errorf("ntech: ServisniRadoviRepo.Dodaj: last insert id: %w", err)
|
|
}
|
|
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
|
|
}
|
|
|
|
// 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 {
|
|
return fmt.Errorf("ntech: ServisniRadoviRepo.Obrisi: %w", err)
|
|
}
|
|
return nil
|
|
}
|