Skip to main content

furs-fiscalization

Python library for simplified communication with FURS (Finančna uprava Republike Slovenije).

Installation

$ pip install furs_fiscalization

Logging

This library uses Python's standard logging module and does not call logging.basicConfig() (so it plays nicely with Odoo's logging configuration).

Odoo integration

By default, logs from this package propagate to the application's root logger. In Odoo, they will appear in the Odoo logs if your Odoo log level includes them.

Dedicated log file (optional)

You can enable a rotating log file either via environment variables:

  • FURS_FISCALIZATION_LOG_FILE (path to the log file)
  • FURS_FISCALIZATION_LOG_LEVEL (e.g. DEBUG, INFO)

Or from code (call once at startup):

from furs_fiscalization.logging_utils import configure_logging

configure_logging(log_file="/var/log/odoo/furs_fiscalization.log", level="DEBUG")

Trust and verification

The FURS endpoints (blagajne.fu.gov.si, blagajne-test.fu.gov.si) are not signed by a public CA; the library ships their anchors in furs_fiscalization/certs/furs-ca-bundle.pem (SIGOV-CA and SI-TRUST Root). TLS verification against that bundle is available but off by default (verify_tls=False, the behaviour of releases before 1.0.15 - only urllib3's InsecureRequestWarning is silenced); pass verify_tls=True to enable it. Verification of the signed responses is available but off by default (verify_response_signature=False), so a FURS certificate rotation can never block fiscalization. With verify_response_signature=True the certificate FURS puts into the x5c JWS header must chain to the same bundle, be valid and carry the expected common name (DavPotRac in production, DavPotRacTEST on the test system); only then is the RS256 signature verified. A failed check raises ResponseVerificationException and the response is discarded.

api = FURSInvoiceAPI(p12_path='my_cert.p12', p12_password='cert_pass', production=True,
                     verify_tls=True, verify_response_signature=True)

Both anchors can be replaced with the ca_bundle= and signer_common_name= keyword arguments of any API class, for example when FURS rotates its certificates before a new release ships.

The protective mark (ZOI) is computed exactly as the FURS technical documentation prescribes: SHA256withRSA (PKCS#1 v1.5, deterministic) over tax number, dd.MM.yyyy HH:mm:ss, invoice number, business premise, electronic device and the amount with two decimals, reduced with MD5.

Quick Start

Registering Immovable Business Premise

Registering new Business Premises is simple. But you will need to obtain certain information from your client such as:

  • Real Estate Cadastral Number
  • Real Estate Building Number
  • Real Estate Building Section Number

One thing you should also keep in mind is your premise address - if your premise is located at Tovarniška ulica you will need to pass house number 12 and additional number A as separate parameters. If your street does not have additional house number/letter just pass None.

from furs_fiscalization.api import FURSBusinessPremiseAPI

api = FURSBusinessPremiseAPI(p12_path = 'my_cert.p12',
                             p12_password = 'cert_pass',
                             production = True, request_timeout=2.0)

api.register_immovable_business_premise(tax_number = 10128085,
                                        premise_id = 'PP001',
                                        real_estate_cadastral_number = 1322,
                                        real_estate_building_number = 1,
                                        real_estate_building_section_number = 1,
                                        street = 'Tovarniška ulica',
                                        house_number = '12',
                                        house_number_additional = 'A',
                                        community = 'Krško',
                                        city = 'Krško',
                                        postal_code = '8270',
                                        validity_date = datetime.now() - timedelta(days=60),
                                        software_supplier_tax_number = 10128085,
                                        foreign_software_supplier_name = None,
                                        special_notes = '')

NOTE: As of 23.11.2015 FURS does require you to send some kind of Special note to them. Empty string will raise invalid JSON on their side.

Registering Movable Business Premise

In order to register Movable Business Premise you will need to define one of three types:

  • TYPE_MOVABLE_PREMISE_A: Movable object such as vehicle, movable stand etc.
  • TYPE_MOVABLE_PREMISE_B: Object at permanent location such as news stand, market stand etc.
  • TYPE_MOVABLE_PREMISE_C: Individual electronic device in cases when the company does not use other business premises
from furs_fiscalization.api import FURSBusinessPremiseAPI, TYPE_MOVABLE_PREMISE_A

api = FURSBusinessPremiseAPI(p12_path = 'my_cert.p12',
                             p12_password = 'cert_pass',
                             production = False,
                             request_timeout = 2.0)

api.register_movable_business_premise(tax_number = 10128085,
                                      premise_id = 'PP001',
                                      movable_type = TYPE_MOVABLE_PREMISE_A,
                                      validity_date = datetime.now() - timedelta(days=60),
                                      software_supplier_tax_number = 10128085,
                                      foreign_software_supplier_name = None,
                                      special_notes = '')

Calculate Invoice ZOI - Protected ID

At the end of every Invoice your should print ZOI (Protected ID). To obtain it follow the next procedure:

from furs_fiscalization.api import FURSInvoiceAPI

api = FURSInvoiceAPI(p12_path = 'my_cert.p12',
                     p12_password = 'cert_pass',
                     production = False,
                     request_timeout = 1.0)

date_issued = datetime.now()

zoi = api.calculate_zoi(tax_number = 10128085,
                        issued_date = date_issued,
                        invoice_number = '11',
                        business_premise_id = 'PP001',
                        electronic_device_id = 'BLAG1',
                        invoice_amount = Decimal('19.15'))

Generate Data for QR/Code128/PDF417

You're supposed to print QR Code/Code128 or PDF 417 on every invoice after the ZOI. To obtain the data for QR/Code128/PDF417 perform the following method call on FURSInvoiceAPI object.

qr_data = api.prepare_printable(tax_number = 10128085,
                                zoi = zoi,
                                issued_date = date_issued)

Get EOR From FURS

To obtain FURS EOR code - UniqueID, you'll have to call the following method. It provides several other parameters, for issuing invoice storno and special tax rules. Please read the full documentation.

eor = api.get_invoice_eor(zoi = zoi,
                          tax_number = 10128085,
                          issued_date = date_issued,
                          invoice_number = '11',
                          business_premise_id = 'PP001',
                          electronic_device_id = 'BLAG1',
                          invoice_amount = 66.71,
                          low_tax_rate_base = 35.14,
                          low_tax_rate_amount = 3.34,
                          high_tax_rate_base = 23.14,
                          high_tax_rate_amount = 5.09,
                          lowered_tax_rate_base = None,
                          lowered_tax_rate_amount = None,
                          operator_tax_number = 12345678)

Contact

Hermes d.o.o.

Metadata

Release files for furs-fiscalization 1.0.15

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for furs-fiscalization 1.0.15
File Size Uploaded Provenance Actions
furs_fiscalization-1.0.15.tar.gz 30.8 kB Without provenance Details for furs_fiscalization-1.0.15.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for furs-fiscalization 1.0.15
File Interpreter ABI Platform Actions
furs_fiscalization-1.0.15-py3-none-any.whl Python 3 none any Details for furs_fiscalization-1.0.15-py3-none-any.whl

Total release size: 53.5 kB

Release files / furs_fiscalization-1.0.15.tar.gz

Download URL furs_fiscalization-1.0.15.tar.gz
Size 30.8 kB
Tags Source
SHA-256 checksum
How to use checksums
d62310613a890ddd0f6838268be2a1457896ba666aad209a2ce6b2753ddce508
BLAKE2b-256 checksum
How to use checksums
5134971fae2530761bd7780182cb0bb718c57afb710611bd1ed43e07859808de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.0

Release files / furs_fiscalization-1.0.15-py3-none-any.whl

Download URL furs_fiscalization-1.0.15-py3-none-any.whl
Size 22.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b69246b1989eee0692ed139deaa7a4d10eb41d60b91a1447daa89786450409c7
BLAKE2b-256 checksum
How to use checksums
0c10134fe5562347b89044e98524eafc762d989c32f20a721b855fa44d46ed03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.0

Security for furs-fiscalization 1.0.15

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page