Skip to content

Latest commit

 

History

History
137 lines (76 loc) · 12.9 KB

File metadata and controls

137 lines (76 loc) · 12.9 KB

PROJECT_TECHNICAL_OVERVIEW.md

Dirección técnica recomendada para el producto definido en PROJECT_OVERVIEW.md (la fuente de verdad de comportamiento). Son recomendaciones, no un mandato rígido: pueden adaptarse cuando mejore la corrección, mantenibilidad, velocidad, seguridad, accesibilidad o el encaje con el entorno real, documentando la desviación.


Filosofía

Una aplicación web pequeña, clara y mantenible que digitaliza un flujo manual sencillo. Evitar construir un CRM, e-commerce, gestor de inventario o suite de administración sobredimensionada. Optimizar para: operación diaria rápida, baja carga cognitiva para usuarios no técnicos, lógica de dominio mantenible, buena cobertura de tests de los flujos críticos, UI responsive (especialmente la operativa admin), despliegue simple y extensibilidad futura sin abstracción prematura.

Todo decide en favor del flujo central:

Buscar cliente/tarjeta → abrir tarjeta → añadir firma → ver progreso/premio

Stack recomendado

Laravel 12 · PHP 8.3+ · Pest · Inertia.js · Vue 3 · Tailwind CSS · shadcn-vue (o base Tailwind/Vue equivalente)

Encaja con la forma del producto: un portal admin privado más un portal cliente sencillo, ambos beneficiados por routing server-driven y experiencia SPA sin necesitar una API pública separada en esta fase.


Arquitectura

Monolito Laravel con páginas Inertia + Vue. No introducir una API separada salvo necesidad clara (la PoC no requiere arquitectura API-first).

Laravel
├── routing, controllers, requests, policies
├── Actions/Services de dominio para las operaciones de negocio
├── Modelos Eloquent y migraciones
├── Páginas Inertia (admin y cliente)
├── Componentes Vue reutilizables
├── Tests Pest (feature y dominio)
└── Sistema de componentes sobre Tailwind

Inertia/Vue — Inertia para routing por página e hidratación de datos. Convención de carpetas: resources/js/Pages/{Admin,Customer}/..., resources/js/Components/... (incluyendo Components/Loyalty/...) y Layouts/. Grupos de páginas por área (Dashboard, Search, Customers, Products, LoyaltyPrograms, LoyaltyCards, Rewards en admin; Dashboard, LoyaltyCards, History en cliente). Se pueden consolidar o renombrar si resulta más simple.


Componentes de UI

Base recomendada: Tailwind + shadcn-vue, por preferir un conjunto pequeño de componentes accesibles y personalizables, con los componentes viviendo en el propio repositorio (fáciles de inspeccionar y adaptar) frente a una plantilla de admin pesada. Alternativas libres válidas si encajan mejor: FlyonUI, Headless UI, daisyUI, PrimeVue, Preline UI o componentes Tailwind propios. Cualquier librería debe ser compatible con Vue 3 y Tailwind, libre para el uso previsto, accesible (formularios, diálogos, dropdowns, navegación) y no excesiva para la PoC.

Componentes de dominio propios (independientes de la librería base): LoyaltyCardVisual, StampGrid, StampSlot, StampActionPanel, RewardStatusBanner, GlobalSearchBox, GlobalSearchResultCard, CustomerSummaryCard, ProductBadge, ProgramBadge, AdminMetricCard, PendingRewardCard. Representan la experiencia real del producto; no deben forzarse a componentes genéricos de tabla/formulario.

UX — Usable en PC, tablet y móvil en condiciones reales adversas. Priorizar objetivos grandes de pulsado, contraste claro, jerarquía visual simple, lenguaje directo, pantallas de baja densidad, acción principal visible, mínima fricción de modales, estados claros de éxito/error/aviso (nunca solo color) y usabilidad móvil de búsqueda y sellado. Evitar tablas densas como patrón principal, desorden de plantilla admin, menús anidados profundos, formularios largos y gráficos/dashboards innecesarios.


Dominio Laravel

La lógica de negocio no vive en controllers ni en componentes Vue, sino en Actions/Services pequeños, explícitos y testeables. Ejemplos: Loyalty/CreateLoyaltyCard, AddStampToLoyaltyCard, VoidStamp, CompleteLoyaltyCard, GenerateReward, RedeemReward; Customers/CreateCustomer, Products/CreateProduct, Search/SearchOperationalRecords.

  • Controllers: autorizan, validan vía Form Requests, llaman a Actions y devuelven redirects o respuestas Inertia.
  • Componentes Vue: renderizan estado, recogen input, envían formularios Inertia y muestran feedback.

