Ugrás a tartalomra
kassza

Pénzszámítás

A kassza a számla tételeinek nettó, áfa és bruttó értékét maga számolja ki az egységárból és az áfakulcsból. Ugyanezek a függvények a kassza/money modulból is elérhetők, így a kosárban, a rendelés-összesítőben vagy a visszaigazoló e-mailben pontosan azt az összeget mutathatod, ami a számlára kerül. A modul nem hív hálózatot és nem kell hozzá Agent kulcs, ezért böngészőben is futtatható.

Bizonylat
Az ár alapja
Pénznem
Nettó egységár
4716,67 Ft
Nettó érték
14 150 Ft
Áfa
3820 Ft
Bruttó érték
17 970 Ft
calculateInvoiceItem({ quantity: 3, grossUnitPrice: 5990, vat: 27 })

Az összes export#

ExportMire való?
calculateInvoiceItem(input, currency?)Egy számlatétel összegei a számla kerekítési szabályai szerint
calculateReceiptItem(input, currency?)Egy nyugtatétel összegei a nyugta kerekítési szabályai szerint
calculateItemAmounts(input, { kind, currency? })Ugyanez, a bizonylat fajtája ('invoice' vagy 'receipt') paraméterben
summarizeItems(items)Végösszeg és áfakulcsonkénti bontás a kiszámolt tételekből
roundMoney(value, decimals?)Kereskedelmi kerekítés, alapból egészre
addMoney(...values)Összeadás lebegőpontos zaj nélkül
decimalPlaces(value)Egy szám tizedesjegyeinek száma
isVatRate(value)Típusőr: a Számlázz.hu által elfogadott áfakulcs-e
vatPercentage(rate)Az áfakulcs százalékban, a szöveges kódoknál 0
formatVatRate(rate)Az áfakulcs szövegként, ahogy az XML-be kerül
NUMERIC_VAT_RATESA 36 számmal megadható áfakulcs
SPECIAL_VAT_CODESA 16 szöveges áfakód, például AAM, TAM, EUFAD37
isHuf(currency)Forintnak számít-e a megadott pénznem

A típusok is innen importálhatók: ItemPriceInput, ItemAmounts, DocumentKind, DocumentTotals, VatBreakdown, VatRate, NumericVatRate és SpecialVatCode.

Egy tétel kiszámolása#

import { calculateInvoiceItem, calculateReceiptItem } from 'kassza/money'

const b2b = calculateInvoiceItem({ quantity: 3, netUnitPrice: 500, vat: 27 })
const b2c = calculateInvoiceItem({ quantity: 3, grossUnitPrice: 500, vat: 27 })
const euro = calculateInvoiceItem({ quantity: 7, netUnitPrice: 12.35, vat: 27 }, 'EUR')
const nyugta = calculateReceiptItem({ grossUnitPrice: 1_000, vat: 27 })
VáltozónetUnitPricenetAmountvatAmountgrossAmount
b2b5001 5004051 905
b2c393,671 1813191 500
euro12,3586,4523,34109,79
nyugta787,4787,4212,61 000

A bemenet (ItemPriceInput) mezői:

MezőLeírás
vatÁfakulcs, számmal (27) vagy kóddal ('AAM'). Kötelező.
quantityMennyiség, alapból 1. Nem lehet 0, negatív lehet.
netUnitPriceNettó egységár, nettó alapú számításhoz.
grossUnitPriceBruttó egységár, bruttó alapú számításhoz. A kettő közül pontosan egyet adj meg.
netAmount, vatAmount, grossAmountSaját összegek. Ha bármelyiket megadod, mindhármat meg kell adnod, és a függvény nem számol.

Az eredmény (ItemAmounts) a quantity, vat, netUnitPrice, netAmount, vatAmount és grossAmount mezőt tartalmazza. Bruttó alapú számításnál a netUnitPrice a nettó értékből visszaszámolt egységár.

A második paraméter a pénznem. Ha elhagyod, vagy az isHuf() szerint forint, a forintos szabályok érvényesek, minden más pénznemnél a devizásak:

BizonylatNettó értékÁfa értékBruttó érték
Forintos számlaegészegészegész
Forintos nyugta2 tizedes2 tizedesegész
Devizás számla vagy nyugta2 tizedes2 tizedes2 tizedes

A lépések sorrendjét és a bruttó alapú visszaszámolást a Kerekítés oldal, a nyugta szabályait a Tételösszegek oldal írja le.

Kosár végösszege#

A kerekítés tételenként történik, ezért a végösszeget is a kiszámolt tételekből kell összeadni. Ezt csinálja a summarizeItems():

import { calculateInvoiceItem, summarizeItems } from 'kassza/money'

