# Bug: formulario de catálogo de máquinas fallaba siempre (lead perdido + descarga rota)

## Síntoma

En la ficha de cualquier máquina (`/machinery/{slug}/detail`), pedir el catálogo por el
formulario (`CatalogueContactForm`) tiraba error genérico ("messages.error-email") — no se
guardaba el lead ni se mandaba el correo a `machinery@`/`info@group-itg.com`.

## Causa raíz

`resources/views/machinery/show.blade.php:170` pasaba `'product_name' => $machine->name` al
componente Livewire. `App\Models\Machine` **no tiene** un atributo `name` — no hay
`getNameAttribute()`, y `name` no está en `$translatable` (Spatie). El nombre traducido vive en
`$machine->translation->name` (accessor propio, `getTranslationAttribute()` +
`HasLanguageFallback::resolveByLanguage()`) — patrón que el resto del mismo archivo usa bien
(líneas 9, 10, 46). `$machine->name` siempre resolvía `null`.

`catalogue_contacts.product_name` es `NOT NULL` en la tabla, así que el `create()` en
`CatalogueContactForm::store()` (línea 77-84) tiraba
`SQLSTATE[23000]: ... Column 'product_name' cannot be null` — capturado por el `catch`, mostraba
el alert de error genérico y **no guardaba nada ni mandaba el correo**. Afectaba a **cualquier**
solicitud de catálogo desde una ficha de máquina, no un caso puntual — probable pérdida de leads
reales mientras estuvo así.

Los otros dos usos del mismo componente están bien:
- `resources/views/products/show.blade.php:127` → `$selectedSector->title` (sí es
  `$translatable` de `ProductSector`, Spatie resuelve el accessor correcto).
- `resources/views/sale-used-machine/customer/show.blade.php:262` → `$machineName`, variable
  calculada en el controller desde `brand`/`model` con `??` de por medio, no depende de este bug.

## Fix (bug 1: `product_name` null)

Una línea: `$machine->name` → `$machine->translation->name`
(`resources/views/machinery/show.blade.php:170`). Verificado con tinker: `$machine->name` es
`NULL`, `$machine->translation->name` resuelve el nombre real (`'Water Looms'` para el machine_id
de prueba).

## Bug 2: descarga del catálogo — `public_path()` en vez del disco `public`

Con el bug 1 arreglado, el formulario ya guardaba el lead y mandaba el correo, pero la descarga
del PDF seguía fallando: `CatalogueContactForm::store()` armaba la ruta con
`public_path($this->urlCatalogue)`, asumiendo que el archivo vive directo en `public/...`. El
valor real de `urlCatalogue` (`machine_catalogues.url` / `product_sector_catalogues.url`) es una
ruta **relativa al disco `public`** (`storage/app/public/...`), no a la carpeta `public/` del
webroot — mismo patrón de bug que el de `ContactRequestPost`/`ContactRequestResource` (ver
`CLAUDE-CONTACT-REQUEST-ATTACHMENT.md`), pero acá con `public_path()` en vez de `asset('storage/
...')`.

**Fix**: `Storage::disk('public')->path($this->urlCatalogue)` en vez de
`public_path($this->urlCatalogue)`, con un `abort_unless(... exists ..., 404)` antes. Verificado
con tinker contra el path real del error
(`machinery/catalogues-pdfs/Weaving/Jacquard/CAT. Jacquard-GCS.ENG.pdf`): resuelve a
`storage/app/public/machinery/catalogues-pdfs/...`, coincide con dónde vive el archivo real en
producción. Afecta por igual a `products/show.blade.php` (mismo componente, misma línea de
descarga) — no es exclusivo de `machinery`.
