Prodaja: modal naplate sa fiskalnim računom (kao u Servisu)

- dugme Naplati otvara modal (primljeno/kusur, način plaćanja, prikaz računa)
- primljeni iznos se prosleđuje u fiskalni zahtev radi tačnog Gotovina/Povraćaj
- nova ruta i handler za prikaz/štampu fiskalnog računa prodaje
- fiskalni tab se otvara preko imenovanog prozora (bez blokiranja popup-a)
- Fisk mock: refund se sada računa iz stvarnih plaćanja, ne fiksno 0
This commit is contained in:
2026-07-01 21:03:47 +02:00
parent 1df83866df
commit fd762a6527
7 changed files with 204 additions and 57 deletions
+22
View File
@@ -138,6 +138,10 @@ document.addEventListener('alpine:init', () => {
Alpine.data('prodajaForma', () => ({
stavke: [{artikal_id: '', kolicina: 1, cena: 0, cena_sa_pdv: 0, pdv_stopa: 20, popust: 0, kategorija_naziv: '', _naziv: '', _pretraga: '', _prikaziListu: false, _limit: 30}],
zbirnoHover: false,
nacinPlacanja: 'gotovina',
primljenoIznos: '',
prikaziRacun: true,
_fiskalniTab: null,
artikliOpcije: [],
pretragaArtikal: '',
pdvObveznik: true,
@@ -357,6 +361,24 @@ document.addEventListener('alpine:init', () => {
this.stavke = this.stavke.filter(s => s.artikal_id)
this.$nextTick(() => e.target.submit())
},
otvoriModalNaplate() {
this.primljenoIznos = ''
this.$refs.dijalogNaplate.showModal()
},
kusurIznos() {
return (parseFloat(this.primljenoIznos) || 0) - parseFloat(this.ukupnoSvega())
},
naplataValidna() {
return this.primljenoIznos !== '' && (parseFloat(this.primljenoIznos) || 0) >= parseFloat(this.ukupnoSvega())
},
// pripremiFiskalniTab otvara prazan tab SINHRONO unutar klika (očuvan user gesture),
// da bi kasnije, posle redirekta na stranicu detalja prodaje, mogao da se imenom
// popuni URL-om fiskalnog računa bez blokiranja popup-blokera
pripremiFiskalniTab() {
if (this.prikaziRacun) {
this._fiskalniTab = window.open('', 'ntech-fiskalni-tab')
}
},
ukupnoStavke(s) {
const cena = parseFloat(s.cena) || 0
const popust = parseFloat(s.popust) || 0