# Return Portal + Auto-Label — Documentación completa

> Portal de devoluciones autoservicio para clientes, etiquetas de retorno multi-transportista generadas automáticamente, flujo de inspección admin y motor de resolución (reembolso, vale bonificado, reemplazo) para WooCommerce. Versión: 1.0.7 Compatibilidad: WordPress…

- Página: <https://www.datafirefly.com/es/documentation/dfreturnportal/>
- Idioma: es
- Actualizado el: 2026-08-05
- Otros idiomas: [fr](https://www.datafirefly.com/documentation/dfreturnportal/index.md), [en](https://www.datafirefly.com/en/documentation/dfreturnportal/index.md), [de](https://www.datafirefly.com/de/documentation/dfreturnportal/index.md), [it](https://www.datafirefly.com/it/documentation/dfreturnportal/index.md), [pl](https://www.datafirefly.com/pl/documentation/dfreturnportal/index.md), [nl](https://www.datafirefly.com/nl/documentation/dfreturnportal/index.md), [pt](https://www.datafirefly.com/pt/documentation/dfreturnportal/index.md)
- Índice: <https://www.datafirefly.com/es/documentation/llms.txt>

Portal de devoluciones autoservicio para clientes, etiquetas de retorno multi-transportista generadas automáticamente, flujo de inspección admin y motor de resolución (reembolso, vale bonificado, reemplazo) para WooCommerce.

**Versión:** 1.0.7
**Compatibilidad:** WordPress 6.2+ • WooCommerce 8.0+ • PHP 8.0+ • HPOS y Cart/Checkout Blocks

## Visión general

Return Portal + Auto-Label automatiza todo el ciclo de vida de una devolución de producto en tu tienda WooCommerce:

- **Lado cliente**: el cliente solicita su devolución sin contactar soporte, selecciona artículos, elige un motivo y recibe inmediatamente su etiqueta PDF.
- **Lado administrador**: panel con línea de tiempo, inspección línea por línea, registro de actividad completo y resolución automática.
- **6 transportistas**: Manual (PDF nativo), Colissimo, Mondial Relay, Chronopost, UPS, DPD.
- **3 resoluciones**: reembolso WooCommerce nativo, vale bonificado (+X%) o reemplazo automático.

### Estados de una devolución

Una devolución pasa por hasta 7 etapas:

| Estado | Descripción |
| --- | --- |
| `requested` | Solicitud recibida, pendiente de validación |
| `approved` | Aprobada por admin (o auto-aprobada bajo umbral) |
| `label_sent` | Etiqueta generada y enviada al cliente |
| `in_transit` | Paquete en tránsito |
| `received` | Paquete recibido en el almacén |
| `inspecting` | Artículos en inspección |
| `resolved` | Resolución aplicada (reembolso / vale / reemplazo) |

Dos estados terminales adicionales: `rejected` y `cancelled`.

## Instalación

### Método 1 — Vía admin WordPress

1. Descarga el ZIP `dfreturnportal.zip`.
2. En WordPress, ve a **Plugins → Añadir nuevo → Subir plugin**.
3. Selecciona el ZIP, haz clic en **Instalar ahora**.
4. Activa el plugin.

### Método 2 — Vía FTP/SSH

```bash
cd wp-content/plugins/
unzip dfreturnportal.zip
# Luego activa desde el admin WordPress
```

### Verificaciones post-instalación

- Aparece un menú **Devoluciones** en la barra lateral de WordPress.
- Se crea automáticamente un endpoint `/es/my-account/devoluciones/`.
- Se crean las tablas personalizadas `wp_dfrp_returns`, `wp_dfrp_return_items`, `wp_dfrp_history`, `wp_dfrp_attachments`.

Si la pestaña "Devoluciones" no aparece en Mi Cuenta, ve a **Ajustes → Enlaces permanentes** y haz clic en "Guardar" para refrescar las reglas de reescritura.

## Configuración inicial

Ve a **Devoluciones → Ajustes**.

### General

| Ajuste | Descripción |
| --- | --- |
| **Ventana de elegibilidad** | Número de días tras el pedido durante los cuales se permite una devolución. Por defecto: 30 días. |
| **Página del portal cliente** | Página de WordPress donde se mostrará el shortcode `[dfrp_portal]`. Opcional si solo usas el endpoint Mi Cuenta. |
| **Notificaciones admin** | Dirección de email que recibirá las notificaciones de nuevas solicitudes. Por defecto: admin del sitio. |

### Transportista

Selecciona el transportista **activo** entre los 6 disponibles. También puedes configurar el **formato de etiqueta** (A4, A5, A6, 10x15).

### Dirección de devolución

Indica la dirección física donde se enviarán los paquetes de devolución. **Obligatorio** para generar las etiquetas. Campos: Empresa, Calle, Ciudad, Código postal, País (código ISO 2 letras), Teléfono, Email.

### Credenciales de transportistas

Para cada transportista API (Colissimo, Mondial Relay, etc.), un bloque desplegable contiene las credenciales requeridas. Rellena **únicamente** las del transportista que vayas a usar.

### Resolución

| Ajuste | Descripción |
| --- | --- |
| **Bonus vale (%)** | Porcentaje añadido al importe reembolsado cuando el cliente elige el vale bonificado. Por defecto: 10%. |
| **Umbral de auto-aprobación** | Por debajo de este importe (moneda de la tienda), las solicitudes se aprueban automáticamente y la etiqueta se genera sin intervención del admin. Pon 0 para desactivar. |
| **Resolución propuesta por motivo** | Para cada motivo (8 motivos por defecto), elige la resolución propuesta: reembolso / vale bonificado / reemplazo. |

### Exclusiones

- **Categorías excluidas**: IDs de WooCommerce separados por comas. Los productos de estas categorías nunca serán elegibles para devolución.
- **SKUs excluidos**: un SKU por línea.

## Experiencia del cliente

### Vía la página Mi Cuenta (clientes conectados)

La opción más simple y utilizada. La pestaña **Devoluciones** aparece automáticamente en el menú `/es/my-account/` junto a "Pedidos", "Direcciones", etc.

El cliente hace clic en Devoluciones, ve la lista de sus pedidos elegibles (sin necesidad de introducir email/número), pulsa Iniciar una devolución en el pedido correspondiente, selecciona los artículos, elige un motivo y cantidad por artículo, añade opcionalmente fotos (si el motivo lo exige), elige su resolución preferida y recibe inmediatamente un número de RMA (ej.: `RMA-20260523-A1B2C3`) más un email de confirmación.

### Vía una página pública (clientes invitados)

Crea una página de WordPress, inserta el shortcode:

```
[dfrp_portal]
```

El cliente deberá introducir su **número de pedido** + **email** para autenticarse. El resto del flujo es idéntico.

### Seguimiento de una solicitud existente

En la página pública del portal, un bloque "Seguir una solicitud existente" permite a los clientes invitados verificar el estado de su RMA (estado, número de seguimiento del transportista, enlace a la etiqueta).

### Personalización del shortcode

```
[dfrp_portal title="Solicitud de devolución" context="page"]
```

| Atributo | Valores | Descripción |
| --- | --- | --- |
| `title` | texto libre | Título del portal (raramente usado visualmente). |
| `context` | `page` o `myaccount` | Fuerza el contexto. `myaccount` salta el paso lookup para usuarios conectados. |

## Flujo de administrador

### Panel

Accesible vía **Devoluciones → Panel**. Contiene 9 tarjetas estadísticas de colores (recuento por estado, clicables para filtrar la lista), los 10 últimos RMA con acceso rápido al detalle, y un banner con la URL del portal cliente con botón "Copiar" para compartir.

### Lista de solicitudes

Accesible vía **Devoluciones → Todas las solicitudes**. Tabla con filtros por estado, búsqueda libre (RMA, email cliente, número de pedido) y paginación (20 por página).

### Página de detalle de una solicitud

Componentes:

1. **Cabecera**: código RMA + insignia de estado + vuelta a la lista.
2. **Línea de tiempo**: 7 puntos de colores mostrando el progreso visual.
3. **Artículos a devolver**: tabla con producto, SKU, cantidad, precio unitario, motivo e inspección por artículo (desplegable Conforme / Parcialmente / Rechazado — activado tras estado `received`).
4. **Fotos del cliente**: galería si el cliente subió justificantes.
5. **Registro de actividad**: historial cronológico completo.
6. **Información**: email cliente, enlace del pedido, preferencia de resolución, nota del cliente.
7. **Etiqueta de devolución**: transportista, número de seguimiento, botón descargar PDF, botón regenerar.
8. **Acciones**: botones "Pasar a: [siguiente estado]" según la máquina de estados.
9. **Resolver** (visible si estado es `received` o `inspecting`): selector de resolución + botón "Aplicar".

### Transiciones permitidas

La máquina de estados impide transiciones inválidas:

```
requested  → approved | rejected | cancelled
approved   → label_sent | rejected | cancelled
label_sent → in_transit | cancelled
in_transit → received
received   → inspecting
inspecting → resolved | rejected
```

Los estados `resolved`, `rejected` y `cancelled` son terminales.

### Auto-aprobación

Si has configurado un umbral de auto-aprobación (ej.: 50 €), cualquier solicitud cuyo importe total sea menor o igual al umbral pasa automáticamente de `requested` a `approved`, la etiqueta se genera inmediatamente y se envía al cliente, sin intervención del admin.

## Transportistas soportados

### Manual (sin API)

**Ideal para empezar.** Genera un comprobante PDF nativo con código QR, sin ninguna dependencia de API externa. Cero configuración, gratuito, funciona inmediatamente. Limitación: sin seguimiento automático. Uso: el cliente lo imprime y tú lo metes en el paquete en el envío inicial, o él lo pega para la devolución postal clásica.

### Colissimo (La Poste)

API REST oficial (Sls Service `generateLabel`). Credenciales requeridas: Contract Number, Password. Particularidades: genera un código de barras `parcelNumber`, tipo de devolución "3", formato PDF por defecto.

### Mondial Relay

API SOAP (`WSI4_CreationEtiquette`). Credenciales requeridas: Enseigne, Private Key, Pickup Point. Particularidades: modo de recogida `CCC` (Paquete Confiado al Cliente), firma MD5 obligatoria.

### Chronopost

API SOAP (`shippingMultiParcelV5`). Credenciales requeridas: Account Number, Password, Subaccount. Particularidades: Product Code `8R` (devolución Relais), modo retorno `2`.

### UPS

API REST v2403 (`/ship`). Credenciales requeridas: Client ID (OAuth2), Client Secret, Shipper Number. Particularidades: `ReturnService.Code` = `8` (Electronic Return Label), formato GIF base64 por defecto.

### DPD

API REST (cargonet endpoint). Credenciales requeridas: Username, Password, Customer ID. Particularidades: Autenticación Basic Auth, formato PDF A6.

## Resoluciones

### Reembolso

Usa la función nativa `wc_create_refund()` de WooCommerce. Acredita el método de pago original, restock automático de artículos (configurable), crea una nota de reembolso en el pedido y dispara un email de confirmación nativo de WooCommerce.

### Vale bonificado

Crea automáticamente un cupón WooCommerce:

- **Importe** = total devuelto + bonus (% configurable, por defecto 10%).
- **Restricción email**: utilizable únicamente por el email del cliente.
- **Caducidad**: 6 meses por defecto.
- **Uso único**.

El cliente recibe un email con su código de cupón en grande.

### Reemplazo

Crea un **nuevo pedido WooCommerce** a 0 € (gratuito para el cliente). Direcciones de envío/facturación copiadas del pedido original, artículos idénticos a los devueltos conformes, estado inicial `processing` (lo envías normalmente). El cliente recibe un email con el número del nuevo pedido.

### Propuesta automática

El motor analiza los motivos de los artículos devueltos y propone la resolución más pertinente. Configuración en **Devoluciones → Ajustes → Resolución propuesta por motivo**. Mapeo por defecto:

| Motivo | Resolución propuesta |
| --- | --- |
| Artículo dañado | Reemplazo |
| Artículo defectuoso | Reemplazo |
| Artículo equivocado recibido | Reemplazo |
| Conforme a la descripción pero no encaja | Reembolso |
| Cambio de opinión | Vale bonificado |
| Talla o color incorrectos | Vale bonificado |
| Entrega tardía | Reembolso |
| Otro | Reembolso |

## Personalización

### Override de plantillas

Todas las plantillas de email son sobreescribibles desde tu tema. Copia el archivo fuente `templates/emails/*.php` a `yourtheme/dfreturnportal/emails/*.php`.

### Hooks (acciones)

```php
do_action('dfrp_after_return_created', int $returnId, array $return);
do_action('dfrp_status_changed', int $returnId, string $fromStatus, string $toStatus);
do_action('dfrp_label_generated', int $returnId, array $label);
do_action('dfrp_before_resolution', int $returnId, string $resolution);
do_action('dfrp_after_resolution', int $returnId, string $resolution, array $result);
```

### Filtros

```php
// Personalizar los estados de pedido elegibles (por defecto: ['completed', 'processing'])
add_filter('dfrp_eligible_order_statuses', function($statuses) {
    $statuses[] = 'on-hold';
    return $statuses;
});

// Personalizar los motivos de devolución
add_filter('dfrp_reasons', function($reasons) {
    $reasons[] = [
        'code'          => 'motivo_custom',
        'label'         => 'Mi motivo personalizado',
        'require_photo' => false,
    ];
    return $reasons;
});

// Personalizar el slug del endpoint Mi Cuenta (por defecto: 'returns')
add_filter('dfrp_myaccount_endpoint', function() {
    return 'mis-devoluciones';
});

// Personalizar la etiqueta del menú Mi Cuenta
add_filter('dfrp_myaccount_menu_label', function() {
    return 'Mis devoluciones';
});

// Añadir un transportista personalizado
add_filter('dfrp_register_carriers', function($carriers) {
    $carriers[] = new MiTransportistaCustom();
    return $carriers;
});
```

### Desinstalación limpia

Por defecto, la desinstalación **conserva** los datos (tablas y opciones). Para purgar todo en la desinstalación, añade a `wp-config.php`:

```php
define('DFRP_DELETE_DATA_ON_UNINSTALL', true);
```

## API REST

Todos los endpoints están bajo el namespace `dfrp/v1`. URL base: `https://tusitio.com/wp-json/dfrp/v1/`.

### Endpoints públicos

| Endpoint | Método | Descripción |
| --- | --- | --- |
| `/lookup` | POST | Busca un pedido por número + email. |
| `/create` | POST | Crea una nueva solicitud de devolución. |
| `/track` | POST | Seguir un RMA vía código + email. |
| `/upload-photo` | POST | Sube una foto justificativa (multipart). |

### Endpoints cliente conectado

| Endpoint | Método | Descripción |
| --- | --- | --- |
| `/my-orders` | GET | Lista los pedidos elegibles del cliente conectado. |

### Endpoints admin (capability `manage_woocommerce`)

| Endpoint | Método | Descripción |
| --- | --- | --- |
| `/admin/returns` | GET | Lista paginada con filtros. |
| `/admin/returns/{id}` | GET | Detalle de una devolución. |
| `/admin/returns/{id}/transition` | POST | Cambiar el estado. |
| `/admin/returns/{id}/inspect-item` | POST | Resultado de inspección de un artículo. |
| `/admin/returns/{id}/resolve` | POST | Aplicar una resolución. |
| `/admin/returns/{id}/regenerate-label` | POST | Regenerar la etiqueta. |

## Resolución de problemas

### El portal muestra "Cargando..." indefinidamente

- Verifica la consola del navegador (F12) — deberías ver `[Return Portal] script frontend.js ejecutado`.
- Si no aparece nada, un plugin de seguridad (Wordfence, Sucuri, NinjaFirewall) está bloqueando el script inline. Desactívalo temporalmente para probar.
- Verifica también los optimizadores JS (WP Rocket "Delay JS", Autoptimize, Cloudflare Rocket Loader) — el plugin ya emite los atributos opt-out necesarios, pero algunas configuraciones muy agresivas pueden seguir bloqueando.

### La pestaña "Devoluciones" no aparece en Mi Cuenta

Ve a **Ajustes → Enlaces permanentes** y haz clic en "Guardar cambios" (sin cambiar nada). Esto fuerza a WordPress a regenerar las reglas de reescritura.

### Error "Constant DFRP_VERSION already defined"

La carpeta del plugin está duplicada. Verifica:

```bash
ls -la wp-content/plugins/ | grep dfreturnportal
```

Elimina las copias duplicadas (ej.: `dfreturnportal-old/`, `dfreturnportal-1/`).

### El cliente no recibe los emails

- Verifica que el envío de emails funciona globalmente.
- Configura un SMTP adecuado (WP Mail SMTP, FluentSMTP).
- Verifica los logs de spam del dominio destinatario.

### La etiqueta PDF está vacía o corrupta

- Verifica que la dirección de devolución esté completa.
- Para los transportistas API, verifica las credenciales en modo prueba primero.
- Consulta los logs PHP (`/wp-content/debug.log` si `WP_DEBUG_LOG` está activo).

## FAQ

**¿El plugin requiere una suscripción a un transportista?**
No. El modo **Manual** genera un comprobante PDF nativo sin ninguna dependencia API. Los modos API (Colissimo, etc.) son opcionales.

**¿Compatible HPOS (High-Performance Order Storage)?**
Sí, totalmente. El plugin declara su compatibilidad al arrancar WooCommerce.

**¿Compatible Cart/Checkout Blocks?**
Sí.

**¿Se gestionan las variaciones de producto?**
Sí, cada variación se trata como un artículo distinto.

**¿Y los productos virtuales o descargables?**
Se excluyen automáticamente de las devoluciones.

**¿Puede el cliente devolver un pedido parcialmente?**
Sí. La elegibilidad tiene en cuenta las cantidades ya devueltas vía RMA anteriores.

**¿Multi-idioma?**
El plugin está listo para traducción (Text Domain `dfreturnportal`, archivo `.pot` incluido). Compatible con WPML, Polylang, TranslatePress.

**¿Las fotos del cliente se almacenan de forma segura?**
Sí, en la biblioteca de medios de WordPress con reglas `.htaccess` que impiden el listado de directorio.
