Zalihe: razlikovanje manjka i viška pri popisu (manjak_popis/visak_popis tip promene)

This commit is contained in:
2026-06-30 17:08:50 +02:00
parent 4daac1eed6
commit 4806840ba4
8 changed files with 48 additions and 8 deletions
+3 -3
View File
@@ -29,8 +29,8 @@ type ArtikalRepository interface {
Vrati(ctx context.Context, id int64) error
// SledecaSifra vraća predlog sledeće auto-šifre (npr. KOMP-0042 ili ART-0042)
SledecaSifra(ctx context.Context, kategorijaID *int64) (string, error)
// KorigujKolicinu postavlja novu količinu artikla i upisuje korekciju u magacinske_promene
KorigujKolicinu(ctx context.Context, artikalID int64, novaKolicina int, korisnikID *int64, napomena string) error
// KorigujKolicinu postavlja novu količinu artikla i upisuje promenu u magacinske_promene
KorigujKolicinu(ctx context.Context, artikalID int64, novaKolicina int, korisnikID *int64, napomena, tipPromene string) error
// DobavljaciArtikla vraća ID-jeve dobavljača vezanih za artikal
DobavljaciArtikla(ctx context.Context, artikalID int64) ([]int64, error)
// PostaviDobavljaceArtikla zamenjuje skup dobavljača artikla datim ID-jevima
@@ -152,7 +152,7 @@ type NabavkaRepository interface {
DohvatiStavke(ctx context.Context, nabavkaID int64) ([]model.StavkaSaArtiklom, error)
DohvatiTroskove(ctx context.Context, nabavkaID int64) ([]model.NabavkaTrosak, error)
Kreiraj(ctx context.Context, n *model.Nabavka, stavke []model.StavkaNabavke, troskovi []model.NabavkaTrosak, korisnikID *int64) (int64, error)
Obrisi(ctx context.Context, id int64, korisnikID *int64) error
Storno(ctx context.Context, id int64, razlog string, korisnikID *int64) error
}
// DobavljacRepository definiše operacije nad dobavljačima
+4 -3
View File
@@ -397,8 +397,9 @@ func (r *ArtikalRepo) SveDobavljaceArtikala(ctx context.Context) (map[int64][]in
return mapa, nil
}
// KorigujKolicinu postavlja novu količinu i upisuje korekciju u magacinske_promene
func (r *ArtikalRepo) KorigujKolicinu(ctx context.Context, artikalID int64, novaKolicina int, korisnikID *int64, napomena string) error {
// KorigujKolicinu postavlja novu količinu i upisuje promenu u magacinske_promene;
// tipPromene određuje vrstu traga (korekcija, manjak_popis, visak_popis)
func (r *ArtikalRepo) KorigujKolicinu(ctx context.Context, artikalID int64, novaKolicina int, korisnikID *int64, napomena, tipPromene string) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("ntech: ArtikalRepo.KorigujKolicinu: begin: %w", err)
@@ -418,7 +419,7 @@ func (r *ArtikalRepo) KorigujKolicinu(ctx context.Context, artikalID int64, nova
}
promena := novaKolicina - staraKolicina
if err = zabeleziMagacinPromenu(ctx, tx, artikalID, model.PromenaKorekcija, promena,
if err = zabeleziMagacinPromenu(ctx, tx, artikalID, tipPromene, promena,
staraKolicina, novaKolicina, 0, korisnikID, napomena); err != nil {
return fmt.Errorf("ntech: ArtikalRepo.KorigujKolicinu: %w", err)
}
+5 -1
View File
@@ -413,7 +413,11 @@ func (h *Handler) SacuvajPopis(w http.ResponseWriter, r *http.Request) {
continue
}
povecano := nova > a.Kolicina
if err := h.Artikli.KorigujKolicinu(r.Context(), a.ID, nova, &k.ID, napomena); err != nil {
tipPromene := model.PromenaManjak
if povecano {
tipPromene = model.PromenaVisak
}
if err := h.Artikli.KorigujKolicinu(r.Context(), a.ID, nova, &k.ID, napomena, tipPromene); err != nil {
slog.Error("popis: korekcija artikla", "id", a.ID, "error", err)
greskaBroj++
continue
+1 -1
View File
@@ -264,7 +264,7 @@ func (h *Handler) SacuvajIzmenuArtikla(w http.ResponseWriter, r *http.Request) {
// ako se količina promenila, koriguj stanje uz magacinski trag
if novaKolicina != staraKolicina {
if e := h.Artikli.KorigujKolicinu(r.Context(), id, novaKolicina, &k.ID, "izmena artikla"); e != nil {
if e := h.Artikli.KorigujKolicinu(r.Context(), id, novaKolicina, &k.ID, "izmena artikla", model.PromenaKorekcija); e != nil {
slog.Error("korekcija količine pri izmeni artikla nije uspela", "artikal_id", id, "error", e)
}
}
+2
View File
@@ -9,6 +9,8 @@ const (
PromenaIzlazServis = "izlaz_servis"
PromenaPovracaj = "povracaj"
PromenaKorekcija = "korekcija"
PromenaManjak = "manjak_popis"
PromenaVisak = "visak_popis"
)
// MagacinskaPromenaSaDetaljem je promena stanja artikla sa nazivom artikla
+25
View File
@@ -0,0 +1,25 @@
-- Proširuje CHECK constraint na magacinske_promene da uključi manjak_popis i visak_popis
-- SQLite ne podržava ALTER TABLE za CHECK, pa rekreiramo tabelu
PRAGMA foreign_keys=OFF;
CREATE TABLE magacinske_promene_nova (
id INTEGER PRIMARY KEY AUTOINCREMENT,
artikal_id INTEGER NOT NULL REFERENCES artikli(id) ON DELETE RESTRICT,
tip_promene TEXT NOT NULL CHECK (tip_promene IN (
'ulaz_nabavka', 'izlaz_prodaja', 'izlaz_servis',
'povracaj', 'korekcija', 'manjak_popis', 'visak_popis'
)),
referentni_id INTEGER NOT NULL,
promena_kolicine INTEGER NOT NULL,
stanje_pre INTEGER NOT NULL,
stanje_posle INTEGER NOT NULL,
korisnik_id INTEGER REFERENCES korisnici(id) ON DELETE SET NULL,
napomena TEXT,
datum DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO magacinske_promene_nova SELECT * FROM magacinske_promene;
DROP TABLE magacinske_promene;
ALTER TABLE magacinske_promene_nova RENAME TO magacinske_promene;
PRAGMA foreign_keys=ON;
@@ -129,6 +129,10 @@
<span class="bedz" style="background:rgba(168,85,247,0.12);color:#a855f7;">Povraćaj</span>
{{else if eq .TipPromene "korekcija"}}
<span class="bedz" style="background:rgba(156,163,175,0.12);color:#9ca3af;">Korekcija</span>
{{else if eq .TipPromene "manjak_popis"}}
<span class="bedz" style="background:rgba(220,38,38,0.12);color:#dc2626;">Manjak (popis)</span>
{{else if eq .TipPromene "visak_popis"}}
<span class="bedz" style="background:rgba(34,197,94,0.12);color:#22c55e;">Višak (popis)</span>
{{else}}
<span class="bedz">{{.TipPromene}}</span>
{{end}}
@@ -66,6 +66,10 @@
<span class="bedz" style="background:rgba(168,85,247,0.12);color:#a855f7;">Povraćaj</span>
{{else if eq .TipPromene "korekcija"}}
<span class="bedz" style="background:rgba(156,163,175,0.12);color:#9ca3af;">Korekcija</span>
{{else if eq .TipPromene "manjak_popis"}}
<span class="bedz" style="background:rgba(220,38,38,0.12);color:#dc2626;">Manjak (popis)</span>
{{else if eq .TipPromene "visak_popis"}}
<span class="bedz" style="background:rgba(34,197,94,0.12);color:#22c55e;">Višak (popis)</span>
{{else}}
<span class="bedz">{{.TipPromene}}</span>
{{end}}