Compare commits
5
Commits
99ae077082
...
21e79055e9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21e79055e9
|
||
|
|
19d88901c3
|
||
|
|
4ea411996f
|
||
|
|
0df0ea2876
|
||
|
|
f1acee98e8
|
@@ -151,8 +151,8 @@ type NabavkaRepository interface {
|
|||||||
DohvatiID(ctx context.Context, id int64) (*model.Nabavka, error)
|
DohvatiID(ctx context.Context, id int64) (*model.Nabavka, error)
|
||||||
DohvatiStavke(ctx context.Context, nabavkaID int64) ([]model.StavkaSaArtiklom, error)
|
DohvatiStavke(ctx context.Context, nabavkaID int64) ([]model.StavkaSaArtiklom, error)
|
||||||
DohvatiTroskove(ctx context.Context, nabavkaID int64) ([]model.NabavkaTrosak, error)
|
DohvatiTroskove(ctx context.Context, nabavkaID int64) ([]model.NabavkaTrosak, error)
|
||||||
Kreiraj(ctx context.Context, n *model.Nabavka, stavke []model.StavkaNabavke, troskovi []model.NabavkaTrosak) (int64, error)
|
Kreiraj(ctx context.Context, n *model.Nabavka, stavke []model.StavkaNabavke, troskovi []model.NabavkaTrosak, korisnikID *int64) (int64, error)
|
||||||
Obrisi(ctx context.Context, id int64) error
|
Obrisi(ctx context.Context, id int64, korisnikID *int64) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// DobavljacRepository definiše operacije nad dobavljačima
|
// DobavljacRepository definiše operacije nad dobavljačima
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ func (r *NabavkaRepo) DohvatiTroskove(ctx context.Context, nabavkaID int64) ([]m
|
|||||||
|
|
||||||
// Kreiraj upisuje novu nabavku sa svim stavkama i zavisnim troškovima u jednoj
|
// Kreiraj upisuje novu nabavku sa svim stavkama i zavisnim troškovima u jednoj
|
||||||
// transakciji i ažurira stanje magacina
|
// transakciji i ažurira stanje magacina
|
||||||
func (r *NabavkaRepo) Kreiraj(ctx context.Context, n *model.Nabavka, stavke []model.StavkaNabavke, troskovi []model.NabavkaTrosak) (int64, error) {
|
func (r *NabavkaRepo) Kreiraj(ctx context.Context, n *model.Nabavka, stavke []model.StavkaNabavke, troskovi []model.NabavkaTrosak, korisnikID *int64) (int64, error) {
|
||||||
tx, err := r.db.BeginTx(ctx, nil)
|
tx, err := r.db.BeginTx(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: begin: %w", err)
|
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: begin: %w", err)
|
||||||
@@ -193,13 +193,27 @@ func (r *NabavkaRepo) Kreiraj(ctx context.Context, n *model.Nabavka, stavke []mo
|
|||||||
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: insert stavka: %w", err)
|
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: insert stavka: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stanjePre int
|
||||||
|
err = tx.QueryRowContext(ctx,
|
||||||
|
"SELECT kolicina FROM artikli WHERE id = ?", s.ArtikalID,
|
||||||
|
).Scan(&stanjePre)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: dohvati stanje: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stanjePosle := stanjePre + s.Kolicina
|
||||||
_, err = tx.ExecContext(ctx,
|
_, err = tx.ExecContext(ctx,
|
||||||
"UPDATE artikli SET kolicina = kolicina + ? WHERE id = ?",
|
"UPDATE artikli SET kolicina = ? WHERE id = ?",
|
||||||
s.Kolicina, s.ArtikalID,
|
stanjePosle, s.ArtikalID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: update kolicina: %w", err)
|
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: update kolicina: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = zabeleziMagacinPromenu(ctx, tx, s.ArtikalID, model.PromenaUlazNabavka,
|
||||||
|
s.Kolicina, stanjePre, stanjePosle, nabavkaID, korisnikID, ""); err != nil {
|
||||||
|
return 0, fmt.Errorf("ntech: NabavkaRepo.Kreiraj: magacin: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
@@ -209,12 +223,64 @@ func (r *NabavkaRepo) Kreiraj(ctx context.Context, n *model.Nabavka, stavke []mo
|
|||||||
return nabavkaID, nil
|
return nabavkaID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obrisi briše nabavku po ID-u — stavke se brišu automatski (ON DELETE CASCADE)
|
// Obrisi briše nabavku po ID-u, vraća količine artikala na stanje i beleži korekciju u magacinski trag.
|
||||||
// Napomena: brisanje ne vraća količine artikala u magacin
|
func (r *NabavkaRepo) Obrisi(ctx context.Context, id int64, korisnikID *int64) error {
|
||||||
func (r *NabavkaRepo) Obrisi(ctx context.Context, id int64) error {
|
tx, err := r.db.BeginTx(ctx, nil)
|
||||||
_, err := r.db.ExecContext(ctx, "DELETE FROM nabavke WHERE id = ?", id)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: %w", err)
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: begin: %w", err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
// učitaj stavke pre brisanja (CASCADE ih briše zajedno sa nabavkom)
|
||||||
|
redovi, err := tx.QueryContext(ctx,
|
||||||
|
"SELECT artikal_id, kolicina FROM stavke_nabavke WHERE nabavka_id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: dohvati stavke: %w", err)
|
||||||
|
}
|
||||||
|
type stavka struct {
|
||||||
|
artikalID int64
|
||||||
|
kolicina int
|
||||||
|
}
|
||||||
|
var stavke []stavka
|
||||||
|
for redovi.Next() {
|
||||||
|
var s stavka
|
||||||
|
if err := redovi.Scan(&s.artikalID, &s.kolicina); err != nil {
|
||||||
|
redovi.Close()
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: scan stavka: %w", err)
|
||||||
|
}
|
||||||
|
stavke = append(stavke, s)
|
||||||
|
}
|
||||||
|
redovi.Close()
|
||||||
|
|
||||||
|
// vrati količine na stanje i zabeleži korekciju
|
||||||
|
for _, s := range stavke {
|
||||||
|
var stanjePre int
|
||||||
|
if err := tx.QueryRowContext(ctx,
|
||||||
|
"SELECT kolicina FROM artikli WHERE id = ?", s.artikalID,
|
||||||
|
).Scan(&stanjePre); err != nil {
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: dohvati stanje: %w", err)
|
||||||
|
}
|
||||||
|
stanjePosle := stanjePre - s.kolicina
|
||||||
|
if stanjePosle < 0 {
|
||||||
|
stanjePosle = 0
|
||||||
|
}
|
||||||
|
if _, err := tx.ExecContext(ctx,
|
||||||
|
"UPDATE artikli SET kolicina = ? WHERE id = ?", stanjePosle, s.artikalID,
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: update stanje: %w", err)
|
||||||
|
}
|
||||||
|
if err := zabeleziMagacinPromenu(ctx, tx, s.artikalID, model.PromenaKorekcija,
|
||||||
|
-s.kolicina, stanjePre, stanjePosle, id, korisnikID, "brisanje nabavke"); err != nil {
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: magacin: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := tx.ExecContext(ctx, "DELETE FROM nabavke WHERE id = ?", id); err != nil {
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: delete: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return fmt.Errorf("ntech: NabavkaRepo.Obrisi: commit: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,12 +207,12 @@ func (r *ProdajaRepo) Kreiraj(ctx context.Context, n *model.ProdajniNalog, stavk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PDV računamo iz cene ako nije eksplicitno postavljeno
|
// CenaPoKomadu je neto (bez PDV); PDV se dodaje naviše
|
||||||
cenaBezPdv := s.CenaBezPdv
|
cenaBezPdv := s.CenaBezPdv
|
||||||
pdvIznos := s.PdvIznos
|
pdvIznos := s.PdvIznos
|
||||||
if cenaBezPdv == 0 && s.PdvStopa > 0 {
|
if cenaBezPdv == 0 {
|
||||||
cenaBezPdv = s.CenaPoKomadu / (1 + s.PdvStopa/100)
|
cenaBezPdv = s.CenaPoKomadu
|
||||||
pdvIznos = s.CenaPoKomadu - cenaBezPdv
|
pdvIznos = cenaBezPdv * s.PdvStopa / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
ukupnoStavke := float64(s.Kolicina) * s.CenaPoKomadu
|
ukupnoStavke := float64(s.Kolicina) * s.CenaPoKomadu
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"ntech/internal/auth"
|
"ntech/internal/auth"
|
||||||
@@ -549,7 +550,9 @@ func (h *Handler) AdminTotpDeaktivacija(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// isključenjem 2FA brišemo i rezervne kodove
|
// isključenjem 2FA brišemo i rezervne kodove
|
||||||
_ = h.RezervniKodoviRepo.Obrisi(r.Context(), k.ID)
|
if err := h.RezervniKodoviRepo.Obrisi(r.Context(), k.ID); err != nil {
|
||||||
|
slog.Warn("brisanje rezervnih kodova nije uspelo", "korisnik_id", k.ID, "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/admin/profil?sacuvano=1", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/profil?sacuvano=1", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-5
@@ -58,13 +58,32 @@ var sablonskeFunkcije = template.FuncMap{
|
|||||||
return fmt.Sprintf("%d", int64(math.Round(*v)))
|
return fmt.Sprintf("%d", int64(math.Round(*v)))
|
||||||
},
|
},
|
||||||
// dinari formatira iznos sa separatorom hiljada (tačka) i 2 decimale (zarez):
|
// dinari formatira iznos sa separatorom hiljada (tačka) i 2 decimale (zarez):
|
||||||
// 1234567.5 → "1.234.567,50"
|
// 1234567.5 → "1.234.567,50"; prihvata float64 i int64
|
||||||
"dinari": func(v float64) string {
|
"dinari": func(v any) string {
|
||||||
return formatirajDinare(v, 2)
|
switch val := v.(type) {
|
||||||
|
case int64:
|
||||||
|
return formatirajDinare(float64(val), 2)
|
||||||
|
case int:
|
||||||
|
return formatirajDinare(float64(val), 2)
|
||||||
|
case float64:
|
||||||
|
return formatirajDinare(val, 2)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%v", v)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// dinariCeli formatira iznos sa separatorom hiljada, bez decimala: 1234567 → "1.234.567"
|
// dinariCeli formatira iznos sa separatorom hiljada, bez decimala: 1234567 → "1.234.567"
|
||||||
"dinariCeli": func(v float64) string {
|
// Prihvata float64 i int64 (PPPDV polja su int64).
|
||||||
return formatirajDinare(v, 0)
|
"dinariCeli": func(v any) string {
|
||||||
|
switch val := v.(type) {
|
||||||
|
case int64:
|
||||||
|
return formatirajDinare(float64(val), 0)
|
||||||
|
case int:
|
||||||
|
return formatirajDinare(float64(val), 0)
|
||||||
|
case float64:
|
||||||
|
return formatirajDinare(val, 0)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%v", v)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// telefon formatira srpski broj telefona radi lakšeg čitanja: "0641234567" → "064 123 4567"
|
// telefon formatira srpski broj telefona radi lakšeg čitanja: "0641234567" → "064 123 4567"
|
||||||
"telefon": formatirajTelefon,
|
"telefon": formatirajTelefon,
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ func (h *Handler) SacuvajNabavku(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := h.NabavkeRepo.Kreiraj(r.Context(), &nabavka, stavke, troskovi)
|
id, err := h.NabavkeRepo.Kreiraj(r.Context(), &nabavka, stavke, troskovi, &k.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Greška pri čuvanju nabavke", http.StatusInternalServerError)
|
http.Error(w, "Greška pri čuvanju nabavke", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -340,7 +340,8 @@ func (h *Handler) DetaljiNabavke(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// ObrisiNabavku prima POST zahtev i briše nabavku po ID-u
|
// ObrisiNabavku prima POST zahtev i briše nabavku po ID-u
|
||||||
func (h *Handler) ObrisiNabavku(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) ObrisiNabavku(w http.ResponseWriter, r *http.Request) {
|
||||||
if _, ok := h.zahtevajDozvolu(w, r, "nabavka.obrisi"); !ok {
|
k, ok := h.zahtevajDozvolu(w, r, "nabavka.obrisi")
|
||||||
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
id, err := parseID(chi.URLParam(r, "id"))
|
id, err := parseID(chi.URLParam(r, "id"))
|
||||||
@@ -349,7 +350,7 @@ func (h *Handler) ObrisiNabavku(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.NabavkeRepo.Obrisi(r.Context(), id); err != nil {
|
if err := h.NabavkeRepo.Obrisi(r.Context(), id, &k.ID); err != nil {
|
||||||
http.Error(w, "Greška pri brisanju nabavke", http.StatusInternalServerError)
|
http.Error(w, "Greška pri brisanju nabavke", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -944,10 +944,15 @@ func (h *Handler) TestFiskalizacije(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SSRF zaštita: dozvoljeni su samo localhost i privatne mreže (192.168.x.x,
|
// SSRF zaštita: dozvoljeni su samo localhost i privatne mreže (192.168.x.x,
|
||||||
// 10.x.x.x, 172.16-31.x.x, 127.x.x.x). Port izvlačimo kao integer da presečemo
|
// 10.x.x.x, 172.16-31.x.x, 127.x.x.x). URL rekonstruišemo kroz url.URL{}
|
||||||
// CodeQL taint lanac — broj ne može da sadrži URL manipulaciju.
|
// iz validiranih komponenti da CodeQL prepozna sanitizaciju.
|
||||||
parsedURL, err := url.Parse(pfrURL)
|
parsedURL, err := url.Parse(pfrURL)
|
||||||
if err != nil || !jePrivatnaAdresa(parsedURL.Hostname()) {
|
if err != nil {
|
||||||
|
http.Error(w, "Nevažeći PFR URL", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
host := parsedURL.Hostname()
|
||||||
|
if !jePrivatnaAdresa(host) {
|
||||||
http.Error(w, "Nevažeći PFR URL — dozvoljeni su samo lokalni/privatni hostovi (127.x, 192.168.x, 10.x, 172.16-31.x)", http.StatusBadRequest)
|
http.Error(w, "Nevažeći PFR URL — dozvoljeni su samo lokalni/privatni hostovi (127.x, 192.168.x, 10.x, 172.16-31.x)", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -957,7 +962,12 @@ func (h *Handler) TestFiskalizacije(w http.ResponseWriter, r *http.Request) {
|
|||||||
port = n
|
port = n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statusURL := fmt.Sprintf("http://%s:%d/api/status", parsedURL.Hostname(), port)
|
safeURL := url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: net.JoinHostPort(host, strconv.Itoa(port)),
|
||||||
|
Path: "/api/status",
|
||||||
|
}
|
||||||
|
statusURL := safeURL.String()
|
||||||
|
|
||||||
klijent := &http.Client{Timeout: 5 * time.Second}
|
klijent := &http.Client{Timeout: 5 * time.Second}
|
||||||
resp, err := klijent.Get(statusURL)
|
resp, err := klijent.Get(statusURL)
|
||||||
@@ -969,7 +979,11 @@ func (h *Handler) TestFiskalizacije(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var status map[string]any
|
var status map[string]any
|
||||||
_ = json.NewDecoder(resp.Body).Decode(&status)
|
if err := json.NewDecoder(resp.Body).Decode(&status); err != nil {
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
fmt.Fprintf(w, `<div class="fisk-status greska">✗ Neispravan odgovor servera — %s</div>`, html.EscapeString(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sdcDateTime, _ := status["sdcDateTime"].(string)
|
sdcDateTime, _ := status["sdcDateTime"].(string)
|
||||||
lastInvoice, _ := status["lastInvoiceNumber"].(string)
|
lastInvoice, _ := status["lastInvoiceNumber"].(string)
|
||||||
|
|||||||
+24
-11
@@ -2076,7 +2076,10 @@ func (h *Handler) PromeniStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = h.ServisRepo.SacuvajNaplatu(r.Context(), id, nacin, iznos)
|
if err := h.ServisRepo.SacuvajNaplatu(r.Context(), id, nacin, iznos); err != nil {
|
||||||
|
slog.Error("greška pri čuvanju naplate servisa", "id", id, "error", err)
|
||||||
|
middleware.SetFlash(w, r, h.DB, "greska", "Naplata nije sačuvana. Pokušajte ponovo.")
|
||||||
|
}
|
||||||
|
|
||||||
// fiskalizacija servisa — ako je modul uključen
|
// fiskalizacija servisa — ako je modul uključen
|
||||||
if h.modulUkljucen(r.Context(), config.ModulFiskalizacija) {
|
if h.modulUkljucen(r.Context(), config.ModulFiskalizacija) {
|
||||||
@@ -2145,8 +2148,16 @@ func (h *Handler) fiskalizujServis(ctx context.Context, servisID int64, klijent
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
radovi, _ := h.ServisniRadoviRepo.DohvatiZaNalog(ctx, servisID)
|
radovi, err := h.ServisniRadoviRepo.DohvatiZaNalog(ctx, servisID)
|
||||||
delovi, _ := h.deloviSaPotrazivanima(ctx, servisID)
|
if err != nil {
|
||||||
|
slog.Error("fiskalizujServis: greška pri dohvatanju radova", "id", servisID, "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delovi, err := h.deloviSaPotrazivanima(ctx, servisID)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("fiskalizujServis: greška pri dohvatanju delova", "id", servisID, "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// napravi stavke za fiskalni račun
|
// napravi stavke za fiskalni račun
|
||||||
items := make([]fiskal.InvoiceItem, 0)
|
items := make([]fiskal.InvoiceItem, 0)
|
||||||
@@ -2154,12 +2165,11 @@ func (h *Handler) fiskalizujServis(ctx context.Context, servisID int64, klijent
|
|||||||
if r.Predlozeno {
|
if r.Predlozeno {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stopa := 20.0 // podrazumevano — servisne usluge su 20% PDV
|
|
||||||
items = append(items, fiskal.InvoiceItem{
|
items = append(items, fiskal.InvoiceItem{
|
||||||
Name: r.Naziv,
|
Name: r.Naziv,
|
||||||
Labels: []string{fiskal.OznakaPDV(stopa)},
|
Labels: []string{fiskal.OznakaPDV(r.PdvStopa)},
|
||||||
TotalAmount: fiskal.BrutoCena(r.Ukupno(), stopa),
|
TotalAmount: fiskal.BrutoCena(r.Ukupno(), r.PdvStopa),
|
||||||
UnitPrice: fiskal.BrutoCena(r.CenaKomada, stopa),
|
UnitPrice: fiskal.BrutoCena(r.CenaKomada, r.PdvStopa),
|
||||||
Quantity: r.Kolicina,
|
Quantity: r.Kolicina,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -2167,15 +2177,18 @@ func (h *Handler) fiskalizujServis(ctx context.Context, servisID int64, klijent
|
|||||||
if d.Predlozeno {
|
if d.Predlozeno {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stopa := 20.0
|
|
||||||
items = append(items, fiskal.InvoiceItem{
|
items = append(items, fiskal.InvoiceItem{
|
||||||
Name: d.ArtikalNaziv,
|
Name: d.ArtikalNaziv,
|
||||||
Labels: []string{fiskal.OznakaPDV(stopa)},
|
Labels: []string{fiskal.OznakaPDV(d.PdvStopa)},
|
||||||
TotalAmount: fiskal.BrutoCena(d.Ukupno(), stopa),
|
TotalAmount: fiskal.BrutoCena(d.Ukupno(), d.PdvStopa),
|
||||||
UnitPrice: fiskal.BrutoCena(d.CenaKomada, stopa),
|
UnitPrice: fiskal.BrutoCena(d.CenaKomada, d.PdvStopa),
|
||||||
Quantity: float64(d.Kolicina),
|
Quantity: float64(d.Kolicina),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if len(items) == 0 {
|
||||||
|
slog.Warn("fiskalizujServis: nema stavki za fiskalni račun, zahtev odbačen", "id", servisID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
pib := ""
|
pib := ""
|
||||||
if nalog.KlijentID != nil {
|
if nalog.KlijentID != nil {
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ func (k *PdvKir) DodajNeto(osnovica, stopa float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// KirIzProdaje gradi KIR zapis iz prodaje: stavke se grupišu po PDV stopi
|
// KirIzProdaje gradi KIR zapis iz prodaje: stavke se grupišu po PDV stopi
|
||||||
// (20→opšta, 10→posebna, ostalo→oslobođeno). CenaPoKomadu je prodajna cena SA PDV,
|
// (20→opšta, 10→posebna, ostalo→oslobođeno). CenaPoKomadu je prodajna cena BEZ PDV
|
||||||
// pa se osnovica izvodi deljenjem sa (1 + stopa/100).
|
// (neto), PDV se dodaje naviše — isti obrazac kao kod servisnih radova/delova.
|
||||||
func KirIzProdaje(nalog ProdajniNalog, stavke []StavkaProdaje, kupacNaziv, kupacPib, kupacMesto string) PdvKir {
|
func KirIzProdaje(nalog ProdajniNalog, stavke []StavkaProdaje, kupacNaziv, kupacPib, kupacMesto string) PdvKir {
|
||||||
id := nalog.ID
|
id := nalog.ID
|
||||||
k := PdvKir{
|
k := PdvKir{
|
||||||
@@ -120,12 +120,7 @@ func KirIzProdaje(nalog ProdajniNalog, stavke []StavkaProdaje, kupacNaziv, kupac
|
|||||||
IzvorID: &id,
|
IzvorID: &id,
|
||||||
}
|
}
|
||||||
for _, s := range stavke {
|
for _, s := range stavke {
|
||||||
ukupnoLinija := float64(s.Kolicina) * s.CenaPoKomadu
|
k.DodajNeto(float64(s.Kolicina)*s.CenaPoKomadu, s.PdvStopa)
|
||||||
osnovica := ukupnoLinija
|
|
||||||
if s.PdvStopa > 0 {
|
|
||||||
osnovica = ukupnoLinija / (1 + s.PdvStopa/100)
|
|
||||||
}
|
|
||||||
k.dodajStavku(osnovica, ukupnoLinija-osnovica, s.PdvStopa)
|
|
||||||
}
|
}
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,3 +15,7 @@ type Usluga struct {
|
|||||||
Arhiviran bool
|
Arhiviran bool
|
||||||
DatumUnosa string
|
DatumUnosa string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u Usluga) CenaSaPdv() float64 {
|
||||||
|
return u.Cena * (1 + u.PdvStopa/100)
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
.firma-info { font-size: 12px; color: #64748b; margin-top: 4px; line-height: 1.6; }
|
.firma-info { font-size: 12px; color: #64748b; margin-top: 4px; line-height: 1.6; }
|
||||||
|
|
||||||
/* kartica */
|
/* kartica */
|
||||||
.kartica { background: #fff; margin: 12px 12px 0; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); overflow: hidden; }
|
.kartica { background: #fff; margin: 12px; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); overflow: hidden; }
|
||||||
.kartica-naslov { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.7px; color: #64748b; padding: 12px 16px 8px; border-bottom: 1px solid #f1f5f9; }
|
.kartica-naslov { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.7px; color: #64748b; padding: 12px 16px 8px; border-bottom: 1px solid #f1f5f9; }
|
||||||
|
|
||||||
/* red podataka */
|
/* red podataka */
|
||||||
|
|||||||
@@ -79,9 +79,13 @@
|
|||||||
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-jak);">Naziv</th>
|
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-jak);">Naziv</th>
|
||||||
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-jak);">Kategorija</th>
|
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-jak);">Kategorija</th>
|
||||||
<th style="padding:12px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-jak);">Količina</th>
|
<th style="padding:12px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-jak);">Količina</th>
|
||||||
|
{{if index .Moduli "pdv"}}
|
||||||
<th style="padding:12px 16px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-jak);cursor:pointer;white-space:nowrap;" id="cena-zaglavlje" onclick="toggleCenaPdv()">
|
<th style="padding:12px 16px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-jak);cursor:pointer;white-space:nowrap;" id="cena-zaglavlje" onclick="toggleCenaPdv()">
|
||||||
Cena <span id="cena-toggle" style="font-size:10px;color:var(--sb-akcent);">▾ bez PDV</span>
|
Cena <span id="cena-toggle" style="font-size:10px;color:var(--sb-akcent);">▾ bez PDV</span>
|
||||||
</th>
|
</th>
|
||||||
|
{{else}}
|
||||||
|
<th style="padding:12px 16px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-jak);">Cena</th>
|
||||||
|
{{end}}
|
||||||
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-jak);">Lokacija</th>
|
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-jak);">Lokacija</th>
|
||||||
<th style="padding:12px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-jak);">Akcije</th>
|
<th style="padding:12px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-jak);">Akcije</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -104,7 +108,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
<td style="padding:12px 16px;text-align:right;font-size:14px;color:var(--tekst-glavni);">
|
<td style="padding:12px 16px;text-align:right;font-size:14px;color:var(--tekst-glavni);">
|
||||||
<span class="cena-bez-pdv">{{dinari .ProdajnaCena}}</span><span class="cena-sa-pdv" style="display:none">{{dinari .CenaSaPdv}}</span> din
|
<span class="cena-bez-pdv">{{dinari .ProdajnaCena}}</span>{{if index $.Moduli "pdv"}}<span class="cena-sa-pdv" style="display:none">{{dinari .CenaSaPdv}}</span>{{end}} din
|
||||||
</td>
|
</td>
|
||||||
<td style="padding:12px 16px;font-size:13px;color:var(--tekst-sporedni);">
|
<td style="padding:12px 16px;font-size:13px;color:var(--tekst-sporedni);">
|
||||||
{{if .Lokacija}}{{.Lokacija}}{{else}}—{{end}}
|
{{if .Lokacija}}{{.Lokacija}}{{else}}—{{end}}
|
||||||
@@ -259,6 +263,7 @@ document.body.addEventListener('htmx:afterSwap', function (e) {
|
|||||||
rez.classList.remove('bez-anim');
|
rez.classList.remove('bez-anim');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{{if index .Moduli "pdv"}}
|
||||||
// toggle cena: bez PDV ↔ sa PDV
|
// toggle cena: bez PDV ↔ sa PDV
|
||||||
var cenaPdvRezim = false; // false = bez PDV
|
var cenaPdvRezim = false; // false = bez PDV
|
||||||
function toggleCenaPdv() {
|
function toggleCenaPdv() {
|
||||||
@@ -270,6 +275,7 @@ function toggleCenaPdv() {
|
|||||||
for (var j = 0; j < sa.length; j++) { sa[j].style.display = cenaPdvRezim ? '' : 'none'; }
|
for (var j = 0; j < sa.length; j++) { sa[j].style.display = cenaPdvRezim ? '' : 'none'; }
|
||||||
if (tgl) tgl.textContent = cenaPdvRezim ? '▾ sa PDV' : '▾ bez PDV';
|
if (tgl) tgl.textContent = cenaPdvRezim ? '▾ sa PDV' : '▾ bez PDV';
|
||||||
}
|
}
|
||||||
|
{{end}}
|
||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<!-- Magacin je isključivo za proizvode (prate lager); usluge i troškovi
|
<!-- Magacin je isključivo za proizvode (prate lager); usluge i troškovi
|
||||||
imaju svoje module, zato ovde tip više nije izbor -->
|
imaju svoje module, zato ovde tip više nije izbor -->
|
||||||
<input type="hidden" name="tip" value="proizvod">
|
<input type="hidden" name="tip" value="proizvod">
|
||||||
<div style="display:grid;grid-template-columns:1fr 110px 1fr;gap:12px;">
|
<div class="forma-grid-3" style="grid-template-columns:1fr 110px 1fr;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">
|
<label class="polje-labela">
|
||||||
Naziv <span style="color:#dc2626;">*</span>
|
Naziv <span style="color:#dc2626;">*</span>
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<!-- cene: nabavna / prodajna / sa PDV -->
|
<!-- cene: nabavna / prodajna / sa PDV -->
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr{{if index .Moduli "pdv"}} 1fr{{end}};gap:12px;">
|
<div class="{{if index .Moduli "pdv"}}forma-grid-3{{else}}forma-grid-2{{end}}">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Nabavna cena (din)</label>
|
<label class="polje-labela">Nabavna cena (din)</label>
|
||||||
<input type="number" id="nabavna-cena" name="nabavna_cena"
|
<input type="number" id="nabavna-cena" name="nabavna_cena"
|
||||||
|
|||||||
@@ -182,7 +182,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
<div class="forma-grid-2" style="gap:10px;">
|
||||||
<div>
|
<div>
|
||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Količina</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Količina</label>
|
||||||
<input type="number" :name="'kolicina[]'" x-model="stavka.kolicina" @input="preracunajSve()" min="1" :disabled="!isMobile" style="width:100%;">
|
<input type="number" :name="'kolicina[]'" x-model="stavka.kolicina" @input="preracunajSve()" min="1" :disabled="!isMobile" style="width:100%;">
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
<input type="number" :name="'cena_po_komadu[]'" x-model="stavka.cena" @input="preracunajSve()" min="0" step="0.01" :disabled="!isMobile" style="width:100%;">
|
<input type="number" :name="'cena_po_komadu[]'" x-model="stavka.cena" @input="preracunajSve()" min="0" step="0.01" :disabled="!isMobile" style="width:100%;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
<div class="forma-grid-2" style="gap:10px;">
|
||||||
<div>
|
<div>
|
||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Marža %</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Marža %</label>
|
||||||
<input type="number" :name="'marza[]'" x-model="stavka.marza" @input="izracunajProdajnu(stavka)" min="0" step="0.01" :disabled="!isMobile" style="width:100%;">
|
<input type="number" :name="'marza[]'" x-model="stavka.marza" @input="izracunajProdajnu(stavka)" min="0" step="0.01" :disabled="!isMobile" style="width:100%;">
|
||||||
@@ -316,7 +316,7 @@
|
|||||||
style="width:100%;resize:vertical;"></textarea>
|
style="width:100%;resize:vertical;"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
<div class="forma-grid-2">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Količina na stanju</label>
|
<label class="polje-labela">Količina na stanju</label>
|
||||||
<input type="number" x-model="modalKolicina" min="0" placeholder="0" style="width:100%;">
|
<input type="number" x-model="modalKolicina" min="0" placeholder="0" style="width:100%;">
|
||||||
@@ -327,7 +327,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
<div class="forma-grid-2">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Nabavna cena (din)</label>
|
<label class="polje-labela">Nabavna cena (din)</label>
|
||||||
<input type="number" x-model="modalNabavnaCena" min="0" step="0.01"
|
<input type="number" x-model="modalNabavnaCena" min="0" step="0.01"
|
||||||
@@ -392,7 +392,7 @@
|
|||||||
@keydown.enter.prevent="sacuvajDobavljaca()">
|
@keydown.enter.prevent="sacuvajDobavljaca()">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
<div class="forma-grid-2">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Kontakt osoba</label>
|
<label class="polje-labela">Kontakt osoba</label>
|
||||||
<input type="text" x-model="modalDobKontakt" placeholder="npr. Marko Petrović" style="width:100%;">
|
<input type="text" x-model="modalDobKontakt" placeholder="npr. Marko Petrović" style="width:100%;">
|
||||||
@@ -408,7 +408,7 @@
|
|||||||
<input type="text" x-model="modalDobEmail" placeholder="npr. nabavka@techdistrib.rs" style="width:100%;">
|
<input type="text" x-model="modalDobEmail" placeholder="npr. nabavka@techdistrib.rs" style="width:100%;">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
<div class="forma-grid-2">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">PIB</label>
|
<label class="polje-labela">PIB</label>
|
||||||
<input type="text" x-model="modalDobPib" placeholder="npr. 123456789" style="width:100%;">
|
<input type="text" x-model="modalDobPib" placeholder="npr. 123456789" style="width:100%;">
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<!-- dokument -->
|
<!-- dokument -->
|
||||||
<div class="kartica animiraj" style="margin-bottom:16px;">
|
<div class="kartica animiraj" style="margin-bottom:16px;">
|
||||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Dokument</div>
|
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Dokument</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Datum prometa</label>
|
<label class="polje-labela">Datum prometa</label>
|
||||||
<input type="date" name="datum_prometa" value="{{.Danas}}" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="date" name="datum_prometa" value="{{.Danas}}" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<label class="polje-labela">Naziv kupca</label>
|
<label class="polje-labela">Naziv kupca</label>
|
||||||
<input type="text" name="kupac_naziv" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="text" name="kupac_naziv" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
</div>
|
</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">PIB / JMBG</label>
|
<label class="polje-labela">PIB / JMBG</label>
|
||||||
<input type="text" name="kupac_pib" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="text" name="kupac_pib" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
<div class="kartica animiraj" style="margin-bottom:16px;">
|
<div class="kartica animiraj" style="margin-bottom:16px;">
|
||||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:6px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Iznosi po stopama</div>
|
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:6px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Iznosi po stopama</div>
|
||||||
<div class="pomocni-tekst" style="font-size:12px;margin-bottom:14px;">Ostavite 0 gde nema prometa. „Ukupno" se računa automatski kao zbir osnovica, PDV-a i oslobođenog prometa.</div>
|
<div class="pomocni-tekst" style="font-size:12px;margin-bottom:14px;">Ostavite 0 gde nema prometa. „Ukupno" se računa automatski kao zbir osnovica, PDV-a i oslobođenog prometa.</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Osnovica opšta (20%)</label>
|
<label class="polje-labela">Osnovica opšta (20%)</label>
|
||||||
<input type="number" step="0.01" min="0" name="osnovica_opsta" value="0" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="number" step="0.01" min="0" name="osnovica_opsta" value="0" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<!-- dokument -->
|
<!-- dokument -->
|
||||||
<div class="kartica animiraj" style="margin-bottom:16px;">
|
<div class="kartica animiraj" style="margin-bottom:16px;">
|
||||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Dokument</div>
|
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Dokument</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Datum prometa</label>
|
<label class="polje-labela">Datum prometa</label>
|
||||||
<input type="date" name="datum_prometa" value="{{.Danas}}" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="date" name="datum_prometa" value="{{.Danas}}" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<label class="polje-labela">Naziv dobavljača</label>
|
<label class="polje-labela">Naziv dobavljača</label>
|
||||||
<input type="text" name="dobavljac_naziv" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="text" name="dobavljac_naziv" required style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
</div>
|
</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">PIB</label>
|
<label class="polje-labela">PIB</label>
|
||||||
<input type="text" name="dobavljac_pib" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="text" name="dobavljac_pib" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
<div class="kartica animiraj" style="margin-bottom:16px;">
|
<div class="kartica animiraj" style="margin-bottom:16px;">
|
||||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:6px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Iznosi po stopama</div>
|
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:6px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">Iznosi po stopama</div>
|
||||||
<div class="pomocni-tekst" style="font-size:12px;margin-bottom:14px;">PDV (opšta/posebna) je iznos koji se može odbiti. „Ukupno" se računa automatski.</div>
|
<div class="pomocni-tekst" style="font-size:12px;margin-bottom:14px;">PDV (opšta/posebna) je iznos koji se može odbiti. „Ukupno" se računa automatski.</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Osnovica opšta (20%)</label>
|
<label class="polje-labela">Osnovica opšta (20%)</label>
|
||||||
<input type="number" step="0.01" min="0" name="osnovica_opsta" value="0" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
<input type="number" step="0.01" min="0" name="osnovica_opsta" value="0" style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- rezultat: obaveza za uplatu / povraćaj -->
|
<!-- rezultat: obaveza za uplatu / povraćaj -->
|
||||||
<div class="kartica animiraj" style="display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;
|
<div class="kartica animiraj" style="display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;
|
||||||
border-left:4px solid {{if .Obracun.ZaUplatu}}var(--greska){{else}}var(--uspeh){{end}};">
|
border-left:4px solid {{if .Obracun.ZaUplatu}}var(--greska){{else}}var(--uspeh){{end}};">
|
||||||
<div>
|
<div>
|
||||||
<div style="font-size:13px;color:var(--tekst-sporedni);">
|
<div style="font-size:13px;color:var(--tekst-sporedni);">
|
||||||
@@ -124,58 +124,58 @@
|
|||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
<td style="padding:8px 12px;color:var(--tekst-sporedni);">001</td>
|
<td style="padding:8px 12px;color:var(--tekst-sporedni);">001</td>
|
||||||
<td style="padding:8px 12px;">Oslobođen sa pravom na odbitak</td>
|
<td style="padding:8px 12px;">Oslobođen sa pravom na odbitak</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje001}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje001}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;color:var(--tekst-sporedni);">—</td>
|
<td style="padding:8px 12px;text-align:right;color:var(--tekst-sporedni);">—</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
<td style="padding:8px 12px;color:var(--tekst-sporedni);">002</td>
|
<td style="padding:8px 12px;color:var(--tekst-sporedni);">002</td>
|
||||||
<td style="padding:8px 12px;">Oslobođen bez prava na odbitak</td>
|
<td style="padding:8px 12px;">Oslobođen bez prava na odbitak</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje002}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje002}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;color:var(--tekst-sporedni);">—</td>
|
<td style="padding:8px 12px;text-align:right;color:var(--tekst-sporedni);">—</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
<td style="padding:8px 12px;color:var(--tekst-sporedni);">003<div style="font-size:11px;">103</div></td>
|
<td style="padding:8px 12px;color:var(--tekst-sporedni);">003<div style="font-size:11px;">103</div></td>
|
||||||
<td style="padding:8px 12px;">Promet po opštoj stopi (20%)</td>
|
<td style="padding:8px 12px;">Promet po opštoj stopi (20%)</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje003}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje003}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje103}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje103}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
<td style="padding:8px 12px;color:var(--tekst-sporedni);">004<div style="font-size:11px;">104</div></td>
|
<td style="padding:8px 12px;color:var(--tekst-sporedni);">004<div style="font-size:11px;">104</div></td>
|
||||||
<td style="padding:8px 12px;">Promet po posebnoj stopi (10%)</td>
|
<td style="padding:8px 12px;">Promet po posebnoj stopi (10%)</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje004}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje004}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje104}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje104}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);font-weight:500;background:var(--pozadina);">
|
<tr style="border-bottom:0.5px solid var(--ivica);font-weight:500;background:var(--pozadina);">
|
||||||
<td style="padding:8px 12px;">005<div style="font-size:11px;">105</div></td>
|
<td style="padding:8px 12px;">005<div style="font-size:11px;">105</div></td>
|
||||||
<td style="padding:8px 12px;">ZBIR (1+2+3+4)</td>
|
<td style="padding:8px 12px;">ZBIR (1+2+3+4)</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje005}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje005}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje105}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje105}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);"><td style="padding:8px 12px;font-weight:500;padding-top:14px;" colspan="4">II. Prethodni porez</td></tr>
|
<tr style="border-bottom:0.5px solid var(--ivica);"><td style="padding:8px 12px;font-weight:500;padding-top:14px;" colspan="4">II. Prethodni porez</td></tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);color:var(--tekst-sporedni);">
|
<tr style="border-bottom:0.5px solid var(--ivica);color:var(--tekst-sporedni);">
|
||||||
<td style="padding:8px 12px;">006<div style="font-size:11px;">106</div></td>
|
<td style="padding:8px 12px;">006<div style="font-size:11px;">106</div></td>
|
||||||
<td style="padding:8px 12px;">Prethodni porez pri uvozu</td>
|
<td style="padding:8px 12px;">Prethodni porez pri uvozu</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje006}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje006}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje106}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje106}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);color:var(--tekst-sporedni);">
|
<tr style="border-bottom:0.5px solid var(--ivica);color:var(--tekst-sporedni);">
|
||||||
<td style="padding:8px 12px;">007<div style="font-size:11px;">107</div></td>
|
<td style="padding:8px 12px;">007<div style="font-size:11px;">107</div></td>
|
||||||
<td style="padding:8px 12px;">PDV nadoknada poljoprivredniku</td>
|
<td style="padding:8px 12px;">PDV nadoknada poljoprivredniku</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje007}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje007}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje107}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje107}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
<td style="padding:8px 12px;color:var(--tekst-sporedni);">008<div style="font-size:11px;">108</div></td>
|
<td style="padding:8px 12px;color:var(--tekst-sporedni);">008<div style="font-size:11px;">108</div></td>
|
||||||
<td style="padding:8px 12px;">Ostali prethodni porez (domaće nabavke)</td>
|
<td style="padding:8px 12px;">Ostali prethodni porez (domaće nabavke)</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje008}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje008}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje108}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje108}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="font-weight:500;background:var(--pozadina);">
|
<tr style="font-weight:500;background:var(--pozadina);">
|
||||||
<td style="padding:8px 12px;">009<div style="font-size:11px;">109</div></td>
|
<td style="padding:8px 12px;">009<div style="font-size:11px;">109</div></td>
|
||||||
<td style="padding:8px 12px;">ZBIR (6+7+8)</td>
|
<td style="padding:8px 12px;">ZBIR (6+7+8)</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje009}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje009}}</td>
|
||||||
<td style="padding:8px 12px;text-align:right;">{{.PPPDV.Polje109}}</td>
|
<td style="padding:8px 12px;text-align:right;">{{dinari .PPPDV.Polje109}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
Iznos PDV u periodu (105 − 109)
|
Iznos PDV u periodu (105 − 109)
|
||||||
{{if .PPPDV.Povracaj}}<span style="color:var(--uspeh);"> — za povraćaj</span>{{else}}<span style="color:var(--greska);"> — za uplatu</span>{{end}}
|
{{if .PPPDV.Povracaj}}<span style="color:var(--uspeh);"> — za povraćaj</span>{{else}}<span style="color:var(--greska);"> — za uplatu</span>{{end}}
|
||||||
</td>
|
</td>
|
||||||
<td style="padding:10px 12px;text-align:right;color:{{if .PPPDV.Povracaj}}var(--uspeh){{else}}var(--greska){{end}};">{{.PPPDV.Polje110Apsolutno}}</td>
|
<td style="padding:10px 12px;text-align:right;color:{{if .PPPDV.Povracaj}}var(--uspeh){{else}}var(--greska){{end}};">{{dinari .PPPDV.Polje110Apsolutno}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding:8px 12px;color:var(--tekst-sporedni);">11</td>
|
<td style="padding:8px 12px;color:var(--tekst-sporedni);">11</td>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@
|
|||||||
placeholder="npr. Ulica i broj, Grad">
|
placeholder="npr. Ulica i broj, Grad">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
|
<div class="forma-grid-2" style="gap:14px;">
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Telefon</label>
|
<label class="polje-labela">Telefon</label>
|
||||||
<input type="text" name="telefon" value="{{.Telefon}}"
|
<input type="text" name="telefon" value="{{.Telefon}}"
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
||||||
<div class="pomocni-tekst">Verzija programa: <span style="color:var(--tekst-glavni);font-weight:500;">{{.Verzija}}</span></div>
|
<div class="pomocni-tekst">Verzija programa: <span style="color:var(--tekst-glavni);font-weight:500;">{{.Verzija}}</span></div>
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
||||||
<a hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML" href="/podesavanja/backup"
|
<a href="/podesavanja/backup"
|
||||||
style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
|
style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
|
||||||
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
|
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
{{define "sadrzaj"}}
|
{{define "sadrzaj"}}
|
||||||
<div class="stranica-stack" style="width:100%;max-width:100%;">
|
<div class="stranica-stack" style="width:100%;max-width:100%;">
|
||||||
|
|
||||||
<div class="kartica animiraj">
|
<div class="kartica animiraj" style="margin-bottom:16px;">
|
||||||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
|
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--sb-akcent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="5" width="20" height="14" rx="2"/><line x1="2" y1="10" x2="22" y2="10"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--sb-akcent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="5" width="20" height="14" rx="2"/><line x1="2" y1="10" x2="22" y2="10"/></svg>
|
||||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">L-PFR veza</span>
|
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">L-PFR veza</span>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
||||||
<div class="pomocni-tekst">Verzija programa: <span style="color:var(--tekst-glavni);font-weight:500;">{{.Verzija}}</span></div>
|
<div class="pomocni-tekst">Verzija programa: <span style="color:var(--tekst-glavni);font-weight:500;">{{.Verzija}}</span></div>
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
||||||
<a hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML" href="/podesavanja/backup"
|
<a href="/podesavanja/backup"
|
||||||
style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
|
style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
|
||||||
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
|
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||||
|
|||||||
@@ -336,8 +336,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="forma-grid-2" style="gap: 10px">
|
||||||
style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px">
|
|
||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
style="
|
style="
|
||||||
|
|||||||
@@ -557,7 +557,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="cust-sel-lista">
|
<div class="cust-sel-lista">
|
||||||
<div class="cso" data-val="" data-cena="0"><span class="cso-prazno">— odaberi uslugu —</span></div>
|
<div class="cso" data-val="" data-cena="0"><span class="cso-prazno">— odaberi uslugu —</span></div>
|
||||||
{{range .Usluge}}{{if not (index $.KorisceneUsluge .ID)}}<div class="cso" data-val="{{.ID}}" data-cena="{{.Cena}}"><span class="cso-naziv">{{.Naziv}}</span><span class="cso-cena">{{dinari .Cena}} din</span></div>{{end}}{{end}}
|
{{range .Usluge}}{{if not (index $.KorisceneUsluge .ID)}}<div class="cso" data-val="{{.ID}}" data-cena="{{.Cena}}" data-pdv="{{.PdvStopa}}"><span class="cso-naziv">{{.Naziv}}</span><span class="cso-cena">{{if index $.Moduli "pdv"}}{{dinari (.CenaSaPdv)}}{{else}}{{dinari .Cena}}{{end}} din</span></div>{{end}}{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="usluga_id" id="rad-usluga">
|
<input type="hidden" name="usluga_id" id="rad-usluga">
|
||||||
@@ -567,8 +567,9 @@
|
|||||||
<input type="number" name="kolicina" id="rad-kolicina" min="0.01" step="0.01" value="1" style="width:100%;" required>
|
<input type="number" name="kolicina" id="rad-kolicina" min="0.01" step="0.01" value="1" style="width:100%;" required>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Cena/kom (din)</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Cena/kom {{if index .Moduli "pdv"}}s PDV {{end}}(din)</label>
|
||||||
<input type="number" name="cena_komada" id="rad-cena" min="0" step="0.01" value="0" style="width:100%;" required>
|
<input type="number" id="rad-cena" min="0" step="0.01" value="0" style="width:100%;" required>
|
||||||
|
<input type="hidden" name="cena_komada" id="rad-cena-neto" value="0">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button type="submit" class="btn-primarno" style="font-size:13px;padding:8px 14px;white-space:nowrap;">+ Dodaj</button>
|
<button type="submit" class="btn-primarno" style="font-size:13px;padding:8px 14px;white-space:nowrap;">+ Dodaj</button>
|
||||||
@@ -602,7 +603,7 @@
|
|||||||
<td style="padding:9px 10px;text-align:center;font-size:14px;color:var(--tekst-glavni);">{{.Kolicina}}</td>
|
<td style="padding:9px 10px;text-align:center;font-size:14px;color:var(--tekst-glavni);">{{.Kolicina}}</td>
|
||||||
<td style="padding:9px 10px;text-align:right;font-size:14px;color:var(--tekst-glavni);">{{dinari .CenaKomada}} din</td>
|
<td style="padding:9px 10px;text-align:right;font-size:14px;color:var(--tekst-glavni);">{{dinari .CenaKomada}} din</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
||||||
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .Ukupno}} din</td>
|
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .CenaSaPdv}} din</td>{{end}}
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .CenaSaPdv}} din</td>{{end}}
|
||||||
<td style="padding:9px 10px;text-align:center;">
|
<td style="padding:9px 10px;text-align:center;">
|
||||||
{{if and (not $.ZakljucaniUgradjeni) (index $.Dozvole "servis.izmeni")}}
|
{{if and (not $.ZakljucaniUgradjeni) (index $.Dozvole "servis.izmeni")}}
|
||||||
@@ -625,7 +626,7 @@
|
|||||||
<td style="padding:9px 10px;text-align:center;font-size:14px;color:var(--tekst-glavni);">{{.Kolicina}}</td>
|
<td style="padding:9px 10px;text-align:center;font-size:14px;color:var(--tekst-glavni);">{{.Kolicina}}</td>
|
||||||
<td style="padding:9px 10px;text-align:right;font-size:14px;color:var(--tekst-glavni);">{{dinari .CenaKomada}} din</td>
|
<td style="padding:9px 10px;text-align:right;font-size:14px;color:var(--tekst-glavni);">{{dinari .CenaKomada}} din</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
||||||
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .Ukupno}} din</td>
|
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .CenaSaPdv}} din</td>{{end}}
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .CenaSaPdv}} din</td>{{end}}
|
||||||
<td style="padding:9px 10px;text-align:center;">
|
<td style="padding:9px 10px;text-align:center;">
|
||||||
{{if and (index $.Dozvole "servis.izmeni") (ne $.Nalog.Status "U popravci")}}
|
{{if and (index $.Dozvole "servis.izmeni") (ne $.Nalog.Status "U popravci")}}
|
||||||
@@ -695,8 +696,9 @@
|
|||||||
<input type="number" name="kolicina" id="deo-kol" min="1" value="1" style="width:100%;box-sizing:border-box;" required>
|
<input type="number" name="kolicina" id="deo-kol" min="1" value="1" style="width:100%;box-sizing:border-box;" required>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Cena/kom (din)</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Cena/kom {{if index .Moduli "pdv"}}s PDV {{end}}(din)</label>
|
||||||
<input type="number" name="cena_komada" id="deo-cena" min="0" step="0.01" value="0" style="width:100%;" required>
|
<input type="number" id="deo-cena" min="0" step="0.01" value="0" style="width:100%;" required>
|
||||||
|
<input type="hidden" name="cena_komada" id="deo-cena-neto" value="0">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button type="submit" class="btn-primarno" style="font-size:13px;padding:8px 14px;white-space:nowrap;">+ Dodaj</button>
|
<button type="submit" class="btn-primarno" style="font-size:13px;padding:8px 14px;white-space:nowrap;">+ Dodaj</button>
|
||||||
@@ -735,7 +737,7 @@
|
|||||||
</td>
|
</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
||||||
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||||
{{if .Kolicina}}{{dinari .Ukupno}} din{{else}}—{{end}}
|
{{if .Kolicina}}{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}{{else}}—{{end}}
|
||||||
</td>
|
</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||||
{{if .Kolicina}}{{dinari .CenaSaPdv}} din{{else}}—{{end}}
|
{{if .Kolicina}}{{dinari .CenaSaPdv}} din{{else}}—{{end}}
|
||||||
@@ -766,7 +768,7 @@
|
|||||||
</td>
|
</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:center;font-size:12px;color:var(--tekst-sporedni);">{{printf "%.0f" .PdvStopa}}%</td>{{end}}
|
||||||
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||||
{{if .Kolicina}}{{dinari .Ukupno}} din{{else}}—{{end}}
|
{{if .Kolicina}}{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}{{else}}—{{end}}
|
||||||
</td>
|
</td>
|
||||||
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
{{if index $.Moduli "pdv"}}<td style="padding:9px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||||
{{if .Kolicina}}{{dinari .CenaSaPdv}} din{{else}}—{{end}}
|
{{if .Kolicina}}{{dinari .CenaSaPdv}} din{{else}}—{{end}}
|
||||||
@@ -804,6 +806,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<script>(function(){
|
<script>(function(){
|
||||||
window._dinFmt=function(v){var s=Math.round((v||0)*100);var dec=String(s%100).padStart(2,'0');var cel=String(Math.floor(s/100));var r='';for(var i=0;i<cel.length;i++){if(i>0&&(cel.length-i)%3===0)r+='.';r+=cel[i];}return r+','+dec;}
|
window._dinFmt=function(v){var s=Math.round((v||0)*100);var dec=String(s%100).padStart(2,'0');var cel=String(Math.floor(s/100));var r='';for(var i=0;i<cel.length;i++){if(i>0&&(cel.length-i)%3===0)r+='.';r+=cel[i];}return r+','+dec;}
|
||||||
|
window._pdvAktivan={{if index .Moduli "pdv"}}true{{else}}false{{end}};
|
||||||
var k=document.getElementById('deo-kategorija');
|
var k=document.getElementById('deo-kategorija');
|
||||||
var a=document.getElementById('deo-artikal');
|
var a=document.getElementById('deo-artikal');
|
||||||
var u=document.getElementById('deo-umagacinu');
|
var u=document.getElementById('deo-umagacinu');
|
||||||
@@ -817,13 +820,13 @@
|
|||||||
var ka=k?k.value:'';
|
var ka=k?k.value:'';
|
||||||
var aa=window._ntechArtikli||[];
|
var aa=window._ntechArtikli||[];
|
||||||
var html='<div class="cso" data-val="" data-cena="0" data-stanje="0"><span class="cso-prazno">\u2014 odaberi artikal \u2014</span></div>';
|
var html='<div class="cso" data-val="" data-cena="0" data-stanje="0"><span class="cso-prazno">\u2014 odaberi artikal \u2014</span></div>';
|
||||||
aa.forEach(function(x){if(!ka||(x.KategorijaNaziv||'')===ka)html+='<div class="cso" data-val="'+x.ID+'" data-cena="'+x.ProdajnaCena+'" data-stanje="'+(x.Kolicina||0)+'"><span class="cso-naziv">'+x.Naziv+'</span><span class="cso-cena">'+window._dinFmt(x.ProdajnaCena)+' din</span></div>';});
|
aa.forEach(function(x){var prik=window._pdvAktivan?(x.CenaSaPdv||x.ProdajnaCena):x.ProdajnaCena;if(!ka||(x.KategorijaNaziv||'')===ka)html+='<div class="cso" data-val="'+x.ID+'" data-cena="'+x.ProdajnaCena+'" data-pdv="'+(x.PdvStopa||0)+'" data-stanje="'+(x.Kolicina||0)+'"><span class="cso-naziv">'+x.Naziv+'</span><span class="cso-cena">'+window._dinFmt(prik)+' din</span></div>';});
|
||||||
if(lista)lista.innerHTML=html;
|
if(lista)lista.innerHTML=html;
|
||||||
}
|
}
|
||||||
if(k){var aa2=window._ntechArtikli||[];var kgs=[];aa2.forEach(function(x){var n=x.KategorijaNaziv||'';if(n&&kgs.indexOf(n)===-1)kgs.push(n)})
|
if(k){var aa2=window._ntechArtikli||[];var kgs=[];aa2.forEach(function(x){var n=x.KategorijaNaziv||'';if(n&&kgs.indexOf(n)===-1)kgs.push(n)})
|
||||||
k.innerHTML='<option value="">\u2014 sve kategorije \u2014</option>'+kgs.map(function(x){return'<option value="'+x+'">'+x+'</option>'}).join('');k.onchange=pop}
|
k.innerHTML='<option value="">\u2014 sve kategorije \u2014</option>'+kgs.map(function(x){return'<option value="'+x+'">'+x+'</option>'}).join('');k.onchange=pop}
|
||||||
pop();
|
pop();
|
||||||
if(a)a.addEventListener('change',function(){var v=parseFloat(a.getAttribute('data-cena'));if(c)c.value=(!isNaN(v)&&v>0)?v.toFixed(2):'0';osv()});
|
if(a)a.addEventListener('change',function(){var v=parseFloat(a.getAttribute('data-cena'))||0;var pdv=parseFloat(a.getAttribute('data-pdv'))||0;var bruto=(window._pdvAktivan&&pdv>0)?v*(1+pdv/100):v;if(c)c.value=v>0?bruto.toFixed(2):'0';var cn=document.getElementById('deo-cena-neto');if(cn)cn.value=v>0?v.toFixed(2):'0';osv()});
|
||||||
if(l)l.oninput=osv;
|
if(l)l.oninput=osv;
|
||||||
var fd=document.querySelector('form[action$=\"/delovi\"]');
|
var fd=document.querySelector('form[action$=\"/delovi\"]');
|
||||||
if(fd)fd.addEventListener('reset',function(){if(u){u.textContent='\u2014';u.classList.remove('prekoraceno')}if(l)l.classList.remove('prekoraceno')})
|
if(fd)fd.addEventListener('reset',function(){if(u){u.textContent='\u2014';u.classList.remove('prekoraceno')}if(l)l.classList.remove('prekoraceno')})
|
||||||
@@ -849,7 +852,7 @@
|
|||||||
<input type="checkbox" name="rad_id" value="{{.ID}}" checked style="width:16px;height:16px;accent-color:#f59e0b;flex-shrink:0;">
|
<input type="checkbox" name="rad_id" value="{{.ID}}" checked style="width:16px;height:16px;accent-color:#f59e0b;flex-shrink:0;">
|
||||||
<span style="font-size:13px;color:var(--tekst-glavni);">{{.Naziv}}{{if gt .Kolicina 1.0}} × {{printf "%.0f" .Kolicina}}{{end}}</span>
|
<span style="font-size:13px;color:var(--tekst-glavni);">{{.Naziv}}{{if gt .Kolicina 1.0}} × {{printf "%.0f" .Kolicina}}{{end}}</span>
|
||||||
</span>
|
</span>
|
||||||
<span style="font-size:13px;font-weight:500;color:var(--tekst-glavni);white-space:nowrap;">{{dinari .Ukupno}} din</span>
|
<span style="font-size:13px;font-weight:500;color:var(--tekst-glavni);white-space:nowrap;">{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}</span>
|
||||||
</label>
|
</label>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -861,7 +864,7 @@
|
|||||||
<input type="checkbox" name="artikal_id" value="{{.ArtikalID}}" checked style="width:16px;height:16px;accent-color:#f59e0b;flex-shrink:0;">
|
<input type="checkbox" name="artikal_id" value="{{.ArtikalID}}" checked style="width:16px;height:16px;accent-color:#f59e0b;flex-shrink:0;">
|
||||||
<span style="font-size:13px;color:var(--tekst-glavni);">{{.ArtikalNaziv}}{{if gt .Kolicina 1}} × {{.Kolicina}}{{end}}</span>
|
<span style="font-size:13px;color:var(--tekst-glavni);">{{.ArtikalNaziv}}{{if gt .Kolicina 1}} × {{.Kolicina}}{{end}}</span>
|
||||||
</span>
|
</span>
|
||||||
<span style="font-size:13px;font-weight:500;color:var(--tekst-glavni);white-space:nowrap;">{{if .Kolicina}}{{dinari .Ukupno}} din{{else}}—{{end}}</span>
|
<span style="font-size:13px;font-weight:500;color:var(--tekst-glavni);white-space:nowrap;">{{if .Kolicina}}{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}{{else}}—{{end}}</span>
|
||||||
</label>
|
</label>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -895,13 +898,13 @@
|
|||||||
{{range .ServisniRadovi}}
|
{{range .ServisniRadovi}}
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;font-size:13px;">
|
<div style="display:flex;justify-content:space-between;align-items:center;font-size:13px;">
|
||||||
<span style="color:var(--tekst-glavni);">{{.Naziv}}{{if gt .Kolicina 1.0}} ×{{.Kolicina}}{{end}}</span>
|
<span style="color:var(--tekst-glavni);">{{.Naziv}}{{if gt .Kolicina 1.0}} ×{{.Kolicina}}{{end}}</span>
|
||||||
<span style="color:var(--tekst-sporedni);">{{dinari .Ukupno}} din</span>
|
<span style="color:var(--tekst-sporedni);">{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:10px;padding-top:8px;border-top:0.5px solid var(--ivica);">
|
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:10px;padding-top:8px;border-top:0.5px solid var(--ivica);">
|
||||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Ukupno rad</span>
|
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Ukupno rad</span>
|
||||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .UkupnoRadovi}} din</span>
|
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{if index $.Moduli "pdv"}}{{dinari .UkupnoRadoviSaPdv}} din{{else}}{{dinari .UkupnoRadovi}} din{{end}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -915,13 +918,13 @@
|
|||||||
{{range .ServisniDelovi}}
|
{{range .ServisniDelovi}}
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;font-size:13px;">
|
<div style="display:flex;justify-content:space-between;align-items:center;font-size:13px;">
|
||||||
<span style="color:var(--tekst-glavni);">{{.ArtikalNaziv}}{{if gt .Kolicina 1}} ×{{.Kolicina}}{{end}}</span>
|
<span style="color:var(--tekst-glavni);">{{.ArtikalNaziv}}{{if gt .Kolicina 1}} ×{{.Kolicina}}{{end}}</span>
|
||||||
<span style="color:var(--tekst-sporedni);">{{dinari .Ukupno}} din</span>
|
<span style="color:var(--tekst-sporedni);">{{if index $.Moduli "pdv"}}{{dinari .UkupnoSaPdv}} din{{else}}{{dinari .Ukupno}} din{{end}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:10px;padding-top:8px;border-top:0.5px solid var(--ivica);">
|
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:10px;padding-top:8px;border-top:0.5px solid var(--ivica);">
|
||||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Ukupno delovi</span>
|
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Ukupno delovi</span>
|
||||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{dinari .UkupnoDelovi}} din</span>
|
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{if index $.Moduli "pdv"}}{{dinari .UkupnoDeloviSaPdv}} din{{else}}{{dinari .UkupnoDelovi}} din{{end}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -1056,6 +1059,7 @@ document.addEventListener('click', function (e) {
|
|||||||
if (inp) {
|
if (inp) {
|
||||||
inp.value = val;
|
inp.value = val;
|
||||||
inp.setAttribute('data-cena', opt.getAttribute('data-cena') || '0');
|
inp.setAttribute('data-cena', opt.getAttribute('data-cena') || '0');
|
||||||
|
inp.setAttribute('data-pdv', opt.getAttribute('data-pdv') || '0');
|
||||||
inp.setAttribute('data-stanje', opt.getAttribute('data-stanje') || '0');
|
inp.setAttribute('data-stanje', opt.getAttribute('data-stanje') || '0');
|
||||||
inp.dispatchEvent(new Event('change', { bubbles: true }));
|
inp.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
}
|
}
|
||||||
@@ -1068,14 +1072,42 @@ document.addEventListener('click', function (e) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Radovi: pri izboru usluge (custom dropdown → hidden input) popuni predloženu cenu.
|
// Radovi: pri izboru usluge popuni cenu. Kad je PDV aktivan, prikazuje bruto;
|
||||||
|
// hidden polje rad-cena-neto uvek nosi neto i šalje se backend-u.
|
||||||
document.addEventListener('change', function (e) {
|
document.addEventListener('change', function (e) {
|
||||||
if (!e.target || e.target.id !== 'rad-usluga') return;
|
if (!e.target || e.target.id !== 'rad-usluga') return;
|
||||||
var cena = document.getElementById('rad-cena');
|
var vidljivo = document.getElementById('rad-cena');
|
||||||
if (!cena) return;
|
var neto = document.getElementById('rad-cena-neto');
|
||||||
var c = parseFloat(e.target.getAttribute('data-cena'));
|
if (!vidljivo) return;
|
||||||
cena.value = (!isNaN(c) && c > 0) ? c.toFixed(2) : '0';
|
var c = parseFloat(e.target.getAttribute('data-cena')) || 0;
|
||||||
|
var pdv = parseFloat(e.target.getAttribute('data-pdv')) || 0;
|
||||||
|
var bruto = (window._pdvAktivan && pdv > 0) ? c * (1 + pdv / 100) : c;
|
||||||
|
vidljivo.value = c > 0 ? bruto.toFixed(2) : '0';
|
||||||
|
if (neto) neto.value = c > 0 ? c.toFixed(2) : '0';
|
||||||
});
|
});
|
||||||
|
// Kad korisnik ručno menja vidljivo polje, sinhronizuj hidden neto vrednost.
|
||||||
|
(function () {
|
||||||
|
var vidljivo = document.getElementById('rad-cena');
|
||||||
|
if (vidljivo) {
|
||||||
|
vidljivo.addEventListener('input', function () {
|
||||||
|
var neto = document.getElementById('rad-cena-neto');
|
||||||
|
var usluga = document.getElementById('rad-usluga');
|
||||||
|
var pdv = usluga ? (parseFloat(usluga.getAttribute('data-pdv')) || 0) : 0;
|
||||||
|
var bruto = parseFloat(this.value) || 0;
|
||||||
|
if (neto) neto.value = (window._pdvAktivan && pdv > 0) ? (bruto / (1 + pdv / 100)).toFixed(2) : bruto.toFixed(2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var vidljivoDeo = document.getElementById('deo-cena');
|
||||||
|
if (vidljivoDeo) {
|
||||||
|
vidljivoDeo.addEventListener('input', function () {
|
||||||
|
var neto = document.getElementById('deo-cena-neto');
|
||||||
|
var artikal = document.getElementById('deo-artikal');
|
||||||
|
var pdv = artikal ? (parseFloat(artikal.getAttribute('data-pdv')) || 0) : 0;
|
||||||
|
var bruto = parseFloat(this.value) || 0;
|
||||||
|
if (neto) neto.value = (window._pdvAktivan && pdv > 0) ? (bruto / (1 + pdv / 100)).toFixed(2) : bruto.toFixed(2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
// Delovi: kategorija filtrira <select> artikala; izborom artikla popunjavamo
|
// Delovi: kategorija filtrira <select> artikala; izborom artikla popunjavamo
|
||||||
// cenu i prikaz „U magacinu". Običan <select> ima native pretragu kucanjem
|
// cenu i prikaz „U magacinu". Običan <select> ima native pretragu kucanjem
|
||||||
@@ -1121,9 +1153,10 @@ document.addEventListener('change', function (e) {
|
|||||||
var html = '<div class="cso" data-val="" data-cena="0" data-stanje="0"><span class="cso-prazno">— odaberi artikal —</span></div>';
|
var html = '<div class="cso" data-val="" data-cena="0" data-stanje="0"><span class="cso-prazno">— odaberi artikal —</span></div>';
|
||||||
ARTIKLI.filter(function (a) { return !izabrana || (a.KategorijaNaziv || '') === izabrana; })
|
ARTIKLI.filter(function (a) { return !izabrana || (a.KategorijaNaziv || '') === izabrana; })
|
||||||
.forEach(function (a) {
|
.forEach(function (a) {
|
||||||
|
var prik = window._pdvAktivan ? (a.CenaSaPdv || a.ProdajnaCena) : a.ProdajnaCena;
|
||||||
html += '<div class="cso" data-val="' + a.ID + '" data-cena="' + a.ProdajnaCena +
|
html += '<div class="cso" data-val="' + a.ID + '" data-cena="' + a.ProdajnaCena +
|
||||||
'" data-stanje="' + (a.Kolicina || 0) + '"><span class="cso-naziv">' + a.Naziv +
|
'" data-pdv="' + (a.PdvStopa || 0) + '" data-stanje="' + (a.Kolicina || 0) + '"><span class="cso-naziv">' + a.Naziv +
|
||||||
'</span><span class="cso-cena">' + window._dinFmt(a.ProdajnaCena) + ' din</span></div>';
|
'</span><span class="cso-cena">' + window._dinFmt(prik) + ' din</span></div>';
|
||||||
});
|
});
|
||||||
if (lista) lista.innerHTML = html;
|
if (lista) lista.innerHTML = html;
|
||||||
if (umagacinu) umagacinu.textContent = '—';
|
if (umagacinu) umagacinu.textContent = '—';
|
||||||
@@ -1133,8 +1166,12 @@ document.addEventListener('change', function (e) {
|
|||||||
if (kategSel) kategSel.addEventListener('change', popuniArtikle);
|
if (kategSel) kategSel.addEventListener('change', popuniArtikle);
|
||||||
|
|
||||||
artikalSel.addEventListener('change', function () {
|
artikalSel.addEventListener('change', function () {
|
||||||
var c = parseFloat(artikalSel.getAttribute('data-cena'));
|
var c = parseFloat(artikalSel.getAttribute('data-cena')) || 0;
|
||||||
if (cena) cena.value = (!isNaN(c) && c > 0) ? c.toFixed(2) : '0';
|
var pdv = parseFloat(artikalSel.getAttribute('data-pdv')) || 0;
|
||||||
|
var bruto = (window._pdvAktivan && pdv > 0) ? c * (1 + pdv / 100) : c;
|
||||||
|
if (cena) cena.value = c > 0 ? bruto.toFixed(2) : '0';
|
||||||
|
var cenaNeto = document.getElementById('deo-cena-neto');
|
||||||
|
if (cenaNeto) cenaNeto.value = c > 0 ? c.toFixed(2) : '0';
|
||||||
var st = parseInt(artikalSel.getAttribute('data-stanje'), 10);
|
var st = parseInt(artikalSel.getAttribute('data-stanje'), 10);
|
||||||
stanjeIzabrano = isNaN(st) ? 0 : st;
|
stanjeIzabrano = isNaN(st) ? 0 : st;
|
||||||
if (umagacinu) umagacinu.textContent = artikalSel.value ? stanjeIzabrano : '—';
|
if (umagacinu) umagacinu.textContent = artikalSel.value ? stanjeIzabrano : '—';
|
||||||
|
|||||||
@@ -164,7 +164,7 @@
|
|||||||
{{if .Nalog.PopravkaOdbijena}}
|
{{if .Nalog.PopravkaOdbijena}}
|
||||||
<div class="polje-tekst">Izvršena je samo dijagnostika — klijent nije prihvatio ponuđenu popravku.</div>
|
<div class="polje-tekst">Izvršena je samo dijagnostika — klijent nije prihvatio ponuđenu popravku.</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="polje-tekst">{{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
<div class="polje-tekst">{{if .Nalog.Uradjeno}}{{.Nalog.Uradjeno}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user