Metadata-Version: 2.4
Name: qtx-nav-evat
Version: 0.5.2
Summary: Python package for working with the NAV EVAT system via qtx-nav-core
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: lxml>=5.2.0
Requires-Dist: qtx-nav-core>=0.2.3

# qtx-nav-evat

`qtx-nav-evat` is a focused Python client package for the NAV EVAT API, built on top of
`qtx-nav-core`. `qtx-nav-core` provides the shared NAV transport, request envelope,
authentication, XML and hashing utilities; this package adds EVAT-specific
configuration, request bodies, response parsers, and a high-level client.

## Version 0.5.1

This version adds tolerant parsing for customs declaration tax-code responses.
The NAV documentation describes `lineNumber` as present, but real customs
responses can omit it. In that case the client assigns deterministic
one-based line numbers according to the order of the returned
`taxCodeInformation` elements. Explicit values from NAV are preserved. Invoice
responses remain strict and still require `lineNumber`.

The discrepancy between the specification and the observed production
response is intentional and documented here so the parser remains usable with
actual NAV responses.

## Version 0.5.0

This version includes the following API corrections:

- The misspelled `update_enviroment` method was corrected to
  `update_environment`.
- `declaration_submission()` returns no value (`None`) when the request
  succeeds. If NAV or the transport layer reports an error, the exception is
  propagated to the caller.

## What It Contains

- `EvatConfig` and `EvatEnvironment` for selecting the NAV EVAT endpoint
- `EvatClient` for the supported EVAT operations
- `DeclarationSchema`, `AttachmentStatus`, and `DeclarationProcessingStatusCode` string enums
- typed request body classes for tax code, attachment, and declaration flows
- parsed response dataclasses for attachment, tax code, and declaration responses
- a local demo runner in [main.py](main.py)

## Requirements

- Python 3.12 or newer
- `qtx-nav-core>=0.2.3`
- `lxml>=5.2.0`

## Installation

Install from the project root in editable mode during development:

```bash
pip install -e .
```

Or install it as a normal dependency in another project:

```bash
pip install qtx-nav-evat
```

## Quick Start

```python
from qtx_nav_core import NavAuth, NavRequestContext, NavSoftwareInfo
from qtx_nav_evat import DeclarationSchema, EvatClient, EvatConfig, EvatEnvironment

config = EvatConfig(environment=EvatEnvironment.TEST)

context = NavRequestContext(
    auth=NavAuth(
        login="login",
        password="password",
        tax_number="12345678",
        sign_key="sign-key",
    ),
    software=NavSoftwareInfo(),
)

with EvatClient(config=config, context=context) as client:
    catalog = client.query_tax_code_catalog(taxpoint_date="2025-01-01")
    print(catalog.valid_from, catalog.valid_to)
    print(len(catalog.tax_codes))

    attachments = client.query_attachment_list()
    print(len(attachments))

    data = client.query_declaration_data(
        declaration_processing_id="processing-id",
        declaration_schema=DeclarationSchema.A60_DECLARATION,
    )
```

## Supported Operations

### Tax Code Catalog

- `query_tax_code_catalog(taxpoint_date=None, request_body=None)`
- endpoint path: `/queryTaxCodeCatalog`
- returns `QueryTaxCodeCatalogResult`

- `query_invoice_tax_code(invoice_number="", invoice_direction=InvoiceDirection.INBOUND, request_body=None)`
- endpoint path: `/queryInvoiceTaxCode`
- returns `QueryInvoiceTaxCodeResponse`

- `query_customs_declaration_digest(page=1, declaration_direction=DeclarationDirection.IMPORTER, request_body=None)`
- endpoint path: `/queryCustomsDeclarationDigest`
- returns `QueryCustomsDeclarationDigestResponse`

- `query_customs_declaration_tax_code(cdps_id="", resolution_id="", declaration_direction=DeclarationDirection.IMPORTER, request_body=None)`
- endpoint path: `/queryCustomsDeclarationTaxCode`
- returns `QueryCustomsDeclarationTaxCodeResponse`

### Attachments

- `query_attachment_list(request_body=None)`
- endpoint path: `/queryAttachmentList`
- returns `list[AttachmentListItem]`

- `upload_attachment(file_path, request_body=None)`
- endpoint path: `/manageAttachmentUpload`
- returns `AttachmentUploadResult`
- computes the request metadata in EVAT code and delegates file upload transport
  to `qtx-nav-core`

