# Parámetros de correo — Guía (`MailerinfoController::changeCodes`)

Referencia para refactorización de plantillas de email de Guía (Guide).

**Fuente:** `src/NvCarga/Bundle/Controller/MailerinfoController.php`
**Método:** `changeCodes($string, $entity, $type, $aux = null)`
**Servicio:** `nvcarga.mailerservices` → delega en este controlador

**Documento relacionado:** [`mailer-whrec-parameters.md`](mailer-whrec-parameters.md) (Warehouse) · [`twilio-template-parameters.md`](twilio-template-parameters.md) (WhatsApp)

---

## 1. Modos de uso para Guía

| `$type` | `$entity` | `$aux` | Evento / uso típico |
|---------|-----------|--------|---------------------|
| `'Guide'` | `Guide` | — | Creación (`new_guide`), notificaciones, finalización (`sendguide`) |
| `'Statusguide'` | `Statusguide` (estatus) | `Guide` | Cambio de estatus (`StatusController::Sendemail`) |

Equivalente Twilio (otro canal): `new_guide`, `status_change`, `completation` sobre entidad `Guide`.

### Contexto inicial (`$type = 'Guide'`)

| Variable | Origen |
|----------|--------|
| `$shipper` | `$entity->getSender()` (remitente) |
| `$receiver` | `$entity->getAddressee()` (destinatario) |
| `$listrec` | `$entity->getReceipts()` (paquetes asociados a la guía) |
| `$customer` | `$shipper` |
| `$thisnumber` | `$entity->getNumber()` |
| `$linksign` | `'guide'` |
| `$linkshiptype` | **no se asigna** (solo WHrec define `linkshiptype`) |
| `$agency` | `$entity->getAgency()` |
| `$agencydes` | `$entity->getAgencydes()` si existe |
| `$maincompany` | `$entity->getMaincompany()` |
| `$first` | mismo `$entity` (Guide) |

### Contexto inicial (`$type = 'Statusguide'`)

| Variable | Origen |
|----------|--------|
| `$first` | `$aux` (la **Guide**) |
| `$entity` | registro de **estatus** (`Statusguide`) |
| `$listrec` | `$guide->getReceipts()` (sin `oldreceipts`, a diferencia de WHrec) |
| `$shipper` / `$receiver` | `guide.getSender()` / `guide.getAddressee()` |
| `$thisnumber` | número de la guía |
| `$linksign` | `'guide'` |

**Medidas de conversión:** `Measure` con `name = 'Lb'` y `name = 'CF'` de la empresa (para `[TOTALPESO]` y `[TOTALVOLUMEN]`).

**Si un tag no se reemplaza:** queda literal `[TAG]` en el HTML.

**Salida:** `nl2br()` al final del string.

---

## 2. Diferencias clave Guide vs WHrec

| Aspecto | WHrec | Guide |
|---------|-------|-------|
| Remitente | `getShipper()` | `getSender()` |
| Destinatario | `getReceiver()` | `getAddressee()` (también existe `getReceiver()` en la entidad) |
| `[TIPOENVIO]` | `getInstruction()` traducido | `getShippingtype().getName()` traducido |
| `$listrec` en status | receipts + oldreceipts | solo `getReceipts()` |
| `[ENLACEPUBLICOTIPOENVIO]` | Sí (WHrec) | **No** (`linkshiptype` no definido) |
| Tags extra UI | `[NOTA]`, `[AUXILIAR]`, `[FECHAAUX]` | `[MASTERGUIDE]`, `[TEXTAUX]` |

---

## 3. Tags oficiales en UI (`getMailtags()`)

### `Guide` — creación / notificaciones / finalización