const kosar = [
  { name: 'Társasjáték', quantity: 2, grossUnitPrice: 5_990, vat: 27 },
  { name: 'Szakácskönyv', quantity: 1, grossUnitPrice: 3_500, vat: 5 },
  { name: 'Házhoz szállítás', quantity: 1, grossUnitPrice: 1_490, vat: 27 },
]

const tetelek = kosar.map((sor) => calculateInvoiceItem(sor))
const { netAmount, vatAmount, grossAmount, byVat } = summarizeItems(tetelek)
ÁfakulcsNettóÁfaBruttó
27%10 606 Ft2 864 Ft13 470 Ft
5%3 333 Ft167 Ft3 500 Ft
Összesen13 939 Ft3 031 Ft16 970 Ft

A byVat tömb az áfakulcsokat a tételekben való első előfordulásuk sorrendjében tartalmazza. Az összegeket a függvény 6 tizedesjegyre kerekíti, így a devizás tételek összeadásakor sem marad lebegőpontos zaj a végén.

Ha ugyanezekkel a tételekkel állítod ki a számlát, a kassza.invoices.create() válaszában a netTotal 13 939, a grossTotal 16 970 lesz, vagyis a kosárban mutatott összeg és a számla fillérre egyezik:

const szamla = await kassza.invoices.create({
  orderNumber: 'REND-2042',
  buyer: { name: 'Nagy Péter', zip: '1111', city: 'Budapest', address: 'Fő utca 1.' },
  items: kosar,
})

Kerekítés és összegzés

Nettó és bruttó alapú számítás, nyugta kerekítés, deviza, áfabontás.

Futtatás a sandboxban
kerekites.ts
import { , ,  } from 'kassza/money'

const  = ({ : 3, : 1_999, : 27 })
const  = ({ : 3, : 500, : 27 })
const  = ({ : 1_000, : 27 })
const  = ({ : 7, : 12.35, : 27 }, 'EUR')

.('Nettó alapú (B2B):', )
.('Bruttó alapú (B2C):', )
.('Nyugta tétel:', )
.('Euró:', )

const  = ([
  ,
  ,
  ({ : 3_500, : 5 }),
])
.('Áfabontás:', )

Kerekítés és összeadás#

A JavaScript beépített kerekítése pénzösszegeknél meglepetéseket okoz. A roundMoney() kereskedelmi kerekítést használ (a fél érték nulláról elfelé kerekedik), és a lebegőpontos pontatlanságot 15 értékes jegyre normalizálja. Az addMoney() összead, és az eredményt a bemenetek közül a legtöbb tizedesjegyre kerekíti.

import { addMoney, decimalPlaces, roundMoney } from 'kassza/money'

const ketTizedes = roundMoney(1.005, 2)
const negativ = roundMoney(-2.5)
const osszeg = addMoney(0.1, 0.2)
const tizedesek = decimalPlaces(12.35)
VáltozókasszaBeépített megoldással
ketTizedes1.01Math.round(1.005 * 100) / 100 eredménye 1
negativ-3Math.round(-2.5) eredménye -2
osszeg0.30.1 + 0.2 eredménye 0.30000000000000004
tizedesek2

A roundMoney() második paramétere a tizedesjegyek száma, alapból 0. NaN vagy végtelen értékre RangeError-t dob.

Áfakulcsok és pénznem#

Az isVatRate() típusőr megmondja, hogy egy érték a Számlázz.hu által elfogadott áfakulcs-e: szám a NUMERIC_VAT_RATES listából, vagy szöveg a SPECIAL_VAT_CODES listából. Számot tartalmazó szövegre ('27') false-t ad, ezért adatbázisból vagy CSV-ből olvasott értéket előbb alakíts át:

import { isVatRate, type VatRate } from 'kassza/money'

export function afakulcs(ertek: string): VatRate {
  const szoveg = ertek.trim()
  const szam = Number(szoveg)
  const jelolt = szoveg !== '' && Number.isFinite(szam) ? szam : szoveg
  if (!isVatRate(jelolt)) throw new Error(`Ismeretlen áfakulcs: ${ertek}`)
  return jelolt
}

Ezzel a '27' és az ' 5.5 ' számmá, az 'AAM' kóddá alakul, a '28' pedig hibát dob. A kulcsok jelentését és a szöveges kódokat az Áfakulcsok oldal sorolja fel.

A vatPercentage() a számmal megadott kulcsot adja vissza, a szöveges kódoknál 0-t, és a kassza ezzel a százalékkal számolja a tétel áfáját. Az isHuf() akkor ad true-t, ha a pénznem hiányzik, vagy a szóközök levágása után HUF, huf, Ft, FT vagy ft. Más írásmódot, például Huf-ot, devizának vesz.

Oldal szerkesztéseUtoljára frissítve: