Metadata-Version: 2.4
Name: italian-tax-validators
Version: 1.1.0
Summary: Python library for validating Italian Codice Fiscale and Partita IVA
Author-email: Michele Broggi <michele@broggi.work>
License-Expression: MIT
Project-URL: Homepage, https://github.com/thesmokinator/italian-tax-validators
Project-URL: Documentation, https://github.com/thesmokinator/italian-tax-validators#readme
Project-URL: Repository, https://github.com/thesmokinator/italian-tax-validators.git
Project-URL: Issues, https://github.com/thesmokinator/italian-tax-validators/issues
Keywords: italian,codice-fiscale,partita-iva,tax-id,validation,fiscal-code,vat
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Natural Language :: Italian
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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 :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.md
Dynamic: license-file

# Italian Tax Validators

A comprehensive Python library for validating and generating Italian fiscal identification documents:

- **Codice Fiscale (CF)**: Italian personal tax identification code
- **Partita IVA (P.IVA)**: Italian VAT registration number

## Features

✅ **Codice Fiscale Validation**
- Format validation with omocodia handling
- Check digit verification
- Birthdate, age, and gender extraction
- Birth place lookup (municipality name and province)
- Minimum age verification (18+ by default)

✅ **Codice Fiscale Generation**
- Generate CF from personal data (name, surname, birthdate, gender, birth place)
- Automatic check digit calculation
- Municipality code lookup by name

✅ **Partita IVA Validation**
- Format and check digit verification (Italian Luhn algorithm)
- Temporary VAT number detection (starts with 99)
- Provincial office code extraction

✅ **Municipality Database**
- ~200 major Italian municipalities with cadastral codes
- Foreign country codes
- Search by name or code

✅ **Command-Line Interface**
- Validate CF and P.IVA from terminal
- Generate CF from command line
- Search municipality codes

✅ **Developer Friendly**
- Simple, intuitive API
- Type hints for IDE support
- Zero external dependencies
- Python 3.9+

## Installation

```bash
pip install italian-tax-validators
```

## Quick Start

### Validating Codice Fiscale

```python
from italian_tax_validators import validate_codice_fiscale

# Basic validation
result = validate_codice_fiscale("RSSMRA85M01H501Q")
print(result.is_valid)      # True
print(result.birthdate)     # 1985-08-01
print(result.age)           # 40
print(result.gender)        # "M"
print(result.birth_place_name)     # "ROMA"
print(result.birth_place_province) # "RM"

# With age verification
result = validate_codice_fiscale("RSSMRA85M01H501Q", check_adult=True)
print(result.is_valid)  # True (person is 18+)

# With custom minimum age
result = validate_codice_fiscale("RSSMRA85M01H501Q", check_adult=True, minimum_age=21)
```

### Generating Codice Fiscale

```python
from datetime import date
from italian_tax_validators import generate_codice_fiscale

result = generate_codice_fiscale(
    surname="Rossi",
    name="Mario",
    birthdate=date(1985, 8, 1),
    gender="M",
    birth_place_code="H501"  # Rome
)
print(result.codice_fiscale)  # "RSSMRA85M01H501Q"
```

### Validating Partita IVA

```python
from italian_tax_validators import validate_partita_iva

result = validate_partita_iva("12345678903")
print(result.is_valid)       # True
print(result.province_code)  # "890"
print(result.is_temporary)   # False

# Flexible input handling
result = validate_partita_iva("IT 123 456 78903")  # Works with spaces and prefix
```

### Municipality Lookup

```python
from italian_tax_validators import (
    get_municipality_info,
    get_cadastral_code,
    search_municipality
)

# Get info from cadastral code
info = get_municipality_info("H501")
print(info)  # ("ROMA", "RM")

# Get cadastral code from name
code = get_cadastral_code("MILANO")
print(code)  # "F205"

# Search by partial name
results = search_municipality("ROMA")
# [("H501", "ROMA", "RM"), ("Z124", "ROMANIA", "EE")]
```

## Command-Line Interface

The package includes a CLI tool for quick validations:

```bash
# Validate Codice Fiscale
italian-tax-validators validate-cf RSSMRA85M01H501Q

# Validate with age check
italian-tax-validators validate-cf RSSMRA85M01H501Q --check-adult --minimum-age 21

# Validate Partita IVA
italian-tax-validators validate-piva 12345678903

# Generate Codice Fiscale
italian-tax-validators generate-cf \
    --surname Rossi \
    --name Mario \
    --birthdate 1985-08-01 \
    --gender M \
    --birth-place-code H501

# Generate using municipality name
italian-tax-validators generate-cf \
    --surname Rossi \
    --name Mario \
    --birthdate 1985-08-01 \
    --gender M \
    --birth-place ROMA

# Search municipality codes
italian-tax-validators search-municipality MILAN
```

