2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								using  GestionIntegral.Api.Data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  GestionIntegral.Api.Data.Repositories.Distribucion ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  GestionIntegral.Api.Data.Repositories.Suscripciones ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  GestionIntegral.Api.Dtos.Suscripciones ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  GestionIntegral.Api.Models.Suscripciones ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  System.Data ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								using  System.Globalization ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  GestionIntegral.Api.Services.Suscripciones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  class  SuscripcionService  :  ISuscripcionService 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        private  readonly  ISuscripcionRepository  _suscripcionRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        private  readonly  ISuscriptorRepository  _suscriptorRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        private  readonly  IPublicacionRepository  _publicacionRepository ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        private  readonly  IPromocionRepository  _promocionRepository ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        private  readonly  IFacturaRepository  _facturaRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        private  readonly  IFacturaDetalleRepository  _facturaDetalleRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        private  readonly  IFacturacionService  _facturacionService ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        private  readonly  ILogger < SuscripcionService >  _logger ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        private  readonly  DbConnectionFactory  _connectionFactory ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  SuscripcionService ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ISuscripcionRepository  suscripcionRepository , 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ISuscriptorRepository  suscriptorRepository , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        IPublicacionRepository  publicacionRepository , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        IPromocionRepository  promocionRepository , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        IFacturaRepository  facturaRepository , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        IFacturaDetalleRepository  facturaDetalleRepository , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        IFacturacionService  facturacionService , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ILogger < SuscripcionService >  logger , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        DbConnectionFactory  connectionFactory ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            _suscripcionRepository  =  suscripcionRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            _suscriptorRepository  =  suscriptorRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            _publicacionRepository  =  publicacionRepository ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            _promocionRepository  =  promocionRepository ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            _facturaRepository  =  facturaRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            _facturaDetalleRepository  =  facturaDetalleRepository ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            _facturacionService  =  facturacionService ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            _logger  =  logger ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            _connectionFactory  =  connectionFactory ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        private  PromocionDto  MapPromocionToDto ( Promocion  promo )  = >  new  PromocionDto 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            IdPromocion  =  promo . IdPromocion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Descripcion  =  promo . Descripcion , 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            TipoEfecto  =  promo . TipoEfecto , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ValorEfecto  =  promo . ValorEfecto , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TipoCondicion  =  promo . TipoCondicion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ValorCondicion  =  promo . ValorCondicion , 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            FechaInicio  =  promo . FechaInicio . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            FechaFin  =  promo . FechaFin ? . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Activa  =  promo . Activa 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        private  async  Task < SuscripcionDto ? >  MapToDto ( Suscripcion  suscripcion ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( suscripcion  = =  null )  return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  publicacion  =  await  _publicacionRepository . GetByIdSimpleAsync ( suscripcion . IdPublicacion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  new  SuscripcionDto 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdSuscripcion  =  suscripcion . IdSuscripcion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdSuscriptor  =  suscripcion . IdSuscriptor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdPublicacion  =  suscripcion . IdPublicacion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                NombrePublicacion  =  publicacion ? . Nombre  ? ?  "Desconocida" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                FechaInicio  =  suscripcion . FechaInicio . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                FechaFin  =  suscripcion . FechaFin ? . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Estado  =  suscripcion . Estado , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                DiasEntrega  =  suscripcion . DiasEntrega , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Observaciones  =  suscripcion . Observaciones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  async  Task < SuscripcionDto ? >  ObtenerPorId ( int  idSuscripcion ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  suscripcion  =  await  _suscripcionRepository . GetByIdAsync ( idSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( suscripcion  = =  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  await  MapToDto ( suscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  async  Task < IEnumerable < SuscripcionDto > >  ObtenerPorSuscriptorId ( int  idSuscriptor ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  suscripciones  =  await  _suscripcionRepository . GetBySuscriptorIdAsync ( idSuscriptor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  dtosTasks  =  suscripciones . Select ( s  = >  MapToDto ( s ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  dtos  =  await  Task . WhenAll ( dtosTasks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  dtos . Where ( dto  = >  dto  ! =  null ) ! ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  async  Task < ( SuscripcionDto ?  Suscripcion ,  string?  Error ) >  Crear ( CreateSuscripcionDto  createDto ,  int  idUsuario ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( await  _suscriptorRepository . GetByIdAsync ( createDto . IdSuscriptor )  = =  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( null ,  "El suscriptor no existe." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( await  _publicacionRepository . GetByIdSimpleAsync ( createDto . IdPublicacion )  = =  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( null ,  "La publicación no existe." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( createDto . FechaFin . HasValue  & &  createDto . FechaFin . Value  <  createDto . FechaInicio ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( null ,  "La fecha de fin no puede ser anterior a la fecha de inicio." ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa auditoría de envíos masivos y mejora de procesos
Se introduce un sistema completo para auditar los envíos masivos de correos durante el cierre mensual y se refactoriza la interfaz de usuario de procesos para una mayor claridad y escalabilidad. Además, se mejora la lógica de negocio para la gestión de bajas de suscripciones.
### ✨ Nuevas Características
- **Auditoría de Envíos Masivos (Cierre Mensual):**
    - Se crea una nueva tabla `com_LotesDeEnvio` para registrar cada ejecución del proceso de facturación mensual.
    - El `FacturacionService` ahora crea un "lote" al iniciar el cierre, registra el resultado de cada envío de email individual asociándolo a dicho lote, y actualiza las estadísticas finales (enviados, fallidos) al terminar.
    - Se implementa un nuevo `LotesEnvioController` con un endpoint para consultar los detalles de cualquier lote de envío histórico.
### 🔄 Refactorización y Mejoras
- **Rediseño de la Página de Procesos:**
    - La antigua página "Facturación" se renombra a `CierreYProcesosPage` y se rediseña completamente utilizando una interfaz de Pestañas (Tabs).
    - **Pestaña "Procesos Mensuales":** Aisla las acciones principales (Generar Cierre, Archivo de Débito, Procesar Respuesta), mostrando un resumen del resultado del último envío.
    - **Pestaña "Historial de Cierres":** Muestra una tabla con todos los lotes de envío pasados y permite al usuario ver los detalles de cada uno en un modal.
- **Filtros para el Historial de Cierres:**
    - Se añaden filtros por Mes y Año a la pestaña de "Historial de Cierres", permitiendo al usuario buscar y auditar procesos pasados de manera eficiente. El filtrado se realiza en el backend para un rendimiento óptimo.
- **Lógica de `FechaFin` Obligatoria para Bajas:**
    - Se implementa una regla de negocio crucial: al cambiar el estado de una suscripción a "Pausada" o "Cancelada", ahora es obligatorio establecer una `FechaFin`.
    - **Frontend:** El modal de suscripciones ahora gestiona esto automáticamente, haciendo el campo `FechaFin` requerido y visible según el estado seleccionado.
    - **Backend:** Se añade una validación en `SuscripcionService` como segunda capa de seguridad para garantizar la integridad de los datos.
### 🐛 Corrección de Errores
- **Reporte de Distribución:** Se corrigió un bug en la generación del PDF donde la columna de fecha no mostraba la "Fecha de Baja" para las suscripciones finalizadas. Ahora se muestra la fecha correcta según la sección (Altas o Bajas).
- **Errores de Compilación y Dependencias:** Se solucionaron varios errores de compilación en el backend, principalmente relacionados con la falta de registro de los nuevos repositorios (`ILoteDeEnvioRepository`, `IEmailLogService`, etc.) en el contenedor de inyección de dependencias (`Program.cs`).
- **Errores de Tipado en Frontend:** Se corrigieron múltiples errores de TypeScript en `CierreYProcesosPage` debidos a la inconsistencia entre `PascalCase` (C#) y `camelCase` (JSON/TypeScript), asegurando un mapeo correcto de los datos de la API.
											 
										 
										
											2025-08-11 11:14:03 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ( createDto . Estado  = =  "Cancelada"  | |  createDto . Estado  = =  "Pausada" )  & &  ! createDto . FechaFin . HasValue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( null ,  "Se debe especificar una 'Fecha Fin' cuando el estado es 'Cancelada' o 'Pausada'." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( createDto . Estado  = =  "Activa" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                createDto . FechaFin  =  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  nuevaSuscripcion  =  new  Suscripcion 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdSuscriptor  =  createDto . IdSuscriptor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdPublicacion  =  createDto . IdPublicacion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                FechaInicio  =  createDto . FechaInicio , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                FechaFin  =  createDto . FechaFin , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Estado  =  createDto . Estado , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                DiasEntrega  =  string . Join ( "," ,  createDto . DiasEntrega ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Observaciones  =  createDto . Observaciones , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdUsuarioAlta  =  idUsuario 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            await  ( connection  as  System . Data . Common . DbConnection ) ! . OpenAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  transaction  =  connection . BeginTransaction ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  creada  =  await  _suscripcionRepository . CreateAsync ( nuevaSuscripcion ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( creada  = =  null )  throw  new  DataException ( "Error al crear la suscripción." ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                var  ultimoPeriodoFacturadoStr  =  await  _facturaRepository . GetUltimoPeriodoFacturadoAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ultimoPeriodoFacturadoStr  ! =  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    var  ultimoPeriodo  =  DateTime . ParseExact ( ultimoPeriodoFacturadoStr ,  "yyyy-MM" ,  CultureInfo . InvariantCulture ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    var  periodoSuscripcion  =  new  DateTime ( creada . FechaInicio . Year ,  creada . FechaInicio . Month ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( periodoSuscripcion  < =  ultimoPeriodo ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-13 15:53:34 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        _logger . LogInformation ( "Suscripción en período ya cerrado detectada. Generando factura de alta pro-rata." ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        decimal  importeProporcional  =  await  _facturacionService . CalcularImporteParaSuscripcion ( creada ,  creada . FechaInicio . Year ,  creada . FechaInicio . Month ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( importeProporcional  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            var  facturaDeAlta  =  new  Factura 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                IdSuscriptor  =  creada . IdSuscriptor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                Periodo  =  creada . FechaInicio . ToString ( "yyyy-MM" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                FechaEmision  =  DateTime . Now . Date , 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-13 15:53:34 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                FechaVencimiento  =  DateTime . Now . AddDays ( 10 ) . Date , 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                ImporteBruto  =  importeProporcional , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                ImporteFinal  =  importeProporcional , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                EstadoPago  =  "Pendiente" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                EstadoFacturacion  =  "Pendiente de Facturar" , 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-13 15:53:34 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                TipoFactura  =  "Alta" 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat(suscripciones): Implementa facturación pro-rata para altas y excluye del débito automático
Se introduce una refactorización mayor del ciclo de facturación para manejar correctamente las suscripciones que inician en un período ya cerrado. Esto soluciona el problema de cobrar un mes completo a un nuevo suscriptor, mejorando la transparencia y la experiencia del cliente.
### ✨ Nuevas Características y Lógica de Negocio
- **Facturación Pro-rata Automática (Factura de Alta):**
    - Al crear una nueva suscripción cuya fecha de inicio corresponde a un período de facturación ya cerrado, el sistema ahora calcula automáticamente el costo proporcional por los días restantes de ese mes.
    - Se genera de forma inmediata una nueva factura de tipo "Alta" por este monto parcial, separándola del ciclo de facturación mensual regular.
- **Exclusión del Débito Automático para Facturas de Alta:**
    - Se implementa una regla de negocio clave: las facturas de tipo "Alta" son **excluidas** del proceso de generación del archivo de débito automático para el banco.
    - Esto fuerza a que el primer cobro (el proporcional) se gestione a través de un medio de pago manual (efectivo, transferencia, etc.), evitando cargos inesperados en la cuenta bancaria del cliente.
    - El débito automático comenzará a operar normalmente a partir del primer ciclo de facturación completo.
### 🔄 Cambios en el Backend
- **Base de Datos:**
    - Se ha añadido la columna `TipoFactura` (`varchar(20)`) a la tabla `susc_Facturas`.
    - Se ha implementado una `CHECK constraint` para permitir únicamente los valores 'Mensual' y 'Alta'.
- **Servicios:**
    - **`SuscripcionService`:** Ahora contiene la lógica para detectar una alta retroactiva, invocar al `FacturacionService` para el cálculo pro-rata y crear la "Factura de Alta" y su detalle correspondiente dentro de la misma transacción.
    - **`FacturacionService`:** Expone públicamente el método `CalcularImporteParaSuscripcion` y se ha actualizado `ObtenerResumenesDeCuentaPorPeriodo` para que envíe la propiedad `TipoFactura` al frontend.
    - **`DebitoAutomaticoService`:** El método `GetFacturasParaDebito` ahora filtra y excluye explícitamente las facturas donde `TipoFactura = 'Alta'`.
### 🎨 Mejoras en la Interfaz de Usuario (Frontend)
- **`ConsultaFacturasPage.tsx`:**
    - **Nueva Columna:** Se ha añadido una columna "Tipo Factura" en la tabla de detalle, que muestra un `Chip` distintivo para identificar fácilmente las facturas de "Alta".
    - **Nuevo Filtro:** Se ha agregado un nuevo menú desplegable para filtrar la vista por "Tipo de Factura" (`Todas`, `Mensual`, `Alta`), permitiendo a los administradores auditar rápidamente los nuevos ingresos.
											 
										 
										
											2025-08-13 14:55:24 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            var  facturaCreada  =  await  _facturaRepository . CreateAsync ( facturaDeAlta ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            if  ( facturaCreada  = =  null )  throw  new  DataException ( "No se pudo crear la factura de alta." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            var  publicacion  =  await  _publicacionRepository . GetByIdSimpleAsync ( creada . IdPublicacion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            var  finDeMes  =  new  DateTime ( creada . FechaInicio . Year ,  creada . FechaInicio . Month ,  1 ) . AddMonths ( 1 ) . AddDays ( - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            await  _facturaDetalleRepository . CreateAsync ( new  FacturaDetalle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                IdFactura  =  facturaCreada . IdFactura , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                IdSuscripcion  =  creada . IdSuscripcion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                Descripcion  =  $"Suscripción proporcional {publicacion?.Nombre} ({creada.FechaInicio:dd/MM} al {finDeMes:dd/MM})" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                ImporteBruto  =  importeProporcional , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                ImporteNeto  =  importeProporcional , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                DescuentoAplicado  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            _logger . LogInformation ( "Factura de alta #{IdFactura} por ${Importe} generada para la nueva suscripción #{IdSuscripcion}." ,  facturaCreada . IdFactura ,  importeProporcional ,  creada . IdSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                transaction . Commit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                _logger . LogInformation ( "Suscripción ID {Id} creada por Usuario ID {UserId}." ,  creada . IdSuscripcion ,  idUsuario ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( await  MapToDto ( creada ) ,  null ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                try  {  transaction . Rollback ( ) ;  }  catch  {  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                _logger . LogError ( ex ,  "Error al crear suscripción para suscriptor ID {IdSuscriptor}" ,  createDto . IdSuscriptor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( null ,  $"Error interno: {ex.Message}" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  async  Task < ( bool  Exito ,  string?  Error ) >  Actualizar ( int  idSuscripcion ,  UpdateSuscripcionDto  updateDto ,  int  idUsuario ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  existente  =  await  _suscripcionRepository . GetByIdAsync ( idSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( existente  = =  null )  return  ( false ,  "Suscripción no encontrada." ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa auditoría de envíos masivos y mejora de procesos
Se introduce un sistema completo para auditar los envíos masivos de correos durante el cierre mensual y se refactoriza la interfaz de usuario de procesos para una mayor claridad y escalabilidad. Además, se mejora la lógica de negocio para la gestión de bajas de suscripciones.
### ✨ Nuevas Características
- **Auditoría de Envíos Masivos (Cierre Mensual):**
    - Se crea una nueva tabla `com_LotesDeEnvio` para registrar cada ejecución del proceso de facturación mensual.
    - El `FacturacionService` ahora crea un "lote" al iniciar el cierre, registra el resultado de cada envío de email individual asociándolo a dicho lote, y actualiza las estadísticas finales (enviados, fallidos) al terminar.
    - Se implementa un nuevo `LotesEnvioController` con un endpoint para consultar los detalles de cualquier lote de envío histórico.
### 🔄 Refactorización y Mejoras
- **Rediseño de la Página de Procesos:**
    - La antigua página "Facturación" se renombra a `CierreYProcesosPage` y se rediseña completamente utilizando una interfaz de Pestañas (Tabs).
    - **Pestaña "Procesos Mensuales":** Aisla las acciones principales (Generar Cierre, Archivo de Débito, Procesar Respuesta), mostrando un resumen del resultado del último envío.
    - **Pestaña "Historial de Cierres":** Muestra una tabla con todos los lotes de envío pasados y permite al usuario ver los detalles de cada uno en un modal.
- **Filtros para el Historial de Cierres:**
    - Se añaden filtros por Mes y Año a la pestaña de "Historial de Cierres", permitiendo al usuario buscar y auditar procesos pasados de manera eficiente. El filtrado se realiza en el backend para un rendimiento óptimo.
- **Lógica de `FechaFin` Obligatoria para Bajas:**
    - Se implementa una regla de negocio crucial: al cambiar el estado de una suscripción a "Pausada" o "Cancelada", ahora es obligatorio establecer una `FechaFin`.
    - **Frontend:** El modal de suscripciones ahora gestiona esto automáticamente, haciendo el campo `FechaFin` requerido y visible según el estado seleccionado.
    - **Backend:** Se añade una validación en `SuscripcionService` como segunda capa de seguridad para garantizar la integridad de los datos.
### 🐛 Corrección de Errores
- **Reporte de Distribución:** Se corrigió un bug en la generación del PDF donde la columna de fecha no mostraba la "Fecha de Baja" para las suscripciones finalizadas. Ahora se muestra la fecha correcta según la sección (Altas o Bajas).
- **Errores de Compilación y Dependencias:** Se solucionaron varios errores de compilación en el backend, principalmente relacionados con la falta de registro de los nuevos repositorios (`ILoteDeEnvioRepository`, `IEmailLogService`, etc.) en el contenedor de inyección de dependencias (`Program.cs`).
- **Errores de Tipado en Frontend:** Se corrigieron múltiples errores de TypeScript en `CierreYProcesosPage` debidos a la inconsistencia entre `PascalCase` (C#) y `camelCase` (JSON/TypeScript), asegurando un mapeo correcto de los datos de la API.
											 
										 
										
											2025-08-11 11:14:03 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // Validación de lógica de negocio en el backend 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ( updateDto . Estado  = =  "Cancelada"  | |  updateDto . Estado  = =  "Pausada" )  & &  ! updateDto . FechaFin . HasValue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( false ,  "Se debe especificar una 'Fecha Fin' cuando el estado es 'Cancelada' o 'Pausada'." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Si el estado es 'Activa', nos aseguramos de que la FechaFin sea nula. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( updateDto . Estado  = =  "Activa" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                updateDto . FechaFin  =  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            if  ( updateDto . FechaFin . HasValue  & &  updateDto . FechaFin . Value  <  updateDto . FechaInicio ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( false ,  "La fecha de fin no puede ser anterior a la fecha de inicio." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . FechaInicio  =  updateDto . FechaInicio ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . FechaFin  =  updateDto . FechaFin ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . Estado  =  updateDto . Estado ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . DiasEntrega  =  string . Join ( "," ,  updateDto . DiasEntrega ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . Observaciones  =  updateDto . Observaciones ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . IdUsuarioMod  =  idUsuario ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            existente . FechaMod  =  DateTime . Now ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            await  ( connection  as  System . Data . Common . DbConnection ) ! . OpenAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  transaction  =  connection . BeginTransaction ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  actualizado  =  await  _suscripcionRepository . UpdateAsync ( existente ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ! actualizado )  throw  new  DataException ( "Error al actualizar la suscripción." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                transaction . Commit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                _logger . LogInformation ( "Suscripción ID {Id} actualizada por Usuario ID {UserId}." ,  idSuscripcion ,  idUsuario ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( true ,  null ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                try  {  transaction . Rollback ( ) ;  }  catch  {  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                _logger . LogError ( ex ,  "Error al actualizar suscripción ID: {IdSuscripcion}" ,  idSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( false ,  $"Error interno: {ex.Message}" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        public  async  Task < IEnumerable < PromocionAsignadaDto > >  ObtenerPromocionesAsignadas ( int  idSuscripcion ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            var  asignaciones  =  await  _suscripcionRepository . GetPromocionesAsignadasBySuscripcionIdAsync ( idSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  asignaciones . Select ( a  = >  new  PromocionAsignadaDto 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                IdPromocion  =  a . Promocion . IdPromocion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Descripcion  =  a . Promocion . Descripcion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                TipoEfecto  =  a . Promocion . TipoEfecto , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ValorEfecto  =  a . Promocion . ValorEfecto , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                TipoCondicion  =  a . Promocion . TipoCondicion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ValorCondicion  =  a . Promocion . ValorCondicion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                FechaInicio  =  a . Promocion . FechaInicio . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                FechaFin  =  a . Promocion . FechaFin ? . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Activa  =  a . Promocion . Activa , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                VigenciaDesdeAsignacion  =  a . Asignacion . VigenciaDesde . ToString ( "yyyy-MM-dd" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                VigenciaHastaAsignacion  =  a . Asignacion . VigenciaHasta ? . ToString ( "yyyy-MM-dd" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  async  Task < IEnumerable < PromocionDto > >  ObtenerPromocionesDisponibles ( int  idSuscripcion ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  todasLasPromosActivas  =  await  _promocionRepository . GetAllAsync ( true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            var  promosAsignadasData  =  await  _suscripcionRepository . GetPromocionesAsignadasBySuscripcionIdAsync ( idSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  idsAsignadas  =  promosAsignadasData . Select ( p  = >  p . Promocion . IdPromocion ) . ToHashSet ( ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  todasLasPromosActivas 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                . Where ( p  = >  ! idsAsignadas . Contains ( p . IdPromocion ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                . Select ( MapPromocionToDto ) ;  // Usa el helper que ya creamos 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        public  async  Task < ( bool  Exito ,  string?  Error ) >  AsignarPromocion ( int  idSuscripcion ,  AsignarPromocionDto  dto ,  int  idUsuario ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            await  ( connection  as  System . Data . Common . DbConnection ) ! . OpenAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  transaction  =  connection . BeginTransaction ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( await  _suscripcionRepository . GetByIdAsync ( idSuscripcion )  = =  null )  return  ( false ,  "Suscripción no encontrada." ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( await  _promocionRepository . GetByIdAsync ( dto . IdPromocion )  = =  null )  return  ( false ,  "Promoción no encontrada." ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                var  nuevaAsignacion  =  new  SuscripcionPromocion 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    IdSuscripcion  =  idSuscripcion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    IdPromocion  =  dto . IdPromocion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    IdUsuarioAsigno  =  idUsuario , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    VigenciaDesde  =  dto . VigenciaDesde , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    VigenciaHasta  =  dto . VigenciaHasta 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                await  _suscripcionRepository . AsignarPromocionAsync ( nuevaAsignacion ,  transaction ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                transaction . Commit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( true ,  null ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ex . Message . Contains ( "PRIMARY KEY constraint" ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  ( false ,  "Esta promoción ya está asignada a la suscripción." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                try  {  transaction . Rollback ( ) ;  }  catch  {  } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-08 09:48:15 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                _logger . LogError ( ex ,  "Error al asignar promoción {IdPromocion} a suscripción {IdSuscripcion}" ,  dto . IdPromocion ,  idSuscripcion ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Feat: Implementa flujo completo de facturación y promociones
Este commit introduce la funcionalidad completa para la facturación mensual,
la gestión de promociones y la comunicación con el cliente en el módulo
de suscripciones.
Backend:
- Se añade el servicio de Facturación que calcula automáticamente los importes
  mensuales basándose en las suscripciones activas, días de entrega y precios.
- Se implementa el servicio DebitoAutomaticoService, capaz de generar el
  archivo de texto plano para "Pago Directo Galicia" y de procesar el
  archivo de respuesta para la conciliación de pagos.
- Se desarrolla el ABM completo para Promociones (Servicio, Repositorio,
  Controlador y DTOs), permitiendo la creación de descuentos por porcentaje
  o monto fijo.
- Se implementa la lógica para asignar y desasignar promociones a suscripciones
  específicas.
- Se añade un servicio de envío de email (EmailService) integrado con MailKit
  y un endpoint para notificar facturas a los clientes.
- Se crea la lógica para registrar pagos manuales (efectivo, tarjeta, etc.)
  y actualizar el estado de las facturas.
- Se añaden todos los permisos necesarios a la base de datos para
  segmentar el acceso a las nuevas funcionalidades.
Frontend:
- Se crea la página de Facturación, que permite al usuario seleccionar un
  período, generar la facturación, listar los resultados y generar el archivo
  de débito para el banco.
- Se implementa la funcionalidad para subir y procesar el archivo de
  respuesta del banco, actualizando la UI en consecuencia.
- Se añade la página completa para el ABM de Promociones.
- Se integra un modal en la gestión de suscripciones para asignar y
  desasignar promociones a un cliente.
- Se añade la opción "Enviar Email" en el menú de acciones de las facturas,
  conectada al nuevo endpoint del backend.
- Se completan y corrigen los componentes `PagoManualModal` y `FacturacionPage`
  para incluir la lógica de registro de pagos y solucionar errores de TypeScript.
											 
										 
										
											2025-08-01 12:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                return  ( false ,  "Error interno al asignar la promoción." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        public  async  Task < ( bool  Exito ,  string?  Error ) >  QuitarPromocion ( int  idSuscripcion ,  int  idPromocion ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            await  ( connection  as  System . Data . Common . DbConnection ) ! . OpenAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  transaction  =  connection . BeginTransaction ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  exito  =  await  _suscripcionRepository . QuitarPromocionAsync ( idSuscripcion ,  idPromocion ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ! exito )  return  ( false ,  "La promoción no estaba asignada a esta suscripción." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                transaction . Commit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( true ,  null ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                try  {  transaction . Rollback ( ) ;  }  catch  {  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                _logger . LogError ( ex ,  "Error al quitar promoción {IdPromocion} de suscripción {IdSuscripcion}" ,  idPromocion ,  idSuscripcion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  ( false ,  "Error interno al quitar la promoción." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 10:24:26 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}