Modelos

Núcleo: User, Customer, Pet, Product, LoyaltyProgram, LoyaltyCard, Stamp, Reward, AuditEvent; pivote LoyaltyProgramProduct. Relaciones esperadas: Customer hasMany Pet/LoyaltyCard/Reward y opcional hasOne User; Pet belongsTo Customer y hasMany LoyaltyCard; Product belongsToMany LoyaltyProgram y hasMany Stamp; LoyaltyProgram belongsToMany Product y hasMany LoyaltyCard; LoyaltyCard belongsTo Customer/Pet(nullable)/LoyaltyProgram con hasMany Stamp y Reward; Stamp belongsTo LoyaltyCard/Product(nullable)/User(created_by,voided_by); Reward belongsTo LoyaltyCard/Customer/LoyaltyProgram/Product(redeemed_product)/User(redeemed_by).

Detalles clave: al crear una tarjeta se copia en ella el nº de firmas requeridas del programa (no se depende del valor actual del programa para tarjetas históricas); una firma anulada no cuenta para el progreso; valores computados posibles en LoyaltyCard (valid_stamps_count, remaining_stamps_count, is_complete, has_pending_reward) vía accessors/scopes/DTOs/resources; AuditEvent como tabla/modelo propio simple.


Base de datos

Migraciones Laravel estándar con constraints relacionales simples: FKs razonables, referencia de mascota nullable en tarjetas, código de tarjeta único, índices en campos de búsqueda (nombres de cliente, código de barras de producto, estado de premio, estado de tarjeta). Estados (active/completed/cancelled en tarjetas, valid/voided en firmas, pending/redeemed/cancelled en premios, is_active en catálogos) como enums PHP backed o constantes, almacenados como VARCHAR para compatibilidad SQLite/MariaDB. No sobrecomplicar la gestión de estados.


Autenticación y autorización

Email/contraseña tanto para admin como para cliente. El admin requiere rol admin o permiso equivalente. Un registro de Customer no requiere cuenta de acceso: la operativa admin funciona para clientes sin email ni usuario. Control de acceso con policies/gates: el admin gestiona datos operativos; el usuario cliente solo ve su propio registro, tarjetas, premios e historial y no modifica firmas, tarjetas, productos, programas ni premios.


Búsqueda

Funcionalidad central, no accesoria. Búsqueda server-side simple que cubra: nombre y email de cliente, nombre de mascota, código de tarjeta, nombre y código de barras de producto, nombre de programa. Inicialmente SQL LIKE con joins/scopes cuidados; sin motor de búsqueda salvo razón clara. Resultados optimizados para la acción operativa: cliente, mascota (si hay), contexto de programa/producto, estado y progreso de la tarjeta, estado del premio, acción principal "abrir tarjeta" y atajo opcional "añadir firma".


Códigos de barras

Dos tipos: código de tarjeta (identificador interno único, generado automáticamente) y código de barras de producto (opcional). Añadir una firma no requiere código. Si se aporta un código de producto, el sistema puede resolverlo; si no coincide con el programa, muestra advertencia en lugar de bloquear, y cualquier override queda trazable. Sin escaneo por cámara en la primera implementación. Un lector USB actúa como teclado, así que campos de input enfocados cubren muchos flujos sin integración hardware especial.


Auditoría, validación y feedback

Auditoría — Eventos ligeros para cambios críticos (customer.created, loyalty_card.created, stamp.created, stamp.voided, loyalty_card.completed, reward.generated, reward.redeemed, reward.cancelled, product.created/updated, loyalty_program.created/updated). Campos: id, actor_user_id (nullable), event_type, subject_type/subject_id (nullable), payload JSON (nullable), created_at. Sin UI compleja inicial: una vista admin básica o registros internos bastan.

Validación — Form Requests por entidad (Store/Update de Customer, Pet, Product, LoyaltyProgram; Store de LoyaltyCard; AddStamp, VoidStamp, RedeemReward). Estricta para proteger integridad pero sin crear fricción: nombre de cliente requerido, email nullable pero válido, código de barras nullable pero único, mascota nullable, productos requeridos en programas, producto de firma nullable, motivo de anulación opcional.

