Como funciona el proyecto
⚠️ Importante - Arquitectura Multivertical
Section titled “⚠️ Importante - Arquitectura Multivertical”Este proyecto está diseñado para alimentar todas las verticales de Alebat Education. Cada función, servicio y componente debe desarrollarse pensando en la modularidad y reutilización entre múltiples tiendas.
🎯 Objetivo Principal
Section titled “🎯 Objetivo Principal”- Una sola lógica unificada que sirva a todas las tiendas simultáneamente
- Mantenimiento de productos y funcionamiento independientes por vertical
- Distribución de pagos y relaciones con CRMs individuales e independientes
- Escalabilidad y sostenibilidad - un cambio necesario en todas las tiendas se modifica solo una vez
🚀 Instalación y Configuración Inicial
Section titled “🚀 Instalación y Configuración Inicial”📦 Comandos de Inicialización
Section titled “📦 Comandos de Inicialización”# Instalar dependenciasnpm i
# Iniciar el proyecto en desarrollo (NO usar 'develop')npm run dev🏗️ Arquitectura del Proyecto
Section titled “🏗️ Arquitectura del Proyecto”📋 Tecnología Base
Section titled “📋 Tecnología Base”Este proyecto está construido con Strapi 5 y utiliza TypeScript como lenguaje principal.
- CMS: Strapi v5
- Lenguaje: TypeScript (obligatorio)
- Base de datos: Compatible con múltiples BBDD - MySQL(recomendada), PostgreSQL, SQLite, etc.
📁 Estructura de Carpetas - Strapi 5
Section titled “📁 Estructura de Carpetas - Strapi 5”La estructura sigue la organización estándar de Strapi 5:
src/├── api/ # 📂 APIs personalizadas│ ├── [collection]/ # Colecciones individuales│ │ ├── content-types/ # Schemas de la estructura│ │ | └── lifecycles # Hooks de ciclo de vida│ │ ├── controllers/ # Controladores de API│ │ ├── routes/ # Rutas personalizadas│ │ ├── services/ # Servicios de negocio│ └── ...├── components/ # 🧩 Componentes reutilizables├── constants/ # 📋 Constantes del sistema├── plugins/ # 🔌 Plugins personalizados├── types/ # 📝 Tipos TypeScript└── utils/ # 🔧 Utilidades generales🛠️ Configuración del Entorno de Desarrollo
Section titled “🛠️ Configuración del Entorno de Desarrollo”Linters Obligatorios
Section titled “Linters Obligatorios”⚠️ IMPORTANTE: Los siguientes linters DEBEN estar instalados y configurados en Visual Studio Code:
// .vscode/extensions.json (recomendado){ "recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]}Configuración VS Code
Section titled “Configuración VS Code”{ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "eslint.validate": ["javascript", "typescript"]}¿Por qué son obligatorios?
- ESLint: Detecta errores de código, magic strings, variables no utilizadas
- Prettier: Mantiene formato consistente de código
🔒 Plugin User-Permissions
Section titled “🔒 Plugin User-Permissions”Este proyecto utiliza el plugin de user-permissions de Strapi para la gestión de:
- Roles y permisos de usuarios
- Seguridad de las APIs del proyecto
- Autenticación y autorización
📖 Documentación específica: User-Permissions
📐 Reglas de Desarrollo Obligatorias
Section titled “📐 Reglas de Desarrollo Obligatorias”🎯 1. TypeScript Obligatorio
Section titled “🎯 1. TypeScript Obligatorio”TODOS los archivos deben estar escritos en TypeScript.
✅ ¿Por qué TypeScript?
Section titled “✅ ¿Por qué TypeScript?”// ✅ Con TypeScript - Detección temprana de erroresinterface User { id: number; name: string; email: string;}
const getUser = (id: number): User => { // TypeScript verifica los tipos en tiempo de compilación return strapi.entityService.findOne("api::user.user", id);};// ❌ Sin TypeScript - Errores en runtimeconst getUser = (id) => { // ¿Qué tipo es 'id'? ¿Qué devuelve esta función? return strapi.entityService.findOne("api::user.user", id);};🎯 2. Prohibición de Magic Strings
Section titled “🎯 2. Prohibición de Magic Strings”NO pueden existir strings hardcodeados en el código.
❌ Problema - Magic Strings y Magic Numbers
Section titled “❌ Problema - Magic Strings y Magic Numbers”// ❌ Imagina que 'admin' se usa en 15 archivos diferentes, 10 veces en cada unoif (user.role === "admin") { // Lógica administrativa}
// En otro archivo:if (user.role === "admin") { // Más lógica}
// Y en 148 lugares más...💥 ¿Qué pasa cuando necesitas cambiar ‘admin’ por ‘administrator’?
❌ Debes encontrar y reemplazar 150 ocurrencias manualmente
❌ Riesgo de olvidar algunas y crear bugs
❌ No hay autocompleta ni verificación de tipos
❌ Errores silenciosos si escribes mal el string
✅ Solución - Constantes Tipadas
Section titled “✅ Solución - Constantes Tipadas”export const USER_ROLES = { ADMIN: "admin", USER: "user", MODERATOR: "moderator",} as const;
// Uso en cualquier archivo:if (user.role === USER_ROLES.ADMIN) { // Lógica administrativa - ¡Autocompleta y verificación de tipos!}🎯 Beneficios:
- ✅ Un solo lugar para cambiar el valor (1 línea vs 150)
- ✅ Autocompleta de TypeScript
- ✅ Errores en tiempo de compilación si escribes mal
- ✅ Refactoring seguro con herramientas IDE
📋 Sistema de Constantes
Section titled “📋 Sistema de Constantes”📁 Estructura Actual del Proyecto
Section titled “📁 Estructura Actual del Proyecto”src/constants/├── errors/ # 🚨 Mensajes de error organizados├── structures/ # 🏗️ Estructuras de datos complejas├── countryCodes.ts # 🌍 Códigos de países internacionales├── crmStripe.ts # 💳 Configuraciones de Stripe CRM├── defaultLocale.ts # 🌐 Configuración de idiomas por defecto├── emails.ts # 📧 Templates y configuraciones de email├── laabProServices.ts # 🔬 Servicios de LaabPro├── record.ts # 📊 Constantes para records/grabaciones├── regex.ts # 📝 Patrones de expresiones regulares└── verticals.ts # 🏢 Configuraciones de verticales🎯 ¿Por qué esta organización?
Section titled “🎯 ¿Por qué esta organización?”Esta estructura está diseñada para soportar múltiples verticales de manera eficiente:
- 📁
errors/- Mensajes de error centralizados y tipados - 📁
structures/- Estructuras de datos complejas reutilizables - 📄 Archivos específicos - Cada uno enfocado en un dominio particular
🎯 Ejemplo Real del Proyecto - Constantes de Productos
Section titled “🎯 Ejemplo Real del Proyecto - Constantes de Productos”Este es un ejemplo real de cómo están organizadas las constantes en el proyecto:
// constants/products.ts - Ejemplo real del proyecto
// 📝 Campos básicos de productosexport const FIELDS_PRODUCT = [ "id", "SKU", "acronym", "contract", "locale", "order", "type", "publishedAt", "slug", "stripeID", "title", "vertical", "stripeCrm",];
// 🧩 Componentes reutilizablesexport const COMPONENTS_PRODUCT = [ "fullPrice", "tuitionPrice", "instalmentsPrices", "laabConnection",];
// 🔗 Referencias de servicios APIexport const PRODUCT = "api::product.product";export const PRODUCT_STRIPE_SERVICE = "api::product.stripe";export const PRODUCT_HANDLER_SERVICE = "api::product.handler";🏗️ Principios de Organización Aplicados
Section titled “🏗️ Principios de Organización Aplicados”Este ejemplo muestra las mejores prácticas implementadas:
✅ 1. Agrupación Lógica
Section titled “✅ 1. Agrupación Lógica”- Campos base vs campos específicos por tipo de producto
- Componentes generales vs componentes especializados
- Configuraciones (IVA, tipos) separadas de datos operacionales
✅ 2. Nomenclatura Consistente
Section titled “✅ 2. Nomenclatura Consistente”FIELDS_*para campos de base de datosCOMPONENTS_*para componentes Strapi*_TYPESpara enumeraciones de tipos*_SERVICEpara referencias de servicios
✅ 3. Escalabilidad Multivertical
Section titled “✅ 3. Escalabilidad Multivertical”- Las constantes soportan múltiples tipos de productos
- Reutilización entre diferentes verticales
- Extensibilidad fácil para nuevos tipos de productos
🧩 Componentes de Strapi
Section titled “🧩 Componentes de Strapi”Los componentes son bloques de contenido reutilizables que se pueden usar múltiples veces dentro de diferentes tipos de contenido.
🎯 ¿Cuándo usar componentes?
Section titled “🎯 ¿Cuándo usar componentes?”✅ Úsalos cuando:
- Un conjunto de campos se repite en múltiples collection types
- Necesitas estructuras de datos complejas y reutilizables
- Quieres mantener consistencia en la estructura de datos
💡 Ejemplos Comunes
Section titled “💡 Ejemplos Comunes”// 📞 Componente: Phone{ "displayName": "Phone", "attributes": { "countryCode": { "type": "string" }, "number": { "type": "string" }, "extension": { "type": "string" } }}
// 🏠 Componente: Address{ "displayName": "Address", "attributes": { "street": { "type": "string" }, "city": { "type": "string" }, "postalCode": { "type": "string" }, "country": { "type": "string" } }}🔄 Uso en Collection Types
Section titled “🔄 Uso en Collection Types”// En User collection{ "attributes": { "name": { "type": "string" }, "phone": { "type": "component", "component": "contact.phone", "repeatable": true // Múltiples teléfonos }, "address": { "type": "component", "component": "contact.address" } }}📚 Recursos Adicionales
Section titled “📚 Recursos Adicionales”📖 Documentación de Referencia
Section titled “📖 Documentación de Referencia”🔗 Enlaces Útiles del Proyecto
Section titled “🔗 Enlaces Útiles del Proyecto”- User Endpoints - APIs de usuarios
- Strapi Queries - Consultas optimizadas
- Validación de APIs
- Sistema de Checkout