## API Reference

See [API.md](API.md) for complete API documentation.

### Quick Reference

| Function | Description |
|----------|-------------|
| `validate_codice_fiscale(value, check_adult, minimum_age)` | Validate a Codice Fiscale |
| `validate_partita_iva(value)` | Validate a Partita IVA |
| `generate_codice_fiscale(surname, name, birthdate, gender, birth_place_code)` | Generate a Codice Fiscale |
| `get_municipality_info(code)` | Get municipality name and province from cadastral code |
| `get_cadastral_code(name)` | Get cadastral code from municipality name |
| `search_municipality(query)` | Search municipalities by partial name |
| `is_foreign_country(code)` | Check if cadastral code is a foreign country |

## Codice Fiscale Structure

The Italian Codice Fiscale is a 16-character alphanumeric code:

```
RSSMRA85M01H501Q
├─ RSS    → Surname (first 3 consonants)
├─ MRA    → Name (first 3 consonants, or 1st+3rd+4th if 4+ consonants)
├─ 85     → Birth year (1985)
├─ M      → Birth month (M = August)
├─ 01     → Birth day (01), +40 for females (e.g., 41 = day 1, female)
├─ H501   → Birth place cadastral code (H501 = Rome)
└─ Q      → Check digit
```

### Month Codes
| Code | Month | Code | Month |
|------|-------|------|-------|
| A | January | L | July |
| B | February | M | August |
| C | March | P | September |
| D | April | R | October |
| E | May | S | November |
| H | June | T | December |

### Omocodia
When multiple people share the same CF, digits can be replaced with letters:
- L=0, M=1, N=2, P=3, Q=4, R=5, S=6, T=7, U=8, V=9

The library automatically handles omocodia substitutions during validation.

## Partita IVA Structure

The Italian Partita IVA is an 11-digit number:

```
12345678903
├─ 1234567  → Company registration number (matricola)
├─ 890      → Provincial office code
└─ 3        → Check digit (Luhn algorithm variant)
```

**Note:** VAT numbers starting with `99` are temporary numbers.

## Testing

```bash
# Run tests with pytest
pytest tests/

# Run with coverage
pytest tests/ --cov=italian_tax_validators

# Run with unittest
python -m unittest discover tests/
```

## Examples

### Django Integration

```python
from django.core.exceptions import ValidationError
from italian_tax_validators import validate_codice_fiscale

def validate_cf(value):
    result = validate_codice_fiscale(value, check_adult=True)
    if not result.is_valid:
        raise ValidationError(f"Invalid CF: {result.error_code}")

class Person(models.Model):
    codice_fiscale = models.CharField(max_length=16, validators=[validate_cf])
```

### Pydantic Integration

```python
from pydantic import BaseModel, field_validator
from italian_tax_validators import validate_codice_fiscale

class PersonForm(BaseModel):
    codice_fiscale: str
    
    @field_validator('codice_fiscale')
    @classmethod
    def validate_cf(cls, v):
        result = validate_codice_fiscale(v, check_adult=True)
        if not result.is_valid:
            raise ValueError(f"Invalid Codice Fiscale: {result.error_code}")
        return result.formatted_value
```

### FastAPI Integration

```python
from fastapi import FastAPI, HTTPException
from italian_tax_validators import validate_codice_fiscale, validate_partita_iva

app = FastAPI()

@app.get("/validate/cf/{value}")
def validate_cf(value: str, check_adult: bool = False):
    result = validate_codice_fiscale(value, check_adult=check_adult)
    if not result.is_valid:
        raise HTTPException(400, detail=result.error_code)
    return {
        "codice_fiscale": result.formatted_value,
        "birthdate": str(result.birthdate),
        "age": result.age,
        "gender": result.gender,
        "birth_place": result.birth_place_name,
    }
```

## License

MIT License - See [LICENSE.md](LICENSE.md) for details.

## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## Changelog

### v1.1.0
- ✨ Added Codice Fiscale generation
- ✨ Added gender extraction from CF
- ✨ Added birth place lookup (municipality database)
- ✨ Added temporary VAT number detection
- ✨ Added provincial office code extraction from P.IVA
- ✨ Added command-line interface (CLI)
- 📚 Added comprehensive API documentation

### v1.0.0
- Initial release with CF and P.IVA validation

## Resources

- [Agenzia delle Entrate](https://www.agenziaentrate.gov.it/) - Official Italian Tax Agency
- [Codice Fiscale Format](https://it.wikipedia.org/wiki/Codice_fiscale) - Wikipedia
- [Partita IVA Format](https://it.wikipedia.org/wiki/Partita_IVA) - Wikipedia
