Metadata-Version: 2.4
Name: byteinnov-fiscal-invoice
Version: 0.1.0
Summary: Calcul des totaux d'une facture fiscale (TVA, accise, impôts de sécurité, remises) — port Python de fiscal-invoice-starter
Project-URL: Homepage, https://gitlab.byteinnov.com/bi-dev-team/packages/fiscal-invoice
Project-URL: Source, https://gitlab.byteinnov.com/bi-dev-team/packages/fiscal-invoice/-/tree/main/python
Author: Byteinnov
License: Apache-2.0
Keywords: cote-divoire,facture,fiscal,invoice,tax,vat
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# byteinnov-fiscal-invoice

Calcul des totaux d'une facture fiscale : cascade par ligne (remise → accise → TVA) puis
document (impôts de sécurité, timbre).

Port Python de `fiscal-invoice-starter` (Kotlin), à la virgule près : mêmes règles, mêmes
arrondis (`ROUND_HALF_UP`, échelle 2), mêmes tests. Arithmétique décimale exacte (module
`decimal` de la bibliothèque standard), zéro dépendance — le module ne connaît ni PDV, ni
certification, ni paiement.

## Installation

```bash
pip install byteinnov-fiscal-invoice
```

Python 3.10+.

## Utilisation

```python
from fiscal_invoice import (
    Invoice, InvoiceLine, PriceDefinitionMode, SecurityTax, SpecificTax, TaxGroup,
    calculate_invoice,
)

result = calculate_invoice(Invoice(
    lines=[
        InvoiceLine(
            description="Ordinateur portable",
            quantity=2,
            price="3000",                                   # prix unitaire
            price_definition_mode=PriceDefinitionMode.TTC,  # ... défini TTC (accise comprise)
            tax_group=TaxGroup(code="B", vat_rate_percent="18"),
            tax_specific=SpecificTax(amount="10"),          # accise forfaitaire par unité
            discount_percent="5",                           # remise de ligne
        ),
    ],
    discount_percent="3",                                   # remise document
    security_taxes=[SecurityTax(code="AIB1", rate_percent="1")],  # surcharge sur la base taxable
    stamp="100",                                            # timbre
))

result.total.total.ttc          # total toutes taxes comprises (Decimal)
result.total.security_tax_amount  # montant de l'AIB
result.tax_breakdown            # ventilation par groupe de TVA (taux décroissant)
```

Les montants d'entrée acceptent `int`, `str`, `float` ou `Decimal` (préférez `str`/`Decimal`
pour l'exactitude) ; les montants de sortie sont des `decimal.Decimal`.

## Règles de calcul

**Par ligne**

| Mode de prix | HT unitaire dérivé | Accise |
|---|---|---|
| `HT` | le prix **est** le HT | valeur forfaitaire, ou % du HT |
| `TTC` (accise en valeur) | `prix / (1 + tva) − accise` | la valeur forfaitaire |
| `TTC` (accise en %) | `prix / ((1 + accise%) × (1 + tva))` | `HT × accise%` |

Cascade : HT brut → remise de ligne → remise document → **HT net**.
Base TVA = **HT net + accise** (l'accise n'est pas remisée).

En mode `TTC`, **le TTC prime** : le TTC de la ligne vaut exactement `quantité × prix saisi`
(moins les remises converties en TTC) et la TVA est le **complément** (`TTC − base taxable`).
Sans cela, recomposer `base + arrondi(base × taux)` dérive d'un centime.

**Au niveau document**

- Impôts de sécurité (AIRSI, AIB…) : taux **toujours** appliqué sur la base taxable
  (HT net + accise), plusieurs surcharges possibles.
- `TTC document = TTC des biens + impôts de sécurité + timbre`.
- Ventilation TVA triée par taux décroissant.

## Développement

```bash
pip install -e . --group dev
pytest              # tests (portés depuis le starter Kotlin)
python -m build     # wheel + sdist
```

## Publication (mainteneurs)

Mettre à jour `version` dans `pyproject.toml` et `__version__` dans
`src/fiscal_invoice/__init__.py`, committer, puis :

```sh
git tag python-v0.1.0 && git push origin python-v0.1.0
```

Le job GitLab CI `release-python` construit et publie sur PyPI (variable CI/CD `PYPI_TOKEN`,
token API du projet sur pypi.org).

## Licence

[Apache-2.0](../LICENSE)