Feedback — Mensajes concisos y prácticos en pantallas operativas (firma añadida, tarjeta completada, premio generado/redimido, firma anulada, advertencia de producto, tarjeta no sellable por completada/cancelada, sin tarjetas activas, sin resultados). Ejemplos: Firma añadida., Tarjeta completada. Se ha generado un saco gratis pendiente., Este producto no pertenece al programa de esta tarjeta., La tarjeta ya está completada y no admite más firmas., Premio marcado como entregado.


Testing

Pest, priorizando el comportamiento de negocio sobre el detalle visual. Dominio/Actions: crear tarjeta copia el nº de firmas; una firma válida incrementa el progreso y las anuladas no cuentan; la tarjeta se completa al alcanzar el nº requerido, genera premio pendiente y no admite firmas por el flujo normal; el premio se redime sin crear firma; un cliente sin usuario puede tener tarjetas; mascota opcional; discrepancia de producto registrable como aviso. Feature: acceso admin al dashboard y bloqueo a no-admin; el admin crea cliente/producto/programa/tarjeta, añade firma y redime premio; el cliente ve sus tarjetas pero no las de otro. Añadir tests de regresión al corregir bugs de flujos centrales; browser/E2E no requerido en la PoC inicial.

Seeders/demo — Datos demo desde el principio para probar sin configuración manual: admin, cliente con y sin cuenta, varias mascotas y productos, al menos dos programas, y tarjetas en estados representativos (0/10, 7/10, completa con premio pendiente, completa con premio redimido, ejemplo de firma anulada).


Responsive y fases

Responsive — Admin usable en escritorio, tablet y móvil; prioridad móvil en búsqueda global, tarjetas de resultado, detalle de tarjeta, añadir firma, estado y redención de premio. Menor prioridad móvil: configuración compleja de productos/programas, listados largos y filtrado avanzado. Portal cliente mobile-first.

Fases — (1) Fundación: auth, roles, layout base, shell del dashboard, primitivas UI, migraciones, modelos y seeders. (2) Dominio admin: clientes, mascotas, productos, programas, tarjetas, detalle de tarjeta, firmas, completar, generar y redimir premios, auditoría. (3) Búsqueda operativa: buscador global, tarjetas de resultado, navegación rápida, lookup por código. (4) Portal cliente: login, dashboard, tarjetas activas, premios pendientes, históricos. (5) Endurecimiento: validaciones, tests de autorización, pulido UX, responsive, estados vacíos/carga/error, flujo demo final. El flujo de sellado debe ser demostrable cuanto antes.


Política de dependencias y fuera de alcance

Añadir dependencias solo cuando reduzcan riesgo de forma material, estén mantenidas y compatibles, no añadan complejidad desproporcionada y tengan un propósito claro en la PoC. Evitarlas para funciones fuera de alcance, dashboards pesados, grids complejos, analítica, gráficos, jobs en background, tiempo real, escaneo por cámara, notificaciones o features de CRM/e-commerce.

Fuera del alcance técnico inicial (salvo petición posterior): SMS/WhatsApp, magic links, multi-tenant, inventario, facturación/TPV, analítica avanzada, escaneo por cámara, PWA offline, import/export complejo, edición de perfil por el cliente, matriz granular de permisos, API pública, SSR y notificaciones en tiempo real.


Decisiones por defecto y criterio de calidad

Por defecto: monolito Laravel + Inertia/Vue; UI Tailwind + shadcn-vue o similar; auth email/contraseña; acceso por rol admin/cliente; búsqueda SQL server-side; código de barras por campos de input normales; auditoría con tabla audit_events propia ligera; tests Pest feature/dominio; SSR desactivado; sin API-first; prioridad móvil en portal cliente y flujos operativos admin.

La implementación se considera lograda cuando el flujo demo funciona con fluidez: el admin entra, encuentra/crea cliente y producto, crea un programa con productos y nº de firmas, crea una tarjeta (opcionalmente con mascota), busca y abre la tarjeta, añade firmas con una acción grande y clara, ve el progreso, la tarjeta se completa al alcanzar el nº, se genera un premio pendiente, lo marca como entregado, y el cliente (si tiene cuenta) ve sus tarjetas activas, premios e historial. La experiencia debe sentirse como un reemplazo digital directo de la tarjeta física, no como una aplicación de gestión genérica.