- `purge_attachment(claim_check_id, request_body=None)`
- endpoint path: `/purgeAttachment`
- returns `True` if the request completed without an exception

### Declarations

- `query_declaration_list(taxpoint_date_from=None, taxpoint_date_to=None, request_body=None)`
- endpoint path: `/queryDeclarationList`
- returns `list[DeclarationListItem]`

- `query_declaration_processing_status(declaration_processing_id="", declaration_schema=DeclarationSchema.VAT_DECLARATION, request_body=None)`
- endpoint path: `/queryDeclarationProcessingStatus`
- returns `QueryDeclarationProcessingStatusResponse`

- `query_declaration_data(declaration_processing_id="", declaration_schema=DeclarationSchema.VAT_DECLARATION, request_body=None)`
- endpoint path: `/queryDeclarationData`
- returns `DeclarationDataResponse`

- `query_vat_declaration_data(declaration_processing_id="", declaration_schema=DeclarationSchema.VAT_DECLARATION, request_body=None)`
- endpoint path: `/queryVatDeclarationData`
- returns `QueryVatDeclarationDataResponse` with metadata and gzipped XML file bytes
- handles the multipart response internally; `client.call()` itself remains a
  simple XML-document entry point

- `declaration_upload(file_path=..., declaration_schema=DeclarationSchema.VAT_DECLARATION, period_start=None, period_end=None)`
- runs `manageDeclarationUpload`, `manageDeclarationPartition`, and `manageDeclarationFinalize`
- gzips and splits the XML file before partition upload
- uses `period_start`/`period_end` when provided; otherwise reads the VAT declaration period from the XML
- returns the resulting `declarationProcessingId`

- `declaration_submission(declaration_processing_id="", declaration_schema=DeclarationSchema.VAT_DECLARATION, request_body=None)`
- endpoint path: `/manageDeclarationSubmission`
- returns `None` on success; raises the underlying exception on error

`declaration_schema` accepts `DeclarationSchema.VAT_DECLARATION`
(`"VAT_DECLARATION"`) and `DeclarationSchema.A60_DECLARATION` (`"A60"`).
Response parsers expose declaration schema, attachment status, and declaration
processing status code fields as string enum values.

Multipart download example:

```python
result = client.query_vat_declaration_data(
    declaration_processing_id="processing-id",
    declaration_schema=DeclarationSchema.VAT_DECLARATION,
)

print(result.declaration_schema)
print(result.original_request_version)

if result.has_file:
    result.save_file()
    result.save_xml("vat-declaration.xml")
```

`query_vat_declaration_data()` hides the multipart parsing. The returned
`file_content` is the gzipped declaration XML file part as bytes. Use
`save_file()` to persist the gzipped file, `extract_xml()` to get decompressed
XML bytes, or `save_xml(path)` to write the decompressed XML. There is no public
`multipart_response` switch on `client.call()`; use this high-level method for
the VAT declaration data download.

## Configuration

`EvatConfig` currently selects one of the built-in NAV EVAT base URLs:

- `EvatEnvironment.TEST` -> `https://api-test.eafa.nav.gov.hu/analyticsService/v1`
- `EvatEnvironment.PRODUCTION` -> `https://api.eafa.nav.gov.hu/analyticsService/v1`

```python
from qtx_nav_evat import EvatConfig, EvatEnvironment

config = EvatConfig(environment=EvatEnvironment.TEST)
```

## Local Demo Script

[main.py](main.py) is a local manual test runner configured through top-level
constants. Fill in the credentials and select the operation before running it.

Common constants:

- `ENVIRONMENT`
- `OPERATION`
- `USERNAME`
- `PASSWORD`
- `TAX_NUMBER`
- `SIGN_KEY`
- `TAXPOINT_DATE`
- `ATTACHMENT_FILE`
- `LOG_XML`
- `INCLUDE_SOFTWARE_INFO`

PowerShell example:

```powershell
.\.venv\Scripts\python.exe .\main.py
```

## Documentation

- English usage guide: [docs/usage.md](docs/usage.md)
- API reference: [docs/api.md](docs/api.md)
- Model and payload reference: [docs/models.md](docs/models.md)
- Hungarian overview: [README.hu.md](README.hu.md)

## Development Notes

- the project uses a standard `src` layout
- packaging is configured in [pyproject.toml](pyproject.toml)
- tests currently include an import smoke test
- request and response XML can be inspected through `on_request_xml` and `on_response_xml`