| Tag | Descripción UI | Origen del valor |
|-----|----------------|------------------|
| `[NOMBREEMPRESA]` | Nombre Empresa | `maincompany.getName()` |
| `[NUMERO]` | Número de Guía | `guide.getNumber()` |
| `[DESTINATARIO]` | Nombre Destinatario | `addressee.getComplete()` |
| `[REMITENTE]` | Nombre Remitente | `sender.name + lastname` |
| `[FECHACREACION]` | Fecha de Creación | `guide.getCreationdate()` con `maincompany.getFormatdate()` |
| `[DETALLES]` | Detalles de Paquetes | Tabla HTML por cada `Receipt` en `$listrec` |
| `[TOTALPIEZAS]` | Total de Piezas | Σ `receipt.getNpack()` |
| `[TOTALPESO]` | Peso Total | Σ pesos con conversión Lb/Kg |
| `[TOTALVOLUMEN]` | Volumen Total | Σ volúmenes con conversión CF/Mt3 |
| `[TIPOENVIO]` | Tipo de Envío | `translator(shippingtype.getName())` |
| `[NOMBREAGENCIA]` | Nombre Agencia | `agency.getName()` |
| `[DIRECCIONAGENCIA]` | Dirección Agencia | `agency.getAddress()` |
| `[EMAILAGENCIA]` | Email Agencia | `agency.getEmail()` |
| `[TELEFONOAGENCIA]` | Teléfono Agencia | `agency.getPhone()` |
| `[LINKCASILLERO]` | Enlace para Ingresar | Link HTML homepage |
| `[MASTERGUIDE]` | Master Courier Shipment | `guide.getMasterguide()` si existe |
| `[TEXTAUX]` | Text Auxiliar | `guide.getAux()` si existe |
| `[LINKTRACKING]` | Enlace Tracking | `https://{homepage}/tracking/tracking` |
| `[LINKEMPRESA]` | Enlace Empresa | `http://{maincompany.getUrl()}/` |
| `[ENLACEFIRMA]` | Enlace firmar declaración | Plan firma + sin `sigimage` → link casillero |
| `[ENLACEPUBLICOFIRMA]` | Enlace público firma | `/guide/public/{id}/{pubtoken}` |
| `[NOMBREAGENCIADESTINO]` … | Agencia destino | `agencydes` o `N/A` (si `configguide.agencydes`) |

Condicionales en UI:

- `[ENLACEFIRMA]` / `[ENLACEPUBLICOFIRMA]`: si `maincompany.plan.signvalue`
- Tags agencia destino: si `configguide.agencydes`

**No listado en UI pero resoluble en código:** `[AGENTE]`, `[NOTA]`, `[FECHAAUX]` (ver §4).

### `Statusguide` — cambio de estatus

Incluye tags de datos de guía/paquetes, más:

| Tag | Descripción UI | Origen del valor |
|-----|----------------|------------------|
| `[FECHASTATUS]` | Fecha del Estatus | `status.getDate()` con fecha + hora |
| `[STATUS]` | Nombre del Estatus | `status.step.name` |
| `[CIUDADSTATUS]` | Ciudad del Estatus | `status.place` → ciudad, estado, país; o `N/A` |
| `[COMENTARIOSTATUS]` | Comentario del Estatus | `status.comment` o `N/A` |
| `[TIPOENVIO]` | Tipo de Envío | `status.getGuide().getShippingtype().getName()` traducido |

No incluye en UI: `[MASTERGUIDE]`, `[TEXTAUX]`, `[DETALLES]` en el bloque base (pero el `switch` los resuelve igual si están en la plantilla).

---

## 4. Tabla completa — resolución por tag

