# Códigos de error: Cotizaciones

> Armar, versionar, aprobar, rechazar y convertir cotizaciones en órdenes. Los errores de armado vienen como cuerpo de operación (`buildOperationErrorBody`): `code`, `message`, `recoverable`, `retryable`, `errors[]` por campo o línea y `side_effects`.

**Cómo se detecta (toda la familia):** La respuesta: el `code` general y, en `errors[]`, un renglón por campo o línea con su propio `code`. Los 503 de conversión a orden vienen de Zauru.

**Qué hacer (toda la familia):** Corregir lo que dice `errors[]` y volver a guardar. Si `side_effects` dice que ya se creó algo en Zauru (cliente promovido, orden), NO repitas a ciegas: revisa Zauru primero.

Lo que un código no dice lo hereda de la familia.

## `attachment_not_found`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El adjunto elegido no es de esta cotización.

## `by_category_requires_category_sections`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Con agrupación por categoría, cada sección tiene que usar el título de categoría.

## `by_category_requires_real_category`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Con agrupación por categoría, cada sección tiene que apuntar a una categoría real o a «Sin categoría».

## `contact_not_available`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El contacto elegido no es de este lead.

## `custom_brochure_invalid_type`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El folleto personalizado tiene que ser un PDF.

## `custom_logo_invalid_type`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El logo personalizado tiene que ser png, jpg, jpeg o webp.

## `custom_video_invalid_type`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El video personalizado tiene que ser mp4, webm o mov.

## `duplicate_category_section`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Con agrupación por categoría, solo puede haber una sección por categoría.

## `duplicate_line_client_uid`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Dos líneas traen el mismo `client_uid` (identificador que pone el front).

## `duplicate_section_client_uid`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Dos secciones traen el mismo `client_uid`.

## `duplicate_subsection_client_uid`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Dos subsecciones traen el mismo `client_uid`.

## `grouping_mode_none_disallows_sections`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Sin agrupación (`grouping_mode = none`) no se admiten secciones.

## `grouping_mode_none_disallows_subsections`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Sin agrupación no se admiten subsecciones.

## `line_not_found`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La línea elegida no es de esta cotización.

## `line_section_missing`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La línea apunta a una sección que no existe.

## `line_section_not_allowed`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Sin agrupación, las líneas no pueden apuntar a secciones.

## `line_section_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Si hay secciones, toda línea tiene que pertenecer a una.

## `line_subsection_missing`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La línea apunta a una subsección que no existe.

## `line_subsection_not_allowed`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Sin agrupación, las líneas no pueden apuntar a subsecciones.

## `line_subsection_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Si la sección tiene subsecciones, toda línea de esa sección tiene que estar en una.

## `line_subsection_section_mismatch`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La subsección de la línea no pertenece a la sección indicada.

## `quote_approval_compose_invalid`

- **Tipo:** HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La cotización no se puede aprobar: su conversión a orden tiene errores que bloquean (ver `errors[]`).

## `quote_compose_invalid`

- **Tipo:** HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La cotización tiene errores de armado que bloquean guardarla (ver `errors[]`).

## `quote_context_invalid`

- **Tipo:** HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** No se pudo resolver el contexto de la cotización (lead, vendedor, agencia o moneda).

## `quote_duplicate_family_persist_failed`

- **Tipo:** detalle, HTTP · **HTTP:** 500 · **Estado:** vigente
- **Qué significa:** La cotización se duplicó pero no se pudo guardar su familia de hermanas (500). La copia existe: revisar antes de repetir.

## `quote_lead_mismatch`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El lead elegido no es el de la cotización existente.

## `quote_not_editable`

- **Tipo:** detalle, HTTP · **HTTP:** 409 · **Estado:** vigente
- **Qué significa:** La cotización ya no se puede editar: ya tiene una resolución (aprobada o rechazada).
- **Qué hacer:** Duplicarla y editar la copia, o crear una versión nueva.

## `quote_order_context_incomplete`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La cotización no se puede convertir en orden sin agencia y término de pago.

## `quote_order_create_failed`

- **Tipo:** HTTP · **HTTP:** 503 · **Estado:** vigente
- **Qué significa:** Zauru no devolvió el id de la orden al convertir la cotización (503).
- **Causa típica:** Zauru falló o tardó a mitad de la creación.
- **Qué hacer:** Revisar en Zauru si la orden quedó creada ANTES de reintentar, para no duplicarla.

## `quote_order_create_failed_after_lead_promotion`

- **Tipo:** HTTP · **HTTP:** 503 · **Estado:** vigente
- **Qué significa:** El lead ya se promovió a cliente en Zauru pero la orden no se pudo crear (503). `side_effects` lo dice.
- **Qué hacer:** El cliente ya existe en Zauru: reintentar la conversión (no volverá a crear el cliente). Revisar que la orden no haya quedado a medias.

## `quote_public_decision_already_locked`

- **Tipo:** detalle, HTTP · **HTTP:** 409 · **Estado:** vigente
- **Qué significa:** El cliente ya respondió (aprobó o rechazó) esta versión de la cotización desde el enlace público.

## `quote_rejection_observation_required`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El motivo de rechazo elegido exige una observación.

## `quote_rejection_reason_not_found`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El motivo de rechazo elegido no está disponible.

## `quote_rejection_reason_scope_invalid`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** El motivo de rechazo no se puede usar en ese tipo de decisión (pública o interna).

## `quote_stock_insufficient`

- **Tipo:** HTTP · **HTTP:** 409 · **Estado:** vigente
- **Qué significa:** No se puede aprobar: uno o más productos no tienen existencia suficiente.

## `section_category_label_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una sección con título de categoría necesita la etiqueta de la categoría.

## `section_category_reference_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Con agrupación por categoría, cada sección necesita su categoría.

## `section_empty`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una sección no tiene líneas.

## `section_manual_name_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una sección con título manual necesita su nombre.

## `section_not_found`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La sección elegida no es de esta cotización.

## `subsection_category_label_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una subsección con título de categoría necesita la etiqueta de la categoría.

## `subsection_empty`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una subsección no tiene líneas.

## `subsection_manual_name_required`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una subsección con título manual necesita su nombre.

## `subsection_not_found`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La subsección elegida no es de esta cotización.

## `subsection_section_missing`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Una subsección apunta a una sección que no existe.

## `subsections_require_sections`

- **Tipo:** detalle · **HTTP:** — · **Estado:** vigente
- **Qué significa:** No puede haber subsecciones sin secciones.

## `template_not_available`

- **Tipo:** detalle, HTTP · **HTTP:** 400 · **Estado:** vigente
- **Qué significa:** La plantilla de PDF elegida (portada, cuerpo o pie) no está disponible para esta cotización.
