Add instance index + date update audit + ai quota to token
This commit is contained in:
parent
19a0157b19
commit
f2228617ca
@ -16,7 +16,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
{
|
{
|
||||||
public class AiControllerTests
|
public class AiControllerTests
|
||||||
{
|
{
|
||||||
private static readonly AiChatResponse FakeResponse = new AiChatResponse { Reply = "OK" };
|
private static readonly AiChatResponse FakeResponse = new AiChatResponse { Reply = "OK", TokensUsed = 42 };
|
||||||
|
|
||||||
private AiController BuildController(MyInfoMateDbContext db, Mock<IAssistantService>? mockService = null)
|
private AiController BuildController(MyInfoMateDbContext db, Mock<IAssistantService>? mockService = null)
|
||||||
{
|
{
|
||||||
@ -101,13 +101,13 @@ namespace ManagerService.Tests.Controllers
|
|||||||
// ── QUOTA COUNTER ────────────────────────────────────────────────────
|
// ── QUOTA COUNTER ────────────────────────────────────────────────────
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Chat_FirstRequestOfMonth_ResetsCounterAndSets1()
|
public async Task Chat_FirstRequestOfMonth_ResetsCounterAndAddsTokensUsed()
|
||||||
{
|
{
|
||||||
using var db = DbContextFactory.Create();
|
using var db = DbContextFactory.Create();
|
||||||
db.Instances.Add(new Instance
|
db.Instances.Add(new Instance
|
||||||
{
|
{
|
||||||
Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow,
|
Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow,
|
||||||
AiRequestsThisMonth = 99, AiUsageMonthKey = "2020-01"
|
AiTokensThisMonth = 99, AiUsageMonthKey = "2020-01"
|
||||||
});
|
});
|
||||||
db.ApplicationInstances.Add(new ApplicationInstance
|
db.ApplicationInstances.Add(new ApplicationInstance
|
||||||
{
|
{
|
||||||
@ -119,19 +119,19 @@ namespace ManagerService.Tests.Controllers
|
|||||||
await BuildController(db).Chat(MakeRequest("i1"));
|
await BuildController(db).Chat(MakeRequest("i1"));
|
||||||
|
|
||||||
var inst = db.Instances.First();
|
var inst = db.Instances.First();
|
||||||
Assert.Equal(1, inst.AiRequestsThisMonth);
|
Assert.Equal(42, inst.AiTokensThisMonth);
|
||||||
Assert.Equal(DateTime.UtcNow.ToString("yyyy-MM"), inst.AiUsageMonthKey);
|
Assert.Equal(DateTime.UtcNow.ToString("yyyy-MM"), inst.AiUsageMonthKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Chat_SameMonth_IncrementsCounter()
|
public async Task Chat_SameMonth_AddsTokensUsedToCounter()
|
||||||
{
|
{
|
||||||
using var db = DbContextFactory.Create();
|
using var db = DbContextFactory.Create();
|
||||||
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
||||||
db.Instances.Add(new Instance
|
db.Instances.Add(new Instance
|
||||||
{
|
{
|
||||||
Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow,
|
Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow,
|
||||||
AiRequestsThisMonth = 3, AiUsageMonthKey = monthKey
|
AiTokensThisMonth = 3, AiUsageMonthKey = monthKey
|
||||||
});
|
});
|
||||||
db.ApplicationInstances.Add(new ApplicationInstance
|
db.ApplicationInstances.Add(new ApplicationInstance
|
||||||
{
|
{
|
||||||
@ -142,7 +142,34 @@ namespace ManagerService.Tests.Controllers
|
|||||||
|
|
||||||
await BuildController(db).Chat(MakeRequest("i1"));
|
await BuildController(db).Chat(MakeRequest("i1"));
|
||||||
|
|
||||||
Assert.Equal(4, db.Instances.First().AiRequestsThisMonth);
|
Assert.Equal(45, db.Instances.First().AiTokensThisMonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Chat_QuotaAlreadyReached_ReturnsTooManyRequestsWithoutCallingAssistantService()
|
||||||
|
{
|
||||||
|
using var db = DbContextFactory.Create();
|
||||||
|
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
||||||
|
db.Instances.Add(new Instance
|
||||||
|
{
|
||||||
|
Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow,
|
||||||
|
AiTokensThisMonth = 100, AiTokensPerMonth = 100, AiUsageMonthKey = monthKey
|
||||||
|
});
|
||||||
|
db.ApplicationInstances.Add(new ApplicationInstance
|
||||||
|
{
|
||||||
|
Id = "ai1", InstanceId = "i1", AppType = AppType.Tablet, IsAssistant = true,
|
||||||
|
Languages = new List<string>()
|
||||||
|
});
|
||||||
|
db.SaveChanges();
|
||||||
|
|
||||||
|
var mockService = new Mock<IAssistantService>();
|
||||||
|
mockService.Setup(s => s.ChatAsync(It.IsAny<AiChatRequest>())).ReturnsAsync(FakeResponse);
|
||||||
|
|
||||||
|
var result = await BuildController(db, mockService).Chat(MakeRequest("i1"));
|
||||||
|
|
||||||
|
var status = Assert.IsType<ObjectResult>(result);
|
||||||
|
Assert.Equal(429, status.StatusCode);
|
||||||
|
mockService.Verify(s => s.ChatAsync(It.IsAny<AiChatRequest>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── NOMINAL ──────────────────────────────────────────────────────────
|
// ── NOMINAL ──────────────────────────────────────────────────────────
|
||||||
|
|||||||
@ -130,7 +130,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
var ok = Assert.IsType<OkObjectResult>(result);
|
var ok = Assert.IsType<OkObjectResult>(result);
|
||||||
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
||||||
Assert.Equal(0, dto.storageQuotaBytes);
|
Assert.Equal(0, dto.storageQuotaBytes);
|
||||||
Assert.Equal(0, dto.aiRequestsPerMonth);
|
Assert.Equal(0, dto.aiTokensPerMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -141,7 +141,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
{
|
{
|
||||||
Id = "p1", Name = "Standard",
|
Id = "p1", Name = "Standard",
|
||||||
StorageQuotaBytes = 10_000_000_000L,
|
StorageQuotaBytes = 10_000_000_000L,
|
||||||
AiRequestsPerMonth = 100
|
AiTokensPerMonth = 100
|
||||||
});
|
});
|
||||||
db.Instances.Add(new Instance
|
db.Instances.Add(new Instance
|
||||||
{
|
{
|
||||||
@ -154,7 +154,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
var ok = Assert.IsType<OkObjectResult>(result);
|
var ok = Assert.IsType<OkObjectResult>(result);
|
||||||
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
||||||
Assert.Equal(10_000_000_000L, dto.storageQuotaBytes);
|
Assert.Equal(10_000_000_000L, dto.storageQuotaBytes);
|
||||||
Assert.Equal(100, dto.aiRequestsPerMonth);
|
Assert.Equal(100, dto.aiTokensPerMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -184,7 +184,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
db.Instances.Add(new Instance
|
db.Instances.Add(new Instance
|
||||||
{
|
{
|
||||||
Id = "i1", Name = "Musée", DateCreation = DateTime.UtcNow,
|
Id = "i1", Name = "Musée", DateCreation = DateTime.UtcNow,
|
||||||
AiRequestsThisMonth = 7, AiUsageMonthKey = monthKey
|
AiTokensThisMonth = 7, AiUsageMonthKey = monthKey
|
||||||
});
|
});
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
|
|
||||||
var ok = Assert.IsType<OkObjectResult>(result);
|
var ok = Assert.IsType<OkObjectResult>(result);
|
||||||
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
||||||
Assert.Equal(7, dto.aiRequestsUsed);
|
Assert.Equal(7, dto.aiTokensUsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -202,7 +202,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
db.Instances.Add(new Instance
|
db.Instances.Add(new Instance
|
||||||
{
|
{
|
||||||
Id = "i1", Name = "Musée", DateCreation = DateTime.UtcNow,
|
Id = "i1", Name = "Musée", DateCreation = DateTime.UtcNow,
|
||||||
AiRequestsThisMonth = 7, AiUsageMonthKey = "2020-01"
|
AiTokensThisMonth = 7, AiUsageMonthKey = "2020-01"
|
||||||
});
|
});
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
|
|
||||||
var ok = Assert.IsType<OkObjectResult>(result);
|
var ok = Assert.IsType<OkObjectResult>(result);
|
||||||
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
var dto = Assert.IsType<InstanceQuotaDTO>(ok.Value);
|
||||||
Assert.Equal(0, dto.aiRequestsUsed);
|
Assert.Equal(0, dto.aiTokensUsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── DELETE ───────────────────────────────────────────────────────────
|
// ── DELETE ───────────────────────────────────────────────────────────
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
using var db = DbContextFactory.Create();
|
using var db = DbContextFactory.Create();
|
||||||
db.SubscriptionPlans.Add(new SubscriptionPlan
|
db.SubscriptionPlans.Add(new SubscriptionPlan
|
||||||
{
|
{
|
||||||
Id = "p1", Name = "Starter", StorageQuotaBytes = 1024, AiRequestsPerMonth = 50
|
Id = "p1", Name = "Starter", StorageQuotaBytes = 1024, AiTokensPerMonth = 50
|
||||||
});
|
});
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
var dto = Assert.IsType<SubscriptionPlanDTO>(ok.Value);
|
var dto = Assert.IsType<SubscriptionPlanDTO>(ok.Value);
|
||||||
Assert.Equal("Starter", dto.name);
|
Assert.Equal("Starter", dto.name);
|
||||||
Assert.Equal(1024, dto.storageQuotaBytes);
|
Assert.Equal(1024, dto.storageQuotaBytes);
|
||||||
Assert.Equal(50, dto.aiRequestsPerMonth);
|
Assert.Equal(50, dto.aiTokensPerMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -67,7 +67,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
public void Create_ValidDto_PersistsAndReturnsDto()
|
public void Create_ValidDto_PersistsAndReturnsDto()
|
||||||
{
|
{
|
||||||
using var db = DbContextFactory.Create();
|
using var db = DbContextFactory.Create();
|
||||||
var dto = new SubscriptionPlanDTO { name = "Premium", storageQuotaBytes = 5000, aiRequestsPerMonth = 100 };
|
var dto = new SubscriptionPlanDTO { name = "Premium", storageQuotaBytes = 5000, aiTokensPerMonth = 100 };
|
||||||
|
|
||||||
var result = BuildController(db).Create(dto);
|
var result = BuildController(db).Create(dto);
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ namespace ManagerService.Tests.Controllers
|
|||||||
db.SubscriptionPlans.Add(new SubscriptionPlan { Id = "p1", Name = "Old" });
|
db.SubscriptionPlans.Add(new SubscriptionPlan { Id = "p1", Name = "Old" });
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
var result = BuildController(db).Update(new SubscriptionPlanDTO { id = "p1", name = "New", storageQuotaBytes = 0, aiRequestsPerMonth = 0 });
|
var result = BuildController(db).Update(new SubscriptionPlanDTO { id = "p1", name = "New", storageQuotaBytes = 0, aiTokensPerMonth = 0 });
|
||||||
|
|
||||||
Assert.IsType<OkObjectResult>(result);
|
Assert.IsType<OkObjectResult>(result);
|
||||||
Assert.Equal("New", db.SubscriptionPlans.First().Name);
|
Assert.Equal("New", db.SubscriptionPlans.First().Name);
|
||||||
|
|||||||
@ -58,18 +58,20 @@ namespace ManagerService.Controllers
|
|||||||
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
||||||
if (instance.AiUsageMonthKey != monthKey)
|
if (instance.AiUsageMonthKey != monthKey)
|
||||||
{
|
{
|
||||||
instance.AiRequestsThisMonth = 0;
|
instance.AiTokensThisMonth = 0;
|
||||||
instance.AiUsageMonthKey = monthKey;
|
instance.AiUsageMonthKey = monthKey;
|
||||||
|
_context.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
var quota = instance.AiRequestsPerMonth;
|
var quota = instance.AiTokensPerMonth;
|
||||||
if (quota > 0 && instance.AiRequestsThisMonth >= quota)
|
if (quota > 0 && instance.AiTokensThisMonth >= quota)
|
||||||
return StatusCode(429, "Quota IA mensuel dépassé");
|
return StatusCode(429, "Quota IA mensuel dépassé");
|
||||||
|
|
||||||
instance.AiRequestsThisMonth++;
|
var result = await _assistantService.TranslateAsync(request);
|
||||||
|
|
||||||
|
instance.AiTokensThisMonth += result.TokensUsed;
|
||||||
_context.SaveChanges();
|
_context.SaveChanges();
|
||||||
|
|
||||||
var result = await _assistantService.TranslateAsync(request);
|
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -110,18 +112,20 @@ namespace ManagerService.Controllers
|
|||||||
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
||||||
if (instance.AiUsageMonthKey != monthKey)
|
if (instance.AiUsageMonthKey != monthKey)
|
||||||
{
|
{
|
||||||
instance.AiRequestsThisMonth = 0;
|
instance.AiTokensThisMonth = 0;
|
||||||
instance.AiUsageMonthKey = monthKey;
|
instance.AiUsageMonthKey = monthKey;
|
||||||
|
_context.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
var quota = instance.AiRequestsPerMonth;
|
var quota = instance.AiTokensPerMonth;
|
||||||
if (quota > 0 && instance.AiRequestsThisMonth >= quota)
|
if (quota > 0 && instance.AiTokensThisMonth >= quota)
|
||||||
return StatusCode(429, "Quota IA mensuel dépassé");
|
return StatusCode(429, "Quota IA mensuel dépassé");
|
||||||
|
|
||||||
instance.AiRequestsThisMonth++;
|
var result = await _assistantService.ChatAsync(request);
|
||||||
|
|
||||||
|
instance.AiTokensThisMonth += result.TokensUsed;
|
||||||
_context.SaveChanges();
|
_context.SaveChanges();
|
||||||
|
|
||||||
var result = await _assistantService.ChatAsync(request);
|
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@ -48,8 +48,8 @@ namespace ManagerService.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a list of all configuration (summary)
|
/// Get a list of all configuration (summary)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">id instance</param>
|
/// <param name="id">id instance</param>
|
||||||
[Authorize(Policy = ManagerService.Service.Security.Policies.AppReadAccess)]
|
[AllowAnonymous]
|
||||||
[ProducesResponseType(typeof(List<ConfigurationDTO>), 200)]
|
[ProducesResponseType(typeof(List<ConfigurationDTO>), 200)]
|
||||||
[ProducesResponseType(typeof(string), 500)]
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@ -113,8 +113,8 @@ namespace ManagerService.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a specific display configuration
|
/// Get a specific display configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">id configuration</param>
|
/// <param name="id">id configuration</param>
|
||||||
[Authorize(Policy = ManagerService.Service.Security.Policies.AppReadAccess)]
|
[AllowAnonymous]
|
||||||
[ProducesResponseType(typeof(ConfigurationDTO), 200)]
|
[ProducesResponseType(typeof(ConfigurationDTO), 200)]
|
||||||
[ProducesResponseType(typeof(string), 404)]
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
[ProducesResponseType(typeof(string), 500)]
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
|||||||
@ -123,7 +123,7 @@ namespace ManagerService.Controllers
|
|||||||
if (plan != null)
|
if (plan != null)
|
||||||
{
|
{
|
||||||
instance.StorageQuotaBytes = plan.StorageQuotaBytes;
|
instance.StorageQuotaBytes = plan.StorageQuotaBytes;
|
||||||
instance.AiRequestsPerMonth = plan.AiRequestsPerMonth;
|
instance.AiTokensPerMonth = plan.AiTokensPerMonth;
|
||||||
instance.HasStats = plan.HasStats;
|
instance.HasStats = plan.HasStats;
|
||||||
instance.StatsHistoryDays = plan.StatsHistoryDays;
|
instance.StatsHistoryDays = plan.StatsHistoryDays;
|
||||||
instance.HasAdvancedStats = plan.HasAdvancedStats;
|
instance.HasAdvancedStats = plan.HasAdvancedStats;
|
||||||
@ -338,10 +338,10 @@ namespace ManagerService.Controllers
|
|||||||
.Sum(r => (long?)r.SizeBytes) ?? 0;
|
.Sum(r => (long?)r.SizeBytes) ?? 0;
|
||||||
|
|
||||||
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
var monthKey = DateTime.UtcNow.ToString("yyyy-MM");
|
||||||
var aiUsed = instance.AiUsageMonthKey == monthKey ? instance.AiRequestsThisMonth : 0;
|
var aiUsed = instance.AiUsageMonthKey == monthKey ? instance.AiTokensThisMonth : 0;
|
||||||
|
|
||||||
var storageQuota = instance.StorageQuotaBytes;
|
var storageQuota = instance.StorageQuotaBytes;
|
||||||
var aiQuota = instance.AiRequestsPerMonth;
|
var aiQuota = instance.AiTokensPerMonth;
|
||||||
|
|
||||||
if ((storageQuota == 0 || aiQuota == 0) && instance.SubscriptionPlanId != null)
|
if ((storageQuota == 0 || aiQuota == 0) && instance.SubscriptionPlanId != null)
|
||||||
{
|
{
|
||||||
@ -349,7 +349,7 @@ namespace ManagerService.Controllers
|
|||||||
if (plan != null)
|
if (plan != null)
|
||||||
{
|
{
|
||||||
if (storageQuota == 0) storageQuota = plan.StorageQuotaBytes;
|
if (storageQuota == 0) storageQuota = plan.StorageQuotaBytes;
|
||||||
if (aiQuota == 0) aiQuota = plan.AiRequestsPerMonth;
|
if (aiQuota == 0) aiQuota = plan.AiTokensPerMonth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,8 +357,8 @@ namespace ManagerService.Controllers
|
|||||||
{
|
{
|
||||||
storageUsedBytes = storageUsed,
|
storageUsedBytes = storageUsed,
|
||||||
storageQuotaBytes = storageQuota,
|
storageQuotaBytes = storageQuota,
|
||||||
aiRequestsUsed = aiUsed,
|
aiTokensUsed = aiUsed,
|
||||||
aiRequestsPerMonth = aiQuota
|
aiTokensPerMonth = aiQuota
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@ -851,7 +851,6 @@ namespace ManagerService.Controllers
|
|||||||
[HttpPut("order")]
|
[HttpPut("order")]
|
||||||
public ObjectResult UpdateOrder([FromBody] List<SectionDTO> updatedSectionsOrder)
|
public ObjectResult UpdateOrder([FromBody] List<SectionDTO> updatedSectionsOrder)
|
||||||
{
|
{
|
||||||
// TODO REWRITE LOGIC..
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (updatedSectionsOrder == null)
|
if (updatedSectionsOrder == null)
|
||||||
@ -864,16 +863,42 @@ namespace ManagerService.Controllers
|
|||||||
throw new KeyNotFoundException($"Section {section.label} with id {section.id} does not exist");
|
throw new KeyNotFoundException($"Section {section.label} with id {section.id} does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var updatedSection in updatedSectionsOrder)
|
// The client may only send a subset of the configuration's sections (e.g. a filtered
|
||||||
|
// reorder view) — renormalize against the full top-level set so `Order` always stays
|
||||||
|
// 0-based and contiguous, instead of blindly writing the payload's values.
|
||||||
|
foreach (var configurationId in updatedSectionsOrder.Select(s => s.configurationId).Distinct())
|
||||||
{
|
{
|
||||||
var section = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == updatedSection.id);
|
var baseline = _myInfoMateDbContext.Sections
|
||||||
//OldSection section = _sectionService.GetById(updatedSection.id);
|
.Where(s => s.ConfigurationId == configurationId && !s.IsSubSection)
|
||||||
section.Order = updatedSection.order.GetValueOrDefault();
|
.OrderBy(s => s.Order)
|
||||||
_myInfoMateDbContext.SaveChanges();
|
.ToList();
|
||||||
|
|
||||||
//_sectionService.Update(section.Id, section);
|
var includedIds = updatedSectionsOrder
|
||||||
|
.Where(s => s.configurationId == configurationId)
|
||||||
|
.Select(s => s.id)
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
var newSubsequence = updatedSectionsOrder
|
||||||
|
.Where(s => s.configurationId == configurationId)
|
||||||
|
.OrderBy(s => s.order.GetValueOrDefault())
|
||||||
|
.Select(s => baseline.First(b => b.Id == s.id))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var slots = baseline
|
||||||
|
.Select((section, index) => (section, index))
|
||||||
|
.Where(t => includedIds.Contains(t.section.Id))
|
||||||
|
.Select(t => t.index)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
for (int k = 0; k < slots.Count; k++)
|
||||||
|
baseline[slots[k]] = newSubsequence[k];
|
||||||
|
|
||||||
|
for (int i = 0; i < baseline.Count; i++)
|
||||||
|
baseline[i].Order = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_myInfoMateDbContext.SaveChanges();
|
||||||
|
|
||||||
if (updatedSectionsOrder.Count > 0) {
|
if (updatedSectionsOrder.Count > 0) {
|
||||||
MqttClientService.PublishMessage($"config/{updatedSectionsOrder[0].configurationId}", JsonConvert.SerializeObject(new PlayerMessageDTO() { configChanged = true }));
|
MqttClientService.PublishMessage($"config/{updatedSectionsOrder[0].configurationId}", JsonConvert.SerializeObject(new PlayerMessageDTO() { configChanged = true }));
|
||||||
}
|
}
|
||||||
@ -975,7 +1000,7 @@ namespace ManagerService.Controllers
|
|||||||
var configuration = _myInfoMateDbContext.Configurations.FirstOrDefault(c => c.Id == section.ConfigurationId);
|
var configuration = _myInfoMateDbContext.Configurations.FirstOrDefault(c => c.Id == section.ConfigurationId);
|
||||||
|
|
||||||
List<Section> sections = _myInfoMateDbContext.Sections.Where(s => s.ConfigurationId == section.ConfigurationId && !s.IsSubSection).ToList();
|
List<Section> sections = _myInfoMateDbContext.Sections.Where(s => s.ConfigurationId == section.ConfigurationId && !s.IsSubSection).ToList();
|
||||||
int i = 1;
|
int i = 0;
|
||||||
List<Section> orderedSection = sections.OrderBy(s => s.Order).ToList();
|
List<Section> orderedSection = sections.OrderBy(s => s.Order).ToList();
|
||||||
foreach (var sectionDb in orderedSection)
|
foreach (var sectionDb in orderedSection)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -50,6 +50,7 @@ namespace ManagerService.DTOs
|
|||||||
/// Le front peut désactiver l'écoute automatique après le TTS.
|
/// Le front peut désactiver l'écoute automatique après le TTS.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ExpectsReply { get; set; } = true;
|
public bool ExpectsReply { get; set; } = true;
|
||||||
|
public long TokensUsed { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AiTranslateRequest
|
public class AiTranslateRequest
|
||||||
@ -62,5 +63,6 @@ namespace ManagerService.DTOs
|
|||||||
public class AiTranslateResponse
|
public class AiTranslateResponse
|
||||||
{
|
{
|
||||||
public Dictionary<string, string> Translations { get; set; } = new();
|
public Dictionary<string, string> Translations { get; set; } = new();
|
||||||
|
public long TokensUsed { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,10 +23,10 @@ namespace ManagerService.DTOs
|
|||||||
|
|
||||||
public string? subscriptionPlanId { get; set; }
|
public string? subscriptionPlanId { get; set; }
|
||||||
public SubscriptionPlanDTO? subscriptionPlan { get; set; }
|
public SubscriptionPlanDTO? subscriptionPlan { get; set; }
|
||||||
public int? aiRequestsThisMonth { get; set; }
|
public long? aiTokensThisMonth { get; set; }
|
||||||
public string? aiUsageMonthKey { get; set; }
|
public string? aiUsageMonthKey { get; set; }
|
||||||
public long? storageQuotaBytes { get; set; }
|
public long? storageQuotaBytes { get; set; }
|
||||||
public int? aiRequestsPerMonth { get; set; }
|
public long? aiTokensPerMonth { get; set; }
|
||||||
public bool? hasStats { get; set; }
|
public bool? hasStats { get; set; }
|
||||||
public int? statsHistoryDays { get; set; }
|
public int? statsHistoryDays { get; set; }
|
||||||
public bool? hasAdvancedStats { get; set; }
|
public bool? hasAdvancedStats { get; set; }
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace ManagerService.DTOs
|
|||||||
{
|
{
|
||||||
public long storageUsedBytes { get; set; }
|
public long storageUsedBytes { get; set; }
|
||||||
public long storageQuotaBytes { get; set; }
|
public long storageQuotaBytes { get; set; }
|
||||||
public int aiRequestsUsed { get; set; }
|
public long aiTokensUsed { get; set; }
|
||||||
public int aiRequestsPerMonth { get; set; }
|
public long aiTokensPerMonth { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace ManagerService.DTOs
|
|||||||
public string? id { get; set; }
|
public string? id { get; set; }
|
||||||
public string name { get; set; }
|
public string name { get; set; }
|
||||||
public long storageQuotaBytes { get; set; }
|
public long storageQuotaBytes { get; set; }
|
||||||
public int aiRequestsPerMonth { get; set; }
|
public long aiTokensPerMonth { get; set; }
|
||||||
public bool hasStats { get; set; }
|
public bool hasStats { get; set; }
|
||||||
public int statsHistoryDays { get; set; }
|
public int statsHistoryDays { get; set; }
|
||||||
public bool hasAdvancedStats { get; set; }
|
public bool hasAdvancedStats { get; set; }
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations;
|
|||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
public class ApiKey
|
public class ApiKey : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
@ -28,6 +28,8 @@ namespace ManagerService.Data
|
|||||||
|
|
||||||
public DateTime DateCreation { get; set; }
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
public DateTime? DateExpiration { get; set; }
|
public DateTime? DateExpiration { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,11 +13,15 @@ namespace ManagerService.Data
|
|||||||
/// application instances, optionally with an order or active status.
|
/// application instances, optionally with an order or active status.
|
||||||
/// Useful for managing configuration assignment and display logic per app type.
|
/// Useful for managing configuration assignment and display logic per app type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AppConfigurationLink
|
public class AppConfigurationLink : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public string ConfigurationId { get; set; }
|
public string ConfigurationId { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -2,18 +2,21 @@
|
|||||||
using ManagerService.Data.SubSection;
|
using ManagerService.Data.SubSection;
|
||||||
using ManagerService.DTOs;
|
using ManagerService.DTOs;
|
||||||
using ManagerService.Services;
|
using ManagerService.Services;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the link between an application instance and a configuration,
|
/// Defines the link between an application instance and a configuration,
|
||||||
/// allowing apps to use one or multiple configurations.
|
/// allowing apps to use one or multiple configurations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ApplicationInstance
|
[Index(nameof(InstanceId))]
|
||||||
|
public class ApplicationInstance : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
@ -21,6 +24,10 @@ namespace ManagerService.Data
|
|||||||
[Required]
|
[Required]
|
||||||
public string InstanceId { get; set; }
|
public string InstanceId { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public AppType AppType { get; set; }
|
public AppType AppType { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
|
[Index(nameof(InstanceId))]
|
||||||
public class AuditLog
|
public class AuditLog
|
||||||
{
|
{
|
||||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||||
|
|||||||
@ -5,13 +5,15 @@ using System.ComponentModel.DataAnnotations;
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configuration Information
|
/// Configuration Information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Configuration
|
[Index(nameof(InstanceId))]
|
||||||
|
public class Configuration : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Required]
|
[Required]
|
||||||
@ -39,6 +41,8 @@ namespace ManagerService.Data
|
|||||||
|
|
||||||
public DateTime DateCreation { get; set; }
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
public bool IsOffline { get; set; }
|
public bool IsOffline { get; set; }
|
||||||
|
|
||||||
public string LoaderImageId { get; set; } // Config can have their specific loader if needed
|
public string LoaderImageId { get; set; } // Config can have their specific loader if needed
|
||||||
|
|||||||
@ -2,13 +2,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Device Information (Tablet)
|
/// Device Information (Tablet)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Device
|
[Index(nameof(InstanceId))]
|
||||||
|
public class Device : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Required]
|
[Required]
|
||||||
|
|||||||
10
ManagerService/Data/IAuditableEntity.cs
Normal file
10
ManagerService/Data/IAuditableEntity.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ManagerService.Data
|
||||||
|
{
|
||||||
|
public interface IAuditableEntity
|
||||||
|
{
|
||||||
|
DateTime DateCreation { get; set; }
|
||||||
|
DateTime DateUpdate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@ namespace ManagerService.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instance Information
|
/// Instance Information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Instance
|
public class Instance : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Required]
|
[Required]
|
||||||
@ -20,6 +20,8 @@ namespace ManagerService.Data
|
|||||||
|
|
||||||
public DateTime DateCreation { get; set; }
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
public string PinCode { get; set; }
|
public string PinCode { get; set; }
|
||||||
|
|
||||||
public bool IsPushNotification { get; set; }
|
public bool IsPushNotification { get; set; }
|
||||||
@ -43,13 +45,13 @@ namespace ManagerService.Data
|
|||||||
[ForeignKey("SubscriptionPlanId")]
|
[ForeignKey("SubscriptionPlanId")]
|
||||||
public SubscriptionPlan? SubscriptionPlan { get; set; }
|
public SubscriptionPlan? SubscriptionPlan { get; set; }
|
||||||
|
|
||||||
public int AiRequestsThisMonth { get; set; } = 0;
|
public long AiTokensThisMonth { get; set; } = 0;
|
||||||
|
|
||||||
public string AiUsageMonthKey { get; set; } = "";
|
public string AiUsageMonthKey { get; set; } = "";
|
||||||
|
|
||||||
public long StorageQuotaBytes { get; set; } = 0;
|
public long StorageQuotaBytes { get; set; } = 0;
|
||||||
|
|
||||||
public int AiRequestsPerMonth { get; set; } = 0;
|
public long AiTokensPerMonth { get; set; } = 0;
|
||||||
|
|
||||||
public bool HasStats { get; set; } = false;
|
public bool HasStats { get; set; } = false;
|
||||||
|
|
||||||
@ -76,10 +78,10 @@ namespace ManagerService.Data
|
|||||||
publicApiKey = PublicApiKey,
|
publicApiKey = PublicApiKey,
|
||||||
subscriptionPlanId = SubscriptionPlanId,
|
subscriptionPlanId = SubscriptionPlanId,
|
||||||
subscriptionPlan = SubscriptionPlan?.ToDTO(),
|
subscriptionPlan = SubscriptionPlan?.ToDTO(),
|
||||||
aiRequestsThisMonth = AiRequestsThisMonth,
|
aiTokensThisMonth = AiTokensThisMonth,
|
||||||
aiUsageMonthKey = AiUsageMonthKey,
|
aiUsageMonthKey = AiUsageMonthKey,
|
||||||
storageQuotaBytes = StorageQuotaBytes,
|
storageQuotaBytes = StorageQuotaBytes,
|
||||||
aiRequestsPerMonth = AiRequestsPerMonth,
|
aiTokensPerMonth = AiTokensPerMonth,
|
||||||
hasStats = HasStats,
|
hasStats = HasStats,
|
||||||
statsHistoryDays = StatsHistoryDays,
|
statsHistoryDays = StatsHistoryDays,
|
||||||
hasAdvancedStats = HasAdvancedStats,
|
hasAdvancedStats = HasAdvancedStats,
|
||||||
@ -106,8 +108,8 @@ namespace ManagerService.Data
|
|||||||
SubscriptionPlanId = instanceDTO.subscriptionPlanId;
|
SubscriptionPlanId = instanceDTO.subscriptionPlanId;
|
||||||
if (instanceDTO.storageQuotaBytes.HasValue)
|
if (instanceDTO.storageQuotaBytes.HasValue)
|
||||||
StorageQuotaBytes = instanceDTO.storageQuotaBytes.Value;
|
StorageQuotaBytes = instanceDTO.storageQuotaBytes.Value;
|
||||||
if (instanceDTO.aiRequestsPerMonth.HasValue)
|
if (instanceDTO.aiTokensPerMonth.HasValue)
|
||||||
AiRequestsPerMonth = instanceDTO.aiRequestsPerMonth.Value;
|
AiTokensPerMonth = instanceDTO.aiTokensPerMonth.Value;
|
||||||
if (instanceDTO.hasStats.HasValue)
|
if (instanceDTO.hasStats.HasValue)
|
||||||
HasStats = instanceDTO.hasStats.Value;
|
HasStats = instanceDTO.hasStats.Value;
|
||||||
if (instanceDTO.statsHistoryDays.HasValue)
|
if (instanceDTO.statsHistoryDays.HasValue)
|
||||||
|
|||||||
@ -64,8 +64,19 @@ namespace ManagerService.Data
|
|||||||
// Audit
|
// Audit
|
||||||
public DbSet<AuditLog> AuditLogs { get; set; }
|
public DbSet<AuditLog> AuditLogs { get; set; }
|
||||||
|
|
||||||
|
public override int SaveChanges(bool acceptAllChangesOnSuccess)
|
||||||
|
{
|
||||||
|
StampAuditableEntities();
|
||||||
|
var auditEntries = BuildAuditEntries();
|
||||||
|
var result = base.SaveChanges(acceptAllChangesOnSuccess);
|
||||||
|
if (auditEntries.Any())
|
||||||
|
base.SaveChanges(acceptAllChangesOnSuccess);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
StampAuditableEntities();
|
||||||
var auditEntries = BuildAuditEntries();
|
var auditEntries = BuildAuditEntries();
|
||||||
var result = await base.SaveChangesAsync(cancellationToken);
|
var result = await base.SaveChangesAsync(cancellationToken);
|
||||||
if (auditEntries.Any())
|
if (auditEntries.Any())
|
||||||
@ -73,6 +84,18 @@ namespace ManagerService.Data
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void StampAuditableEntities()
|
||||||
|
{
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
foreach (var entry in ChangeTracker.Entries<IAuditableEntity>())
|
||||||
|
{
|
||||||
|
if (entry.State == EntityState.Added)
|
||||||
|
entry.Entity.DateCreation = now;
|
||||||
|
if (entry.State is EntityState.Added or EntityState.Modified)
|
||||||
|
entry.Entity.DateUpdate = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly HashSet<Type> AuditedTypes = new()
|
private static readonly HashSet<Type> AuditedTypes = new()
|
||||||
{
|
{
|
||||||
typeof(Section), typeof(Resource), typeof(Configuration),
|
typeof(Section), typeof(Resource), typeof(Configuration),
|
||||||
@ -399,7 +422,7 @@ namespace ManagerService.Data
|
|||||||
modelBuilder.Entity<Instance>()
|
modelBuilder.Entity<Instance>()
|
||||||
.Property(i => i.StorageQuotaBytes).ValueGeneratedNever();
|
.Property(i => i.StorageQuotaBytes).ValueGeneratedNever();
|
||||||
modelBuilder.Entity<Instance>()
|
modelBuilder.Entity<Instance>()
|
||||||
.Property(i => i.AiRequestsPerMonth).ValueGeneratedNever();
|
.Property(i => i.AiTokensPerMonth).ValueGeneratedNever();
|
||||||
modelBuilder.Entity<Instance>()
|
modelBuilder.Entity<Instance>()
|
||||||
.Property(i => i.HasStats).ValueGeneratedNever();
|
.Property(i => i.HasStats).ValueGeneratedNever();
|
||||||
modelBuilder.Entity<Instance>()
|
modelBuilder.Entity<Instance>()
|
||||||
@ -414,7 +437,7 @@ namespace ManagerService.Data
|
|||||||
Id = "plan-starter",
|
Id = "plan-starter",
|
||||||
Name = "Starter",
|
Name = "Starter",
|
||||||
StorageQuotaBytes = 1L * 1024 * 1024 * 1024, // 1 GB
|
StorageQuotaBytes = 1L * 1024 * 1024 * 1024, // 1 GB
|
||||||
AiRequestsPerMonth = 0,
|
AiTokensPerMonth = 0,
|
||||||
HasStats = false,
|
HasStats = false,
|
||||||
StatsHistoryDays = 30,
|
StatsHistoryDays = 30,
|
||||||
HasAdvancedStats = false,
|
HasAdvancedStats = false,
|
||||||
@ -424,7 +447,7 @@ namespace ManagerService.Data
|
|||||||
Id = "plan-standard",
|
Id = "plan-standard",
|
||||||
Name = "Standard",
|
Name = "Standard",
|
||||||
StorageQuotaBytes = 10L * 1024 * 1024 * 1024, // 10 GB
|
StorageQuotaBytes = 10L * 1024 * 1024 * 1024, // 10 GB
|
||||||
AiRequestsPerMonth = 500,
|
AiTokensPerMonth = 5_000_000, // ~500 req/mois * ~10k tokens/req estimés, à ajuster selon l'usage réel observé
|
||||||
HasStats = true,
|
HasStats = true,
|
||||||
StatsHistoryDays = 30,
|
StatsHistoryDays = 30,
|
||||||
HasAdvancedStats = false,
|
HasAdvancedStats = false,
|
||||||
@ -434,7 +457,7 @@ namespace ManagerService.Data
|
|||||||
Id = "plan-premium",
|
Id = "plan-premium",
|
||||||
Name = "Premium",
|
Name = "Premium",
|
||||||
StorageQuotaBytes = 50L * 1024 * 1024 * 1024, // 50 GB
|
StorageQuotaBytes = 50L * 1024 * 1024 * 1024, // 50 GB
|
||||||
AiRequestsPerMonth = 2000,
|
AiTokensPerMonth = 20_000_000, // ~2000 req/mois * ~10k tokens/req estimés, à ajuster selon l'usage réel observé
|
||||||
HasStats = true,
|
HasStats = true,
|
||||||
StatsHistoryDays = 0,
|
StatsHistoryDays = 0,
|
||||||
HasAdvancedStats = true,
|
HasAdvancedStats = true,
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
using ManagerService.DTOs;
|
using ManagerService.DTOs;
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resource Information
|
/// Resource Information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Resource
|
[Index(nameof(InstanceId))]
|
||||||
|
public class Resource : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Required]
|
[Required]
|
||||||
@ -28,6 +30,8 @@ namespace ManagerService.Data
|
|||||||
/*[BsonElement("DateCreation")]*/
|
/*[BsonElement("DateCreation")]*/
|
||||||
public DateTime DateCreation { get; set; }
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
/*[BsonElement("InstanceId")]
|
/*[BsonElement("InstanceId")]
|
||||||
[BsonRequired]*/
|
[BsonRequired]*/
|
||||||
[Required]
|
[Required]
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
@ -10,7 +11,8 @@ namespace ManagerService.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Section Information
|
/// Section Information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Section
|
[Index(nameof(InstanceId))]
|
||||||
|
public class Section : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Required]
|
[Required]
|
||||||
@ -45,6 +47,8 @@ namespace ManagerService.Data
|
|||||||
|
|
||||||
public DateTime DateCreation { get; set; }
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public string InstanceId { get; set; }
|
public string InstanceId { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
using ManagerService.Data;
|
using ManagerService.Data;
|
||||||
using ManagerService.DTOs;
|
using ManagerService.DTOs;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data.SubSection
|
namespace ManagerService.Data.SubSection
|
||||||
{
|
{
|
||||||
public class GuidedPath // Parcours
|
[Index(nameof(InstanceId))]
|
||||||
|
public class GuidedPath : IAuditableEntity // Parcours
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
@ -15,6 +18,10 @@ namespace ManagerService.Data.SubSection
|
|||||||
[Required]
|
[Required]
|
||||||
public string InstanceId { get; set; }
|
public string InstanceId { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
[Column(TypeName = "jsonb")]
|
[Column(TypeName = "jsonb")]
|
||||||
public List<TranslationDTO> Title { get; set; }
|
public List<TranslationDTO> Title { get; set; }
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace ManagerService.Data
|
|||||||
|
|
||||||
public long StorageQuotaBytes { get; set; } = 0;
|
public long StorageQuotaBytes { get; set; } = 0;
|
||||||
|
|
||||||
public int AiRequestsPerMonth { get; set; } = 0;
|
public long AiTokensPerMonth { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>Whether the plan includes any stats at all.</summary>
|
/// <summary>Whether the plan includes any stats at all.</summary>
|
||||||
public bool HasStats { get; set; } = false;
|
public bool HasStats { get; set; } = false;
|
||||||
@ -32,7 +32,7 @@ namespace ManagerService.Data
|
|||||||
id = Id,
|
id = Id,
|
||||||
name = Name,
|
name = Name,
|
||||||
storageQuotaBytes = StorageQuotaBytes,
|
storageQuotaBytes = StorageQuotaBytes,
|
||||||
aiRequestsPerMonth = AiRequestsPerMonth,
|
aiTokensPerMonth = AiTokensPerMonth,
|
||||||
hasStats = HasStats,
|
hasStats = HasStats,
|
||||||
statsHistoryDays = StatsHistoryDays,
|
statsHistoryDays = StatsHistoryDays,
|
||||||
hasAdvancedStats = HasAdvancedStats,
|
hasAdvancedStats = HasAdvancedStats,
|
||||||
@ -43,7 +43,7 @@ namespace ManagerService.Data
|
|||||||
{
|
{
|
||||||
Name = dto.name;
|
Name = dto.name;
|
||||||
StorageQuotaBytes = dto.storageQuotaBytes;
|
StorageQuotaBytes = dto.storageQuotaBytes;
|
||||||
AiRequestsPerMonth = dto.aiRequestsPerMonth;
|
AiTokensPerMonth = dto.aiTokensPerMonth;
|
||||||
HasStats = dto.hasStats;
|
HasStats = dto.hasStats;
|
||||||
StatsHistoryDays = dto.statsHistoryDays;
|
StatsHistoryDays = dto.statsHistoryDays;
|
||||||
HasAdvancedStats = dto.hasAdvancedStats;
|
HasAdvancedStats = dto.hasAdvancedStats;
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
using ManagerService.DTOs;
|
using ManagerService.DTOs;
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ManagerService.Data
|
namespace ManagerService.Data
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// User Information
|
/// User Information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class User
|
[Index(nameof(InstanceId))]
|
||||||
|
public class User : IAuditableEntity
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Required]
|
[Required]
|
||||||
@ -42,6 +44,8 @@ namespace ManagerService.Data
|
|||||||
//[BsonElement("DateCreation")]
|
//[BsonElement("DateCreation")]
|
||||||
public DateTime DateCreation { get; set; }
|
public DateTime DateCreation { get; set; }
|
||||||
|
|
||||||
|
public DateTime DateUpdate { get; set; }
|
||||||
|
|
||||||
/*[BsonElement("InstanceId")]
|
/*[BsonElement("InstanceId")]
|
||||||
[BsonRequired]*/
|
[BsonRequired]*/
|
||||||
[Required]
|
[Required]
|
||||||
|
|||||||
1647
ManagerService/Migrations/20260715143705_AddInstanceIdIndexes.Designer.cs
generated
Normal file
1647
ManagerService/Migrations/20260715143705_AddInstanceIdIndexes.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,90 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ManagerService.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddInstanceIdIndexes : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Users_InstanceId",
|
||||||
|
table: "Users",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Sections_InstanceId",
|
||||||
|
table: "Sections",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Resources_InstanceId",
|
||||||
|
table: "Resources",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_GuidedPaths_InstanceId",
|
||||||
|
table: "GuidedPaths",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Devices_InstanceId",
|
||||||
|
table: "Devices",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Configurations_InstanceId",
|
||||||
|
table: "Configurations",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AuditLogs_InstanceId",
|
||||||
|
table: "AuditLogs",
|
||||||
|
column: "InstanceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ApplicationInstances_InstanceId",
|
||||||
|
table: "ApplicationInstances",
|
||||||
|
column: "InstanceId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Users_InstanceId",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Sections_InstanceId",
|
||||||
|
table: "Sections");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Resources_InstanceId",
|
||||||
|
table: "Resources");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_GuidedPaths_InstanceId",
|
||||||
|
table: "GuidedPaths");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Devices_InstanceId",
|
||||||
|
table: "Devices");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Configurations_InstanceId",
|
||||||
|
table: "Configurations");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_AuditLogs_InstanceId",
|
||||||
|
table: "AuditLogs");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_ApplicationInstances_InstanceId",
|
||||||
|
table: "ApplicationInstances");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1683
ManagerService/Migrations/20260715144504_AddDateUpdateAudit.Designer.cs
generated
Normal file
1683
ManagerService/Migrations/20260715144504_AddDateUpdateAudit.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
165
ManagerService/Migrations/20260715144504_AddDateUpdateAudit.cs
Normal file
165
ManagerService/Migrations/20260715144504_AddDateUpdateAudit.cs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ManagerService.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddDateUpdateAudit : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Users",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Sections",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Resources",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Instances",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateCreation",
|
||||||
|
table: "GuidedPaths",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "GuidedPaths",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Configurations",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateCreation",
|
||||||
|
table: "ApplicationInstances",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "ApplicationInstances",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateCreation",
|
||||||
|
table: "AppConfigurationLinks",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "AppConfigurationLinks",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "ApiKeys",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
// Backfill : pour les lignes existantes, DateUpdate reprend la DateCreation connue.
|
||||||
|
migrationBuilder.Sql("UPDATE \"Users\" SET \"DateUpdate\" = \"DateCreation\";");
|
||||||
|
migrationBuilder.Sql("UPDATE \"Sections\" SET \"DateUpdate\" = \"DateCreation\";");
|
||||||
|
migrationBuilder.Sql("UPDATE \"Resources\" SET \"DateUpdate\" = \"DateCreation\";");
|
||||||
|
migrationBuilder.Sql("UPDATE \"Instances\" SET \"DateUpdate\" = \"DateCreation\";");
|
||||||
|
migrationBuilder.Sql("UPDATE \"Configurations\" SET \"DateUpdate\" = \"DateCreation\";");
|
||||||
|
migrationBuilder.Sql("UPDATE \"ApiKeys\" SET \"DateUpdate\" = \"DateCreation\";");
|
||||||
|
|
||||||
|
// GuidedPaths/ApplicationInstances/AppConfigurationLinks n'avaient aucune date avant cette migration :
|
||||||
|
// on ne peut pas reconstituer la vraie date de création, donc on initialise les deux au moment du backfill.
|
||||||
|
migrationBuilder.Sql("UPDATE \"GuidedPaths\" SET \"DateCreation\" = now(), \"DateUpdate\" = now();");
|
||||||
|
migrationBuilder.Sql("UPDATE \"ApplicationInstances\" SET \"DateCreation\" = now(), \"DateUpdate\" = now();");
|
||||||
|
migrationBuilder.Sql("UPDATE \"AppConfigurationLinks\" SET \"DateCreation\" = now(), \"DateUpdate\" = now();");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Sections");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Resources");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateCreation",
|
||||||
|
table: "GuidedPaths");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "GuidedPaths");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "Configurations");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateCreation",
|
||||||
|
table: "ApplicationInstances");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "ApplicationInstances");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateCreation",
|
||||||
|
table: "AppConfigurationLinks");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "AppConfigurationLinks");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DateUpdate",
|
||||||
|
table: "ApiKeys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1683
ManagerService/Migrations/20260717121501_AiQuotaTokensInsteadOfRequests.Designer.cs
generated
Normal file
1683
ManagerService/Migrations/20260717121501_AiQuotaTokensInsteadOfRequests.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,126 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ManagerService.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AiQuotaTokensInsteadOfRequests : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AiRequestsPerMonth",
|
||||||
|
table: "SubscriptionPlans");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AiRequestsPerMonth",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AiRequestsThisMonth",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<long>(
|
||||||
|
name: "AiTokensPerMonth",
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0L);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<long>(
|
||||||
|
name: "AiTokensPerMonth",
|
||||||
|
table: "Instances",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0L);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<long>(
|
||||||
|
name: "AiTokensThisMonth",
|
||||||
|
table: "Instances",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0L);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "plan-premium",
|
||||||
|
column: "AiTokensPerMonth",
|
||||||
|
value: 20000000L);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "plan-standard",
|
||||||
|
column: "AiTokensPerMonth",
|
||||||
|
value: 5000000L);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "plan-starter",
|
||||||
|
column: "AiTokensPerMonth",
|
||||||
|
value: 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AiTokensPerMonth",
|
||||||
|
table: "SubscriptionPlans");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AiTokensPerMonth",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AiTokensThisMonth",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "AiRequestsPerMonth",
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "AiRequestsPerMonth",
|
||||||
|
table: "Instances",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "AiRequestsThisMonth",
|
||||||
|
table: "Instances",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "plan-premium",
|
||||||
|
column: "AiRequestsPerMonth",
|
||||||
|
value: 2000);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "plan-standard",
|
||||||
|
column: "AiRequestsPerMonth",
|
||||||
|
value: 500);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "plan-starter",
|
||||||
|
column: "AiRequestsPerMonth",
|
||||||
|
value: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,6 +41,9 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<DateTime?>("DateExpiration")
|
b.Property<DateTime?>("DateExpiration")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("InstanceId")
|
b.Property<string>("InstanceId")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@ -78,6 +81,12 @@ namespace ManagerService.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateCreation")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("DeviceId")
|
b.Property<string>("DeviceId")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
@ -139,6 +148,12 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<int>("AppType")
|
b.Property<int>("AppType")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateCreation")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("InstanceId")
|
b.Property<string>("InstanceId")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@ -172,6 +187,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.HasIndex("SectionEventId");
|
b.HasIndex("SectionEventId");
|
||||||
|
|
||||||
b.ToTable("ApplicationInstances");
|
b.ToTable("ApplicationInstances");
|
||||||
@ -208,6 +225,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.ToTable("AuditLogs");
|
b.ToTable("AuditLogs");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -219,6 +238,9 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<DateTime>("DateCreation")
|
b.Property<DateTime>("DateCreation")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("ImageId")
|
b.Property<string>("ImageId")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
@ -266,6 +288,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.ToTable("Configurations");
|
b.ToTable("Configurations");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -325,6 +349,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasIndex("ConfigurationId");
|
b.HasIndex("ConfigurationId");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.ToTable("Devices");
|
b.ToTable("Devices");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -333,11 +359,11 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<string>("Id")
|
b.Property<string>("Id")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<int>("AiRequestsPerMonth")
|
b.Property<long>("AiTokensPerMonth")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<int>("AiRequestsThisMonth")
|
b.Property<long>("AiTokensThisMonth")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<string>("AiUsageMonthKey")
|
b.Property<string>("AiUsageMonthKey")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@ -345,6 +371,9 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<DateTime>("DateCreation")
|
b.Property<DateTime>("DateCreation")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<bool>("HasAdvancedStats")
|
b.Property<bool>("HasAdvancedStats")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
@ -449,6 +478,9 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<DateTime>("DateCreation")
|
b.Property<DateTime>("DateCreation")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("InstanceId")
|
b.Property<string>("InstanceId")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@ -468,6 +500,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.ToTable("Resources");
|
b.ToTable("Resources");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -486,6 +520,9 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<DateTime>("DateCreation")
|
b.Property<DateTime>("DateCreation")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
@ -544,6 +581,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.HasIndex("SectionMenuId");
|
b.HasIndex("SectionMenuId");
|
||||||
|
|
||||||
b.ToTable("Sections");
|
b.ToTable("Sections");
|
||||||
@ -705,6 +744,12 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<string>("Id")
|
b.Property<string>("Id")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateCreation")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
@ -753,6 +798,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasIndex("ImageResourceId");
|
b.HasIndex("ImageResourceId");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.HasIndex("SectionEventId");
|
b.HasIndex("SectionEventId");
|
||||||
|
|
||||||
b.HasIndex("SectionParcoursId");
|
b.HasIndex("SectionParcoursId");
|
||||||
@ -953,8 +1000,8 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<string>("Id")
|
b.Property<string>("Id")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<int>("AiRequestsPerMonth")
|
b.Property<long>("AiTokensPerMonth")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<bool>("HasAdvancedStats")
|
b.Property<bool>("HasAdvancedStats")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
@ -980,7 +1027,7 @@ namespace ManagerService.Migrations
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = "plan-starter",
|
Id = "plan-starter",
|
||||||
AiRequestsPerMonth = 0,
|
AiTokensPerMonth = 0L,
|
||||||
HasAdvancedStats = false,
|
HasAdvancedStats = false,
|
||||||
HasStats = false,
|
HasStats = false,
|
||||||
Name = "Starter",
|
Name = "Starter",
|
||||||
@ -990,7 +1037,7 @@ namespace ManagerService.Migrations
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = "plan-standard",
|
Id = "plan-standard",
|
||||||
AiRequestsPerMonth = 500,
|
AiTokensPerMonth = 5000000L,
|
||||||
HasAdvancedStats = false,
|
HasAdvancedStats = false,
|
||||||
HasStats = true,
|
HasStats = true,
|
||||||
Name = "Standard",
|
Name = "Standard",
|
||||||
@ -1000,7 +1047,7 @@ namespace ManagerService.Migrations
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = "plan-premium",
|
Id = "plan-premium",
|
||||||
AiRequestsPerMonth = 2000,
|
AiTokensPerMonth = 20000000L,
|
||||||
HasAdvancedStats = true,
|
HasAdvancedStats = true,
|
||||||
HasStats = true,
|
HasStats = true,
|
||||||
Name = "Premium",
|
Name = "Premium",
|
||||||
@ -1017,6 +1064,9 @@ namespace ManagerService.Migrations
|
|||||||
b.Property<DateTime>("DateCreation")
|
b.Property<DateTime>("DateCreation")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("Email")
|
b.Property<string>("Email")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@ -1045,6 +1095,8 @@ namespace ManagerService.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
b.ToTable("Users");
|
b.ToTable("Users");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -57,7 +57,7 @@ namespace ManagerService.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var translations = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(json) ?? new();
|
var translations = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(json) ?? new();
|
||||||
return new AiTranslateResponse { Translations = translations };
|
return new AiTranslateResponse { Translations = translations, TokensUsed = response.Usage?.TotalTokenCount ?? 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string StripHtml(string? html) =>
|
private static string StripHtml(string? html) =>
|
||||||
@ -493,7 +493,7 @@ namespace ManagerService.Services
|
|||||||
reply = response.Text ?? "";
|
reply = response.Text ?? "";
|
||||||
expectsReply = true;
|
expectsReply = true;
|
||||||
}
|
}
|
||||||
return new AiChatResponse { Reply = reply, Cards = cards, Navigation = navigation, ExpectsReply = expectsReply };
|
return new AiChatResponse { Reply = reply, Cards = cards, Navigation = navigation, ExpectsReply = expectsReply, TokensUsed = response.Usage?.TotalTokenCount ?? 0 };
|
||||||
}
|
}
|
||||||
catch (System.ClientModel.ClientResultException ex)
|
catch (System.ClientModel.ClientResultException ex)
|
||||||
{
|
{
|
||||||
@ -789,7 +789,7 @@ namespace ManagerService.Services
|
|||||||
reply = response.Text ?? "";
|
reply = response.Text ?? "";
|
||||||
expectsReply = true;
|
expectsReply = true;
|
||||||
}
|
}
|
||||||
return new AiChatResponse { Reply = reply, Navigation = navigation, ExpectsReply = expectsReply };
|
return new AiChatResponse { Reply = reply, Navigation = navigation, ExpectsReply = expectsReply, TokensUsed = response.Usage?.TotalTokenCount ?? 0 };
|
||||||
}
|
}
|
||||||
catch (System.ClientModel.ClientResultException ex)
|
catch (System.ClientModel.ClientResultException ex)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user