| Tag | Guide | Status | Origen detallado |
|-----|:-----:|:------:|------------------|
| `[NOMBREEMPRESA]` | ✓ | ✓ | `maincompany.getName()` |
| `[NUMERO]` | ✓ | ✓ | Número de la guía (`$thisnumber`) |
| `[DESTINATARIO]` | ✓ | ✓ | `addressee.getComplete()` |
| `[REMITENTE]` | ✓ | ✓ | `sender.name + lastname` |
| `[FECHACREACION]` | ✓ | ✓ | `first.getCreationdate()` formateada |
| `[DETALLES]` | ✓ | ✓ | HTML por cada receipt en `$listrec` |
| `[TOTALPIEZAS]` | ✓* | ✓* | Σ `npack`; *si `$listrec` no vacío |
| `[TOTALPESO]` | ✓* | ✓* | Σ peso receipts + conversión unidades |
| `[TOTALVOLUMEN]` | ✓* | ✓* | Σ volumen receipts + conversión CF/Mt3 |
| `[TIPOENVIO]` | ✓ | ✓ | Guide: `shippingtype.name`; Status: vía `status.getGuide()` |
| `[MASTERGUIDE]` | ✓ | ○ | `guide.getMasterguide()` (entity Guide) |
| `[TEXTAUX]` | ✓ | ○ | `guide.getAux()` |
| `[NOTA]` | ○ | — | `guide.getNote()` si existe propiedad |
| `[AUXILIAR]` | ○ | — | `guide.getAux()` (mismo campo que TEXTAUX, otro tag) |
| `[FECHAAUX]` | ○ | — | `guide.getAuxdate()` o `N/A` |
| `[AGENTE]` | ○ | ✓ | `first.getAgent().getName()` o `<br>` |
| `[NOMBREAGENCIA]` | ✓ | ✓ | `agency.getName()` |
| `[DIRECCIONAGENCIA]` | ✓ | ✓ | `agency.getAddress()` |
| `[EMAILAGENCIA]` | ✓ | ✓ | `agency.getEmail()` |
| `[TELEFONOAGENCIA]` | ✓ | ✓ | `agency.getPhone()` |
| `[LINKCASILLERO]` | ✓ | ✓ | Link homepage |
| `[LINKTRACKING]` | ✓ | ✓ | Link tracking |
| `[LINKEMPRESA]` | ✓ | ✓ | Link URL empresa |
| `[ENLACEFIRMA]` | ✓† | ✓† | †Plan firma; ruta `guide/pobox/{entity.id}/{systoken}` |
| `[ENLACEPUBLICOFIRMA]` | ✓† | ✓† | `/guide/public/{id}/{pubtoken}` |
| `[ENLACEPUBLICOTIPOENVIO]` | — | — | Solo WHrec (`linkshiptype`) |
| `[FECHASTATUS]` | — | ✓ | `status.getDate()` |
| `[STATUS]` | — | ✓ | `status.step.name` |
| `[CIUDADSTATUS]` | — | ✓ | `status.place` |
| `[COMENTARIOSTATUS]` | — | ✓ | `status.comment` o `N/A` |
| `[NOMBREAGENCIADESTINO]` | ✓‡ | ✓‡ | `agencydes` o `N/A` |
| `[DIRECCIONAGENCIADESTINO]` | ✓‡ | ✓‡ | idem |
| `[EMAILAGENCIADESTINO]` | ✓‡ | ✓‡ | idem |
| `[TELEFONOAGENCIADESTINO]` | ✓‡ | ✓‡ | idem |
| `[NUMEROCLIENTE]` | ○ | ○ | `sender.getNumber()` |
| `[CONSIGNEE]` / `[SHIPPER]` | ○ | ○ | Alias nombres destinatario/remitente |

**Leyenda:** ✓ = aplica · ✓* = requiere receipts · ✓† = plan firma · ✓‡ = config agencia destino · ○ = funciona con datos, no siempre en `getMailtags` · — = no aplica

### Tags del `switch` que no aplican a Guía

Pickup, Bill, Alert, Pobox, WHrec-only, pagos, reempaque, consolidado, etc.

---

## 5. Detalle: `[DETALLES]`

Igual que WHrec: por cada `Receipt` en `$listrec` genera HTML con tracking, carrier, tipo, descripción, piezas, dimensiones, peso y `round(volume, 2)`.

Solo reemplaza si hay al menos un receipt en `$listrec`.

---

## 6. Detalle: totales desde paquetes (`$listrec`)

Misma lógica que Warehouse (ver `mailer-whrec-parameters.md` §5).

