fix(facturapi): configure legal data after org creation/reuse to enable Live mode
This commit is contained in:
@@ -206,7 +206,7 @@ def find_organization_by_rfc(tenant_config: dict) -> dict | None:
|
||||
|
||||
|
||||
def create_organization(tenant_config: dict) -> dict:
|
||||
"""Create a new Facturapi organization for the tenant and return live key.
|
||||
"""Create or reuse a Facturapi organization, configure legal data and return a live key.
|
||||
|
||||
Requires FACTURAPI_USER_KEY env or a user key (sk_user_*) in tenant_config.
|
||||
Uses tenant RFC/razon_social if available.
|
||||
@@ -227,13 +227,56 @@ def create_organization(tenant_config: dict) -> dict:
|
||||
if not org_id:
|
||||
raise FacturapiError("Could not create organization: no id returned")
|
||||
|
||||
# Configure fiscal/legal data (required before Live mode can be used)
|
||||
try:
|
||||
update_organization_legal(tenant_config, org_id)
|
||||
except FacturapiError:
|
||||
# If legal update fails, still return org info so the caller can surface it,
|
||||
# but do not generate a live key because it would be unusable.
|
||||
return {"org_id": org_id, "api_key": None, "legal_updated": False}
|
||||
|
||||
# Generate live secret key
|
||||
key_resp = _request("PUT", f"/organizations/{org_id}/apikeys/live", user_key, json_payload={}, timeout=60)
|
||||
live_key = key_resp.get("key") if isinstance(key_resp, dict) else str(key_resp)
|
||||
if not live_key:
|
||||
raise FacturapiError(f"Could not generate live key for org {org_id}")
|
||||
|
||||
return {"org_id": org_id, "api_key": live_key}
|
||||
return {"org_id": org_id, "api_key": live_key, "legal_updated": True}
|
||||
|
||||
|
||||
def _build_legal_payload(tenant_config: dict) -> dict:
|
||||
"""Build Facturapi /organizations/{id}/legal payload from tenant config."""
|
||||
rfc = (tenant_config.get("rfc") or "").upper().strip()
|
||||
legal_name = (tenant_config.get("razon_social") or "").strip()
|
||||
tax_system = (tenant_config.get("regimen_fiscal") or "").strip() or "601"
|
||||
zip_code = (tenant_config.get("cp") or tenant_config.get("tenant_cp") or "").strip() or "00000"
|
||||
if not rfc or not legal_name:
|
||||
raise FacturapiError("RFC y Razón Social son obligatorios para configurar la organización en Facturapi")
|
||||
return {
|
||||
"tax_id": rfc,
|
||||
"legal_name": legal_name,
|
||||
"tax_system": tax_system,
|
||||
"address": {
|
||||
"zip": zip_code,
|
||||
"street": (tenant_config.get("direccion") or "").strip(),
|
||||
"exterior": "",
|
||||
"interior": "",
|
||||
"neighborhood": "",
|
||||
"city": "",
|
||||
"municipality": "",
|
||||
"state": "",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def update_organization_legal(tenant_config: dict, org_id: str) -> dict:
|
||||
"""Update the legal/fiscal data of a Facturapi organization.
|
||||
|
||||
Uses the user key (admin) because the org may not have a live key yet.
|
||||
"""
|
||||
user_key = _get_user_key_for_tenant(tenant_config)
|
||||
payload = _build_legal_payload(tenant_config)
|
||||
return _request("PUT", f"/organizations/{org_id}/legal", user_key, json_payload=payload, timeout=60)
|
||||
|
||||
|
||||
def get_org_status(tenant_config: dict) -> dict:
|
||||
@@ -264,21 +307,31 @@ def get_org_status(tenant_config: dict) -> dict:
|
||||
result["has_org_id"] = True
|
||||
result["org_id"] = org_id
|
||||
|
||||
try:
|
||||
def _fetch():
|
||||
org = get_organization(org_id, api_key)
|
||||
legal = org.get("legal", {})
|
||||
cert = org.get("certificate", {})
|
||||
result.update(
|
||||
{
|
||||
"configured": True,
|
||||
"has_csd": bool(cert.get("has_certificate")),
|
||||
"legal_name": legal.get("name") or legal.get("legal_name"),
|
||||
"tax_id": legal.get("tax_id"),
|
||||
"pending_steps": org.get("pending_steps", []),
|
||||
}
|
||||
)
|
||||
return {
|
||||
"configured": True,
|
||||
"has_csd": bool(cert.get("has_certificate")),
|
||||
"legal_name": legal.get("name") or legal.get("legal_name"),
|
||||
"tax_id": legal.get("tax_id"),
|
||||
"pending_steps": org.get("pending_steps", []),
|
||||
}
|
||||
|
||||
try:
|
||||
result.update(_fetch())
|
||||
except FacturapiError as e:
|
||||
result["error"] = str(e)
|
||||
# If the org reports "not configured for Live" (401) and we have a user key,
|
||||
# try to backfill legal data and retry.
|
||||
if e.status_code == 401 and _get_user_key_for_tenant(tenant_config):
|
||||
try:
|
||||
update_organization_legal(tenant_config, org_id)
|
||||
result.update(_fetch())
|
||||
except FacturapiError as e2:
|
||||
result["error"] = str(e2)
|
||||
else:
|
||||
result["error"] = str(e)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user