Metadata-Version: 2.4
Name: finanfut-billing-sdk
Version: 2.1.18
Summary: Python SDK for Finanfut Billing External API
Author: Finanfut
License: MIT License
        
        Copyright (c) 2025 erovirafinanfut
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://finanfut.com
Project-URL: Source, https://github.com/finanfut/finanfut-billing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic<3.0,>=2.0
Requires-Dist: requests>=2.31
Dynamic: license-file

# Finanfut Billing Python SDK

Client oficial sincrònic per consumir la **Finanfut Billing External API (`/external/v1`)** amb models compatibles amb **Pydantic v2**, ara preparat per treballar amb **Business Units**.

## Instal·lació

- Pydantic 2.x: `pip install finanfut-billing-sdk>=2.0`
- Pydantic 1.x: `pip install finanfut-billing-sdk<2.0`
- Des del repositori local: `pip install -e backend/sdk`

Dependències principals:

- `pydantic>=2.0,<3.0`
- `requests>=2.31`

## Configuració bàsica i Business Units

```python
from finanfut_billing_sdk import FinanfutBillingClient

client = FinanfutBillingClient(
    base_url="https://api.finanfut-billing.com",
    api_key="sk_live_xxx",
    business_unit_id="bu_default",  # opcional: aplicada a serveis/factures/liquidacions per defecte
    timeout=10,
    max_retries=2,
)
```

### Com funciona `business_unit_id`

- **Global al client:** passa `business_unit_id` al constructor i s'aplicarà automàticament a les operacions compatibles.
- **Per operació:** pots sobreescriure-la en cada mètode (`business_unit_id="bu_alt"`).
- **Endpoints sense BU:** tax rates i partner payment methods són d'abast de companyia i ignoren la BU (l'SDK emet un avís si n'hi ha una definida).
- **Liquidacions (settlements):** la BU és opcional però s'envia quan està disponible per enrutar payouts.
- **External API:** serveis i factures externes accepten BU però actualment poden ignorar-la; l'SDK ja no la tracta com a obligatòria.

## Exemples d'ús

### Crear producte/servei amb BU
```python
from decimal import Decimal
from finanfut_billing_sdk.models import ExternalServiceUpsertRequest

payload = ExternalServiceUpsertRequest(
    external_reference="service_abc",
    type="service",
    name="Monthly subscription",
    description="Access to premium content",
    price=Decimal("29.90"),
    vat_rate_code="vat_21",
)
service = client.upsert_service(payload)  # usa la BU global
```

### Crear factura amb BU (sobre-escrivint la BU global)
```python
from finanfut_billing_sdk.models import ExternalInvoiceCreateRequest, ExternalInvoiceLine

invoice = client.create_invoice(
    ExternalInvoiceCreateRequest(
        client_external_reference="client_123",
        currency="EUR",
        lines=[
            ExternalInvoiceLine(
                service_external_reference="service_abc",
                description="Premium plan",
                qty=1,
                price=29.90,
                vat_rate_id="tax_rate_uuid",
            ),
        ],
    ),
    business_unit_id="bu_sales",  # prioritat respecte la BU global
)
```

### Operacions sense BU (àmbit de companyia)
```python
# Els tax rates i partner payment methods ignoren la BU.
client.list_tax_rates()
client.partner_payment_methods.list_partner_payment_methods()
```

### Idempotència en liquidacions
```python
settlement = client.settlements.create_settlement(
    payload,
    idempotency_key="settlement-create-2024-12-31",
)
```

### Enviar factura i registrar pagament
```python
from finanfut_billing_sdk.models import ExternalInvoiceEmailRequest, ExternalPaymentCreateRequest

email = client.send_invoice_email(
    invoice.invoice_id,
    ExternalInvoiceEmailRequest(subject="La teva factura", body="Adjunt trobaràs el PDF"),
)

payment = client.register_payment(
    invoice.invoice_id,
    ExternalPaymentCreateRequest(amount=29.90, method="stripe"),
)
```

### Checkout i onboarding de Stripe Connect
```python
from finanfut_billing_sdk.models import ExternalCheckoutCreateRequest, ExternalConnectOnboardRequest

checkout = client.payments.create_checkout(
    "stripe",
    ExternalCheckoutCreateRequest(
        amount=29.90,
        currency="EUR",
        business_unit_id="bu_sales",
        provider_payload={"payment_method_types": ["card"]},
    ),
)

connect = client.payments.connect_onboard(
    "stripe",
    ExternalConnectOnboardRequest(
        provider_id="provider_uuid",
        return_url="https://app.example.com/connect/return",
        refresh_url="https://app.example.com/connect/refresh",
    ),
)
```

### Checkout sessions de Stripe (external)
```python
from finanfut_billing_sdk.models import ExternalCheckoutSessionCreateRequest

session = client.payments.create_checkout_session(
    ExternalCheckoutSessionCreateRequest(
        amount=49.90,
        currency="EUR",
        success_url="https://app.example.com/ok",
        cancel_url="https://app.example.com/cancel",
        description="Pagament",
    ),
    idempotency_key="checkout-session-2024-12-01",
)
```

### Subscripcions BU
```python
from finanfut_billing_sdk.models import SubscriptionPricingSnapshot, SubscriptionStartRequest

payload = SubscriptionStartRequest(
    request_id="sports-pro-2025-01",
    business_unit_id="bu_sales",
    subject_type="team",
    subject_id="team_123",
    billing_client_id="client_uuid",
    bu_plan_ref="pro_v3",
    pricing_snapshot=SubscriptionPricingSnapshot(
        amount=29.9,
        currency="EUR",
        interval="month",
    ),
    success_url="https://app.example.com/billing/success",
    cancel_url="https://app.example.com/billing/cancel",
)

response = client.subscriptions.start_subscription(payload)
```

## Errors

```python
from finanfut_billing_sdk.errors import (
    FinanfutBillingAuthError,
    FinanfutBillingServiceError,
    FinanfutBillingValidationError,
)

try:
    client.list_tax_rates()
except FinanfutBillingAuthError:
    print("API key incorrecta o sense permisos")
except FinanfutBillingValidationError as e:
    print("Error de validació:", e.payload)
except FinanfutBillingServiceError as e:
    print(f"Error de servei ({e.request_id}): {e.error}")
    if e.retry_after is not None:
        print(f"Reintenta després de {e.retry_after:.0f}s")
```

Els errors del backend inclouen sempre `error`, `message` i `request_id`. El client reintenta automàticament errors transitoris (`429`, `500`, `502`, `503`, `504`) en lectures i en mutacions només quan la petició porta `Idempotency-Key`.

## Publicació a PyPI

El paquet està preparat per publicar-se a PyPI quan es creen tags `v*` al repositori. El workflow `publish-sdk.yml` valida la versió (`__version__`) i fa l'upload amb Twine.
