Files
zentral/src/backend/Zentral.API/Controllers/ModulesController.cs

353 lines
11 KiB
C#

using Zentral.API.Services;
using Zentral.Domain.Entities;
using Microsoft.AspNetCore.Mvc;
namespace Zentral.API.Controllers;
/// <summary>
/// Controller per la gestione dei moduli applicativi e delle subscription
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ModulesController : ControllerBase
{
private readonly ModuleService _moduleService;
private readonly ILogger<ModulesController> _logger;
public ModulesController(ModuleService moduleService, ILogger<ModulesController> logger)
{
_moduleService = moduleService;
_logger = logger;
}
/// <summary>
/// Ottiene tutti i moduli disponibili con stato subscription
/// </summary>
[HttpGet]
public async Task<ActionResult<List<ModuleDto>>> GetAllModules()
{
var modules = await _moduleService.GetAllModulesAsync();
return Ok(modules.Select(MapToDto).ToList());
}
/// <summary>
/// Ottiene solo i moduli attivi (per costruzione menu)
/// </summary>
[HttpGet("active")]
public async Task<ActionResult<List<ModuleDto>>> GetActiveModules()
{
var modules = await _moduleService.GetActiveModulesAsync();
return Ok(modules.Select(MapToDto).ToList());
}
/// <summary>
/// Ottiene un modulo specifico per codice
/// </summary>
[HttpGet("{code}")]
public async Task<ActionResult<ModuleDto>> GetModule(string code)
{
var module = await _moduleService.GetModuleByCodeAsync(code);
if (module == null)
return NotFound(new { message = $"Modulo '{code}' non trovato" });
return Ok(MapToDto(module));
}
/// <summary>
/// Verifica se un modulo è abilitato
/// </summary>
[HttpGet("{code}/enabled")]
public async Task<ActionResult<ModuleStatusDto>> IsModuleEnabled(string code)
{
var module = await _moduleService.GetModuleByCodeAsync(code);
if (module == null)
return NotFound(new { message = $"Modulo '{code}' non trovato" });
var isEnabled = await _moduleService.IsModuleEnabledAsync(code);
var hasValidSubscription = await _moduleService.HasValidSubscriptionAsync(code);
return Ok(new ModuleStatusDto
{
Code = code,
IsEnabled = isEnabled,
HasValidSubscription = hasValidSubscription,
IsCore = module.IsCore,
DaysRemaining = module.Subscription?.GetDaysRemaining(),
IsExpiringSoon = module.Subscription?.IsExpiringSoon() ?? false
});
}
/// <summary>
/// Attiva un modulo
/// </summary>
[HttpPut("{code}/enable")]
public async Task<ActionResult<SubscriptionDto>> EnableModule(string code, [FromBody] EnableModuleRequest request)
{
try
{
var subscription = await _moduleService.EnableModuleAsync(
code,
request.SubscriptionType,
request.StartDate,
request.EndDate,
request.AutoRenew,
request.PaidPrice,
request.Notes);
return Ok(MapSubscriptionToDto(subscription));
}
catch (ArgumentException ex)
{
return NotFound(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// Disattiva un modulo
/// </summary>
[HttpPut("{code}/disable")]
public async Task<ActionResult> DisableModule(string code)
{
try
{
await _moduleService.DisableModuleAsync(code);
return Ok(new { message = $"Modulo '{code}' disattivato" });
}
catch (ArgumentException ex)
{
return NotFound(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// Ottiene tutte le subscription
/// </summary>
[HttpGet("subscriptions")]
public async Task<ActionResult<List<SubscriptionDto>>> GetAllSubscriptions()
{
var subscriptions = await _moduleService.GetAllSubscriptionsAsync();
return Ok(subscriptions.Select(MapSubscriptionToDto).ToList());
}
/// <summary>
/// Aggiorna la subscription di un modulo
/// </summary>
[HttpPut("{code}/subscription")]
public async Task<ActionResult<SubscriptionDto>> UpdateSubscription(string code, [FromBody] UpdateSubscriptionRequest request)
{
try
{
var subscription = await _moduleService.UpdateSubscriptionAsync(
code,
request.SubscriptionType,
request.EndDate,
request.AutoRenew,
request.Notes);
return Ok(MapSubscriptionToDto(subscription));
}
catch (ArgumentException ex)
{
return NotFound(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// Rinnova la subscription di un modulo
/// </summary>
[HttpPost("{code}/subscription/renew")]
public async Task<ActionResult<SubscriptionDto>> RenewSubscription(string code, [FromBody] RenewSubscriptionRequest? request = null)
{
try
{
var subscription = await _moduleService.RenewSubscriptionAsync(code, request?.PaidPrice);
return Ok(MapSubscriptionToDto(subscription));
}
catch (ArgumentException ex)
{
return NotFound(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// Ottiene i moduli in scadenza
/// </summary>
[HttpGet("expiring")]
public async Task<ActionResult<List<ModuleDto>>> GetExpiringModules([FromQuery] int daysThreshold = 30)
{
var modules = await _moduleService.GetExpiringModulesAsync(daysThreshold);
return Ok(modules.Select(MapToDto).ToList());
}
/// <summary>
/// Inizializza i moduli di default (per setup iniziale)
/// </summary>
[HttpPost("seed")]
public async Task<ActionResult> SeedDefaultModules()
{
await _moduleService.SeedDefaultModulesAsync();
return Ok(new { message = "Moduli di default inizializzati" });
}
/// <summary>
/// Forza il controllo delle subscription scadute
/// </summary>
[HttpPost("check-expired")]
public async Task<ActionResult> CheckExpiredSubscriptions()
{
var count = await _moduleService.CheckExpiredSubscriptionsAsync();
return Ok(new { message = $"Controllate le subscription, {count} moduli disattivati per scadenza" });
}
/// <summary>
/// Invalida la cache dei moduli
/// </summary>
[HttpPost("invalidate-cache")]
public ActionResult InvalidateCache()
{
_moduleService.InvalidateCache();
return Ok(new { message = "Cache moduli invalidata" });
}
#region Mapping
private static ModuleDto MapToDto(AppModule module)
{
return new ModuleDto
{
Id = module.Id,
Code = module.Code,
Name = module.Name,
Description = module.Description,
Icon = module.Icon,
BasePrice = module.BasePrice,
MonthlyPrice = module.GetMonthlyPrice(),
MonthlyMultiplier = module.MonthlyMultiplier,
SortOrder = module.SortOrder,
IsCore = module.IsCore,
Dependencies = module.GetDependencies().ToList(),
RoutePath = module.RoutePath,
IsAvailable = module.IsAvailable,
IsEnabled = module.IsCore || ((module.Subscription?.IsEnabled ?? false) && (module.Subscription?.IsValid() ?? false)),
Subscription = module.Subscription != null ? MapSubscriptionToDto(module.Subscription) : null
};
}
private static SubscriptionDto MapSubscriptionToDto(ModuleSubscription subscription)
{
return new SubscriptionDto
{
Id = subscription.Id,
ModuleId = subscription.ModuleId,
ModuleCode = subscription.Module?.Code,
ModuleName = subscription.Module?.Name,
IsEnabled = subscription.IsEnabled,
SubscriptionType = subscription.SubscriptionType,
SubscriptionTypeName = subscription.SubscriptionType.ToString(),
StartDate = subscription.StartDate,
EndDate = subscription.EndDate,
AutoRenew = subscription.AutoRenew,
Notes = subscription.Notes,
LastRenewalDate = subscription.LastRenewalDate,
PaidPrice = subscription.PaidPrice,
IsValid = subscription.IsValid(),
DaysRemaining = subscription.GetDaysRemaining(),
IsExpiringSoon = subscription.IsExpiringSoon()
};
}
#endregion
}
#region DTOs
public class ModuleDto
{
public int Id { get; set; }
public string Code { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
public string? Icon { get; set; }
public decimal BasePrice { get; set; }
public decimal MonthlyPrice { get; set; }
public decimal MonthlyMultiplier { get; set; }
public int SortOrder { get; set; }
public bool IsCore { get; set; }
public List<string> Dependencies { get; set; } = new();
public string? RoutePath { get; set; }
public bool IsAvailable { get; set; }
public bool IsEnabled { get; set; }
public SubscriptionDto? Subscription { get; set; }
}
public class SubscriptionDto
{
public int Id { get; set; }
public int ModuleId { get; set; }
public string? ModuleCode { get; set; }
public string? ModuleName { get; set; }
public bool IsEnabled { get; set; }
public SubscriptionType SubscriptionType { get; set; }
public string SubscriptionTypeName { get; set; } = string.Empty;
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool AutoRenew { get; set; }
public string? Notes { get; set; }
public DateTime? LastRenewalDate { get; set; }
public decimal? PaidPrice { get; set; }
public bool IsValid { get; set; }
public int? DaysRemaining { get; set; }
public bool IsExpiringSoon { get; set; }
}
public class ModuleStatusDto
{
public string Code { get; set; } = string.Empty;
public bool IsEnabled { get; set; }
public bool HasValidSubscription { get; set; }
public bool IsCore { get; set; }
public int? DaysRemaining { get; set; }
public bool IsExpiringSoon { get; set; }
}
public class EnableModuleRequest
{
public SubscriptionType SubscriptionType { get; set; } = SubscriptionType.Annual;
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool AutoRenew { get; set; }
public decimal? PaidPrice { get; set; }
public string? Notes { get; set; }
}
public class UpdateSubscriptionRequest
{
public SubscriptionType? SubscriptionType { get; set; }
public DateTime? EndDate { get; set; }
public bool? AutoRenew { get; set; }
public string? Notes { get; set; }
}
public class RenewSubscriptionRequest
{
public decimal? PaidPrice { get; set; }
}
#endregion