📋 Versión y Log

Historial de cambios de la aplicación

v3.11.4
€” 2026-08-23

MAIA — Astro Chart Application

Aplicación de cartas natales

CHANGELOG



v3.11.4 — 2026-08-23



Corregido


  • Aspectos a los ángulos en el informe: los aspectos a Ascendente/Medio Cielo/Descendente/Fondo del Cielo aparecían sin nombre (ej. "Quincuncio a (…)", "Trígono a (…)"). AstrologiaHelper::getTranslate() no resolvía las claves de ángulo del AspectosCalculator (Ascendant, Midheaven, Descendant, IC) → añadidas las constantes TRANSLATE_ASCENDANT/MIDHEAVEN/DESCENDANT/IC. Ahora se muestran como "Ascendente", "Medio Cielo", "Descendente", "Fondo del Cielo". El fix es central: aplica también al grid de aspectos y a la rueda.


v3.11.3 — 2026-08-23



Añadido


  • Nueva clase includes/FuncionInferiorCalculator.php (doc 03 §01–§03): detecta funciones inferiores por los criterios de elemento único, modalidad única y grado 29°, con la excepción transpersonal (Urano/Neptuno/Plutón/Quirón solo cuentan como representantes si aspectan a un planeta personal/social). Universo: Sun–Quirón.


Corregido


  • Card de planeta en el informe: un planeta que sea el único en su elemento o modalidad (ej. la Luna como único planeta de Fuego a 3° Aries, carta de Anais Mateo) ahora se marca como "Función inferior (elemento único)" / "(modalidad única)", no solo cuando está a 29°.

  • Traducciones (7 idiomas): claves "Función inferior (elemento único)" y "Función inferior (modalidad única)".


v3.11.2 — 2026-08-21



Corregido


  • Roadmap (/admin/roadmap): el renderizador Markdown propio no soportaba ~~strikethrough~~ → se mostraba ~~texto~~ literal en vez de tachado. Ahora ~~ → <del> (inline y en items de lista, conservando numeración/viñetas).

  • Roadmap: parseRoadmap solo reconocía pending|done → las secciones in_progress (cobro y suscripción, gestor de email) se incrustaban dentro del item "Realizado" anterior. Ahora se parsean como tarjetas propias con badge "🔨 En curso" e incluidas en la pestaña Pendientes (contador + índice).


Cambiado


  • Roadmap: nueva sección "Pendientes" consolidada arriba del documento (<!-- status: pending -->, visible en la pestaña Pendientes) con los pendientes reales movidos desde las secciones en proceso (promotores, IVA, prorrateo, audit log, hardcodeos, emails) y todo lo ya realizado tachado en cada sección.


v3.11.1 — 2026-08-21



