353 lines
11 KiB
C#
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
|