Files
GoNtech/internal/model/nabavka.go
T
Dasko 30db396ee6 feat(kalkulacija): Faza C — marža po kategoriji/artiklu + zavisni troškovi (backend)
Celina 1 (kompletna) — marža po kategoriji/artiklu:
- migracija 046: nullable marza na artikli i kategorije
- model Marza *float64 (Artikal, Kategorija) + KategorijaMarza u ArtikalSaKategorijom
- repo: čitanje/pisanje marže; nove DohvatiID/Izmeni za kategoriju
- dozvola kategorija.izmeni; handler IzmeniKategoriju + ruta
- UI: polje marže u formi artikla i kategorije; modal izmene kategorije
- nabavka: fallback predlog marže artikal → kategorija → globalna (izaberiArtikal)

Celina 2 (backend) — zavisni troškovi nabavke:
- migracija 047: tabela nabavka_troskovi + kolona metod_raspodele na nabavke
- model NabavkaTrosak, MetodRaspodele; čista funkcija RasporediTroskove + test
- repo: Kreiraj upisuje troškove i metod; DohvatiTroskove
- handler: parsiranje troškova/metoda; kalkulativna nabavna cena na serveru

UI forme troškova i prikaz u detaljima nabavke slede.
2026-06-14 16:12:03 +02:00

85 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model
import (
"math"
"time"
)
// Nabavka predstavlja zaglavlje jedne nabavke
type Nabavka struct {
ID int64
DobavljacID *int64
Napomena string
Ukupno float64
MetodRaspodele string // "vrednost" ili "kolicina"; prazno = nema zavisnih troškova
Datum time.Time
}
// NabavkaTrosak je jedna stavka zavisnih troškova nabavke (npr. prevoz, carina)
type NabavkaTrosak struct {
ID int64
NabavkaID int64
Naziv string
Iznos float64
}
// StavkaNabavke predstavlja jednu liniju (artikal) unutar nabavke
type StavkaNabavke struct {
ID int64
NabavkaID int64
ArtikalID int64
Kolicina int
CenaPoKomadu float64
Ukupno float64
}
// RasporediTroskove raspodeljuje ukupan zavisni trošak na stavke nabavke i vraća
// kalkulativnu nabavnu cenu po komadu za svaku stavku (isti redosled kao ulazne stavke).
// metod "kolicina" deli trošak po broju komada; svaka druga vrednost (uklj. "vrednost")
// deli po nabavnoj vrednosti stavke (količina × cena).
// Ako nema troška ili je osnovica nula, vraća nepromenjenu cenu po komadu.
func RasporediTroskove(stavke []StavkaNabavke, ukupanTrosak float64, metod string) []float64 {
kalk := make([]float64, len(stavke))
// osnovica raspodele po izabranom metodu
var osnovica float64
for _, s := range stavke {
if metod == "kolicina" {
osnovica += float64(s.Kolicina)
} else {
osnovica += float64(s.Kolicina) * s.CenaPoKomadu
}
}
for i, s := range stavke {
kalk[i] = s.CenaPoKomadu
// bez troška, bez osnovice ili bez količine — nema šta da se raspodeli
if ukupanTrosak <= 0 || osnovica <= 0 || s.Kolicina == 0 {
continue
}
var udeo float64
if metod == "kolicina" {
udeo = float64(s.Kolicina) / osnovica
} else {
udeo = (float64(s.Kolicina) * s.CenaPoKomadu) / osnovica
}
trosakPoKomadu := (ukupanTrosak * udeo) / float64(s.Kolicina)
// zaokruženo na 2 decimale — kalkulativna nabavna je cena koja se čuva
kalk[i] = math.Round((s.CenaPoKomadu+trosakPoKomadu)*100) / 100
}
return kalk
}
// NabavkaSaDetaljem je nabavka sa nazivom dobavljača — za prikaz u listi
type NabavkaSaDetaljem struct {
Nabavka
DobavljacNaziv string
}
// StavkaSaArtiklom je stavka nabavke sa nazivom artikla — za prikaz u formi i detaljima
type StavkaSaArtiklom struct {
StavkaNabavke
ArtikalNaziv string
}