### `[TOTALPIEZAS]`

```
Σ receipt.getNpack()
```

- **Guide:** `guide.getReceipts()`
- **Statusguide:** `guide.getReceipts()` (sin paquetes históricos `oldreceipts`)

### `[TOTALPESO]`

Por cada receipt, conversión según `unitweight` (`Lb` / `Kg` / `Ninguna`) hacia la unidad `Lb` configurada en la empresa.

### `[TOTALVOLUMEN]`

Por cada receipt, conversión según `unitvolume` (`CF` / `Mt3` / `Ninguna`) hacia la unidad `CF` de la empresa; resultado `round(total, 2)`.

**Si `$listrec` está vacío:** no se sustituyen `[TOTALPIEZAS]`, `[TOTALPESO]` ni `[TOTALVOLUMEN]`.

---

## 7. `[TIPOENVIO]` — lógica específica Guide

```php
// $type = 'Guide' — className Guide
$envio = translator(guide.getShippingtype().getName());

// $type = 'Statusguide' — className Statusguide
$element = status.getGuide();
$envio = translator(element.getShippingtype().getName());
```

A diferencia de WHrec, **no** usa `getInstruction()`.

---

## 8. Enlaces de firma

### `[ENLACEFIRMA]`

- `$linksign = 'guide'`
- Si `plan.signvalue` y sin `sigimage` en `$entity`:
  - `https://{SERVER_NAME}/guide/pobox/{entity.id}/{entity.systoken}`
- Si no: `<br>`

### `[ENLACEPUBLICOFIRMA]`

- `https://{SERVER_NAME}/guide/public/{entity.id}/{entity.pubtoken}`

### `[ENLACEPUBLICOTIPOENVIO]`

- **No aplica** a Guide (`$linkshiptype` no se define en el case `Guide`).

**Nota Statusguide:** `$entity` es el **status**; los enlaces usan `entity.getId()` y tokens del status, no de la guía en `$aux`.

---

## 9. Reemplazos manuales fuera de `changeCodes`

### Finalización — `GuideController` / `GuideAPIController` (`sendguide`)

Antes de `changeCodes($body, $guide, 'Guide')`:

| Tag | Valor manual |
|-----|----------------|
| `[STATUS]` | `"Finalizado"` |
| `[FECHASTATUS]` | `guide.getDelidate()` o fecha actual |
| `[CIUDADSTATUS]` | `guide.getReceiver().getCity().getName()` |
| `[COMENTARIOSTATUS]` | `$comment` del método |

`Bodyemail` por defecto: `tableclass = 'Statusguide'` o plantilla de finalización según implementación.

### Cambio de estatus — `StatusController::Sendemail($guide, $status)`

Cuerpo por defecto si no hay `Bodyemail` activo con `tableclass = 'Statusguide'`:

- Incluye `[STATUS]`, `[COMENTARIOSTATUS]`, `[FECHASTATUS]`, `[NUMERO]`, `[REMITENTE]`, `[DESTINATARIO]`, `[TOTALPIEZAS]`, `[TOTALPESO]`, `[LINKTRACKING]`, `[NOMBREEMPRESA]`

Luego:

```php
changeCodes($body, $status, 'Statusguide', $guide);
```

Los tags de estatus se resuelven desde `$entity` = **status**, no desde la guía.

---

## 10. Invocaciones en el proyecto

```php
// Guía directa
changeCodes($body, $guide, 'Guide');

// Cambio de estatus
changeCodes($body, $status, 'Statusguide', $guide);
```

| Archivo | Contexto |
|---------|----------|
| `GuideController.php` | Email creación, `sendguide` (finalización) |
| `GuideAPIController.php` | API — creación y finalización |
| `StatusController.php` | `Sendemail($guide, $status)` — cambio estatus |
| `UtilsController.php` | Utilidades email Guide |
| `PickupAPIController.php` | Referencia Guide en flujos pickup |

---

