validate_cedente_prestatore
Validates seller (CedentePrestatore) data for FatturaPA invoices: ensures valid name, fiscal regime code, and Italian VAT format. Outputs block for XML or error list.
Instructions
Validate and build the CedentePrestatore (seller) block for FatturaPA.
Use this as step 4 in the invoice generation workflow, after build_transmission_header() and before validate_cessionario(). Call get_regime_fiscale_codes() first if you need to look up the RF code.
Validates: either denominazione or both nome+cognome must be provided (mutually exclusive); regime_fiscale must be a valid RF01–RF19 code; Italian Partita IVA (id_paese='IT') must be exactly 11 digits.
On success returns {'CedentePrestatore': {...}} ready to pass to generate_fattura_xml(). On failure returns {'error': ''} listing all validation issues joined by '; '.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id_paese | Yes | ISO 3166-1 two-letter country code of the seller (e.g. 'IT'). | |
| id_codice | Yes | Partita IVA (11 digits) or foreign VAT number of the seller. | |
| denominazione | No | Company name (Denominazione). Mutually exclusive with nome+cognome. | |
| nome | No | First name (Nome), for individual sellers. | |
| cognome | No | Last name (Cognome), for individual sellers. | |
| regime_fiscale | No | Fiscal regime code RF01–RF19. Use get_regime_fiscale_codes() for the complete list. Most companies use RF01 (ordinary regime). | RF01 |
| indirizzo | No | Street address (via, piazza…) of the registered office. | |
| cap | No | Italian postal code (5 digits) or foreign equivalent. | |
| comune | No | City/municipality of the registered office. | |
| nazione | No | ISO 3166-1 two-letter country code of the registered office. | IT |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- tools/header_tools.py:151-255 (handler)Main handler for validate_cedente_prestatore — validates seller (CedentePrestatore) block: checks denominazione vs nome+cognome mutual exclusivity, regime_fiscale validity against REGIME_FISCALE dict, Italian Partita IVA must be 11 digits, returns structured CedentePrestatore dict or error.
def validate_cedente_prestatore( id_paese: Annotated[ str, Field(description="ISO 3166-1 two-letter country code of the seller (e.g. 'IT')."), ], id_codice: Annotated[ str, Field(description="Partita IVA (11 digits) or foreign VAT number of the seller."), ], denominazione: Annotated[ Optional[str], Field( default=None, description="Company name (Denominazione). Mutually exclusive with nome+cognome.", ), ] = None, nome: Annotated[ Optional[str], Field(default=None, description="First name (Nome), for individual sellers."), ] = None, cognome: Annotated[ Optional[str], Field(default=None, description="Last name (Cognome), for individual sellers."), ] = None, regime_fiscale: Annotated[ str, Field( description=( "Fiscal regime code RF01–RF19. Use get_regime_fiscale_codes() for the " "complete list. Most companies use RF01 (ordinary regime)." ) ), ] = "RF01", indirizzo: Annotated[ str, Field(description="Street address (via, piazza…) of the registered office."), ] = "", cap: Annotated[ str, Field(description="Italian postal code (5 digits) or foreign equivalent."), ] = "", comune: Annotated[ str, Field(description="City/municipality of the registered office."), ] = "", nazione: Annotated[ str, Field(description="ISO 3166-1 two-letter country code of the registered office."), ] = "IT", ) -> dict: """Validate and build the CedentePrestatore (seller) block for FatturaPA. Use this as step 4 in the invoice generation workflow, after build_transmission_header() and before validate_cessionario(). Call get_regime_fiscale_codes() first if you need to look up the RF code. Validates: either denominazione or both nome+cognome must be provided (mutually exclusive); regime_fiscale must be a valid RF01–RF19 code; Italian Partita IVA (id_paese='IT') must be exactly 11 digits. On success returns {'CedentePrestatore': {...}} ready to pass to generate_fattura_xml(). On failure returns {'error': '<reason>'} listing all validation issues joined by '; '. """ errors: list[str] = [] if not denominazione and not (nome and cognome): errors.append("Either 'denominazione' or both 'nome' and 'cognome' are required.") if denominazione and (nome or cognome): errors.append("'denominazione' is mutually exclusive with 'nome'/'cognome'.") if regime_fiscale not in REGIME_FISCALE: errors.append( f"Invalid regime_fiscale '{regime_fiscale}'. " f"Valid codes: {', '.join(REGIME_FISCALE.keys())}." ) if id_paese == "IT" and not re.match(r"^\d{11}$", id_codice): errors.append("Italian Partita IVA must be exactly 11 digits.") if errors: return {"error": "; ".join(errors)} anagrafica: dict = {} if denominazione: anagrafica["Denominazione"] = denominazione else: anagrafica["Nome"] = nome anagrafica["Cognome"] = cognome return { "CedentePrestatore": { "DatiAnagrafici": { "IdFiscaleIVA": {"IdPaese": id_paese.upper(), "IdCodice": id_codice}, "Anagrafica": anagrafica, "RegimeFiscale": regime_fiscale, }, "Sede": { "Indirizzo": indirizzo, "CAP": cap, "Comune": comune, "Nazione": nazione.upper(), }, } } - tools/header_tools.py:151-200 (schema)Pydantic Field-based input schema for the tool — defines parameters: id_paese, id_codice, denominazione, nome, cognome, regime_fiscale, indirizzo, cap, comune, nazione with descriptions and defaults.
def validate_cedente_prestatore( id_paese: Annotated[ str, Field(description="ISO 3166-1 two-letter country code of the seller (e.g. 'IT')."), ], id_codice: Annotated[ str, Field(description="Partita IVA (11 digits) or foreign VAT number of the seller."), ], denominazione: Annotated[ Optional[str], Field( default=None, description="Company name (Denominazione). Mutually exclusive with nome+cognome.", ), ] = None, nome: Annotated[ Optional[str], Field(default=None, description="First name (Nome), for individual sellers."), ] = None, cognome: Annotated[ Optional[str], Field(default=None, description="Last name (Cognome), for individual sellers."), ] = None, regime_fiscale: Annotated[ str, Field( description=( "Fiscal regime code RF01–RF19. Use get_regime_fiscale_codes() for the " "complete list. Most companies use RF01 (ordinary regime)." ) ), ] = "RF01", indirizzo: Annotated[ str, Field(description="Street address (via, piazza…) of the registered office."), ] = "", cap: Annotated[ str, Field(description="Italian postal code (5 digits) or foreign equivalent."), ] = "", comune: Annotated[ str, Field(description="City/municipality of the registered office."), ] = "", nazione: Annotated[ str, Field(description="ISO 3166-1 two-letter country code of the registered office."), ] = "IT", ) -> dict: - tools/header_tools.py:51-53 (registration)The function register_header_tools() that registers the tool via @mcp.tool() decorator on FastMCP instance.
def register_header_tools(mcp: FastMCP) -> None: """Register the 7 FatturaElettronicaHeader tools on the FastMCP instance.""" - tools/header_tools.py:25-44 (helper)REGIME_FISCALE constant dictionary mapping RF01–RF19 codes to descriptions, used for validating the regime_fiscale parameter.
REGIME_FISCALE: dict[str, str] = { "RF01": "Regime ordinario", "RF02": "Regime contribuenti minimi (art. 1, c.96-117, L. 244/2007)", "RF04": "Agricoltura e attività connesse e pesca (artt. 34 e 34-bis, DPR 633/72)", "RF05": "Vendita sali e tabacchi (art. 74, c.1, DPR. 633/72)", "RF06": "Commercio fiammiferi (art. 74, c.1, DPR. 633/72)", "RF07": "Editoria (art. 74, c.1, DPR. 633/72)", "RF08": "Gestione servizi telefonia pubblica (art. 74, c.1, DPR. 633/72)", "RF09": "Rivendita documenti di trasporto pubblico e di sosta (art. 74, c.1, DPR. 633/72)", "RF10": "Intrattenimenti, giochi e altre attività (art. 74, c.6, DPR. 633/72)", "RF11": "Agenzie viaggi e turismo (art. 74-ter, DPR. 633/72)", "RF12": "Agriturismo (art. 5, c.2, L. 413/91)", "RF13": "Vendite a domicilio (art. 25-bis, c.6, DPR. 600/73)", "RF14": "Rivendita beni usati, oggetti d'arte, d'antiquariato o da collezione (art. 36, DL 41/95)", "RF15": "Agenzie di vendite all'asta di oggetti d'arte, antiquariato o da collezione (art. 40-bis, DL 41/95)", "RF16": "IVA per cassa P.A. (art. 6, c.5, DPR. 633/72)", "RF17": "IVA per cassa (art. 32-bis, DL 83/2012)", "RF18": "Altro", "RF19": "Regime forfettario (art. 1, c.54-89, L. 190/2014)", } - server.py:83-85 (registration)Top-level registration call: register_header_tools(mcp) invoked in server.py entry point.
register_header_tools(mcp) register_body_tools(mcp) register_global_tools(mcp)