refactor(log): prelazak sa log na log/slog (strukturisano logovanje)
Uveden podrazumevani slog logger u main.go (podesiLog): JSON u produkciji, tekst u razvoju, nivo Info. Svih ~70 poziva log.Printf/Println/Fatalf zamenjeno slog.Error/Warn/Info: greška se prosleđuje kao atribut "error", informativne vrednosti kao imenovani atributi (port, broj, putanja...), Fatalf -> Error + os.Exit(1). Upozorenja (inicijalizacija/čišćenje dozvola, migracija kolone) idu kao slog.Warn. Auth log (internal/auth/log.go) namerno NIJE diran — ostaje zaseban *log.Logger u fail2ban formatu. (slog.SetDefault usput preusmerava i standardni log paket.)
This commit is contained in:
+32
-18
@@ -7,7 +7,7 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"mime"
|
||||
@@ -31,10 +31,24 @@ import (
|
||||
// Verzija se postavlja pri produkcijskom buildu: go build -ldflags "-X main.Verzija=1.2.0"
|
||||
var Verzija = "dev"
|
||||
|
||||
// podesiLog postavlja podrazumevani slog logger: JSON u produkciji (za mašinsku
|
||||
// obradu logova), tekst u razvoju (čitljivije). Nivo je Info.
|
||||
func podesiLog() {
|
||||
opcije := &slog.HandlerOptions{Level: slog.LevelInfo}
|
||||
var handler slog.Handler
|
||||
if os.Getenv("NTECH_ENV") == "production" {
|
||||
handler = slog.NewJSONHandler(os.Stdout, opcije)
|
||||
} else {
|
||||
handler = slog.NewTextHandler(os.Stdout, opcije)
|
||||
}
|
||||
slog.SetDefault(slog.New(handler))
|
||||
}
|
||||
|
||||
func main() {
|
||||
mime.AddExtensionType(".js", "text/javascript")
|
||||
mime.AddExtensionType(".css", "text/css")
|
||||
godotenv.Load("ntech.env")
|
||||
podesiLog()
|
||||
auth.InitAuthLog()
|
||||
|
||||
// disk-first logika: ako folder postoji pored binarnog fajla — koristi disk, inače embed.
|
||||
@@ -73,38 +87,38 @@ func main() {
|
||||
|
||||
db, err := sqlite.OtvoriDB(putanjaBaze)
|
||||
if err != nil {
|
||||
log.Fatalf("Greška pri otvaranju baze: %v", err)
|
||||
slog.Error("Greška pri otvaranju baze", "error", err); os.Exit(1)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := sqlite.PokreniMigracije(db, migrFS); err != nil {
|
||||
log.Fatalf("Greška pri migracijama: %v", err)
|
||||
slog.Error("Greška pri migracijama", "error", err); os.Exit(1)
|
||||
}
|
||||
log.Println("Migracije uspešno izvršene")
|
||||
slog.Info("migracije uspešno izvršene")
|
||||
|
||||
// popuni tabelu dozvola podrazumevanim vrednostima ako je prazna
|
||||
if err := sqlite.InicijalizujDozvole(context.Background(), db, ntechmw.ImaDozvolu, ntechmw.SveAkcije()); err != nil {
|
||||
log.Printf("Upozorenje: greška pri inicijalizaciji dozvola: %v", err)
|
||||
slog.Warn("greška pri inicijalizaciji dozvola", "error", err)
|
||||
}
|
||||
|
||||
// ukloni zastarele dozvole (siročiće) koje više ne postoje u kodu
|
||||
if br, err := sqlite.OcistiSirociceDoz(context.Background(), db, ntechmw.SveAkcije()); err != nil {
|
||||
log.Printf("Upozorenje: greška pri čišćenju dozvola: %v", err)
|
||||
slog.Warn("greška pri čišćenju dozvola", "error", err)
|
||||
} else if br > 0 {
|
||||
log.Printf("Dozvole: uklonjeno %d zastarelih redova", br)
|
||||
slog.Info("uklonjene zastarele dozvole", "broj", br)
|
||||
}
|
||||
|
||||
// ključ za šifrovanje TOTP tajni u mirovanju (AES-256-GCM)
|
||||
totpKljuc, err := ucitajTotpKljuc()
|
||||
if err != nil {
|
||||
log.Fatalf("Greška pri učitavanju ključa za TOTP: %v", err)
|
||||
slog.Error("Greška pri učitavanju ključa za TOTP", "error", err); os.Exit(1)
|
||||
}
|
||||
|
||||
// jednokratno šifruj eventualne stare TOTP tajne koje su ostale kao čist tekst
|
||||
if br, err := sqlite.ZasifrujPostojeceTotp(context.Background(), db, totpKljuc); err != nil {
|
||||
log.Printf("Upozorenje: greška pri šifrovanju postojećih TOTP tajni: %v", err)
|
||||
slog.Warn("greška pri šifrovanju postojećih TOTP tajni", "error", err)
|
||||
} else if br > 0 {
|
||||
log.Printf("TOTP: šifrovano %d postojećih tajni", br)
|
||||
slog.Info("šifrovane postojeće TOTP tajne", "broj", br)
|
||||
}
|
||||
|
||||
napraviBackup(db, putanjaBaze)
|
||||
@@ -123,10 +137,10 @@ func main() {
|
||||
if os.Getenv("NTECH_ENV") == "production" {
|
||||
kes, err := handler.KreirajKes(templFS)
|
||||
if err != nil {
|
||||
log.Fatalf("Greška pri kreiranju keša šablona: %v", err)
|
||||
slog.Error("Greška pri kreiranju keša šablona", "error", err); os.Exit(1)
|
||||
}
|
||||
h.Templates = kes
|
||||
log.Printf("Keš šablona kreiran: %d šablona", len(kes))
|
||||
slog.Info("keš šablona kreiran", "broj", len(kes))
|
||||
}
|
||||
|
||||
// Pozadinske gorutine se pokreću posle kreiranja h i rade preko h.SaBazom,
|
||||
@@ -309,10 +323,10 @@ func main() {
|
||||
r.With(doz("tema.lokalno")).Post("/profil/pozadina/stilovi", h.ProfilSacuvajPozadinuStilove)
|
||||
})
|
||||
|
||||
log.Printf("NTech pokrenut na portu %s", port)
|
||||
slog.Info("NTech pokrenut", "port", port)
|
||||
err = http.ListenAndServe(":"+port, r)
|
||||
if err != nil {
|
||||
log.Fatalf("Greška: port %s je zauzet ili nije dostupan", port)
|
||||
slog.Error("port je zauzet ili nije dostupan", "port", port); os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,7 +364,7 @@ func ucitajTotpKljuc() ([]byte, error) {
|
||||
return nil, fmt.Errorf("upis ključa u ntech.env: %w", err)
|
||||
}
|
||||
os.Setenv("NTECH_TOTP_KEY", enkodiran)
|
||||
log.Println("Generisan nov NTECH_TOTP_KEY i upisan u ntech.env")
|
||||
slog.Info("generisan nov NTECH_TOTP_KEY i upisan u ntech.env")
|
||||
return kljuc, nil
|
||||
}
|
||||
|
||||
@@ -363,7 +377,7 @@ func napraviBackup(db *sql.DB, putanjaBaze string) {
|
||||
|
||||
folder := "backups"
|
||||
if err := os.MkdirAll(folder, 0755); err != nil {
|
||||
log.Printf("backup: ne mogu kreirati folder: %v", err)
|
||||
slog.Error("backup: ne mogu kreirati folder", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -371,11 +385,11 @@ func napraviBackup(db *sql.DB, putanjaBaze string) {
|
||||
odrediste := filepath.Join(folder, ime)
|
||||
|
||||
if _, err := db.ExecContext(context.Background(), "VACUUM INTO ?", odrediste); err != nil {
|
||||
log.Printf("backup: greška pri pravljenju backup-a: %v", err)
|
||||
slog.Error("backup: greška pri pravljenju backup-a", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Backup kreiran: %s", odrediste)
|
||||
slog.Info("backup kreiran", "putanja", odrediste)
|
||||
ocistiStareBackupe(folder, procitajIntPodesavanje(db, "backup_broj_kopija", 7))
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -48,7 +49,7 @@ func nadjiLokalneAdrese() []string {
|
||||
func PokreniSetup(fsys fs.FS) {
|
||||
port := NadjiSlobodanPort()
|
||||
if port == 0 {
|
||||
log.Fatal("ntech: setup: nije pronađen nijedan slobodan port")
|
||||
slog.Error("setup: nije pronađen nijedan slobodan port"); os.Exit(1)
|
||||
}
|
||||
|
||||
gotov := make(chan struct{})
|
||||
@@ -102,7 +103,7 @@ func PokreniSetup(fsys fs.FS) {
|
||||
|
||||
go func() {
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("ntech: setup server: %v", err)
|
||||
slog.Error("setup server", "error", err); os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -87,7 +87,7 @@ func PokreniMigracije(db *sql.DB, fsys fs.FS) error {
|
||||
// "duplicate column name" znači da kolona već postoji — željeno stanje je ispunjeno,
|
||||
// pa nastavljamo i beležimo migraciju kao izvršenu
|
||||
if strings.Contains(err.Error(), "duplicate column name") {
|
||||
log.Printf("Upozorenje: migration %s: kolona već postoji, preskačemo", naziv)
|
||||
slog.Warn("migracija: kolona već postoji, preskačemo", "migracija", naziv)
|
||||
} else {
|
||||
return fmt.Errorf("ntech: PokreniMigracije: izvršavanje %s: %w", naziv, err)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -39,14 +39,14 @@ func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
||||
if err := h.DB.QueryRowContext(ctx,
|
||||
"SELECT COUNT(*) FROM artikli",
|
||||
).Scan(&brojArtikala); err != nil {
|
||||
log.Printf("dashboard: broj artikala: %v", err)
|
||||
slog.Error("dashboard: broj artikala", "error", err)
|
||||
}
|
||||
|
||||
if err := h.DB.QueryRowContext(ctx, `
|
||||
SELECT COUNT(*) FROM servisni_nalozi
|
||||
WHERE status != 'Završeno'`,
|
||||
).Scan(&aktivniServisi); err != nil {
|
||||
log.Printf("dashboard: aktivni servisi: %v", err)
|
||||
slog.Error("dashboard: aktivni servisi", "error", err)
|
||||
}
|
||||
|
||||
// prihod se dohvata samo ako korisnik ima dozvolu dashboard.prihod
|
||||
@@ -56,14 +56,14 @@ func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
||||
SELECT COALESCE(SUM(ukupno), 0) FROM prodajni_nalozi
|
||||
WHERE substr(datum, 1, 7) = strftime('%Y-%m', 'now', 'localtime')`,
|
||||
).Scan(&prihodOvogMeseca); err != nil {
|
||||
log.Printf("dashboard: prihod ovog meseca: %v", err)
|
||||
slog.Error("dashboard: prihod ovog meseca", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.DB.QueryRowContext(ctx,
|
||||
"SELECT COUNT(*) FROM artikli WHERE kolicina <= kolicina_min",
|
||||
).Scan(&kriticnaZaliha); err != nil {
|
||||
log.Printf("dashboard: kriticna zaliha: %v", err)
|
||||
slog.Error("dashboard: kriticna zaliha", "error", err)
|
||||
}
|
||||
|
||||
korisnikFilter := appdb.PodsetnikFilter{}
|
||||
@@ -71,7 +71,7 @@ func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
||||
korisnikFilter.KorisnikID = &korisnikDash.ID
|
||||
}
|
||||
if n, err := h.PodsetnikRepo.BrojAktivnih(ctx, korisnikFilter); err != nil {
|
||||
log.Printf("dashboard: aktivni podsetnici: %v", err)
|
||||
slog.Error("dashboard: aktivni podsetnici", "error", err)
|
||||
} else {
|
||||
aktivniPodsetnici = n
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
||||
SELECT uredjaj, status, datum_prijema FROM servisni_nalozi
|
||||
ORDER BY datum_prijema DESC LIMIT 5`)
|
||||
if err != nil {
|
||||
log.Printf("dashboard: poslednji servisi: %v", err)
|
||||
slog.Error("dashboard: poslednji servisi", "error", err)
|
||||
}
|
||||
|
||||
var poslednjiServisi []model.StavkaServisa
|
||||
@@ -104,7 +104,7 @@ func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
||||
WHERE kolicina <= kolicina_min
|
||||
ORDER BY kolicina ASC LIMIT 5`)
|
||||
if err != nil {
|
||||
log.Printf("dashboard: kriticne zalihe: %v", err)
|
||||
slog.Error("dashboard: kriticne zalihe", "error", err)
|
||||
}
|
||||
|
||||
var kriticneZalihe []model.StavkaZalihe
|
||||
@@ -132,7 +132,7 @@ func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
||||
LEFT JOIN klijent_prikaz kp ON kp.id = pn.klijent_id
|
||||
ORDER BY pn.datum DESC LIMIT 5`)
|
||||
if err != nil {
|
||||
log.Printf("dashboard: poslednje prodaje: %v", err)
|
||||
slog.Error("dashboard: poslednje prodaje", "error", err)
|
||||
}
|
||||
|
||||
var poslednjeProdaje []model.StavkaProdajePregled
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -92,7 +92,7 @@ func (h *Handler) Izvestaji(w http.ResponseWriter, r *http.Request) {
|
||||
WHERE substr(datum, 1, 10) >= date('now', '-11 months', 'start of month')
|
||||
GROUP BY substr(datum, 1, 7)`)
|
||||
if err != nil {
|
||||
log.Printf("izvestaji: prihod prodaja: %v", err)
|
||||
slog.Error("izvestaji: prihod prodaja", "error", err)
|
||||
} else {
|
||||
defer prodajaRed.Close()
|
||||
for prodajaRed.Next() {
|
||||
@@ -113,7 +113,7 @@ func (h *Handler) Izvestaji(w http.ResponseWriter, r *http.Request) {
|
||||
AND substr(datum_zavrsetka, 1, 10) >= date('now', '-11 months', 'start of month')
|
||||
GROUP BY substr(datum_zavrsetka, 1, 7)`)
|
||||
if err != nil {
|
||||
log.Printf("izvestaji: prihod servis: %v", err)
|
||||
slog.Error("izvestaji: prihod servis", "error", err)
|
||||
} else {
|
||||
defer servisRed.Close()
|
||||
for servisRed.Next() {
|
||||
@@ -171,7 +171,7 @@ func (h *Handler) Izvestaji(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var stariNalozi []StariNalog
|
||||
if err != nil {
|
||||
log.Printf("izvestaji: stari nalozi: %v", err)
|
||||
slog.Error("izvestaji: stari nalozi", "error", err)
|
||||
} else {
|
||||
defer stariRed.Close()
|
||||
for stariRed.Next() {
|
||||
@@ -197,7 +197,7 @@ func (h *Handler) Izvestaji(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var topArtikli []TopArtikal
|
||||
if err != nil {
|
||||
log.Printf("izvestaji: top artikli: %v", err)
|
||||
slog.Error("izvestaji: top artikli", "error", err)
|
||||
} else {
|
||||
defer artRed.Close()
|
||||
for artRed.Next() {
|
||||
@@ -231,7 +231,7 @@ func (h *Handler) Izvestaji(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var topKlijenti []TopKlijent
|
||||
if err != nil {
|
||||
log.Printf("izvestaji: top klijenti: %v", err)
|
||||
slog.Error("izvestaji: top klijenti", "error", err)
|
||||
} else {
|
||||
defer klijRed.Close()
|
||||
for klijRed.Next() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -90,7 +90,7 @@ func (h *Handler) renderujTemplate(w http.ResponseWriter, ime string, podaci any
|
||||
if h.Templates != nil {
|
||||
t, ok := h.Templates[ime]
|
||||
if !ok {
|
||||
log.Printf("kes: šablon '%s' nije pronađen", ime)
|
||||
slog.Error("šablon nije pronađen", "ime", ime)
|
||||
http.Error(w, "Greška pri učitavanju stranice", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -101,14 +101,14 @@ func (h *Handler) renderujTemplate(w http.ResponseWriter, ime string, podaci any
|
||||
fajlovi = append(fajlovi, "web/templates/stranice/"+ime+".html")
|
||||
var err error
|
||||
if tmpl, err = template.New(ime).Funcs(sablonskeFunkcije).ParseFS(h.TemplatesFS, fajlovi...); err != nil {
|
||||
log.Printf("greška pri parsiranju šablona %s: %v", ime, err)
|
||||
slog.Error("greška pri parsiranju šablona", "ime", ime, "error", err)
|
||||
http.Error(w, "Greška pri učitavanju stranice", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := tmpl.ExecuteTemplate(w, "base", podaci); err != nil {
|
||||
log.Printf("greška pri renderovanju šablona %s: %v", ime, err)
|
||||
slog.Error("greška pri renderovanju šablona", "ime", ime, "error", err)
|
||||
http.Error(w, "Greška pri prikazu stranice", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (h *Handler) renderujStandalone(w http.ResponseWriter, ime string, podaci a
|
||||
if h.Templates != nil {
|
||||
t, ok := h.Templates[ime]
|
||||
if !ok {
|
||||
log.Printf("kes: standalone šablon '%s' nije pronađen", ime)
|
||||
slog.Error("standalone šablon nije pronađen", "ime", ime)
|
||||
http.Error(w, "Greška pri učitavanju stranice", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -128,14 +128,14 @@ func (h *Handler) renderujStandalone(w http.ResponseWriter, ime string, podaci a
|
||||
} else {
|
||||
var err error
|
||||
if tmpl, err = template.ParseFS(h.TemplatesFS, "web/templates/stranice/"+ime+".html"); err != nil {
|
||||
log.Printf("greška pri parsiranju šablona %s: %v", ime, err)
|
||||
slog.Error("greška pri parsiranju šablona", "ime", ime, "error", err)
|
||||
http.Error(w, "Greška pri učitavanju stranice", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := tmpl.Execute(w, podaci); err != nil {
|
||||
log.Printf("greška pri renderovanju šablona %s: %v", ime, err)
|
||||
slog.Error("greška pri renderovanju šablona", "ime", ime, "error", err)
|
||||
http.Error(w, "Greška pri prikazu stranice", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -101,7 +101,7 @@ func (h *Handler) SacuvajKlijenta(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if _, err := h.KlijentiRepo.Kreiraj(r.Context(), &klijent); err != nil {
|
||||
log.Printf("greška pri čuvanju klijenta: %v", err)
|
||||
slog.Error("greška pri čuvanju klijenta", "error", err)
|
||||
podesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
|
||||
ps := h.popuniPodaciStranice(r, podesavanja)
|
||||
ps.Stranica = "klijenti"
|
||||
@@ -182,7 +182,7 @@ func (h *Handler) SacuvajIzmenuKlijenta(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
klijent.ID = id
|
||||
if err := h.KlijentiRepo.Izmeni(r.Context(), &klijent); err != nil {
|
||||
log.Printf("greška pri čuvanju izmene klijenta: %v", err)
|
||||
slog.Error("greška pri čuvanju izmene klijenta", "error", err)
|
||||
podesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
|
||||
ps := h.popuniPodaciStranice(r, podesavanja)
|
||||
ps.Stranica = "klijenti"
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -155,14 +155,14 @@ func (h *Handler) VratiBackup(w http.ResponseWriter, r *http.Request) {
|
||||
// pre obnove, sačuvaj trenutno stanje baze
|
||||
sigurnosni := filepath.Join("backups", fmt.Sprintf("ntech_%s_pred_vracanjem.db", time.Now().Format("20060102_150405")))
|
||||
if _, err := h.DB.ExecContext(r.Context(), "VACUUM INTO ?", sigurnosni); err != nil {
|
||||
log.Printf("vrati backup: greška pri kreiranju sigurnosne kopije: %v", err)
|
||||
slog.Error("vrati backup: greška pri kreiranju sigurnosne kopije", "error", err)
|
||||
http.Redirect(w, r, "/podesavanja?backup_greska=Greška+pri+kreiranju+sigurnosne+kopije", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// isprazni WAL u glavni fajl
|
||||
if _, err := h.DB.ExecContext(r.Context(), "PRAGMA wal_checkpoint(TRUNCATE)"); err != nil {
|
||||
log.Printf("vrati backup: wal_checkpoint greška: %v", err)
|
||||
slog.Error("vrati backup: wal_checkpoint greška", "error", err)
|
||||
}
|
||||
|
||||
// Sama zamena baze (zatvaranje stare, kopiranje, otvaranje nove) radi se u
|
||||
@@ -178,10 +178,10 @@ func (h *Handler) VratiBackup(w http.ResponseWriter, r *http.Request) {
|
||||
defer h.mu.Unlock()
|
||||
|
||||
if err := h.DB.Close(); err != nil {
|
||||
log.Printf("vrati backup: greška pri zatvaranju baze: %v", err)
|
||||
slog.Error("vrati backup: greška pri zatvaranju baze", "error", err)
|
||||
}
|
||||
if err := kopiraFajl(putanjaBackupa, h.PutanjaBaze); err != nil {
|
||||
log.Printf("vrati backup: greška pri kopiranju (baza je zatvorena, potreban restart): %v", err)
|
||||
slog.Error("vrati backup: greška pri kopiranju (baza je zatvorena, potreban restart)", "error", err)
|
||||
return
|
||||
}
|
||||
os.Remove(h.PutanjaBaze + "-wal")
|
||||
@@ -189,11 +189,11 @@ func (h *Handler) VratiBackup(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
novaDB, err := ntechsqlite.OtvoriDB(h.PutanjaBaze)
|
||||
if err != nil {
|
||||
log.Printf("vrati backup: greška pri otvaranju nove baze (potreban restart): %v", err)
|
||||
slog.Error("vrati backup: greška pri otvaranju nove baze (potreban restart)", "error", err)
|
||||
return
|
||||
}
|
||||
h.reinicijalizujRepozitorijume(novaDB)
|
||||
log.Printf("Baza uspešno obnovljena iz: %s", ime)
|
||||
slog.Info("baza uspešno obnovljena", "izvor", ime)
|
||||
}()
|
||||
|
||||
http.Redirect(w, r, "/podesavanja?sacuvano=vraceno", http.StatusSeeOther)
|
||||
@@ -364,14 +364,14 @@ func (h *Handler) OtpremiLogo(w http.ResponseWriter, r *http.Request) {
|
||||
odrediste := "web/static/uploads/logo" + ext
|
||||
dst, err := os.Create(odrediste)
|
||||
if err != nil {
|
||||
log.Printf("upload loga: ne mogu kreirati fajl: %v", err)
|
||||
slog.Error("upload loga: ne mogu kreirati fajl", "error", err)
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+čuvanju+fajla", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, fajl); err != nil {
|
||||
log.Printf("upload loga: greška pri kopiranju: %v", err)
|
||||
slog.Error("upload loga: greška pri kopiranju", "error", err)
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+čuvanju+fajla", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
@@ -379,7 +379,7 @@ func (h *Handler) OtpremiLogo(w http.ResponseWriter, r *http.Request) {
|
||||
// timestamp u URL-u sprečava browser da koristi staru keširanu sliku
|
||||
putanja := fmt.Sprintf("/static/uploads/logo%s?v=%d", ext, time.Now().Unix())
|
||||
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "logo_putanja", putanja); err != nil {
|
||||
log.Printf("upload loga: greška pri čuvanju putanje: %v", err)
|
||||
slog.Error("upload loga: greška pri čuvanju putanje", "error", err)
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+čuvanju+podešavanja", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
@@ -463,7 +463,7 @@ func (h *Handler) OtpremiLoginPozadinu(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
novoIme, err := generisiImeUploada(ext)
|
||||
if err != nil {
|
||||
log.Printf("upload login pozadine: greška pri generisanju imena: %v", err)
|
||||
slog.Error("upload login pozadine: greška pri generisanju imena", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju fajla.")
|
||||
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
|
||||
return
|
||||
@@ -472,7 +472,7 @@ func (h *Handler) OtpremiLoginPozadinu(w http.ResponseWriter, r *http.Request) {
|
||||
odrediste := filepath.Join("web/static/uploads", novoIme)
|
||||
dst, err := os.Create(odrediste)
|
||||
if err != nil {
|
||||
log.Printf("upload login pozadine: ne mogu kreirati fajl: %v", err)
|
||||
slog.Error("upload login pozadine: ne mogu kreirati fajl", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju fajla.")
|
||||
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
|
||||
return
|
||||
@@ -480,7 +480,7 @@ func (h *Handler) OtpremiLoginPozadinu(w http.ResponseWriter, r *http.Request) {
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, fajl); err != nil {
|
||||
log.Printf("upload login pozadine: greška pri kopiranju: %v", err)
|
||||
slog.Error("upload login pozadine: greška pri kopiranju", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju fajla.")
|
||||
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
|
||||
return
|
||||
@@ -488,7 +488,7 @@ func (h *Handler) OtpremiLoginPozadinu(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
putanja := fmt.Sprintf("/static/uploads/%s?v=%d", novoIme, time.Now().Unix())
|
||||
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "login_pozadina", putanja); err != nil {
|
||||
log.Printf("upload login pozadine: greška pri čuvanju putanje: %v", err)
|
||||
slog.Error("upload login pozadine: greška pri čuvanju putanje", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.")
|
||||
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
|
||||
return
|
||||
@@ -514,7 +514,7 @@ func (h *Handler) UkloniLoginPozadinu(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "login_pozadina", ""); err != nil {
|
||||
log.Printf("ukloni login pozadinu: greška pri čuvanju: %v", err)
|
||||
slog.Error("ukloni login pozadinu: greška pri čuvanju", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri uklanjanju slike.")
|
||||
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
|
||||
return
|
||||
@@ -572,7 +572,7 @@ func (h *Handler) SacuvajLoginPozadinaStilove(w http.ResponseWriter, r *http.Req
|
||||
"login_pozadina_zatamnjenje_kartice": zatamnjenjeKarticeStr,
|
||||
} {
|
||||
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, kljuc, vrednost); err != nil {
|
||||
log.Printf("stilovi login pozadine: greška pri čuvanju %s: %v", kljuc, err)
|
||||
slog.Error("greška pri čuvanju stila login pozadine", "kljuc", kljuc, "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.")
|
||||
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
|
||||
return
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -116,7 +116,7 @@ func (h *Handler) SacuvajPodsetnik(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if _, err := h.PodsetnikRepo.Kreiraj(r.Context(), &podsetnik); err != nil {
|
||||
log.Printf("greška pri čuvanju podsetnika: %v", err)
|
||||
slog.Error("greška pri čuvanju podsetnika", "error", err)
|
||||
h.prikaziGreskuPodsetnika(w, r, k, podsetnik, "Došlo je do greške pri čuvanju. Pokušajte ponovo.", false)
|
||||
return
|
||||
}
|
||||
@@ -187,7 +187,7 @@ func (h *Handler) SacuvajIzmenePodsetnika(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
if err := h.PodsetnikRepo.Izmeni(r.Context(), &podsetnik); err != nil {
|
||||
log.Printf("greška pri čuvanju izmene podsetnika: %v", err)
|
||||
slog.Error("greška pri čuvanju izmene podsetnika", "error", err)
|
||||
h.prikaziGreskuPodsetnika(w, r, k, podsetnik, "Došlo je do greške pri čuvanju. Pokušajte ponovo.", true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"html/template"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -171,7 +171,7 @@ func (h *Handler) SacuvajProdaju(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
brojNaloga, err := h.ProdajaRepo.SledeciBroj(r.Context())
|
||||
if err != nil {
|
||||
log.Printf("greška pri generisanju broja naloga: %v", err)
|
||||
slog.Error("greška pri generisanju broja naloga", "error", err)
|
||||
renderujGresku("Greška pri generisanju broja naloga.")
|
||||
return
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func (h *Handler) SacuvajProdaju(w http.ResponseWriter, r *http.Request) {
|
||||
if errors.As(err, &errStanje) {
|
||||
renderujGresku(errStanje.Error())
|
||||
} else {
|
||||
log.Printf("greška pri čuvanju prodaje: %v", err)
|
||||
slog.Error("greška pri čuvanju prodaje", "error", err)
|
||||
renderujGresku("Greška pri čuvanju prodajnog naloga.")
|
||||
}
|
||||
return
|
||||
@@ -403,7 +403,7 @@ func (h *Handler) StornoProdaje(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
razlog := strings.TrimSpace(r.FormValue("razlog"))
|
||||
if err := h.ProdajaRepo.Storno(r.Context(), id, razlog, &k.ID); err != nil {
|
||||
log.Printf("greška pri storniranju naloga: %v", err)
|
||||
slog.Error("greška pri storniranju naloga", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri storniranju. Možda je nalog već storniran.")
|
||||
http.Redirect(w, r, "/prodaja/"+strconv.FormatInt(id, 10), http.StatusSeeOther)
|
||||
return
|
||||
|
||||
@@ -3,7 +3,7 @@ package handler
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -132,7 +132,7 @@ func (h *Handler) ProfilOtpremiPozadinu(w http.ResponseWriter, r *http.Request)
|
||||
odrediste := filepath.Join("web/static/uploads", novoIme)
|
||||
dst, err := os.Create(odrediste)
|
||||
if err != nil {
|
||||
log.Printf("ProfilOtpremiPozadinu: ne mogu kreirati fajl: %v", err)
|
||||
slog.Error("ProfilOtpremiPozadinu: ne mogu kreirati fajl", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju fajla.")
|
||||
http.Redirect(w, r, "/profil/tema", http.StatusSeeOther)
|
||||
return
|
||||
@@ -140,7 +140,7 @@ func (h *Handler) ProfilOtpremiPozadinu(w http.ResponseWriter, r *http.Request)
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, fajl); err != nil {
|
||||
log.Printf("ProfilOtpremiPozadinu: greška pri kopiranju: %v", err)
|
||||
slog.Error("ProfilOtpremiPozadinu: greška pri kopiranju", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju fajla.")
|
||||
http.Redirect(w, r, "/profil/tema", http.StatusSeeOther)
|
||||
return
|
||||
@@ -168,7 +168,7 @@ func (h *Handler) ProfilOtpremiPozadinu(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
if err := h.KorisniciRepo.SacuvajLokalnuPozadinu(r.Context(), k.ID, putanja, opacity, blur, blurPozadine, glassOpacity); err != nil {
|
||||
log.Printf("ProfilOtpremiPozadinu: greška pri čuvanju: %v", err)
|
||||
slog.Error("ProfilOtpremiPozadinu: greška pri čuvanju", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.")
|
||||
http.Redirect(w, r, "/profil/tema", http.StatusSeeOther)
|
||||
return
|
||||
@@ -193,7 +193,7 @@ func (h *Handler) ProfilUkloniPozadinu(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err := h.KorisniciRepo.SacuvajLokalnuPozadinu(r.Context(), k.ID, "", "50", "12", "0", "10"); err != nil {
|
||||
log.Printf("ProfilUkloniPozadinu: %v", err)
|
||||
slog.Error("ProfilUkloniPozadinu", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri uklanjanju slike.")
|
||||
http.Redirect(w, r, "/profil/tema", http.StatusSeeOther)
|
||||
return
|
||||
@@ -241,7 +241,7 @@ func (h *Handler) ProfilSacuvajPozadinuStilove(w http.ResponseWriter, r *http.Re
|
||||
}
|
||||
|
||||
if err := h.KorisniciRepo.SacuvajLokalnuPozadinu(r.Context(), k.ID, pozadina, opacity, blur, blurPozadineSt, glassOpacitySt); err != nil {
|
||||
log.Printf("ProfilSacuvajPozadinuStilove: %v", err)
|
||||
slog.Error("ProfilSacuvajPozadinuStilove", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.")
|
||||
http.Redirect(w, r, "/profil/tema", http.StatusSeeOther)
|
||||
return
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -152,7 +152,7 @@ func (h *Handler) SacuvajNalog(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
id, err := h.ServisRepo.Kreiraj(r.Context(), &nalog)
|
||||
if err != nil {
|
||||
log.Printf("greška pri čuvanju naloga: %v", err)
|
||||
slog.Error("greška pri čuvanju naloga", "error", err)
|
||||
podesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
|
||||
klijenti, _ := h.KlijentiRepo.Lista(r.Context(), "")
|
||||
tehnicari, _ := h.KorisniciRepo.Lista(r.Context())
|
||||
@@ -258,7 +258,7 @@ func (h *Handler) SacuvajIzmenaNaloga(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
nalog.ID = id
|
||||
if err := h.ServisRepo.Izmeni(r.Context(), &nalog); err != nil {
|
||||
log.Printf("greška pri čuvanju izmene naloga: %v", err)
|
||||
slog.Error("greška pri čuvanju izmene naloga", "error", err)
|
||||
podesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
|
||||
klijenti, _ := h.KlijentiRepo.Lista(r.Context(), "")
|
||||
tehnicari, _ := h.KorisniciRepo.Lista(r.Context())
|
||||
@@ -337,13 +337,13 @@ func (h *Handler) DetaljiNaloga(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
delovi, err := h.ServisniDeloviRepo.DohvatiZaNalog(r.Context(), id)
|
||||
if err != nil {
|
||||
log.Printf("greška pri učitavanju delova: %v", err)
|
||||
slog.Error("greška pri učitavanju delova", "error", err)
|
||||
}
|
||||
|
||||
appdb := appdbPkg.ArtikalFilter{}
|
||||
artikli, err := h.Artikli.Lista(r.Context(), appdb)
|
||||
if err != nil {
|
||||
log.Printf("greška pri učitavanju artikala: %v", err)
|
||||
slog.Error("greška pri učitavanju artikala", "error", err)
|
||||
}
|
||||
|
||||
ps := h.popuniPodaciStranice(r, podesavanja)
|
||||
@@ -402,7 +402,7 @@ func (h *Handler) DodajDeloNalogu(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if _, err := h.ServisniDeloviRepo.Dodaj(r.Context(), nalogID, artikalID, kolicina, cena, &k.ID); err != nil {
|
||||
log.Printf("greška pri dodavanju dela: %v", err)
|
||||
slog.Error("greška pri dodavanju dela", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri dodavanju dela. Proverite stanje na magacinu.")
|
||||
http.Redirect(w, r, "/servis/"+strconv.FormatInt(nalogID, 10), http.StatusSeeOther)
|
||||
return
|
||||
@@ -432,7 +432,7 @@ func (h *Handler) ObrisiDeloNaloga(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err := h.ServisniDeloviRepo.Obrisi(r.Context(), deoID, &k.ID); err != nil {
|
||||
log.Printf("greška pri brisanju dela: %v", err)
|
||||
slog.Error("greška pri brisanju dela", "error", err)
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri uklanjanju dela.")
|
||||
} else {
|
||||
middleware.SetFlash(w, r, h.DB, "uspeh", "Deo je uklonjen.")
|
||||
|
||||
Reference in New Issue
Block a user