## 11. Paridad eventos Guide ↔ WHrec ↔ Twilio

| Evento negocio | Email `$type` | Twilio `$action` | Entidad |
|----------------|---------------|------------------|---------|
| Creación | `Guide` | `new_guide` | `Guide` |
| Cambio estatus | `Statusguide` + `$aux` Guide | `status_change` | `Guide` (+ `$status`) |
| Finalización | `Guide` (+ reemplazos manuales) | `completation` | `Guide` |

---

## 12. Diferencia con Twilio (WhatsApp)

| Canal | Tag volumen | Origen |
|-------|-------------|--------|
| **Email** | `[TOTALVOLUMEN]` | Suma `Receipt.getVolume()` en `$listrec` |
| **WhatsApp** | `[TOTALVOLUME]` | `Guide.getVolume()` en `TwilioController` |

| Canal | Tag tipo envío | Origen |
|-------|----------------|--------|
| **Email** | `[TIPOENVIO]` | `Shippingtype` entidad relacionada |
| **WhatsApp** | `[TIPOENVIO]` | `shippingtype.getName()` en la guía |

Ver `docs/twilio-template-parameters.md` sección Guide.

---

## 13. Notas para refactorización

1. Unificar remitente/destinatario: en código email se usan `Sender`/`Addressee`; tags siguen siendo `[REMITENTE]`/`[DESTINATARIO]`.
2. `[TEXTAUX]` vs `[AUXILIAR]`: mismo campo `getAux()`, tags distintos (Guide UI solo documenta `TEXTAUX`).
3. Statusguide no suma `oldreceipts`; totales pueden diferir de WHrec en cambios de estatus con paquetes históricos.
4. Enlaces de firma con `Statusguide` pueden usar id/token del **status** — validar URLs en producción.
5. `sendguide` calcula peso/volumen localmente en algunos flujos (como WHrec) pero los tags de totales en email dependen de `changeCodes` y `$listrec`.
6. Extraer conversión de unidades a servicio compartido entre WHrec, Guide, Receipt y Twilio para evitar divergencias.

---

## 14. Notas de implementación v2 (`GuideEmailService`)

| Método | Uso |
|--------|-----|
| `generateEmailContentByGuideId(string, Guide)` | GUIDE — creación, notificaciones, finalización |
| `generateEmailContentByStatusGuideId(string, Statusguide)` | STATUSGUIDE — delega tags de guía y aplica estatus |
| `sendDeliveredEmailToMany(Guide\|Statusguide, ...)` | `guide_delivered` — adjunta solo STATUSCLOSE + firma |

**Correcciones respecto al código anterior:**

- `[DETALLES]`: HTML por receipt en `guide.getReceipts()` (no `getContain()`).
- `[TELEFONOAGENCIA]`: `agency.getPhone()` (antes usaba email por error).
- `[REMITENTE]` / `[DESTINATARIO]`: nombre completo remitente y `addressee.getFullName()`.
- `[TIPOENVIO]`: `translator(shippingtype.getName())`.
- `[FECHACREACION]`: `maincompany.getFormatdate()`.
- `[AUXILIAR]` / `[TEXTAUX]`: mismo campo `getAux()`; corregido tag `[AUXILIAR]` (sin espacio).
- `[MASTERGUIDE]`: `getMasterguide()`.
- Totales: solo si hay receipts en `getReceipts()`.
- Agencia destino: `currentagency` (equivalente v2 de `agencydes`).
- Enlaces firma: `/guide/pobox/...` y `/guide/public/...` (sin `[ENLACEPUBLICOTIPOENVIO]`).
- Status: `[FECHASTATUS]` con fecha + hora; `[CIUDADSTATUS]` y `[COMENTARIOSTATUS]` con fallback `N/A`.
- Entrega (`guide_delivered`): correo vía `sendDeliveredEmailToMany` con adjuntos `ImagepackTypeEnum::STATUSCLOSE` + campo `Guide.signature` (no galería completa).
