Files
zentral/src/backend/Zentral.API/Controllers/AppsController.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 delle applicazioni e delle subscription
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class AppsController : ControllerBase
{
private readonly AppService _appService;
private readonly ILogger<AppsController> _logger;
public AppsController(AppService appService, ILogger<AppsController> logger)
{
_appService = appService;
_logger = logger;
}
/// <summary>
/// Ottiene tutte le applicazioni disponibili con stato subscription
/// </summary>
[HttpGet]
public async Task<ActionResult<List<AppDto>>> GetAllApps()
{
var apps = await _appService.GetAllAppsAsync();
return Ok(apps.Select(MapToDto).ToList());
}
/// <summary>
/// Ottiene solo le applicazioni attive (per costruzione menu)
/// </summary>
[HttpGet("active")]
public async Task<ActionResult<List<AppDto>>> GetActiveApps()
{
var apps = await _appService.GetActiveAppsAsync();
return Ok(apps.Select(MapToDto).ToList());
}
/// <summary>
/// Ottiene un'applicazione specifica per codice
/// </summary>
[HttpGet("{code}")]
public async Task<ActionResult<AppDto>> GetApp(string code)
{
var app = await _appService.GetAppByCodeAsync(code);
if (app == null)
return NotFound(new { message = $"Applicazione '{code}' non trovata" });
return Ok(MapToDto(app));
}
/// <summary>
/// Verifica se un'applicazione è abilitata
/// </summary>
[HttpGet("{code}/enabled")]
public async Task<ActionResult<AppStatusDto>> IsAppEnabled(string code)
{
var app = await _appService.GetAppByCodeAsync(code);
if (app == null)
return NotFound(new { message = $"Applicazione '{code}' non trovata" });
var isEnabled = await _appService.IsAppEnabledAsync(code);
var hasValidSubscription = await _appService.HasValidSubscriptionAsync(code);
return Ok(new AppStatusDto
{
Code = code,
IsEnabled = isEnabled,
HasValidSubscription = hasValidSubscription,
IsCore = app.IsCore,
DaysRemaining = app.Subscription?.GetDaysRemaining(),
IsExpiringSoon = app.Subscription?.IsExpiringSoon() ?? false
});
}
/// <summary>
/// Attiva un'applicazione
/// </summary>
[HttpPut("{code}/enable")]
public async Task<ActionResult<AppSubscriptionDto>> EnableApp(string code, [FromBody] EnableAppRequest request)
{
try
{
var subscription = await _appService.EnableAppAsync(
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'applicazione
/// </summary>
[HttpPut("{code}/disable")]
public async Task<ActionResult> DisableApp(string code)
{
try
{
await _appService.DisableAppAsync(code);
return Ok(new { message = $"Applicazione '{code}' disattivata" });
}
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<AppSubscriptionDto>>> GetAllAppSubscriptions()
{
var subscriptions = await _appService.GetAllSubscriptionsAsync();
return Ok(subscriptions.Select(MapSubscriptionToDto).ToList());
}
/// <summary>
/// Aggiorna la subscription di un'applicazione
/// </summary>
[HttpPut("{code}/subscription")]
public async Task<ActionResult<AppSubscriptionDto>> UpdateAppSubscription(string code, [FromBody] UpdateAppSubscriptionRequest request)
{
try
{
var subscription = await _appService.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'applicazione
/// </summary>
[HttpPost("{code}/subscription/renew")]
public async Task<ActionResult<AppSubscriptionDto>> RenewAppSubscription(string code, [FromBody] RenewAppSubscriptionRequest? request = null)
{
try
{
var subscription = await _appService.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 le applicazioni in scadenza
/// </summary>
[HttpGet("expiring")]
public async Task<ActionResult<List<AppDto>>> GetExpiringApps([FromQuery] int daysThreshold = 30)
{
var apps = await _appService.GetExpiringAppsAsync(daysThreshold);
return Ok(apps.Select(MapToDto).ToList());
}
/// <summary>
/// Inizializza le applicazioni di default (per setup iniziale)
/// </summary>
[HttpPost("seed")]
public async Task<ActionResult> SeedDefaultApps()
{
await _appService.SeedDefaultAppsAsync();
return Ok(new { message = "Applicazioni di default inizializzate" });
}
/// <summary>
/// Forza il controllo delle subscription scadute
/// </summary>
[HttpPost("check-expired")]
public async Task<ActionResult> CheckExpiredAppSubscriptions()
{
var count = await _appService.CheckExpiredSubscriptionsAsync();
return Ok(new { message = $"Controllate le subscription, {count} applicazioni disattivate per scadenza" });
}
/// <summary>
/// Invalida la cache delle applicazioni
/// </summary>
[HttpPost("invalidate-cache")]
public ActionResult InvalidateAppsCache()
{
_appService.InvalidateCache();
return Ok(new { message = "Cache applicazioni invalidata" });
}
#region Mapping
private static AppDto MapToDto(App app)
{
return new AppDto
{
Id = app.Id,
Code = app.Code,
Name = app.Name,
Description = app.Description,
Icon = app.Icon,
BasePrice = app.BasePrice,
MonthlyPrice = app.GetMonthlyPrice(),
MonthlyMultiplier = app.MonthlyMultiplier,
SortOrder = app.SortOrder,
IsCore = app.IsCore,
Dependencies = app.GetDependencies().ToList(),
RoutePath = app.RoutePath,
IsAvailable = app.IsAvailable,
IsEnabled = app.IsCore || ((app.Subscription?.IsEnabled ?? false) && (app.Subscription?.IsValid() ?? false)),
Subscription = app.Subscription != null ? MapSubscriptionToDto(app.Subscription) : null
};
}
private static AppSubscriptionDto MapSubscriptionToDto(AppSubscription subscription)
{
return new AppSubscriptionDto
{
Id = subscription.Id,
AppId = subscription.AppId,
AppCode = subscription.App?.Code,
AppName = subscription.App?.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 AppDto
{
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 AppSubscriptionDto? Subscription { get; set; }
}
public class AppSubscriptionDto
{
public int Id { get; set; }
public int AppId { get; set; }
public string? AppCode { get; set; }
public string? AppName { 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 AppStatusDto
{
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 EnableAppRequest
{
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 UpdateAppSubscriptionRequest
{
public SubscriptionType? SubscriptionType { get; set; }
public DateTime? EndDate { get; set; }
public bool? AutoRenew { get; set; }
public string? Notes { get; set; }
}
public class RenewAppSubscriptionRequest
{
public decimal? PaidPrice { get; set; }
}
#endregion