Corregido


  • Modal: el .modal-content legacy de styles.css capaba el ancho a 500px; override en .modal-dialog .modal-content (max-width: none, width: 100%, font-size: 16px). El modal large passa a width: 95% (més ample, sense cap de 900px).

  • Gestor email — prova de connexió: admin/email-config.php no definia $user (email de prova buit) i EmailService::send() referenciaba $isHTML no inicialitzada al catch. Corregit.

  • Reply-To: camp "Email de resposta" a la config (per defecte = email d'enviament) aplicat a tots els enviaments.

  • DotEnv: les variables ara es sobreescriuen en carregar .env → els canvis guardats des del panel admin (email, Stripe…) tenen efecte immediat encara que la variable ja existeixi a l'entorn del procés PHP-FPM.

  • Viewer d'email: fonts mínim 16px (abans 12px).


v3.11.0 — 2026-08-21



Afegit — Gestor de email


  • Configuració SMTP a l'admin (/admin/email-config): host, port, xifrat SSL/TLS, usuari, password, email i nom d'enviament. Guarda a .env + botó "Guardar i provar connexió" (envia email de prova).

  • Registre automàtic de tots els emails (email_logs): data/hora, destinatari, assumpte, cos HTML/pla, estat (sent/failed) i missatge d'error. Central a EmailService::send() (no bloquejant).

  • Llistat admin (/admin/email-logs): paginat, amb accions Veure (popup 90% amb format de mail), Reenviar (tal qual) i Borrar.

  • Migració: migrations/add_email_logs_table.sql.

  • Card "📧 Email" al panell admin i enllaços entre configuració i registre.

  • ROADMAP: redactar manualment i editar abans de reenviar com a pendents a futur.


v3.10.1 — 2026-08-21



Corregido


  • Reemborsament de subscripcions: el botó "Reemborsar" de tesoreria fallava amb "No such payment_intent" perquè les transaccions de suscripció guardaven l'id de sessió (cs_...) en lloc del PaymentIntent (pi_...). Ara resolvePaymentIntent() resol el pi_ real (pago inicial del client) tant al reemborsar com al guardar la transacció i a la cancel·lació amb reembors.

  • my-transactions: el modal de cancel·lar subscripció sense l'emoji â›” al títol i amb size: large.


v3.10.0 — 2026-08-21



Afegit


  • Síntesi del balance al final del bloc Balance Astral (gated pel permís view_sintesis_balance).

  • Nova síntesi d'hemisferis i quadrants (SintesisHemisferios) al final del bloc Hemisferis i quadrants (gated pel mateix permís): dominants vertical/horizontal + quadrants amb frases.

  • Consell de la fase lunar (al final de la targeta de la Lluna) i frase de Quiró + afirmacions (al final de la targeta de Quiró): només es mostren si el permís està activat.

  • Permís renomenat: "Mostrar Síntesis Balance Astral" → "Mostrar Síntesis en informe" (BD + traduccions 7 idiomes).

  • Pàgina /my-subscription: estat unificat de la subscripció (pla, caducitat, ús de cartes amb barra de progrés, cancel·lar subscripció, enllaç a historial de pagos i upgrade).


v3.9.0 — 2026-08-21



Cobro i subscripcions (Stripe Subscriptions)


  • Suscripcions recurrents: el checkout de Stripe ara funciona en mode=subscription (preus monthly/annual). Stripe guarda la targeta (Customer + PaymentMethod) i cobra automàticament; l'app no toca mai dades de targeta.

  • Webhooks nous a ajax/stripe-webhook.php: invoice.paid (renova i estén la caducitat), invoice.payment_failed (email d'avís), customer.subscription.deleted (downgrade al grup fallback).

  • Cancel·lació des de Maia: botó "Cancel·lar subscripció" a /my-transactions. Mensual → cancel·la al final del període ("activa fins al X"). Anual → 2 opcions: cancel·lar al final o cancel·lar ara i reemborsar (reembors del darrer pagament + downgrade).

  • Cupons: en subscripcions, el descompte s'aplica a la primera factura (cupó Stripe de durada once).

  • Fix stacking anual: PaymentEngine::extendExpiration() suma la durada amb la unitat correcta (dies/mesos/anys); abans INTERVAL ? MONTH no funcionava per al pla anual (1 any).

  • Migració: migrations/add_stripe_subscription_columns.sql — stripe_customer_id, stripe_subscription_id a usuarios.

  • Preus: $8,5/mes (850¢) i $72/any (7200¢) → ≈ 3 mesos gratis en el pla anual.


Afegit


  • Eliminat Square per complet: eliminats SquarePayment.php, ajax/square-webhook.php, ruta i variables SQUARE_* del .env.example. El motor comú passa a includes/PaymentEngine.php (usat per Stripe).

  • Permisos en 4 seccions a admin/group_edit.php: Permisos Asignados, de Administrador, Avanzados i para IA.

  • Banner Free al dashboard (grups is_free) amb preus USD/EUR (canvi actual, anual ÷12) i llista de funcions desbloquejades per permisos.

  • Tooltip a les cartes bloquejades per quota (segueix el cursor, clic → /upgrade).

  • /upgrade: preus en euros al canvi actual + llista de diferències vs pla actual + "≈ N mesos gratis" al pla anual.

  • Traduccions: texts del banner, tooltip, upgrade i els 16 permisos traduïts als 7 idiomes; corregides cadenes que sortien en castellà quan l'idioma era català.


Corregido


  • Enllaços .php físics (404 en producció perquè el servidor enruta tot pel front controller): corregits a admin/*, charts/*, partes/header.php per usar route().

  • CLI maia: migracions aplicades correctament (columna filename, comentaris --).


v3.8.0 — 2026-08-21



Afegit


  • Reemborsament des de tesoreria: botó "â†©ï¸ Reemborsar" a cada transacció completada de Stripe a admin/treasury.php. Nou endpoint ajax/refund-payment.php (admin + CSRF) que reemborsa via Stripe API (Refund::create amb el payment_intent).

  • Rollback de subscripció en reemborsar: SquarePayment::rollbackSubscription() (extret de processRefund) baixa l'usuari al grup fallback si segueix al grup del pla; StripePayment::refundTransaction() el crida automàticament.

  • Ruta Router::post('/ajax/refund-payment', ...).


v3.7.2 — 2026-08-21



Corregido


  • Premium no se activaba tras el pago: los planes (subscription_prices) tenían group_id = NULL y no existía grupo Premium en user_groups, por lo que aplicarPlanYCupon() no asignaba grupo. Nueva migración add_premium_groups.sql que crea los grupos Premium Mensual (1 mes) y Premium Anual (1 año), con fallback a Users, y los vincula a los planes monthly/annual.


v3.7.1 — 2026-08-21



Corregido


  • Webhook de Stripe inaccesible en producción: el servidor (nginx) enruta todo por el front controller y las rutas van sin .php. Añadidas las rutas Router::post('/ajax/stripe-webhook', ...) y Router::post('/ajax/stripe-webhook.php', ...).

  • URL correcta del webhook: https://astro.omda.es/ajax/stripe-webhook (la app corre en astro.omda.es, no en omda.es). Actualizar la URL del endpoint en el dashboard de Stripe (el whsec_ no cambia).


v3.7.0 — 2026-08-21



Cobro con Stripe (sustituye a Square)


  • Stripe Checkout: nuevo includes/StripePayment.php (SDK stripe/stripe-php v21) que crea sesiones de checkout alojado con tarjeta. ajax/create-checkout.php ahora redirige a Stripe; ajax/stripe-webhook.php procesa checkout.session.completed (firma verificada, fail-closed).

  • Activación de premium reutilizada: handleCheckoutCompleted() usa aplicarPlanYCupon() (idempotente, update atómico condicional) + emails de confirmación/bienvenida ya existentes.

  • Moneda USD: precios 6,5$/mes (650¢) y 78$/año (7800¢); STRIPE_CURRENCY en .env. Visualización de upgrade.php y my-transactions.php en $.

  • Migración: migrations/add_stripe_provider.sql — columnas provider y provider_payment_id en payment_transactions + actualización de precios a USD.

  • Tesorería: columna de proveedor (💳/🧾) y CSV con proveedor e ID de pago; estado refunded en el mapa.

  • Retorno: dashboard.php muestra confirmación al volver de Stripe (?paid=stripe); la activación real la hace el webhook.

  • Config: claves en .env → STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_CURRENCY=USD. Crear endpoint de webhook en Stripe apuntando a /ajax/stripe-webhook.php (evento checkout.session.completed).

  • CLI maia corregido: usaba la columna migration (inexistente; la tabla usa filename) y descartaba bloques SQL cuyo primer bloque empezaba por comentario --. Ahora php maia migrate funciona con los .sql existentes.


v3.6.0 — 2026-08-21



Cobro y suscripción — revisión (roadmap punto 1)


  • Anti-doble-cobro (idempotencia): completePayment() no reprocesa transacciones no-pendientes y usa update atómico condicional (WHERE status='pending'). completeFromRedirect() y completePayment() comparten aplicarPlanYCupon().

  • Cupones de extensión en redirect: completeFromRedirect() ahora aplica cupones extension (antes solo el webhook).

  • Email de confirmación de pago: EmailService::sendPaymentConfirmation() (plan, importe, caducidad, referencia). Se envía al completar el pago (redirect o webhook).

  • Email de bienvenida premium: EmailService::sendPremiumWelcome().

  • Email de aviso de caducidad: EmailService::sendExpiryWarning() disparado desde AuthManager::checkGroupExpiration() con notice_days del plan y throttling de 1/día (columna expiry_warning_sent_at).

  • Limpieza de transacciones stale: SquarePayment::cleanupStaleTransactions() (pending → abandoned), ejecutada en dashboard.php máx. 1 vez/hora.

  • Reembolsos: el webhook maneja refund.updated → processRefund() marca refunded y revierte el grupo al fallback.

  • Export CSV de tesorería: botón en admin/treasury.php con filtro de estado aplicado.

  • Migración: migrations/add_expiry_warning_sent_at.sql (expiry_warning_sent_at en usuarios). Aplicar con php maia migrate o panel admin.


v3.5.0 — 2026-08-20



Afegit


  • MAIA AI local (interpretació amb Ollama): nou botó «🧠 Enviar a MAIA AI» a la pestanya IA, que envia el JSON estructurat de la carta a un motor Python local (~/Proyectos/astrologia-ai) i mostra la interpretació (Part 1 tècnica + Part 2 psicològica) sense dependre de DeepSeek.

- ajax/ia_maia.php: proxy que reenvia el JSON al servidor local. URL configurable amb MAIA_AI_URL (per defecte http://127.0.0.1:8765/chat).
- partes/ia_export.php: botó nou «Enviar a MAIA AI» + missatges d'estat.
  • Chat multi-torn amb MAIA AI: el servidor local manté sessió (POST /chat amb {datos} o {session_id, mensaje}) i la pestanya IA mostra un xat amb historial, camp de pregunta i botó «Nova conversa». L'usuari pot fer preguntes de seguiment sobre la carta enviada.

  • Camp datos JSON a l'export IA: ajax/ia_export.php ara retorna {success, texto, datos} amb la carta estructurada (planetes amb casa, casas, ángles, aspectes ordenats per orbe, balanç en espanyol, patrons). Botó «💾 Exportar JSON» per descarregar-lo (maia_carta_<id>.json).

  • Documentació: documentation/maia_ai_local_module.md amb el contracte de dades, el flux i les instruccions d'arrencada del servidor local.


v3.4.1 — 2026-08-20



Seguretat (ronda 2 — re-scan Strix)


  • Escalada de privilegis a "Rei do Mambo" (CWE-269): admin/users.php ara només permet assignar el grup "Rei do Mambo" si l'actor autenticat en forma part.

  • XSS reflectat (CWE-79): logs/index.php escapa view a l'href; api/v1/update/check.php serveix JSON amb Content-Type correcte i JSON_HEX_*.

  • Stored XSS per nom d'usuari (CWE-79): js/share-manager.js nou helper jsAttrEscape() per onclick + escapeHtml() als sinks innerHTML del modal.

  • Payment bypass (CWE-841): SquarePayment::completeFromRedirect() ara verifica amb Square que el payment és COMPLETED abans d'activar premium (no confia en ?paid=1).

  • CSRF (CWE-352): afegit csrf_token a admin/migrations.php, ajax/translations.php i ajax/create-checkout.php (+ forms/JS).

  • .env i dotfiles: .htaccess raíz denega dotfiles i composer/package; vendor/.htaccess Require all denied.

  • Rate limiting PII: api/v1/chart/logs.php limitat per API key+IP (60/10min).

  • Token Square: eliminat el token sandbox de .env.example.


Seguretat (ronda 1)


  • SSO auth bypass (CRÃTIC): el secret sso_secret es reutilitzava com a X-API-Key del plugin carta-natal-maia (exposat al client JS) i com a secret de signatura SSO. Ara els endpoints SSO (auth/sso_login.php, api/sso_generate.php) i el consumidor de sso_token (partes/RequireLogin.php) només accepten llocs amb plugin_type = 'maia' (secret només al servidor), blocant el forjat de tokens amb el key exposat.

  • Dependència vulnerable: league/commonmark actualitzat de 2.7.1 → 2.10.0, resolent 4 CVEs (DoS per complexitat algorítmica + 3 XSS/bypass). Verificat amb composer (sense advisories restants).

  • Password reset — link poisoning via Host (CWE-640): generateResetLink() ara construeix l'enllaç des de APP_URL (config) en lloc del header Host, i apunta a /reset-password.

  • Password reset — filtrado de token (CWE-522): requestPasswordReset() ja no retorna el reset_link; eliminat el bloc "mode desenvolupament" que el mostrava.

  • Password reset — enumeració de comptes (CWE-203): resposta genèrica tant si l'email existeix com si no.

  • Password reset — flux trencat corregit: auth/reset.php usava $pdo global indefinit i comparava el token cru contra el hash SHA-256. Ara usa findByResetToken()/resetPassword() del repositori.

  • Fuerza bruta en login (CWE-307): nova classe includes/RateLimiter.php (contadors per IP+email en logs/rate_limits/). AuthManager::login() limita a 5 intents fallits per IP+email en 15 min i reseteja en loguejar.

  • Rate limiting en forgot-password (CWE-307): requestPasswordReset() limita a 5 peticions per IP+email en 15 min.

  • XSS reflectat (CWE-79): partes/transitos.php volcava $_GET['id'] sense escapar; ara usa (int)($_GET['id'] ?? 0).

  • IDOR en compartir (CWE-639): charts/share.php get_shared llistava usuaris compartits sense comprovar propietat; ara comprova esPropietario() abans.

  • CSRF en compartir (CWE-352): charts/share.php ara verifica csrf_token abans de cada acció; js/share-manager.js envia el token (meta csrf-token) a totes les peticions.

  • Stored XSS per nom de carta (CWE-79): charts/view.php:563 usava addslashes() en context JS → ara json_encode(). Corregits també els vectors a dashboard.php (onclick de compartir/eliminar) i els sinks innerHTML del modal (share-manager.js, confirmDeleteCarta).

  • Webhook Square (CWE-347): ajax/square-webhook.php ara és fail-closed: sense SQUARE_WEBHOOK_SIGNATURE_KEY configurada retorna 503 i no processa; amb clau, la verificació de firma és obligatòria.

  • CSRF en admin (CWE-352): verificació de csrf_token + camp ocult als formularis de admin/groups.php, admin/group_edit.php, admin/treasury.php i admin/coupons.php.

  • Accés no autenticat a logs/scripts (CWE-306/CWE-532): afegit Require all denied a scripts/, config/ i sql/; gate CLI a scripts/__install.php i scripts/generador_ephemeris.php; logs/index.php ara requereix access_admin_panel.


v3.4.0 — 2026-08-16



Afegit


  • Text per a IA (export) ampliat: abans de les posicions planetàries, ara s'inclou tota la informació de l'informe:

- Àngles principals (ASC, MC, DSC, IC) amb grau i signe.
- Balanç astral (elements, modalitats, polaritats i dominant).
- Hemisferis i quadrants (corregides les claus numèriques que no mostraven res).
- Planetes més influents (via CalculadorInfluenciaPlanetas) amb puntuació i raons.
- Èmfasi en cases i signes (3 o més planetes).
- Fase lunar (separació Sol-Lluna).
  • Pestanyes a les Direccions d'Arc Solar (includes/DireccionesCalculator.php): ara els resultats es mostren en dues pestanyes, com a progressions i trànsits:

- 📊 Direccions Detallades: la taula que ja existia.
- 📋 Texte: llistat en text pla amb botó "Copiar al portapapeles" (aspectes i ingressos amb edat, data, planeta, posició i orbe).
- Nous mètodes renderPestanyes(), renderTextoPlano() i formatEdat().
  • Opció "Direccions" a l'export per a IA (partes/ia_export.php + ajax/ia_export.php): nou checkbox amb rang "des de / fins a" (anys) situat abans de "Revolucions solars". Genera una secció "DIRECCIONES DE ARCO SOLAR" amb el text pla de les direccions (conjunció+oposició, 12 cases i 12 signes). renderTextoPlano() passa a ser públic.


Corregido


  • ajax/ia_export.php: hemisferios/cuadrantes usaven claus errònies (Norte, Cuadrante I) i no imprimien res; ara usen les claus numèriques correctes. També corregit el llistat de "Planetes angulares" i afegits els "Signes amb èmfasi" a la secció Informe.

  • ajax/ia_export.php: fix bug de variable sobrescrida. El foreach ($angPlanetas as $angulo => $datos) de "Planetes angulares" reemplaçava la variable global $datos (les dades de la carta) per l'últim angle (IC). Això trencava les seccions Trànsits (warning "Undefined array key planets") i Progressions (warning "array offset on float" a AspectosCalculator) i embrutava la resposta JSON amb HTML de warnings. Renombrada la variable del bucle a $angDatos.


v3.3.4 — 2026-08-11



Afegit


  • Gestor de traduccions a admin (admin/translations.php): pàgina per revisar, editar i gestionar traduccions sense tocar fitxers .po manualment.

- Cards amb % de cobertura per als 7 idiomes.
- Taula paginada amb cerca, filtres per estat (traduït/fuzzy/buit) i selecció d'idioma.
- Modal d'edició amb msgid (readonly) i msgstr editable.
- Accions en lot: aprovar totes les fuzzy, recompilar tots els .mo.
- Classe includes/TranslationManager.php: parser/editor de .po + compilador msgfmt.
- Endpoint ajax/translations.php amb accions list, save, stats, approve_fuzzy, recompile.
- Permís manage_translations (grup "Rei do Mambo").
- Card 🌠Traduccions al dashboard admin (condicionada al permís).

Corregido


  • 404 divertida: pàgina d'error amb il·lustració SVG animada (Saturn confós, Júpiter/Lluna/Sol detectius), fons clar, layout full-width, text traduït als 7 idiomes, botó "Tornar a l'inici".

  • Migrations idempotents: add_edit_content_texts_permission.sql i add_ia_export_permission.sql canvien INSERT per INSERT IGNORE.


v3.3.3 — 2026-08-10



Corregido


  • Cerca de ciutats amb traduccions: nova taula city_translations (geoname_id, lang, name) amb 159 ciutats × 7 idiomes. api/v1/geo/search.php fa JOIN amb city_translations segons el lang de la petició. Scoring simplificat: exact match (original o traduït) > té traducció > sense traducció, ordenat per població. Resultats:

- display_name i address.city en l'idioma de l'usuari (ex: "Roma, Lazio, Italia" per a lang=es)
- name amb el nom original (ex: "Rome")
- Cerca "Roma" en català/castellà troba Roma (Itàlia) com a primer resultat
  • JS passa l'idioma a l'API: script.js (cerca naixement i residència) i revolucio-solar-js.php llegeixen document.documentElement.lang i l'afegeixen com a &lang= a la petició.

  • Selector de idioma: la funció changeLanguage() definida a js/script.js sobrescrivia la del header.php al carregar-se després (al footer). La de script.js només posava una cookie i recarregava sense canviar el path, fent que el Router tornés a l'idioma per defecte. Eliminada la duplicada de script.js.

  • Idioma per defecte: canviat d'espanyol (es) a català (ca) a .env (DEFAULT_LANGUAGE=ca) i al fallback de header.php.

  • Router.url(): ara sempre afegeix el prefix d'idioma a les URLs (abans només ho feia per idiomes diferents del predeterminat). Eliminada la condició $currentLang !== $defaultLang per mantenir consistència amb changeLanguage().

  • 404 al canviar idioma al login: corregit al alinear el comportament de Router.url() i changeLanguage(). Les URLs ara sempre inclouen prefix d'idioma. També corregides les redireccions antigues (/auth/login.php, /UserLogin.php) per route('/login') a RequireLogin.php, AuthManager.php, logout.php, forgot-password.php i reset.php.


Afegit


  • migrations/023_create_city_translations.sql: taula city_translations

  • data/city_translations.json: 159 ciutats amb traduccions en 7 idiomes

  • scripts/import_city_translations.php: script d'importació per lot


Traduït


  • Todos los textos hardcoded a catalán: ~20 archivos PHP editados para cambiar texto fuente de castellano a catalán y envolverlo en __() o _e().

  • Archivos de traducción regenerados: nuevo messages.pot con 1504 cadenas extraídas de todo el código. Los 7 archivos .po actualizados con msgmerge y compilados a .mo.

  • Traducciones por idioma: ca_ES (1503, fuente=catalán), es_ES (1200 + 303 fuzzy), en_US (1200 + 303 fuzzy), fr_FR (1244 + 259 fuzzy), de_DE (1244 + 259 fuzzy), it_IT (1244 + 259 fuzzy), pt_PT (1244 + 259 fuzzy). Las cadenas no traducidas muestran el texto fuente (catalán) como fallback.


Archivos modificados


  • auth/reset.php: todos los textos a catalán + __()

  • auth/sso_login.php: mensajes die() a catalán + __()

  • auth/change-password.php: placeholders a catalán

  • auth/register.php: placeholders a catalán

  • charts/edit.php: página completa a catalán + __()

  • charts/process.php: mensajes de error a catalán

  • charts/share.php: mensaje de error a catalán

  • partes/ia_export.php: 17 cadenas a catalán + __(), JS usa variables PHP

  • partes/header.php: fallback idioma es → ca

  • admin/ai-config.php: 6 etiquetas a catalán + __()

  • admin/index.php: 4 títulos con emojis a __(), 2 descripciones a catalán

  • admin/integrations.php: opciones <select> a catalán

  • admin/roadmap.php: 3 etiquetas a catalán

  • admin/textos.php: 3 cadenas JS a catalán vía <?= __() ?>

  • includes/Router.php: 404 a catalán, prefijo idioma siempre presente

  • includes/TransitosCalculator.php: 2 mensajes vacíos a catalán

  • includes/AspectosCalculator.php: 3 etiquetas a catalán

  • includes/AspectosGridGenerator.php: título a catalán

  • includes/RevolucioSolarCalculator.php: prefijo Error: a __()

  • ajax/main.php: 10 mensajes de error a catalán + __()

  • ajax/user-transactions.php: 2 mensajes a catalán

  • ajax/transitos.php: mensaje de error a catalán

  • ajax/ia_export.php: mensaje de error a catalán

  • ajax/composite.php: 9 title de tabla a catalán

  • api/v1/chart/calculate.php: 3 etiquetas a catalán

  • js/script.js: eliminada función changeLanguage() duplicada

  • .env: DEFAULT_LANGUAGE=es → ca


v3.3.2 — 2026-08-10



Corregido


  • Planetas más influyentes en relocalización: la pestaña de residencia ahora recalcula CalculadorInfluenciaPlanetas con los datos relocalizados (ASC, casas y regentes distintos). Antes solo se calculaban para la carta natal, ignorando que la relocalización cambia el regente del ASC. Nueva sección â­ Planetas más influyentes (Residencia) en la pestaña ðŸ“.


v3.3.1 — 2026-08-10



Corregido


  • Hemisferios y cuadrantes mal calculados: CartaNatalCalculator::procesarCasas() anteponía el ASC (duplicando H1) y perdía la clave absoluto, provocando que todos los planetas se asignaran a casas incorrectas. También se corrigió la ordenación de casas en Functions.php (uksort → ksort SORT_NATURAL) y en el script Python (que las devolvía en orden H1,H10,H2...).

  • Gráficos de hemisferios con posiciones incorrectas: InformeHemisferios::dibujarCirculo() usaba ángulos que no compensaban la resta de 90° de polarToCartesian. Corregidos los 4 tipos de gráfico (Interior/Exterior, Autonomía/Relación, Cuadrantes, Viaje Conciencia). Las líneas divisorias también estaban intercambiadas (horizontal ↔ vertical).

  • Agrupaciones del Viaje de la Conciencia: el cuarto gráfico usaba casas 1-4, 5-8, 9-12 en lugar de 12+1+2+3, 4-7, 8-11.

  • Orden visual de los gráficos: intercambiados los dos primeros para que Interior/Exterior aparezca primero (con orientación N/S) y Autonomía/Relación segundo (E/O).

  • Caché de sesión: claves forzadas a v4 para evitar datos antiguos. view.php detecta datos estancados (>12 casas o sin absoluto) y fuerza recálculo.


Cambiado


  • Permiso access_ia_export: asignado a 4 grupos (Administrators, Rei do Mambo, Usuario registrado, Aula Astrológica).


v3.3.0 — 2026-08-07



Añadido


  • AI Config en Admin (admin/ai-config.php): formulario para configurar la API Key de DeepSeek. Se guarda en .env como DEEPSEEK_API_KEY. Visible para todos los admins. Nueva card en panel admin.

  • Enviar a la IA: botón 🤖 Enviar a la IA en la pestaña IA de carta natal. Toma el prompt del sistema desde prompt-astrologia-psicologica.md, adjunta el texto generado, y lo envía a DeepSeek (deepseek-chat). La respuesta se renderiza con formato MD (negritas, itálicas, listas, encabezados). Nuevo endpoint ajax/ia_chat.php.


v3.2.0 — 2026-07-28



Añadido


  • Pestaña 🤖 IA (Texto para IA): nueva pestaña en la ficha de carta (permiso access_ia_export). Genera texto estructurado para enviar a un GPT especializado en astrología psicológica. 6 secciones configurables con selectores de período:

- Carta natal (nacimiento y residencia): posiciones planetarias, ASC/MC, balance astral (elementos, modalidades, polaridades, hemisferios, cuadrantes), aspectos mayores ordenados por orbe, nodos lunares.
- Informe astral: desglose de elementos/modalidades/polaridades con planetas, hemisferios, cuadrantes, casas con énfasis, planetas angulares, fase lunar.
- Tránsitos (por defecto 5 años atrás → 5 adelante): lista cronológica con cambios de casa (casa X).
- Progresiones (mismo rango): vía ProgressionsCalculator, extracto del texto plano.
- Revoluciones solares (por defecto 2 años atrás → 2 adelante): posiciones + ASC/MC para cada año.
  • Selectores de período: cada sección dinámica (tránsitos, progresiones, RS) tiene selectores de año desde/hasta, configurables por el usuario.

  • Cambios de casa en tránsitos (normales y compuestos): al saltar de casa el planeta en tránsito, se muestra (casa N) en la línea de texto.


Cambiado


  • TransitosCalculator::adaptarResultadoPython(): añadido transito_longitud al array de salida para detectar cambios de casa.

  • TransitosCalculator::renderTextoPlano(): ahora incluye (casa N) cuando el planeta transitante cambia de casa.

  • ajax/composite.php (tránsitos compuestos): tabla HTML con símbolos planetarios, signos zodiacales, pestañas Tabla/Texto, botón copiar, cambios de casa.


v3.1.0 — 2026-07-28



Añadido


  • Tránsitos sobre la carta compuesta: nueva sub-pestaña 🔄 Tránsitos dentro de la pestaña Compuesta. Selector de fecha inicio, duración y planetas en tránsito. Reutiliza TransitosCalculator y scripts/calculadora_transitos.py sin modificaciones — los datos del composite se pasan como si fueran una carta natal. Cache en sesión por combinación de parámetros. Nueva acción calculate_transits en ajax/composite.php.

  • Progresiones sobre la carta compuesta: nueva sub-pestaña â³ Progresiones. Calcula progresiones secundarias a partir de la fecha virtual del composite (midpoint de las fechas natales). Selector de fecha de referencia y duración. Reutiliza ProgressionsCalculator y scripts/calculadora_sweph_batch.py. Nueva acción calculate_progressions en ajax/composite.php.

  • Cache de datos crudos del composite: se almacenan en $_SESSION["composite_raw_{id1}_{id2}"] los $datos crudos (no solo el HTML renderizado), permitiendo que tránsitos y progresiones puedan usar la carta compuesta como input natal.


Cambiado


  • ajax/composite.php: soporta 3 acciones (calculate_composite, calculate_transits, calculate_progressions). +100 líneas.

  • partes/composite.php: añadidas sub-pestañas y formularios de selección para tránsitos y progresiones.

  • js/composite.js: nuevas funciones calcularTransitosCompuesta() y calcularProgresionesCompuesta(). Limpieza de resultados anteriores al cambiar de carta2.

  • css/composite.css: estilos para los formularios de selección de fecha/duración.


v3.0.2 — 2026-07-28



Añadido


  • Panel de Textos de Información en Admin (admin/textos.php): editor visual por campos con previsualización en vivo (panel derecho). Cada sección tiene formularios adaptados a su estructura: inputs para textos cortos, textareas para descripciones, tags editables (contenteditable) para arrays de palabras clave/frases. Soporta 6 tipos de datos: Balance Astral, Hemisferios, Tablas de Coherencia, Fases Lunares, Quirón por Signo, y Síntesis del Balance. Permiso edit_content_texts. Guardado vía JSON a data/.

  • Sistema de datos externalizados: nuevo helper JsonDataLoader.php con caché estática por request. Las clases consumidoras (TooltipData, InfoAstrologica, SintesisBalance) leen de archivos JSON en data/ con fallback transparente a los valores hardcodeados originales si el archivo no existe o está corrupto. 6 archivos JSON creados desde los datos originales.

  • Permiso edit_content_texts: nueva migración SQL. Asignado al grupo 1 (Rei do Mambo).


Cambiado


  • TooltipData: 4 constantes (BALANCE_ASTRAL, HEMISFERIOS_CUADRANTES, TABLA_BALANCE, TABLA_HEMISFERIOS) → 4 métodos estáticos (balanceAstral(), hemisferiosCuadrantes(), tablaBalance(), tablaHemisferios()).

  • InfoAstrologica::obtenerFasesLluna() y obtenerInfoQuiron(): leen de JSON con fallback.

  • SintesisBalance::get(): carga desde JSON vía JsonDataLoader.

  • InformeAstrologico y partes/informe_carta.php: actualizados los 23 call sites de ::CONST a ::metodo().


v3.0.1 — 2026-07-27



Añadido


  • Aspectos en texto de carta compuesta: nueva sección === ASPECTOS === con todos los aspectos entre planetas de la compuesta, indicando orbe, tipo (A=plicativo/S=eparativo) y nombre traducido (Conjunción, Oposición, Trígono, etc.).

  • Balance astrológico en texto de carta compuesta: nuevas secciones === DISTRIBUCIÓN POR ELEMENTOS ===, === DISTRIBUCIÓN POR MODALIDADES ===, === POLARIDADES === con conteos, porcentajes y dominante de cada categoría. Usa BalanceAstrologico y getDominante().

  • Roadmap: añadidas dos nuevas entradas — "Sinastría profunda entre dos cartas" (house overlay, aspectos interpersonales, bi-wheel, enfoque psicológico) y "Tránsitos y progresiones sobre la carta compuesta" (fases del vínculo, progresiones compuestas, interpretación no predictiva).


Corregido


  • Carta compuesta invisible: partes/composite.php envolvía su contenido en un segundo <div class="chart-pane">, lo que causaba que el contenido quedara oculto aunque el panel externo se activara. Eliminado el wrapper duplicado.

  • JS con PHP inline: js/composite.js usaba <?= $carta['id'] ?? 0 ?> que no se procesaba al ser archivo .js. Cambiado a document.getElementById('tab-composite')?.dataset.cartaId.

  • Python: ord('P') → b'P': pyswisseph 2.10.x requiere byte string para se.houses(), no int.


v3.0.0 — 2026-07-27



Añadido


  • Carta Compuesta (Composite Chart): nueva pestaña "🔗 Compuesta" en el sidebar. Muestra listado alfabético de las otras cartas del usuario (excluyendo la actual). Al hacer clic, calcula el midpoint circular entre ambas cartas natales con Swiss Ephemeris. Sub-pestañas: 🪠Carta (SVG), 📊 Informe (Balance + hemisferios + ángulos), 📋 Texto (resumen copiable). Permiso access_composite_chart. Cache en sesión. Nuevos archivos: scripts/calculadora_composite.py, ajax/composite.php, partes/composite.php, js/composite.js, css/composite.css. Documentación: documentation/composite_chart.md.


Corregido


  • Grados en informe RS con formato Signo GG°MM'

  • RS multi-ubicación: 4 llamadas Python, timeout 180s, $auth en scope

  • Resumen texto con pestañas natal/residencia


v2.9.0 — 2026-07-27



Añadido


  • Revolución Solar multi-ubicación: hasta 3 pestañas (🌟 Natal / 📠Residencia / 🌠Elegida) con cálculo independiente para cada ubicación. Las pestañas son sticky y persisten el sub-tab activo al cambiar de ubicación. Placeholder del campo de ciudad: "Escriu la ciutat (deixar buit = residència ó natal)", con auto-precarga de residencia si existe.

  • Texto RS: nueva pestaña 📋 Texto con resumen completo en texto plano de toda la información RS (balance, posicionamiento, superposición, contactes, regentes). Incluye el tipo de ubicación en el título (Natal), (Residencia) o (Elegida).

  • Búsqueda de ciudad al editar: solucionado el bug donde lugar contenía "Rome, Lazio, Italia" y fallaba. Columnas ciudad y ciudad_residencia guardan solo el nombre. Fallback por coordenadas en API. Badge ✅ Coordenadas cargadas.

  • Cúspides casa residencia en resumen texto: si existe residencia, muestra segundo bloque de cúspides.


Corregido


  • Grados en informe RS: todos los valores de longitud ahora se muestran con formato Signo GG°MM' en lugar de grados absolutos decimales (176.83°).

  • Dashboard: widget de residencia con (new AuthManager())->hasPermission().

  • Transitos: $user['id'] → $userId en línea 243.

  • Venv: instalado scipy (faltaba para tránsitos).

  • Favicon: añadido favicon.svg (círculo verde con M).


v2.8.0 — 2026-07-26



Añadido


  • Relocalización de carta natal: funcionalidad completa. Al editar/crear carta, si el usuario tiene el permiso relocation_access, se muestra la sección "🠠Lugar de Residencia" con autocomplete de ciudades. En la vista de carta, pestañas globales "🌟 Carta Natal Nacimiento" / "📠Carta Natal Residencia" que cambian todo el informe de una vez (SVG, hemisferios, ángulos, casas con énfasis). Pestañas sticky al hacer scroll. Widget "ðŸ " en dashboard. Nuevos archivos/métodos: calcularRelocalizada() en CartaNatalCalculator, guardarDatosRelocalizada() en CartaNatalRepository, columnas lugar_residencia, lat_residencia, lon_residencia, timezone_residencia, datos_relocalizada en cartas_natales, migración add_relocation_fields.sql, permiso relocation_access.


Corregido


  • Dashboard: el widget de residencia usa (new AuthManager())->hasPermission() en lugar de $auth que no estaba en scope dentro de renderCartaCard().

  • Transitos: $user['id'] corregido a $userId en ajax/transitos.php:243.

  • Venv: instalado scipy 1.17.1 (faltaba para el cálculo de tránsitos).

  • Resumen carta texto: ahora muestra las cúspides de la carta relocalizada si existe residencia.

  • Revolución Solar multi-ubicación: cuando la carta tiene residencia (y el usuario el permiso relocation_access), la RS se calcula para hasta 3 ubicaciones: Natal, Residencia y Elegida. Pestañas sticky entre el placeholder y los resultados. El placeholder del campo de ciudad ahora dice "Escriu la ciutat (deixar buit = residència ó natal)" y se auto-precarga con la ciudad de residencia si existe. Nuevo método renderResultatsMulti() y renderResultatsIntern() en RevolucioSolarCalculator. JS añade initLocationTabs() + sticky via scroll.


v2.7.0 — 2026-07-26



Añadido


  • Síntesis combinada del Balance Astral: nuevo bloque al final de la sección Balance Astral que combina el elemento, la modalidad y la polaridad dominantes en una frase interpretativa automática. Nuevos archivos: includes/SintesisBalance.php (24 frases), método getDominante() en BalanceAstrologico, método renderSintesis() en InformeAstrologico.

  • Tooltips contextuales por item individual: cada fila del Balance Astral (elementos, modalidades, polaridades) ahora tiene su propio trigger de tooltip. Hover sobre "Fuego" muestra la cabecera "Elementos" + solo Fuego, en lugar de los 4 elementos a la vez. Ãdem para modalidades y polaridades. JS refactorizado con renderItem(), buildContent() acepta itemIndex, handlers leen data-tooltip-item.

  • Subtítulos introductorios en cada bloque del informe con la pregunta guía.

  • Tablas de coherencia bajo Balance Astral y Hemisferios (indicador → pregunta → función).

  • Roadmap en panel admin: nueva sección admin/roadmap.php que renderiza documentation/ROADMAP.md. Accesible desde los cards del panel de administración.

  • Migración para relocalización: nuevas columnas en cartas_natales (lugar_residencia, lat_residencia, lon_residencia, timezone_residencia, datos_relocalizada) y nuevo permiso relocation_access asignado al grupo 1 (Rei do Mambo). Primera fase de la feature de relocalización de carta natal.

  • Documentación ROADMAP.md: lista de funcionalidades futuras con descripciones, acciones y user stories. Primeros ítems: "Síntesis combinada del Balance Astral", "Relocalización de carta natal", "Panel de Textos de Información en Admin", "Revisión del sistema de cobro y suscripción". Cada ítem lleva status (pending/done) con trazabilidad de versión y fecha.

  • Página de Roadmap en admin: nueva interfaz admin/roadmap.php con pestañas Pendientes/Realizados/Todos, índices de navegación, parser Markdown propio (headers, bullets anidados, código inline, blockquotes). Los items se marcan como done editando el comentario <!-- status: ... --> en ROADMAP.md.


Corregido


  • DebugManager: todas las variables de .env relacionadas con debug (NO_DEBUG, DEBUG_ALLOWED_IPS, SAVEQUERIES, DEBUG_SHOW_WARNING, etc.) ahora se definen como constantes PHP. NO_DEBUG=true funciona.

  • Python venv: reconstruido con Python 3.11 (Homebrew) + pyswisseph 2.10.3.2 + timezonefinder 8.2.5. PYTHON_PATH comentado en .env para usar detección automática del venv.

  • Hemisferio Interior/Exterior: corregidas las descripciones invertidas de los hotspots (el tooltip de la mitad superior ahora corresponde al Mundo Exterior —Casas VII-XII— y el de la mitad inferior al Mundo Interior —Casas I-VI—).


v2.6.0 — 2026-07-02



Añadido


  • Menú hamburguesa ☰: Nou menú desplegable a la capçalera de totes les pàgines. Inclou:

- Nom de l'usuari, enllaços a Inici, Admin (si té permisos), Mis pagos, Orbes, Canviar contrasenya i Tancar sessió.
- Botó sense fons (blanc sobre gradient blau), dropdown amb text fosc sobre fons blanc.
- Substituïts els botons individuals del header i del dashboard.
  • Sistema d'orbes personalitzats per usuari: Nova pàgina 🎯 Orbes al menú. Inclou:

- Configuració d'orbes per a carta natal, trànsits i Revolució Solar.
- Emmagatzematge a BD (user_orbs), restabliment per tipus o global.
- Nova classe: includes/UserOrbManager.php.
- Nova pàgina: orbes.php, ajax/save-orbes.php, js/orbes-js.php.
- Nova migració: migrations/add_user_orbs_table.sql.
  • Orbes de trànsits corregits: Nova constant ANGULOS_Y_ORBES_TRANSITOS (3° conjunció/oposició, 2° trígon/quadratura/sextil, 1° menors) enlloc de reutilitzar els 12° natals. Comparació Python dev > orb → dev >= orb.

  • Cerca de ciutat per RS: El formulari de Revolució Solar ara permet cercar la ciutat on es fa la RS (autocomplete via /api/v1/geo/search) en lloc de demanar lat/lon.


Corregido


  • Hamburger menu: Contrast arreglat (text beige --accent-light sobre fons blanc → text #333).

  • Transits orbs: Plutó a 5° Aquari ja no es detecta com a conjunció amb Mart a 17° Aquari (orb 3° en lloc de 12°).


v2.5.0 — 2026-07-02



Añadido


  • Mòdul de Revolució Solar (RS): Nova pestanya amb dibuix de la carta de RS i dades estructurades. Inclou:

- Sub-pestanyes: Carta RS (SVG wheel), Informe (balanç + posicionament + regents), Superposició (cúspides + planetes per casa), Contactes RS-Natal
- Balanç comparatiu 3 cartes (Natal, RS Anterior, RS Actual) per elements, modes i polaritats (només planetes personals + ASC + MC)
- Ubicació configurable: es pot especificar on es fa la RS (lat/lon), per defecte usa la natal
- Càlcul exacte del moment de RS via Swiss Ephemeris (se.solcross())
- Cases carregades (2+ planetes), planetes angulars (≤5°), contactes nodes (≤1°)
- Angles natals projectats a cases RS, dades d'ASC i Sol de RS
- Superposició de cúspides RS → cases natals, planetes RS per casa
- Contactes RS-Natal ordenats per planeta RS (ordre natural) amb orbes: 5° majors, 3° sextil, 1° menors
- Regents de casa
- Nova classe: includes/RevolucioSolarCalculator.php
- Nou script Python: scripts/calculadora_revolucio_solar.py (flags Swiss Ephemeris correctes, timezone robust)
- Nova migració: migrations/add_revolucio_solar_permission.sql
- Noves views: ajax/revolucio_solar.php, partes/revolucio_solar.php, js/revolucio-solar-js.php, css/revolucio-solar.css
- Tests: scripts/test_revolucio_solar.php
  • Sistema d'orbes personalitzats per usuari: Nova pàgina 🎯 Orbes al menú. Inclou:

- Configuració d'orbes per a carta natal, trànsits i Revolució Solar.
- Emmagatzematge a BD (user_orbs), restabliment per tipus o global.
- Nova classe: includes/UserOrbManager.php.
- Nova pàgina: orbes.php, ajax/save-orbes.php, js/orbes.js.
- Nova migració: migrations/add_user_orbs_table.sql.
  • Orbes de trànsits corregits: Ara usen ANGULOS_Y_ORBES_TRANSITOS (3° conjunció/oposició) enlloc dels 12° natals. Comparació Python dev > orb → dev >= orb.

  • Mòdul de detecció d'eclipsis i Sèries de Saros (Bernadette Brady): Integrat al mòdul de lunaciones. Inclou:

- Orbs precisos per eclipsis solars/lunars (total/ambigu/parcial/marginal)
- Identificació de Sèrie de Saros (1-19 North/South, variants Old/New) per any + polaritat del node
- Targeta interpretativa expandible amb aspectes natals en català
- Vista "Calendari d'Eclipsis" filtrable per any (1900-2050)
- Eix de cases oposades als eclipsis
- Dades completes de 40 sèries a data/saros_series.json
- Classes: includes/SarosSeries.php
- Tests: scripts/test_saros.php

v2.4.0 — 2026-05-24



Añadido


  • Pasarela de pago Square: ... (existing content truncated for brevity - already documented)

  • Vinculación usuario-sitio WP: Columna linked_user_id en wordpress_sites. Al vincular un usuario, su suscripción Premium controla automáticamente el flag is_premium del sitio.

  • Aviso de caducidad en plugin WP: El plugin carta-natal-maia muestra un warning âš ï¸ en su panel de configuración cuando la suscripción del usuario vinculado está a 30 días o menos de caducar.

  • Cambio forzado de contraseña: Botón 🔠en cada fila de admin/users.php permite al admin cambiar la contraseña de cualquier usuario (UserRepository::forcePassword()).

  • Cupón interactivo en upgrade: Validación server-side con detalle del beneficio. Precio original tachado + descuento + precio final. Extensión de suscripción visible en el plan. Solo un cupón a la vez (el formulario desaparece al aplicar). Botón "Eliminar" para quitarlo. Arreglado "60€ / mes" → "60€ / año".

  • Migración 019_add_promoter_fields.sql: promoter_id en usuarios y coupons. Campo promotor en admin/users.php y admin/coupons.php.

  • Migración 020_add_linked_user_to_wp_sites.sql: linked_user_id en wordpress_sites. Dropdown en admin/integrations.php.

  • CLI php maia: Herramienta para ejecutar migraciones desde terminal.

  • Mòdul de detecció d'eclipsis i Sèries de Saros (Bernadette Brady): Nou sistema integrat al mòdul de lunaciones. Inclou:

- Orbs precisos per a eclipsis solars i lunars (total/ambigu/parcial/marginal) segons Brady.
- Classificació de l'eclipsi en 4 nivells (total, ambigu, parcial, marginal).
- Identificació de la Sèrie de Saros (1-19 North/South, variants Old/New) per any + polaritat del node.
- Fitxa interpretativa expandible amb data de naixement/fi, aspectes natals i resum curt/llarg.
- Vista "Calendari d'Eclipsis" filtrable per any (1900-2050).
- Dades completes de les 40 sèries actives 1900-2050 (Brady, Appendix 6) a data/saros_series.json.
- Tests unitaris (scripts/test_saros.php).
- Noves classes: includes/SarosSeries.php.
- Fitxers modificats: includes/LunacionesCalculator.php, ajax/lunaciones.php, partes/lunaciones.php, js/lunaciones-js.php, css/lunaciones.css.
  • Mòdul de Revolució Solar (RS): Nova pestanya amb dibuixa de la carta de RS i dades estructurades (formació 2n nivell). Inclou:

- Càlcul exacte del moment de la RS via Swiss Ephemeris (se.solcross()).
- Sub-pestanyes: Carta RS (SVG wheel), Informe (balanç + posicionament + regents), Superposició (cúspides + planetes per casa), Contactes RS-Natal.
- Balanç comparatiu de 3 cartes (Natal, RS Anterior, RS Actual) per elements, modes i polaritats (només planetes personals + ASC + MC).
- Cases carregades (2+ planetes) a la RS, planetes angulars (≤5°), contactes nodes (≤1°).
- Angles natals projectats a cases de RS, dades d'ASC i Sol de RS.
- Superposició de cúspides RS → cases natals, planetes RS per casa.
- Contactes RS-Natal (orbes: 5° majors, 3° sextil, 1° menors), regents de casa.
- Nova classe: includes/RevolucioSolarCalculator.php.
- Nou script Python: scripts/calculadora_revolucio_solar.py.
- Nova migració: migrations/add_revolucio_solar_permission.sql.
- Noves views: ajax/revolucio_solar.php, partes/revolucio_solar.php, js/revolucio-solar-js.php, css/revolucio-solar.css.
- Tests: scripts/test_revolucio_solar.php.

Corregido


  • 502 Bad Gateway en forgot-password: Timeout SMTP reducido de 30s a 10s.

  • ADD COLUMN IF NOT EXISTS: Eliminado de migraciones (sintaxis MariaDB-only, incompatible con MySQL estándar).

  • Tesorería: Cada fila de plan ahora tiene su propio <form> (antes un solo form para toda la tabla causaba pérdida de datos al guardar).


v2.3.1 — 2026-05-24



Corregido


  • Filtro de carta (ajax/main.php): filtrarDatosCartaNatal() compara strtolower($aspecto['acronimo']) contra los acrónimos. id ya no se pierde al no estar en query string.

  • JS filtro (filtro-carta-natal.js): Extrae el id de window.location.pathname con regex /charts/(\d+) si no está en ?id=.

  • Hover de aspectos (svg.js): highlightAspect() ahora busca la línea SVG correspondiente por data-planet1/data-planet2 en vez de comparar por referencia. Al hacer hover en una celda de la tabla de aspectos, la línea SVG se resalta correctamente.

  • Zoom de carta (WheelRenderer.php): openChartFullscreen() ahora crea el modal dinámicamente si no existe en el DOM. Cierre con Escape arreglado.

  • Updater WP: Plugin_Upgrader::upgrade() → descompresión manual. download_url() → wp_remote_get(). Transient 'no_update' → false. (int) get_option() en validate_license().

  • Footer plugin WP: Eliminado <a> anidado dentro del copyright.

  • Versiones plugins: carta-natal-maia v1.4.2, maia-connector v1.0.3.

  • Changelog en updates: check.php + componentVersion() en Functions.php.

  • Arcos WheelRenderer: Sweep ≤180° + sweepFlipped para SVG.

  • Sidebar: switchChartTab(), display: grid, sizing SVG.

  • download.php: maia-connector alias.


v2.3.0 — 2026-05-23



Añadido


  • Sidebar lateral colapsable en vista de carta: Las pestañas horizontales de charts/view.php se reemplazan por un panel lateral izquierdo con toggle ☰. Colapsado: solo iconos (52px). Expandido: icono + texto (220px). Estado persistente en localStorage. En móvil (<768px) vuelve a tabs horizontales.

  • Motor de Cálculo de Tránsitos Adaptativo: Nuevo script scripts/calculadora_transitos.py (~350 líneas) que sustituye las consultas SQL a ephemerides_planetas (~630M filas, ~8 GB) por cálculo dinámico con Swiss Ephemeris + interpolación cúbica (scipy.CubicSpline).

- Grupo rápido (Sol, Luna, Mercurio, Venus, Marte): swe.calc_ut() diario (0.5d para Luna).
- Grupo lento (Júpiter, Saturno, Urano, Neptuno, Plutón, Quirón, Nodos): muestreo cada 15d + CubicSpline con numpy.unwrap para cruce del punto Aries.
- Detección con orbes reales desde ANGULOS_Y_ORBES_ASPECTOS (antes ignorados, solo matching exacto).
- Partil (hora exacta): extrapolación lineal zero-cost desde la derivada del spline.
- Deduplicación: solo el punto de máximo acercamiento por paso consecutivo.
- Rendimiento: 12 meses = 0.037s / 130 llamadas SWE; 3 años = 0.1s / 370 llamadas SWE.
  • Migración 017_drop_ephemerides_planetas.sql: Elimina v_ephemerides_legible y ephemerides_planetas.

  • Soporte True_South_Node: Derivado automáticamente del Nodo Norte (+180°).


Cambiado


  • TransitosCalculator.php: Refactorizado calcularTransitosCompletos() para usar el motor Python vía proc_open() con JSON stdin/stdout. Añadidos ejecutarCalculoTransitos(), adaptarResultadoPython(), lonToRaw() y formatearGradosMinutos(). obtenerRangosTransitos() ahora lee del resultado Python en memoria.

  • ajax/transitos.php: get_date_limits() usa rangos configurables vía .env (TRANSITOS_ANIO_MIN/MAX) en vez de SQL.

  • routes.php: Limpieza de ruta innecesaria.

  • Dependencia Python: Añadido scipy>=1.17 al Python del sistema ServBay 3.11.


Corregido


  • Rangos de tránsitos: Los min/max de cada planeta ahora se calculan desde las posiciones reales de inicio/fin del período, no desde los puntos de aspecto detectados. Corrige falsos rangos de vuelta completa en Saturno y disparidad entre Nodo Norte/Sur.

  • Arcos de tránsito en la rueda (WheelRenderer): El sweep ahora se fuerza a ≤180° (arco corto) con sweepFlipped para invertir el sweep-flag SVG cuando corresponde. Corrige arcos de ~320° (89% del zodíaco) en planetas retrógrados y la posición del label (tSN, tNN).

  • Sidebar lateral: switchTab() renombrado a switchChartTab() para evitar colisión con la función global de script.js que se carga después vía footer.php.


Obsoleto


  • calcularPuntosDeAspectos() y procesarTransitos(): Marcados como @deprecated. Se eliminarán en v2.4.0.


v2.2.5 — 2026-05-22



Corregido


  • Actualización de Plugins WP: Refactorizado run_update() en ambos plugins. Ahora descarga el zip por separado con SSL relajado y download_url(), usa Automatic_Upgrader_Skin + archivo local en vez de WP_Ajax_Upgrader_Skin + URL remota, fuerza FS_METHOD=direct, verifica tanto $result como $skin->result, y comprueba el retorno de activate_plugin(). Esto resuelve el falso "actualizado correctamente" cuando el upgrader fallaba silenciosamente.


v2.2.4 — 2026-05-22



Mejorado


  • Rueda a Pantalla Completa (Desktop): La rueda SVG de la carta natal en el plugin WP ahora ocupa la altura máxima disponible de la ventana en pantallas ≥1024px, permitiendo verla completa sin scroll vertical.


v2.2.3 — 2026-05-22



Corregido


  • Transient Stale en Updater WP: Los plugins carta-natal-maia y maia ahora invalidan el transient de actualización si la versión cacheada ya no es superior a la versión local. Esto evitaba que apareciese una falsa notificación de "actualización disponible" cuando servidor y plugin tenían la misma versión.


v2.2.2 — 2026-05-22



Corregido


  • Fiabilidad de Actualización: Añadida limpieza de caché de plugins de WordPress tras la actualización para asegurar la detección inmediata de la nueva versión.

  • Interfaz de Ajustes: Corregido error de diseño (layout) en WordPress que causaba desplazamientos visuales en el panel.

  • Descarga Pública: Corregido error "Invalid component" en el enlace de descarga de la pantalla de login.


v2.2.1 — 2026-05-22



Añadido


  • Branding Universal: Enlace a la web personal del autor en todos los pies de página (App y Plugins).

  • Acceso Público a Versión: La página de registro de cambios ahora es accesible sin necesidad de autenticación.

  • Promoción de Plugins: Nueva caja de descarga y contacto en la pantalla de login para usuarios de WordPress.


v2.2.0 — 2026-05-22



Añadido


  • Sistema de Logs para Integraciones:

- Nueva tabla wordpress_chart_logs para registrar cada cálculo realizado desde WordPress.
- Registro de datos: Nombre, fecha/hora de nacimiento, lugar, IP, Sistema Operativo y Navegador.
- Seguimiento de Características: El log ahora registra qué secciones se activaron (Planetas, Aspectos, Balance, Luna, Quirón).
- Nueva vista de "Logs" en el panel de administración de integraciones para visualizar estadísticas detalladas.
  • Mejoras en el Plugin WP v2.2.0:

- Actualizada la lógica de envío para incluir las preferencias de visualización en el log del servidor.
- Corregidos errores de permisos en el proceso de auto-actualización.

v2.1.2 — 2026-05-21



Mejorado


  • Sincronización de Versiones: Actualización global de versiones en todos los componentes del sistema (App y Plugins) para asegurar la coherencia del ecosistema Maia.


v2.1.1 — 2026-05-21



Añadido


  • URL de Copyright Premium: Opción para definir una URL personalizada en el copyright de las integraciones premium. Soporte para ocultar el enlace si se deja vacío.


v2.1.0 — 2026-05-21



Añadido


  • Sistema de Licencias Premium:

- Nuevo endpoint api/v1/license/validate para verificar validez de API Key y estado Premium.
- Columna is_premium en tabla wordpress_sites (Migración 014_add_is_premium_to_wp_sites.sql).
- Capacidad de personalización (White-label) para sitios Premium: Título y Copyright personalizados.
  • Plugin WP Carta Natal Maia v1.3.0:

- Validación de Licencia: Comprobación forzada en ajustes y automática cada 24 horas en el sitio.
- Personalización Premium: Campos para Título y Copyright personalizados en el panel de administración.
- Atributos de Shortcode: Parámetros custom_title y custom_copyright soportados (solo para sitios Premium).
- Fase Lunar y Quirón: Nuevas tarjetas informativas con diseño detallado replicando el informe de Maia.
- Configuración Dinámica: Opciones para activar/desactivar secciones (Planetas, Aspectos, Balance, Luna, Quirón) desde ajustes o vía shortcode.
- Versión 1.3.0: Actualización de versión en cabeceras y encolado de scripts/estilos.

Mejorado


  • Motor de Tránsitos (Propuesta Técnica): Diseño de nueva arquitectura para cálculo dinámico "on-the-fly" usando Swiss Ephemeris (Root-Finding) eliminando la dependencia de base de datos precalculada.

  • Robustez de Fase Lunar: Corregidos "gaps" matemáticos en el cálculo de fases de la luna en InfoAstrologica.php.

  • Seguridad en Frontend: Comprobaciones de existencia de nodos DOM en el plugin de WordPress para evitar errores con cachés de servidor.


v1.1.6 — 2026-05-12



Corregido


  • CSRF en admin/users.php: los 5 formularios (change_group, block, unblock, delete, impersonate) no incluían el campo csrf_token desde que se añadió la validación CSRF en v1.0.5. El intento de impersonar, bloquear, desbloquear, eliminar o cambiar grupo devolvía «Token de seguridad inválido». Añadido <input type="hidden" name="csrf_token"> a todos.

  • Migración 013: columnas default_group_id y force_group_sync faltantes en wordpress_sites. El INSERT de WordPressSiteRepository::create() fallaba con SQLSTATE[42S22]: Column not found: 1054 Unknown column 'default_group_id' al crear integraciones WordPress en producción.


v1.1.5 — 2026-05-12



Mejorado


  • Plugin WP Carta Natal Maia v1.1.1:

- Fuente Nunito: reemplaza la pila de fuentes del sistema por Nunito (Google Fonts, pesos 400/500/600/700) cargada vía @import en el CSS.
- Tamaño mínimo 16px: todo el texto del plugin tiene mínimo 16px. Labels pequeñas (footer, orbes, retro) a 14px.
- Tamaños proporcionales: headings escalados (brand 26px, títulos 24px, secciones 18px).
- Símbolos astrológicos a 30px: .astronomicon, .planeta-header, .simbolo-aspecto, .cnm-summary-glyph, .cnm-pt-symbol escalados al mínimo de 30px establecido por convención.
- Responsive: tamaños del breakpoint 480px actualizados proporcionalmente (inputs/botones/tabs a 16px, step-title a 22px).

v1.1.4 — 2026-05-12



Añadido


  • Generador de imagen PNG (ChartImageRenderer): nueva clase GD+TTF que dibuja la carta natal completa como imagen PNG (1200×1200). Incluye rueda con signos, casas, planetas con grados/signo/minutos, líneas de aspecto con símbolos, cabecera con datos personales y tabla de posiciones planetarias. Usa fuente Astronomicon (TTF) directamente — no depende de renderizado SVG del servidor.

  • API v1 chart_image field: POST /api/v1/chart/calculate ahora devuelve data.chart_image con la imagen PNG en formato data URI base64 (además del SVG y HTML de aspectos).

  • Recálculo automático de cartas antiguas: si charts/view.php detecta datos incompletos (planets o casas vacíos), fuerza recálculo vía calcularCartaNatal() y persiste los datos en BD con el nuevo método CartaNatalRepository::guardarDatosCalculados().

  • Método guardarDatosCalculados(int $cartaId, array $datos) en CartaNatalRepository: actualiza solo la columna datos_calculados de una carta existente.


Corregido


  • API v1 renderAspectosList() no mostraba aspectos: la función usaba claves en español con acentos ('conjunción', 'oposición'…) pero AspectosCalculator devuelve las claves en inglés de ANGULOS_Y_ORBES_ASPECTOS ('conjunction', 'opposition'…). Ahora renderAspectosList() recibe directamente el resultado de AspectosCalculator::getAspectosUnicos() y mapea correctamente las claves.

  • Plugin WP v1.1.0: IDs HTML duplicados (#cnm-wheel-container, #cnm-aspects-container) por tabulación sobrante en shortcode.php. Eliminados los divs cnm-tab-* no utilizados. Estructura HTML corregida. Layout de resultados reorganizado: imagen PNG principal + sección de aspectos.


Modificado


  • api/v1/chart/calculate.php: usa AspectosCalculator para generar el listado de aspectos y el contador de stats; genera imagen PNG vía ChartImageRenderer.

  • integrations/wp-plugins/carta-natal-maia/: JS usa data.chart_image (PNG) como vista principal. CSS con clase .cnm-chart-png responsive.

  • charts/view.php: detección de datos incompletos + recálculo + guardado en BD.


v1.1.3 — 2026-05-11



Mejorado


  • Plugin WP Carta Natal Maia v1.0.6:

- Sin filtros ni interactividad: el SVG de la rueda se renderiza sin controles, zoom, ni fullscreen.
- Listado de aspectos en HTML: sustituye el SVG grid por un listado agrupado por tipo de aspecto con nombres de planetas en texto (no requiere fuente Astronomicon).
- Estilos robustos: prefijo #carta-natal-maia-app en todos los selectores + !important en botones para vencer temas WP.
  • REST API v1: POST /api/v1/chart/calculate ahora acepta API keys de ambos tipos (maia y carta-natal-maia).

  • Router: soporte para preflight CORS (OPTIONS) automático en cualquier ruta registrada.


v1.1.2 — 2026-05-11



Añadido


  • GeoNames local — búsqueda de lugares de nacimiento desde base de datos propia, sin depender de la API externa:

- Migración 008_create_geonames_places.sql: tabla geonames_places con FULLTEXT en name + asciiname + alternatenames.
- Script scripts/import_geonames.php: importa allCountries.txt (solo clase P, ciudades/pueblos) en lotes de 1000. Uso: php scripts/import_geonames.php --file=/ruta/allCountries.txt.
- Directorio data/geonames/ para colocar el archivo allCountries.txt.
- Endpoint GET /api/v1/geo/search ahora consulta la BD local (con fallback a API GeoNames si la tabla no existe).
- Migración 009_geonames_indexes.sql: índices B-tree en name, asciiname y population para acelerar búsquedas LIKE + ORDER BY.

Mejorado


  • Output buffering global: ob_start() en index.php para que los endpoints API puedan emitir headers CORS limpios sin interferencia del debug output de init.php.

  • Robustez API geo/search: doble fallback (file_get_contents → curl) para llamadas a GeoNames como último recurso.

  • Respuesta geo/search unificada: ahora devuelve campos compatibles con formato Nominatim (display_name, lon, address.city/state/country) y formato GeoNames (name, lng, countryCode).

  • Búsqueda en formulario de creación Maia: js/script.js usa /api/v1/geo/search (BD local) en vez de Nominatim. Búsqueda automática al escribir 3+ caracteres (con 400ms debounce). Enter para búsqueda manual de 1-2 caracteres.

  • Nombres de región legibles: migración 010_create_admin1_codes.sql + script import_admin1.php traducen códigos FIPS/ISO a nombres (ej: "56" → "Catalonia"). geo/search hace LEFT JOIN automático.

  • Plugin WP Carta Natal Maia v1.0.4: búsqueda automática a 3+ caracteres (antes 2+).


v1.1.1 — 2026-05-11



Mejorado


  • Plugin WP Carta Natal Maia v1.0.2:

- Menú propio «MaiaCN» en sidebar de WordPress (icono â­, posición 30), en lugar de bajo Ajustes.
- Cabecera «Carta Natal by Maia» sobre el formulario.
- Footer «© 2026 Maia by David Herrero» con enlace a la URL de Maia configurada (abre en nueva ventana).
- Formulario unificado: todos los campos visibles a la vez (nombre, fecha, hora, lugar) con labels. El botón de calcular se habilita automáticamente al rellenar nombre, fecha y seleccionar ciudad.
- Estilos CSS para cabecera y footer.

Corregido


  • Panel integraciones: fallback ?? 'maia' para plugin_type en sitios existentes sin la migración aplicada.


v1.1.0 — 2026-05-11



Añadido


  • Plugin WordPress «Carta Natal Maia» (/integrations/wp-plugins/carta-natal-maia/):

- Shortcode [carta_natal_maia] que muestra un formulario paso a paso (nombre → fecha → hora → lugar) y calcula la carta natal de forma anónima.
- Configuración desde Ajustes → Carta Natal Maia (URL de Maia + API Key).
- Búsqueda de ciudad vía GeoNames con autocompletado.
- Resultados: SVG de la rueda zodiacal + SVG de la tabla de aspectos, con tabs para alternar.
- Plug & play: solo requiere API Key generada desde el panel de integraciones de Maia.
  • REST API v1 (POST /api/v1/chart/calculate):

- Autenticación vía header X-API-Key (clave secreta del sitio).
- Rate limiting: 60 peticiones/minuto por API key.
- Validación de fechas (1800–2400) y coordenadas.
- Sin guardar en BD: cálculo puramente anónimo.
- Devuelve JSON con SVG de la rueda zodiacal + SVG de la tabla de aspectos.
- Contador de cartas calculadas por sitio (chart_count en wordpress_sites).
  • Panel de integraciones mejorado (admin/integrations.php):

- Selector de tipo de plugin al crear sitio: «Maia (acceso total · SSO)» o «Carta Natal Maia (solo cálculo anónimo)».
- Badges visuales en listado para distinguir tipo de integración.
- Contador de cartas calculadas visible para sitios de tipo «Carta Natal Maia».
- Validación CSRF en todos los formularios (crear, editar, toggle, eliminar).
  • Migración 007_add_plugin_type.sql: columna plugin_type y chart_count en tabla wordpress_sites.

  • WordPressSiteRepository: nuevos métodos validateApiKey(), incrementChartCount(), getByType().


Cambiado


  • Renombrado: /integrations/wordpress/ → /integrations/wp-plugins/maia/.


v1.0.5 — 2026-05-11



Seguridad — corregido


  • IDOR en AJAX: obtenerPorId() ahora requiere userId en transitos, direcciones, lunaciones y progressions. Las cartas ajenas ya no son accesibles mediante enumeración de IDs.

  • CSRF en POST: añadida validación de token CSRF en /charts/save, /charts/delete, /admin/users. Formularios de creación/edición incluyen campo oculto csrf_token. El JS de eliminación envía el token desde el <meta>.

  • .env inaccesible vía web: añadido <FilesMatch "\.env$"> Require all denied </FilesMatch> en .htaccess.

  • Logs protegidos en Apache 2.4+: logs/.htaccess actualizado a sintaxis Require all denied (la sintaxis Apache 2.2 anterior era ignorada en servidores modernos).

  • Tokens de recuperación hasheados: reset_token ahora se almacena como hash('sha256', $token) en BD, no en texto plano. findByResetToken() compara hashes.

  • Token sin exponer en retorno: requestPasswordReset() ya no incluye el token en el array de retorno.

  • Sin paths ni trazas en errores AJAX: DebugManager::returnAjaxError() ya no incluye file, line ni trace en respuestas JSON (solo success + error).

  • API con autenticación: /api/ ahora requiere partes/RequireLogin.php.

  • XSS almacenado mitigado: los campos nombre, lugar, relacion, notas de carta se escapan con htmlspecialchars() antes de codificarse a JSON para showCartaInfo() en el dashboard.

  • Fuga de emails en compartir: obtenerUsuariosCompartidos() y obtenerUsuariosDisponibles() ya no devuelven email. share-manager.js actualizado para no mostrar emails.

  • TOCTOU en cuota de cartas: verificarLimiteCartas() usa SELECT ... FOR UPDATE para evitar race condition en creación concurrente de cartas.

  • Cookie de sesión condicional: SameSite y Secure ahora dependen de si la conexión es HTTPS. En HTTP local usa Lax + Secure=0, evitando que falle la autenticación en desarrollo.


Corregido


  • Bug regresión en IDOR fix: las funciones calculateDirecciones(), calculateLunaciones() y calculateProgressions() usaban $user['id'] fuera de scope (la variable no es accesible desde funciones standalone). Ahora reciben int $userId como parámetro explícito desde el switch del scope global.


v1.0.4 — 2026-05-11



Mejorado


  • Formulario paso a paso (wizard) en creación de carta natal (js/script.js + charts/create.php + css/styles.css):

- Al iniciar solo se ve "Nombre completo"
- Al rellenar el nombre, aparece "Fecha y Hora de Nacimiento" con transición suave
- Al rellenar fecha (1800–2400) y hora, aparece "Lugar de Nacimiento" con el buscador activo
- Transiciones CSS con .form-step / .form-step-hidden / .form-step-visible
- Modo edición: todas las secciones visibles desde el inicio
  • Info de ciudad seleccionada ahora aparece dentro del mismo contenedor de resultados, con botón "Cambiar ciudad"

  • Auto-selección: si la búsqueda devuelve un solo resultado, se selecciona automáticamente

  • Ajuste de zona horaria (#timeAdjustment) movido a la sección de lugar, bajo los resultados


Corregido


  • Validación de fecha sin rango: validarFecha() en CartaNatalRepository.php ahora exige 1800–2400

  • Resultados duplicados en búsqueda de ciudad: deduplicación por nombre + región + país (js/script.js)

  • Input date con min="1800-01-01" y max="2400-12-31" en charts/create.php


v1.0.3 — 2026-05-10



Corregido


  • Registro de usuario roto (includes/AuthManager.php:376): phone_country y form_load_time se pasaban a UserRepository::create() y se intentaban insertar en usuarios (columna inexistente → SQLSTATE[42S22]). Añadidos al unset().

  • Links hardcodeados en forgot-password (auth/forgot-password.php:118-120): /UserLogin.php → route('/login'), /UserRegister.php → route('/register').

  • Terminología: "carta astral" / "cartas astrales" → "carta natal" / "cartas natales" en todo el código (PHP, CSS, traducciones .po/.mo). Término astrológico correcto.

  • Versión hardcodeada en admin/version.php: ahora se lee dinámicamente del CHANGELOG.md


Añadido


  • Footer general con copyright + versión en 8 páginas (login, register, forgot-password, dashboard, groups, group_edit, version, view)

  • CSS (css/login.css): clase .app-footer + regla .user-login-container > .app-footer para grid de login

  • Función appVersion() en includes/Functions.php: lee la versión del CHANGELOG.md (cache estática)

  • Función copyrightFooter() en includes/Functions.php: combina APP_COPYRIGHT de .env con appVersion() + versión enlaza a /admin/version

  • Variable APP_COPYRIGHT en .env y .env.example para editar el copyright centralizadamente


v1.0.2 — 2026-05-09



Corregido


  • Eliminados todos los estilos inline (style="") de dashboard.php — extraídos a css/dashboard.css

  • Movido el <style> inline de admin/version.php a css/version.css

  • Estilos de botones de destacado movidos de css/direcciones.css a css/dashboard.css

  • Asegurado font-size mínimo de 16px en todas las nuevas clases CSS

  • Tamaño mínimo de símbolos astrológicos 30px en progresiones y direcciones


Mejoras


  • AGENTS.md documentado con reglas de estilo: sin inline CSS/JS, min 16px texto, min 30px símbolos

  • Botones de acción en cards ahora uniformes (36x36px, solo icono)

  • Orden de botones: Ver → Destacar → Info → Editar → Compartir → Eliminar

  • Nombre de la carta clickable (misma acción que botón Ver)


Archivos creados


  • css/dashboard.css — estilos del dashboard

  • css/version.css — estilos de la página de versión


---

v1.0.1 — 2026-05-09



Corregido


  • Call to undefined method Database::prepare() en dashboard.php y ajax/feature_chart.php

— sustituido por $db->query() y $db->fetchOne() (métodos del singleton Database)
  • SyntaxError: redeclaration of let Modal por carga duplicada de Modal.js

— eliminada la carga redundante en dashboard.php (footer.php ya incluye modal.js)
  • filtro-carta-natal.js mostraba error en páginas sin botón "Aplicar Filtros"

— cambiado Utils.error → Utils.log para que solo sea informativo
  • Tabla chart_featured no existente al primer uso

— añadido CREATE TABLE IF NOT EXISTS automático en dashboard.php y ajax/feature_chart.php
  • Estrella de destacado sin feedback visual al hacer clic

— añadido alert() en caso de error + deshabilitado temporal del botón durante la petición
  • Posición de la estrella de destacado movida junto a la etiqueta "Propia"/"Compartida"


---

v1.0.0 — 2026-05-09



Añadido


  • Módulo de Direcciones de Arco Solar: nueva pestaña "Direccions" en la vista de carta

- Calculadora de direcciones de arco solar (1 año de vida = 1 día de tránsito)
- Tabla de resultados con columnas: Pd, Casa, Asp, Pn, Data, Pos(Pd)
- Soporte para aspectes a planetas natales, nodos, Quirón
- Ingressos de casa (conjunción) → "Casa [nº]"
- Ingressos de signo (conjunción) → símbolo del signo
- Indicador de "funció inferior" cuando el planeta supera los 29° de un signo
- Filtros: fecha inicial, duración en años, orbe, planetas dirigidos, planetas natales, aspectos, casas, signos
- Aspectos por defecto: conjunción y oposición
- Permiso access_direcciones ("Ver Direcciones") añadido al sistema de permisos
  • Cartas destacadas: los usuarios pueden marcar/desmarcar cartas como favoritas

- Icono de estrella (★) junto al nombre de cada carta en el dashboard
- Estrella amarilla rellena cuando está destacada, transparente cuando no
- Las cartas destacadas se ordenan primero alfabéticamente
- El estado de destacado es por usuario (independiente del propietario)
  • Página de Versión y Log en el panel de administración (/admin/version)

- Muestra la versión actual y el changelog completo

Archivos creados


  • includes/DireccionesCalculator.php — clase calculadora de direcciones de arco solar

  • partes/direcciones.php — template de la página de direcciones

  • ajax/direcciones.php — endpoint AJAX para cálculo de direcciones

  • js/direcciones-js.php — JavaScript del módulo de direcciones

  • css/direcciones.css — estilos del módulo de direcciones

  • ajax/feature_chart.php — endpoint AJAX para toggle de destacado

  • migrations/add_direcciones_permission.sql — migración del permiso de direcciones

  • migrations/add_chart_featured.sql — migración de la tabla de destacados

  • admin/version.php — página de versión y changelog

  • CHANGELOG.md — este archivo


Modificaciones


  • charts/view.php — añadida pestaña "Direccions" con verificación de permiso

  • partes/header.php — añadido <link> para direcciones.css

  • partes/footer.php — añadido <script> para direcciones-js.php

  • dashboard.php — añadido icono de estrella para destacar cartas, ordenación por destacadas primero

  • admin/index.php — añadida tarjeta "Versión y Log" en el panel de administración

  • routes.php — añadida ruta /admin/version