diff --git a/docs/development/ZENTRAL.md b/docs/development/ZENTRAL.md index e5bf938..5b9952b 100644 --- a/docs/development/ZENTRAL.md +++ b/docs/development/ZENTRAL.md @@ -20,3 +20,5 @@ File riassuntivo dello stato di sviluppo di Zentral. - Implementazione modulo Gestione Eventi: strutturazione frontend, integrazione funzionalità e attivazione store. - [Event Module Development](./devlog/event-module.md) - Implementazione modulo eventi - [Menu Refactoring](./devlog/menu-refactoring.md) - Riorganizzazione menu e moduli (Dashboard, Clienti, Articoli, Risorse) +- [2025-12-03 Implementazione Modulo Personale](./devlog/2025-12-03_implementazione_modulo_personale.md) - **In Corso** + - Implementazione entità, API e Frontend per gestione Personale (Dipendenti, Contratti, Assenze, Pagamenti). diff --git a/docs/development/devlog/2025-12-04_event_management_plan.md b/docs/development/devlog/2025-12-03_event_management_plan.md similarity index 100% rename from docs/development/devlog/2025-12-04_event_management_plan.md rename to docs/development/devlog/2025-12-03_event_management_plan.md diff --git a/docs/development/devlog/2025-12-03_implementazione_modulo_personale.md b/docs/development/devlog/2025-12-03_implementazione_modulo_personale.md new file mode 100644 index 0000000..c731878 --- /dev/null +++ b/docs/development/devlog/2025-12-03_implementazione_modulo_personale.md @@ -0,0 +1,40 @@ +# Implementazione Modulo Personale + +## Obiettivo +Implementare il modulo "Personale" per la gestione delle risorse umane, come richiesto nelle specifiche di posizionamento di mercato. + +## Funzionalità Richieste +- **Gestione Personale (Dipendenti)**: Anagrafica dipendenti. +- **Contratti**: Gestione dei contratti di lavoro (tipo, date, livello, retribuzione). +- **Assenze**: Tracciamento ferie, malattie, permessi. +- **Pagamenti**: Registro dei pagamenti stipendi. +- **Rimborsi**: Gestione note spese e rimborsi. +- **Analisi**: Dashboard statistiche (da implementare successivamente). + +## Piano di Lavoro + +### Backend (.NET) +1. [ ] Creare cartella `src/backend/Zentral.Domain/Entities/Personale`. +2. [ ] Definire le entità: + * `Dipendente` + * `Contratto` + * `Assenza` + * `Pagamento` + * `Rimborso` +3. [ ] Aggiornare `ZentralDbContext` aggiungendo i `DbSet`. +4. [ ] Creare la migrazione EF Core. +5. [ ] Creare i Controller API in `src/backend/Zentral.API/Controllers/Personale`. + +### Frontend (React) +1. [ ] Strutturare `src/frontend/src/modules/personale`. +2. [ ] Implementare le pagine CRUD: + * `DipendentiPage` + * `ContrattiPage` + * `AssenzePage` + * `PagamentiPage` (include Rimborsi per ora o separato). +3. [ ] Configurare il routing del modulo. +4. [ ] Aggiungere il modulo alla configurazione `AppModule` (se non presente) e verificare l'attivazione. + +### Integrazione +1. [ ] Verificare che il modulo appaia nel menu solo se attivo. +2. [ ] Testare il flusso completo (creazione dipendente -> contratto -> assenza). diff --git a/docs/development/devlog/2025-12-04_menu_refactoring.md b/docs/development/devlog/2025-12-03_menu_refactoring.md similarity index 100% rename from docs/development/devlog/2025-12-04_menu_refactoring.md rename to docs/development/devlog/2025-12-03_menu_refactoring.md diff --git a/src/backend/Zentral.API/Modules/HR/Controllers/AssenzeController.cs b/src/backend/Zentral.API/Modules/HR/Controllers/AssenzeController.cs new file mode 100644 index 0000000..06f7b5a --- /dev/null +++ b/src/backend/Zentral.API/Modules/HR/Controllers/AssenzeController.cs @@ -0,0 +1,94 @@ +using Zentral.Domain.Entities.HR; +using Zentral.Infrastructure.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Zentral.API.Modules.HR.Controllers; + +[ApiController] +[Route("api/hr/[controller]")] +public class AssenzeController : ControllerBase +{ + private readonly ZentralDbContext _context; + + public AssenzeController(ZentralDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> GetAssenze([FromQuery] int? dipendenteId, [FromQuery] DateTime? from, [FromQuery] DateTime? to) + { + var query = _context.Assenze.Include(a => a.Dipendente).AsQueryable(); + + if (dipendenteId.HasValue) + query = query.Where(a => a.DipendenteId == dipendenteId.Value); + + if (from.HasValue) + query = query.Where(a => a.DataInizio >= from.Value); + + if (to.HasValue) + query = query.Where(a => a.DataFine <= to.Value); + + return await query.OrderByDescending(a => a.DataInizio).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetAssenza(int id) + { + var assenza = await _context.Assenze + .Include(a => a.Dipendente) + .FirstOrDefaultAsync(a => a.Id == id); + + if (assenza == null) + return NotFound(); + + return assenza; + } + + [HttpPost] + public async Task> CreateAssenza(Assenza assenza) + { + assenza.CreatedAt = DateTime.UtcNow; + _context.Assenze.Add(assenza); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetAssenza), new { id = assenza.Id }, assenza); + } + + [HttpPut("{id}")] + public async Task UpdateAssenza(int id, Assenza assenza) + { + if (id != assenza.Id) + return BadRequest(); + + assenza.UpdatedAt = DateTime.UtcNow; + _context.Entry(assenza).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await _context.Assenze.AnyAsync(a => a.Id == id)) + return NotFound(); + throw; + } + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeleteAssenza(int id) + { + var assenza = await _context.Assenze.FindAsync(id); + if (assenza == null) + return NotFound(); + + _context.Assenze.Remove(assenza); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} diff --git a/src/backend/Zentral.API/Modules/HR/Controllers/ContrattiController.cs b/src/backend/Zentral.API/Modules/HR/Controllers/ContrattiController.cs new file mode 100644 index 0000000..856409c --- /dev/null +++ b/src/backend/Zentral.API/Modules/HR/Controllers/ContrattiController.cs @@ -0,0 +1,88 @@ +using Zentral.Domain.Entities.HR; +using Zentral.Infrastructure.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Zentral.API.Modules.HR.Controllers; + +[ApiController] +[Route("api/hr/[controller]")] +public class ContrattiController : ControllerBase +{ + private readonly ZentralDbContext _context; + + public ContrattiController(ZentralDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> GetContratti([FromQuery] int? dipendenteId) + { + var query = _context.Contratti.Include(c => c.Dipendente).AsQueryable(); + + if (dipendenteId.HasValue) + query = query.Where(c => c.DipendenteId == dipendenteId.Value); + + return await query.OrderByDescending(c => c.DataInizio).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetContratto(int id) + { + var contratto = await _context.Contratti + .Include(c => c.Dipendente) + .FirstOrDefaultAsync(c => c.Id == id); + + if (contratto == null) + return NotFound(); + + return contratto; + } + + [HttpPost] + public async Task> CreateContratto(Contratto contratto) + { + contratto.CreatedAt = DateTime.UtcNow; + _context.Contratti.Add(contratto); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetContratto), new { id = contratto.Id }, contratto); + } + + [HttpPut("{id}")] + public async Task UpdateContratto(int id, Contratto contratto) + { + if (id != contratto.Id) + return BadRequest(); + + contratto.UpdatedAt = DateTime.UtcNow; + _context.Entry(contratto).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await _context.Contratti.AnyAsync(c => c.Id == id)) + return NotFound(); + throw; + } + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeleteContratto(int id) + { + var contratto = await _context.Contratti.FindAsync(id); + if (contratto == null) + return NotFound(); + + _context.Contratti.Remove(contratto); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} diff --git a/src/backend/Zentral.API/Modules/HR/Controllers/DipendentiController.cs b/src/backend/Zentral.API/Modules/HR/Controllers/DipendentiController.cs new file mode 100644 index 0000000..7de4547 --- /dev/null +++ b/src/backend/Zentral.API/Modules/HR/Controllers/DipendentiController.cs @@ -0,0 +1,93 @@ +using Zentral.Domain.Entities.HR; +using Zentral.Infrastructure.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Zentral.API.Modules.HR.Controllers; + +[ApiController] +[Route("api/hr/[controller]")] +public class DipendentiController : ControllerBase +{ + private readonly ZentralDbContext _context; + + public DipendentiController(ZentralDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> GetDipendenti([FromQuery] string? search) + { + var query = _context.Dipendenti.AsQueryable(); + + if (!string.IsNullOrEmpty(search)) + query = query.Where(d => d.Nome.Contains(search) || + d.Cognome.Contains(search) || + (d.CodiceFiscale != null && d.CodiceFiscale.Contains(search))); + + return await query.OrderBy(d => d.Cognome).ThenBy(d => d.Nome).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetDipendente(int id) + { + var dipendente = await _context.Dipendenti + .Include(d => d.Contratti) + .Include(d => d.Assenze) + .Include(d => d.Pagamenti) + .Include(d => d.Rimborsi) + .FirstOrDefaultAsync(d => d.Id == id); + + if (dipendente == null) + return NotFound(); + + return dipendente; + } + + [HttpPost] + public async Task> CreateDipendente(Dipendente dipendente) + { + dipendente.CreatedAt = DateTime.UtcNow; + _context.Dipendenti.Add(dipendente); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetDipendente), new { id = dipendente.Id }, dipendente); + } + + [HttpPut("{id}")] + public async Task UpdateDipendente(int id, Dipendente dipendente) + { + if (id != dipendente.Id) + return BadRequest(); + + dipendente.UpdatedAt = DateTime.UtcNow; + _context.Entry(dipendente).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await _context.Dipendenti.AnyAsync(d => d.Id == id)) + return NotFound(); + throw; + } + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeleteDipendente(int id) + { + var dipendente = await _context.Dipendenti.FindAsync(id); + if (dipendente == null) + return NotFound(); + + _context.Dipendenti.Remove(dipendente); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} diff --git a/src/backend/Zentral.API/Modules/HR/Controllers/PagamentiController.cs b/src/backend/Zentral.API/Modules/HR/Controllers/PagamentiController.cs new file mode 100644 index 0000000..d6641dd --- /dev/null +++ b/src/backend/Zentral.API/Modules/HR/Controllers/PagamentiController.cs @@ -0,0 +1,94 @@ +using Zentral.Domain.Entities.HR; +using Zentral.Infrastructure.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Zentral.API.Modules.HR.Controllers; + +[ApiController] +[Route("api/hr/[controller]")] +public class PagamentiController : ControllerBase +{ + private readonly ZentralDbContext _context; + + public PagamentiController(ZentralDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> GetPagamenti([FromQuery] int? dipendenteId, [FromQuery] DateTime? from, [FromQuery] DateTime? to) + { + var query = _context.Pagamenti.Include(p => p.Dipendente).AsQueryable(); + + if (dipendenteId.HasValue) + query = query.Where(p => p.DipendenteId == dipendenteId.Value); + + if (from.HasValue) + query = query.Where(p => p.DataPagamento >= from.Value); + + if (to.HasValue) + query = query.Where(p => p.DataPagamento <= to.Value); + + return await query.OrderByDescending(p => p.DataPagamento).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetPagamento(int id) + { + var pagamento = await _context.Pagamenti + .Include(p => p.Dipendente) + .FirstOrDefaultAsync(p => p.Id == id); + + if (pagamento == null) + return NotFound(); + + return pagamento; + } + + [HttpPost] + public async Task> CreatePagamento(Pagamento pagamento) + { + pagamento.CreatedAt = DateTime.UtcNow; + _context.Pagamenti.Add(pagamento); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetPagamento), new { id = pagamento.Id }, pagamento); + } + + [HttpPut("{id}")] + public async Task UpdatePagamento(int id, Pagamento pagamento) + { + if (id != pagamento.Id) + return BadRequest(); + + pagamento.UpdatedAt = DateTime.UtcNow; + _context.Entry(pagamento).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await _context.Pagamenti.AnyAsync(p => p.Id == id)) + return NotFound(); + throw; + } + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeletePagamento(int id) + { + var pagamento = await _context.Pagamenti.FindAsync(id); + if (pagamento == null) + return NotFound(); + + _context.Pagamenti.Remove(pagamento); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} diff --git a/src/backend/Zentral.API/Modules/HR/Controllers/RimborsiController.cs b/src/backend/Zentral.API/Modules/HR/Controllers/RimborsiController.cs new file mode 100644 index 0000000..ebfa15e --- /dev/null +++ b/src/backend/Zentral.API/Modules/HR/Controllers/RimborsiController.cs @@ -0,0 +1,91 @@ +using Zentral.Domain.Entities.HR; +using Zentral.Infrastructure.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Zentral.API.Modules.HR.Controllers; + +[ApiController] +[Route("api/hr/[controller]")] +public class RimborsiController : ControllerBase +{ + private readonly ZentralDbContext _context; + + public RimborsiController(ZentralDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> GetRimborsi([FromQuery] int? dipendenteId, [FromQuery] string? stato) + { + var query = _context.Rimborsi.Include(r => r.Dipendente).AsQueryable(); + + if (dipendenteId.HasValue) + query = query.Where(r => r.DipendenteId == dipendenteId.Value); + + if (!string.IsNullOrEmpty(stato)) + query = query.Where(r => r.Stato == stato); + + return await query.OrderByDescending(r => r.DataSpesa).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetRimborso(int id) + { + var rimborso = await _context.Rimborsi + .Include(r => r.Dipendente) + .FirstOrDefaultAsync(r => r.Id == id); + + if (rimborso == null) + return NotFound(); + + return rimborso; + } + + [HttpPost] + public async Task> CreateRimborso(Rimborso rimborso) + { + rimborso.CreatedAt = DateTime.UtcNow; + _context.Rimborsi.Add(rimborso); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetRimborso), new { id = rimborso.Id }, rimborso); + } + + [HttpPut("{id}")] + public async Task UpdateRimborso(int id, Rimborso rimborso) + { + if (id != rimborso.Id) + return BadRequest(); + + rimborso.UpdatedAt = DateTime.UtcNow; + _context.Entry(rimborso).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await _context.Rimborsi.AnyAsync(r => r.Id == id)) + return NotFound(); + throw; + } + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeleteRimborso(int id) + { + var rimborso = await _context.Rimborsi.FindAsync(id); + if (rimborso == null) + return NotFound(); + + _context.Rimborsi.Remove(rimborso); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} diff --git a/src/backend/Zentral.API/Services/ModuleService.cs b/src/backend/Zentral.API/Services/ModuleService.cs index 5443a68..355a477 100644 --- a/src/backend/Zentral.API/Services/ModuleService.cs +++ b/src/backend/Zentral.API/Services/ModuleService.cs @@ -405,9 +405,6 @@ public class ModuleService /// public async Task SeedDefaultModulesAsync() { - if (await _context.AppModules.AnyAsync()) - return; - var defaultModules = new List { new AppModule @@ -482,12 +479,46 @@ public class ModuleService RoutePath = "/quality", IsAvailable = true, CreatedAt = DateTime.UtcNow + }, + new AppModule + { + Code = "events", + Name = "Gestione Eventi", + Description = "Gestione eventi, pianificazione e controllo avanzamento", + Icon = "Event", + BasePrice = 2000m, + MonthlyMultiplier = 1.2m, + SortOrder = 60, + IsCore = false, + RoutePath = "/events", + IsAvailable = true, + CreatedAt = DateTime.UtcNow + }, + new AppModule + { + Code = "hr", + Name = "Gestione Personale", + Description = "Gestione personale, contratti, pagamenti, assenze, rimborsi e analisi personale", + Icon = "People", + BasePrice = 1600m, + MonthlyMultiplier = 1.2m, + SortOrder = 70, + IsCore = false, + RoutePath = "/hr", + IsAvailable = true, + CreatedAt = DateTime.UtcNow } }; - _context.AppModules.AddRange(defaultModules); - await _context.SaveChangesAsync(); + var existingCodes = await _context.AppModules.Select(m => m.Code).ToListAsync(); + var newModules = defaultModules.Where(m => !existingCodes.Contains(m.Code)).ToList(); - _logger.LogInformation("Seed {Count} moduli di default completato", defaultModules.Count); + if (newModules.Any()) + { + _context.AppModules.AddRange(newModules); + await _context.SaveChangesAsync(); + _logger.LogInformation("Added {Count} new default modules: {Modules}", + newModules.Count, string.Join(", ", newModules.Select(m => m.Code))); + } } } diff --git a/src/backend/Zentral.Domain/Entities/HR/Assenza.cs b/src/backend/Zentral.Domain/Entities/HR/Assenza.cs new file mode 100644 index 0000000..bc0820d --- /dev/null +++ b/src/backend/Zentral.Domain/Entities/HR/Assenza.cs @@ -0,0 +1,15 @@ +using System; + +namespace Zentral.Domain.Entities.HR; + +public class Assenza : BaseEntity +{ + public int DipendenteId { get; set; } + public Dipendente Dipendente { get; set; } = null!; + + public DateTime DataInizio { get; set; } + public DateTime DataFine { get; set; } + public string TipoAssenza { get; set; } = string.Empty; + public string Stato { get; set; } = "Richiesta"; + public string? Note { get; set; } +} diff --git a/src/backend/Zentral.Domain/Entities/HR/Contratto.cs b/src/backend/Zentral.Domain/Entities/HR/Contratto.cs new file mode 100644 index 0000000..2284559 --- /dev/null +++ b/src/backend/Zentral.Domain/Entities/HR/Contratto.cs @@ -0,0 +1,17 @@ +using System; + +namespace Zentral.Domain.Entities.HR; + +public class Contratto : BaseEntity +{ + public int DipendenteId { get; set; } + public Dipendente Dipendente { get; set; } = null!; + + public DateTime DataInizio { get; set; } + public DateTime? DataFine { get; set; } + public string TipoContratto { get; set; } = string.Empty; + public string? Livello { get; set; } + public decimal RetribuzioneLorda { get; set; } + public string? Note { get; set; } + public bool Attivo { get; set; } = true; +} diff --git a/src/backend/Zentral.Domain/Entities/HR/Dipendente.cs b/src/backend/Zentral.Domain/Entities/HR/Dipendente.cs new file mode 100644 index 0000000..050553e --- /dev/null +++ b/src/backend/Zentral.Domain/Entities/HR/Dipendente.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace Zentral.Domain.Entities.HR; + +public class Dipendente : BaseEntity +{ + public string Nome { get; set; } = string.Empty; + public string Cognome { get; set; } = string.Empty; + public string? CodiceFiscale { get; set; } + public string? Email { get; set; } + public string? Telefono { get; set; } + public string? Indirizzo { get; set; } + public DateTime? DataNascita { get; set; } + public string? Ruolo { get; set; } + + public List Contratti { get; set; } = new(); + public List Assenze { get; set; } = new(); + public List Pagamenti { get; set; } = new(); + public List Rimborsi { get; set; } = new(); +} diff --git a/src/backend/Zentral.Domain/Entities/HR/Pagamento.cs b/src/backend/Zentral.Domain/Entities/HR/Pagamento.cs new file mode 100644 index 0000000..c175119 --- /dev/null +++ b/src/backend/Zentral.Domain/Entities/HR/Pagamento.cs @@ -0,0 +1,14 @@ +using System; + +namespace Zentral.Domain.Entities.HR; + +public class Pagamento : BaseEntity +{ + public int DipendenteId { get; set; } + public Dipendente Dipendente { get; set; } = null!; + + public DateTime DataPagamento { get; set; } + public decimal ImportoNetto { get; set; } + public string Descrizione { get; set; } = string.Empty; + public bool Pagato { get; set; } = false; +} diff --git a/src/backend/Zentral.Domain/Entities/HR/Rimborso.cs b/src/backend/Zentral.Domain/Entities/HR/Rimborso.cs new file mode 100644 index 0000000..4693613 --- /dev/null +++ b/src/backend/Zentral.Domain/Entities/HR/Rimborso.cs @@ -0,0 +1,14 @@ +using System; + +namespace Zentral.Domain.Entities.HR; + +public class Rimborso : BaseEntity +{ + public int DipendenteId { get; set; } + public Dipendente Dipendente { get; set; } = null!; + + public DateTime DataSpesa { get; set; } + public decimal Importo { get; set; } + public string Descrizione { get; set; } = string.Empty; + public string Stato { get; set; } = "Richiesto"; +} diff --git a/src/backend/Zentral.Infrastructure/Data/ZentralDbContext.cs b/src/backend/Zentral.Infrastructure/Data/ZentralDbContext.cs index cd2b136..a58ee4c 100644 --- a/src/backend/Zentral.Infrastructure/Data/ZentralDbContext.cs +++ b/src/backend/Zentral.Infrastructure/Data/ZentralDbContext.cs @@ -3,6 +3,7 @@ using Zentral.Domain.Entities.Warehouse; using Zentral.Domain.Entities.Purchases; using Zentral.Domain.Entities.Sales; using Zentral.Domain.Entities.Production; +using Zentral.Domain.Entities.HR; using Microsoft.EntityFrameworkCore; namespace Zentral.Infrastructure.Data; @@ -86,10 +87,70 @@ public class ZentralDbContext : DbContext public DbSet ProductionOrderPhases => Set(); public DbSet MrpSuggestions => Set(); + // Personale module entities + public DbSet Dipendenti => Set(); + public DbSet Contratti => Set(); + public DbSet Assenze => Set(); + public DbSet Pagamenti => Set(); + public DbSet Rimborsi => Set(); + protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); + // =============================================== + // PERSONALE MODULE ENTITIES + // =============================================== + + modelBuilder.Entity(entity => + { + entity.ToTable("Dipendenti"); + entity.HasIndex(e => e.CodiceFiscale).IsUnique(); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Contratti"); + entity.Property(e => e.RetribuzioneLorda).HasPrecision(18, 2); + + entity.HasOne(e => e.Dipendente) + .WithMany(d => d.Contratti) + .HasForeignKey(e => e.DipendenteId) + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Assenze"); + + entity.HasOne(e => e.Dipendente) + .WithMany(d => d.Assenze) + .HasForeignKey(e => e.DipendenteId) + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Pagamenti"); + entity.Property(e => e.ImportoNetto).HasPrecision(18, 2); + + entity.HasOne(e => e.Dipendente) + .WithMany(d => d.Pagamenti) + .HasForeignKey(e => e.DipendenteId) + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Rimborsi"); + entity.Property(e => e.Importo).HasPrecision(18, 2); + + entity.HasOne(e => e.Dipendente) + .WithMany(d => d.Rimborsi) + .HasForeignKey(e => e.DipendenteId) + .OnDelete(DeleteBehavior.Cascade); + }); + // Cliente modelBuilder.Entity(entity => { diff --git a/src/backend/Zentral.Infrastructure/Migrations/20251203190021_AddPersonaleModule.Designer.cs b/src/backend/Zentral.Infrastructure/Migrations/20251203190021_AddPersonaleModule.Designer.cs new file mode 100644 index 0000000..81594b9 --- /dev/null +++ b/src/backend/Zentral.Infrastructure/Migrations/20251203190021_AddPersonaleModule.Designer.cs @@ -0,0 +1,4657 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Zentral.Infrastructure.Data; + +#nullable disable + +namespace Zentral.Infrastructure.Migrations +{ + [DbContext(typeof(ZentralDbContext))] + [Migration("20251203190021_AddPersonaleModule")] + partial class AddPersonaleModule + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("Zentral.Domain.Entities.AppModule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BasePrice") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Dependencies") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Icon") + .HasColumnType("TEXT"); + + b.Property("IsAvailable") + .HasColumnType("INTEGER"); + + b.Property("IsCore") + .HasColumnType("INTEGER"); + + b.Property("MonthlyMultiplier") + .HasPrecision(5, 2) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RoutePath") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("SortOrder"); + + b.ToTable("AppModules"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Articolo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CategoriaId") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CodiceAlternativo") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Immagine") + .HasColumnType("BLOB"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("QtaDisponibile") + .HasColumnType("TEXT"); + + b.Property("QtaStdA") + .HasColumnType("TEXT"); + + b.Property("QtaStdB") + .HasColumnType("TEXT"); + + b.Property("QtaStdS") + .HasColumnType("TEXT"); + + b.Property("TipoMaterialeId") + .HasColumnType("INTEGER"); + + b.Property("UnitaMisura") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CategoriaId"); + + b.HasIndex("Codice") + .IsUnique(); + + b.HasIndex("TipoMaterialeId"); + + b.ToTable("Articoli"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.AutoCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EntityCode") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EntityName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("IsReadOnly") + .HasColumnType("INTEGER"); + + b.Property("LastResetMonth") + .HasColumnType("INTEGER"); + + b.Property("LastResetYear") + .HasColumnType("INTEGER"); + + b.Property("LastSequence") + .HasColumnType("INTEGER"); + + b.Property("ModuleCode") + .HasColumnType("TEXT"); + + b.Property("Pattern") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("ResetSequenceMonthly") + .HasColumnType("INTEGER"); + + b.Property("ResetSequenceYearly") + .HasColumnType("INTEGER"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EntityCode") + .IsUnique(); + + b.HasIndex("ModuleCode"); + + b.ToTable("AutoCodes"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Cliente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cap") + .HasColumnType("TEXT"); + + b.Property("Citta") + .HasColumnType("TEXT"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CodiceAlternativo") + .HasColumnType("TEXT"); + + b.Property("CodiceDestinatario") + .HasColumnType("TEXT"); + + b.Property("CodiceFiscale") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("PartitaIva") + .HasColumnType("TEXT"); + + b.Property("Pec") + .HasColumnType("TEXT"); + + b.Property("Provincia") + .HasColumnType("TEXT"); + + b.Property("RagioneSociale") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PartitaIva"); + + b.HasIndex("RagioneSociale"); + + b.ToTable("Clienti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.CodiceCategoria", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CoeffA") + .HasColumnType("TEXT"); + + b.Property("CoeffB") + .HasColumnType("TEXT"); + + b.Property("CoeffS") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("CodiciCategoria"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Configurazione", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Chiave") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("Valore") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Chiave") + .IsUnique(); + + b.ToTable("Configurazioni"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.CustomFieldDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DefaultValue") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EntityName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsRequired") + .HasColumnType("INTEGER"); + + b.Property("Label") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OptionsJson") + .HasColumnType("TEXT"); + + b.Property("Placeholder") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("ValidationRegex") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EntityName"); + + b.HasIndex("EntityName", "FieldName") + .IsUnique(); + + b.ToTable("CustomFieldDefinitions"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Evento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClienteId") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .HasColumnType("TEXT"); + + b.Property("Confermato") + .HasColumnType("INTEGER"); + + b.Property("CostoPersona") + .HasColumnType("TEXT"); + + b.Property("CostoTotale") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataEvento") + .HasColumnType("TEXT"); + + b.Property("DataScadenzaPreventivo") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("LocationId") + .HasColumnType("INTEGER"); + + b.Property("NoteAllestimento") + .HasColumnType("TEXT"); + + b.Property("NoteCliente") + .HasColumnType("TEXT"); + + b.Property("NoteCucina") + .HasColumnType("TEXT"); + + b.Property("NoteInterne") + .HasColumnType("TEXT"); + + b.Property("NumeroOspiti") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiAdulti") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiBambini") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiBuffet") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiSeduti") + .HasColumnType("INTEGER"); + + b.Property("OraFine") + .HasColumnType("TEXT"); + + b.Property("OraInizio") + .HasColumnType("TEXT"); + + b.Property("Saldo") + .HasColumnType("TEXT"); + + b.Property("Stato") + .HasColumnType("INTEGER"); + + b.Property("TipoEventoId") + .HasColumnType("INTEGER"); + + b.Property("TotaleAcconti") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ClienteId"); + + b.HasIndex("Codice"); + + b.HasIndex("DataEvento"); + + b.HasIndex("LocationId"); + + b.HasIndex("Stato"); + + b.HasIndex("TipoEventoId"); + + b.ToTable("Eventi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAcconto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AConferma") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataPagamento") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Importo") + .HasColumnType("TEXT"); + + b.Property("MetodoPagamento") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Ordine") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiAcconti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAllegato", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Contenuto") + .HasColumnType("BLOB"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("NomeFile") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiAllegati"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAltroCosto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AliquotaIva") + .HasColumnType("TEXT"); + + b.Property("ApplicaIva") + .HasColumnType("INTEGER"); + + b.Property("CostoUnitario") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Ordine") + .HasColumnType("INTEGER"); + + b.Property("Quantita") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiAltriCosti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDegustazione", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completata") + .HasColumnType("INTEGER"); + + b.Property("CostoDegustazione") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataDegustazione") + .HasColumnType("TEXT"); + + b.Property("Detraibile") + .HasColumnType("INTEGER"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Luogo") + .HasColumnType("TEXT"); + + b.Property("Menu") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("NumeroPaganti") + .HasColumnType("INTEGER"); + + b.Property("NumeroPersone") + .HasColumnType("INTEGER"); + + b.Property("Ora") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiDegustazioni"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioOspiti", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CostoUnitario") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Numero") + .HasColumnType("INTEGER"); + + b.Property("Ordine") + .HasColumnType("INTEGER"); + + b.Property("Sconto") + .HasColumnType("TEXT"); + + b.Property("TipoOspiteId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.HasIndex("TipoOspiteId"); + + b.ToTable("EventiDettaglioOspiti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioPrelievo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticoloId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("QtaCalcolata") + .HasColumnType("TEXT"); + + b.Property("QtaEffettiva") + .HasColumnType("TEXT"); + + b.Property("QtaRichiesta") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticoloId"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiDettaglioPrelievo"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioRisorsa", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Costo") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OraFine") + .HasColumnType("TEXT"); + + b.Property("OraInizio") + .HasColumnType("TEXT"); + + b.Property("OreLavoro") + .HasColumnType("TEXT"); + + b.Property("RisorsaId") + .HasColumnType("INTEGER"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.HasIndex("RisorsaId"); + + b.ToTable("EventiDettaglioRisorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cap") + .HasColumnType("TEXT"); + + b.Property("Citta") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DistanzaKm") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Provincia") + .HasColumnType("TEXT"); + + b.Property("Referente") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Nome"); + + b.ToTable("Location"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ModuleSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRenew") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("LastRenewalDate") + .HasColumnType("TEXT"); + + b.Property("ModuleId") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PaidPrice") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("SubscriptionType") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ModuleId") + .IsUnique(); + + b.ToTable("ModuleSubscriptions"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Assenza", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataFine") + .HasColumnType("TEXT"); + + b.Property("DataInizio") + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Stato") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TipoAssenza") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Assenze", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Contratto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataFine") + .HasColumnType("TEXT"); + + b.Property("DataInizio") + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Livello") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("RetribuzioneLorda") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("TipoContratto") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Contratti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Dipendente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CodiceFiscale") + .HasColumnType("TEXT"); + + b.Property("Cognome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataNascita") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CodiceFiscale") + .IsUnique(); + + b.ToTable("Dipendenti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Pagamento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataPagamento") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("ImportoNetto") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Pagato") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Pagamenti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Rimborso", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataSpesa") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Importo") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Stato") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Rimborsi", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterials", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("IsActive"); + + b.ToTable("BillOfMaterials", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterialsComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BillOfMaterialsId") + .HasColumnType("INTEGER"); + + b.Property("ComponentArticleId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ScrapPercentage") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("BillOfMaterialsId"); + + b.HasIndex("ComponentArticleId"); + + b.ToTable("BillOfMaterialsComponents", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.MrpSuggestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("CalculationDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("IsProcessed") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SuggestionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("CalculationDate"); + + b.HasIndex("IsProcessed"); + + b.ToTable("MrpSuggestions", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCycle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("IsActive"); + + b.ToTable("ProductionCycles", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCyclePhase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("DurationPerUnitMinutes") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProductionCycleId") + .HasColumnType("INTEGER"); + + b.Property("Sequence") + .HasColumnType("INTEGER"); + + b.Property("SetupTimeMinutes") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WorkCenterId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProductionCycleId"); + + b.HasIndex("WorkCenterId"); + + b.ToTable("ProductionCyclePhases", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DueDate") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ParentProductionOrderId") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("ParentProductionOrderId"); + + b.HasIndex("StartDate"); + + b.HasIndex("Status"); + + b.ToTable("ProductionOrders", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("ConsumedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("ProductionOrderId") + .HasColumnType("INTEGER"); + + b.Property("RequiredQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("ProductionOrderId"); + + b.ToTable("ProductionOrderComponents", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderPhase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActualDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("EstimatedDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProductionOrderId") + .HasColumnType("INTEGER"); + + b.Property("QuantityCompleted") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("QuantityScrapped") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Sequence") + .HasColumnType("INTEGER"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WorkCenterId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProductionOrderId"); + + b.HasIndex("Status"); + + b.HasIndex("WorkCenterId"); + + b.ToTable("ProductionOrderPhases", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.WorkCenter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CostPerHour") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.ToTable("WorkCenters", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DestinationWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OrderDate") + .HasColumnType("TEXT"); + + b.Property("OrderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("TotalGross") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalNet") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalTax") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DestinationWarehouseId"); + + b.HasIndex("OrderDate"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SupplierId"); + + b.ToTable("PurchaseOrders", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DiscountPercent") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("PurchaseOrderId") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ReceivedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TaxRate") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseArticleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseOrderId"); + + b.HasIndex("WarehouseArticleId"); + + b.ToTable("PurchaseOrderLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Country") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("FiscalCode") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PaymentTerms") + .HasColumnType("TEXT"); + + b.Property("Pec") + .HasColumnType("TEXT"); + + b.Property("Phone") + .HasColumnType("TEXT"); + + b.Property("Province") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("VatNumber") + .HasColumnType("TEXT"); + + b.Property("Website") + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.HasIndex("Name"); + + b.HasIndex("VatNumber"); + + b.ToTable("Suppliers", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ReportFont", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("FileSize") + .HasColumnType("INTEGER"); + + b.Property("FontData") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("FontFamily") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FontStyle") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("MimeType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("FontFamily"); + + b.ToTable("ReportFonts"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ReportImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Categoria") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("FileSize") + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("INTEGER"); + + b.Property("ImageData") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("MimeType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Categoria"); + + b.ToTable("ReportImages"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ReportTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Categoria") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Orientation") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PageSize") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TemplateJson") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Thumbnail") + .HasColumnType("BLOB"); + + b.Property("ThumbnailMimeType") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Categoria"); + + b.HasIndex("Nome"); + + b.ToTable("ReportTemplates"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Risorsa", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cognome") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("TipoRisorsaId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TipoRisorsaId"); + + b.ToTable("Risorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("CustomerId") + .HasColumnType("INTEGER"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OrderDate") + .HasColumnType("TEXT"); + + b.Property("OrderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("TotalGross") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalNet") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalTax") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.HasIndex("OrderDate"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("SalesOrders", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DiscountPercent") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SalesOrderId") + .HasColumnType("INTEGER"); + + b.Property("ShippedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TaxRate") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseArticleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SalesOrderId"); + + b.HasIndex("WarehouseArticleId"); + + b.ToTable("SalesOrderLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoEvento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TipoPastoId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TipoPastoId"); + + b.ToTable("TipiEvento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoMateriale", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiMateriale"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoOspite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiOspite"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoPasto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiPasto"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoRisorsa", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiRisorsa"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Utente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cognome") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Nome") + .HasColumnType("TEXT"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("SolaLettura") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("Utenti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.VirtualDataset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Categoria") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ConfigurationJson") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Categoria"); + + b.HasIndex("Nome") + .IsUnique(); + + b.ToTable("VirtualDatasets"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBarcode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("Barcode") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsPrimary") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("Barcode") + .IsUnique(); + + b.ToTable("ArticleBarcodes", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Certifications") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CurrentQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("ExpiryDate") + .HasColumnType("TEXT"); + + b.Property("InitialQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("LastQualityCheckDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ProductionDate") + .HasColumnType("TEXT"); + + b.Property("QualityStatus") + .HasColumnType("INTEGER"); + + b.Property("ReservedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierBatch") + .HasColumnType("TEXT"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("Status"); + + b.HasIndex("ArticleId", "BatchNumber") + .IsUnique(); + + b.ToTable("ArticleBatches", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("Attributes") + .HasColumnType("TEXT"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CurrentWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("CustomerId") + .HasColumnType("INTEGER"); + + b.Property("ManufacturerSerial") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ProductionDate") + .HasColumnType("TEXT"); + + b.Property("SalesReference") + .HasColumnType("TEXT"); + + b.Property("SerialNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SoldDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarrantyExpiryDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("BatchId"); + + b.HasIndex("CurrentWarehouseId"); + + b.HasIndex("Status"); + + b.HasIndex("ArticleId", "SerialNumber") + .IsUnique(); + + b.ToTable("ArticleSerials", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdjustmentMovementId") + .HasColumnType("INTEGER"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ConfirmedBy") + .HasColumnType("TEXT"); + + b.Property("ConfirmedDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("InventoryDate") + .HasColumnType("TEXT"); + + b.Property("NegativeDifferenceValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PositiveDifferenceValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AdjustmentMovementId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("InventoryDate"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("InventoryCounts", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCountLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CountedAt") + .HasColumnType("TEXT"); + + b.Property("CountedBy") + .HasColumnType("TEXT"); + + b.Property("CountedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("InventoryCountId") + .HasColumnType("INTEGER"); + + b.Property("LocationCode") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("SecondCountBy") + .HasColumnType("TEXT"); + + b.Property("SecondCountQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TheoreticalQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("BatchId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("InventoryCountId", "ArticleId", "WarehouseId", "BatchId") + .IsUnique(); + + b.ToTable("InventoryCountLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.MovementReason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsSystem") + .HasColumnType("INTEGER"); + + b.Property("MovementType") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("RequiresExternalReference") + .HasColumnType("INTEGER"); + + b.Property("RequiresValuation") + .HasColumnType("INTEGER"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("StockSign") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("UpdatesAverageCost") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.HasIndex("MovementType"); + + b.ToTable("MovementReasons", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("LastInventoryDate") + .HasColumnType("TEXT"); + + b.Property("LastMovementDate") + .HasColumnType("TEXT"); + + b.Property("LocationCode") + .HasColumnType("TEXT"); + + b.Property("OnOrderQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ReservedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StockValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BatchId"); + + b.HasIndex("LocationCode"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ArticleId", "WarehouseId", "BatchId") + .IsUnique(); + + b.ToTable("StockLevels", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ConfirmedBy") + .HasColumnType("TEXT"); + + b.Property("ConfirmedDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("CustomerId") + .HasColumnType("INTEGER"); + + b.Property("DestinationWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("DocumentNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ExternalDocumentType") + .HasColumnType("INTEGER"); + + b.Property("ExternalReference") + .HasColumnType("TEXT"); + + b.Property("MovementDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ReasonId") + .HasColumnType("INTEGER"); + + b.Property("SourceWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("TotalValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DestinationWarehouseId"); + + b.HasIndex("DocumentNumber") + .IsUnique(); + + b.HasIndex("ExternalReference"); + + b.HasIndex("MovementDate"); + + b.HasIndex("ReasonId"); + + b.HasIndex("SourceWarehouseId"); + + b.HasIndex("Status"); + + b.HasIndex("Type"); + + b.ToTable("StockMovements", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovementLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DestinationLocationCode") + .HasColumnType("TEXT"); + + b.Property("ExternalLineReference") + .HasColumnType("TEXT"); + + b.Property("LineNumber") + .HasColumnType("INTEGER"); + + b.Property("LineValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("MovementId") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SerialId") + .HasColumnType("INTEGER"); + + b.Property("SourceLocationCode") + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitOfMeasure") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("BatchId"); + + b.HasIndex("SerialId"); + + b.HasIndex("MovementId", "LineNumber") + .IsUnique(); + + b.ToTable("StockMovementLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("ClosedBy") + .HasColumnType("TEXT"); + + b.Property("ClosedDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("InboundQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("InboundValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("IsClosed") + .HasColumnType("INTEGER"); + + b.Property("Method") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OutboundQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("OutboundValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Period") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("ValuationDate") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("IsClosed"); + + b.HasIndex("ValuationDate"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("Period", "ArticleId", "WarehouseId") + .IsUnique(); + + b.ToTable("StockValuations", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuationLayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("IsExhausted") + .HasColumnType("INTEGER"); + + b.Property("LayerDate") + .HasColumnType("TEXT"); + + b.Property("OriginalQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("RemainingQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SourceMovementId") + .HasColumnType("INTEGER"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BatchId"); + + b.HasIndex("IsExhausted"); + + b.HasIndex("SourceMovementId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ArticleId", "WarehouseId", "LayerDate"); + + b.ToTable("StockValuationLayers", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AlternativeCode") + .HasColumnType("TEXT"); + + b.Property("Barcode") + .HasColumnType("TEXT"); + + b.Property("BaseSellingPrice") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Depth") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ExpiryWarningDays") + .HasColumnType("INTEGER"); + + b.Property("HasExpiry") + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("TEXT"); + + b.Property("Image") + .HasColumnType("BLOB"); + + b.Property("ImageMimeType") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsBatchManaged") + .HasColumnType("INTEGER"); + + b.Property("IsSerialManaged") + .HasColumnType("INTEGER"); + + b.Property("LastPurchaseCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("LeadTimeDays") + .HasColumnType("INTEGER"); + + b.Property("ManufacturerCode") + .HasColumnType("TEXT"); + + b.Property("MaximumStock") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("MinimumStock") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ReorderQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SecondaryUnitOfMeasure") + .HasColumnType("TEXT"); + + b.Property("ShortDescription") + .HasColumnType("TEXT"); + + b.Property("StandardCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StockManagement") + .HasColumnType("INTEGER"); + + b.Property("UnitConversionFactor") + .HasPrecision(18, 6) + .HasColumnType("TEXT"); + + b.Property("UnitOfMeasure") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("ValuationMethod") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .HasPrecision(18, 6) + .HasColumnType("TEXT"); + + b.Property("Weight") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("WeightedAverageCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Barcode"); + + b.HasIndex("CategoryId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.ToTable("WarehouseArticles", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AlternativeCode") + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Color") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DefaultValuationMethod") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("FullPath") + .HasColumnType("TEXT"); + + b.Property("Icon") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ParentCategoryId") + .HasColumnType("INTEGER"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("FullPath"); + + b.HasIndex("ParentCategoryId"); + + b.ToTable("WarehouseArticleCategories", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("AlternativeCode") + .HasColumnType("TEXT"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Country") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PostalCode") + .HasColumnType("TEXT"); + + b.Property("Province") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.HasIndex("IsDefault"); + + b.ToTable("WarehouseLocations", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Articolo", b => + { + b.HasOne("Zentral.Domain.Entities.CodiceCategoria", "Categoria") + .WithMany("Articoli") + .HasForeignKey("CategoriaId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.TipoMateriale", "TipoMateriale") + .WithMany("Articoli") + .HasForeignKey("TipoMaterialeId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Categoria"); + + b.Navigation("TipoMateriale"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Evento", b => + { + b.HasOne("Zentral.Domain.Entities.Cliente", "Cliente") + .WithMany("Eventi") + .HasForeignKey("ClienteId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Location", "Location") + .WithMany("Eventi") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.TipoEvento", "TipoEvento") + .WithMany("Eventi") + .HasForeignKey("TipoEventoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Cliente"); + + b.Navigation("Location"); + + b.Navigation("TipoEvento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAcconto", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("Acconti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAllegato", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("Allegati") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAltroCosto", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("AltriCosti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDegustazione", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("Degustazioni") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioOspiti", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("DettagliOspiti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.TipoOspite", "TipoOspite") + .WithMany("DettagliOspiti") + .HasForeignKey("TipoOspiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + + b.Navigation("TipoOspite"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioPrelievo", b => + { + b.HasOne("Zentral.Domain.Entities.Articolo", "Articolo") + .WithMany("DettagliPrelievo") + .HasForeignKey("ArticoloId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("DettagliPrelievo") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Articolo"); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioRisorsa", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("DettagliRisorse") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Risorsa", "Risorsa") + .WithMany("DettagliRisorse") + .HasForeignKey("RisorsaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + + b.Navigation("Risorsa"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ModuleSubscription", b => + { + b.HasOne("Zentral.Domain.Entities.AppModule", "Module") + .WithOne("Subscription") + .HasForeignKey("Zentral.Domain.Entities.ModuleSubscription", "ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Assenza", b => + { + b.HasOne("Zentral.Domain.Entities.Personale.Dipendente", "Dipendente") + .WithMany("Assenze") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Contratto", b => + { + b.HasOne("Zentral.Domain.Entities.Personale.Dipendente", "Dipendente") + .WithMany("Contratti") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Pagamento", b => + { + b.HasOne("Zentral.Domain.Entities.Personale.Dipendente", "Dipendente") + .WithMany("Pagamenti") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Rimborso", b => + { + b.HasOne("Zentral.Domain.Entities.Personale.Dipendente", "Dipendente") + .WithMany("Rimborsi") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterials", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterialsComponent", b => + { + b.HasOne("Zentral.Domain.Entities.Production.BillOfMaterials", "BillOfMaterials") + .WithMany("Components") + .HasForeignKey("BillOfMaterialsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "ComponentArticle") + .WithMany() + .HasForeignKey("ComponentArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BillOfMaterials"); + + b.Navigation("ComponentArticle"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.MrpSuggestion", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCycle", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCyclePhase", b => + { + b.HasOne("Zentral.Domain.Entities.Production.ProductionCycle", "ProductionCycle") + .WithMany("Phases") + .HasForeignKey("ProductionCycleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.WorkCenter", "WorkCenter") + .WithMany() + .HasForeignKey("WorkCenterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ProductionCycle"); + + b.Navigation("WorkCenter"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrder", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.ProductionOrder", "ParentProductionOrder") + .WithMany("ChildProductionOrders") + .HasForeignKey("ParentProductionOrderId"); + + b.Navigation("Article"); + + b.Navigation("ParentProductionOrder"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderComponent", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.ProductionOrder", "ProductionOrder") + .WithMany("Components") + .HasForeignKey("ProductionOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("ProductionOrder"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderPhase", b => + { + b.HasOne("Zentral.Domain.Entities.Production.ProductionOrder", "ProductionOrder") + .WithMany("Phases") + .HasForeignKey("ProductionOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.WorkCenter", "WorkCenter") + .WithMany() + .HasForeignKey("WorkCenterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ProductionOrder"); + + b.Navigation("WorkCenter"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrder", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "DestinationWarehouse") + .WithMany() + .HasForeignKey("DestinationWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Purchases.Supplier", "Supplier") + .WithMany("PurchaseOrders") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DestinationWarehouse"); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrderLine", b => + { + b.HasOne("Zentral.Domain.Entities.Purchases.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PurchaseOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "WarehouseArticle") + .WithMany() + .HasForeignKey("WarehouseArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("WarehouseArticle"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Risorsa", b => + { + b.HasOne("Zentral.Domain.Entities.TipoRisorsa", "TipoRisorsa") + .WithMany("Risorse") + .HasForeignKey("TipoRisorsaId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("TipoRisorsa"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrder", b => + { + b.HasOne("Zentral.Domain.Entities.Cliente", "Customer") + .WithMany("SalesOrders") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrderLine", b => + { + b.HasOne("Zentral.Domain.Entities.Sales.SalesOrder", "SalesOrder") + .WithMany("Lines") + .HasForeignKey("SalesOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "WarehouseArticle") + .WithMany() + .HasForeignKey("WarehouseArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SalesOrder"); + + b.Navigation("WarehouseArticle"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoEvento", b => + { + b.HasOne("Zentral.Domain.Entities.TipoPasto", "TipoPasto") + .WithMany("TipiEvento") + .HasForeignKey("TipoPastoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("TipoPasto"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBarcode", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Barcodes") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Batches") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Serials") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("Serials") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "CurrentWarehouse") + .WithMany() + .HasForeignKey("CurrentWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("CurrentWarehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCount", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.StockMovement", "AdjustmentMovement") + .WithMany() + .HasForeignKey("AdjustmentMovementId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("AdjustmentMovement"); + + b.Navigation("Category"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCountLine", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.InventoryCount", "InventoryCount") + .WithMany("Lines") + .HasForeignKey("InventoryCountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("InventoryCount"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockLevel", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("StockLevels") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("StockLevels") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany("StockLevels") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovement", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "DestinationWarehouse") + .WithMany("DestinationMovements") + .HasForeignKey("DestinationWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Zentral.Domain.Entities.Warehouse.MovementReason", "Reason") + .WithMany("Movements") + .HasForeignKey("ReasonId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "SourceWarehouse") + .WithMany("SourceMovements") + .HasForeignKey("SourceWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("DestinationWarehouse"); + + b.Navigation("Reason"); + + b.Navigation("SourceWarehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovementLine", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("MovementLines") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("MovementLines") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.StockMovement", "Movement") + .WithMany("Lines") + .HasForeignKey("MovementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleSerial", "Serial") + .WithMany("MovementLines") + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("Movement"); + + b.Navigation("Serial"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuation", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuationLayer", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.StockMovement", "SourceMovement") + .WithMany() + .HasForeignKey("SourceMovementId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("SourceMovement"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", "Category") + .WithMany("Articles") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", "ParentCategory") + .WithMany("ChildCategories") + .HasForeignKey("ParentCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ParentCategory"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.AppModule", b => + { + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Articolo", b => + { + b.Navigation("DettagliPrelievo"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Cliente", b => + { + b.Navigation("Eventi"); + + b.Navigation("SalesOrders"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.CodiceCategoria", b => + { + b.Navigation("Articoli"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Evento", b => + { + b.Navigation("Acconti"); + + b.Navigation("Allegati"); + + b.Navigation("AltriCosti"); + + b.Navigation("Degustazioni"); + + b.Navigation("DettagliOspiti"); + + b.Navigation("DettagliPrelievo"); + + b.Navigation("DettagliRisorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Location", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Personale.Dipendente", b => + { + b.Navigation("Assenze"); + + b.Navigation("Contratti"); + + b.Navigation("Pagamenti"); + + b.Navigation("Rimborsi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterials", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCycle", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrder", b => + { + b.Navigation("ChildProductionOrders"); + + b.Navigation("Components"); + + b.Navigation("Phases"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.Supplier", b => + { + b.Navigation("PurchaseOrders"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Risorsa", b => + { + b.Navigation("DettagliRisorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoEvento", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoMateriale", b => + { + b.Navigation("Articoli"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoOspite", b => + { + b.Navigation("DettagliOspiti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoPasto", b => + { + b.Navigation("TipiEvento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoRisorsa", b => + { + b.Navigation("Risorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.Navigation("MovementLines"); + + b.Navigation("Serials"); + + b.Navigation("StockLevels"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.Navigation("MovementLines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.MovementReason", b => + { + b.Navigation("Movements"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovement", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.Navigation("Barcodes"); + + b.Navigation("Batches"); + + b.Navigation("MovementLines"); + + b.Navigation("Serials"); + + b.Navigation("StockLevels"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.Navigation("Articles"); + + b.Navigation("ChildCategories"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseLocation", b => + { + b.Navigation("DestinationMovements"); + + b.Navigation("SourceMovements"); + + b.Navigation("StockLevels"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/backend/Zentral.Infrastructure/Migrations/20251203190021_AddPersonaleModule.cs b/src/backend/Zentral.Infrastructure/Migrations/20251203190021_AddPersonaleModule.cs new file mode 100644 index 0000000..fbc9309 --- /dev/null +++ b/src/backend/Zentral.Infrastructure/Migrations/20251203190021_AddPersonaleModule.cs @@ -0,0 +1,201 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Zentral.Infrastructure.Migrations +{ + /// + public partial class AddPersonaleModule : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Dipendenti", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Nome = table.Column(type: "TEXT", nullable: false), + Cognome = table.Column(type: "TEXT", nullable: false), + CodiceFiscale = table.Column(type: "TEXT", nullable: true), + Email = table.Column(type: "TEXT", nullable: true), + Telefono = table.Column(type: "TEXT", nullable: true), + Indirizzo = table.Column(type: "TEXT", nullable: true), + DataNascita = table.Column(type: "TEXT", nullable: true), + Ruolo = table.Column(type: "TEXT", nullable: true), + CreatedAt = table.Column(type: "TEXT", nullable: true), + CreatedBy = table.Column(type: "TEXT", nullable: true), + UpdatedAt = table.Column(type: "TEXT", nullable: true), + UpdatedBy = table.Column(type: "TEXT", nullable: true), + CustomFieldsJson = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Dipendenti", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Assenze", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DipendenteId = table.Column(type: "INTEGER", nullable: false), + DataInizio = table.Column(type: "TEXT", nullable: false), + DataFine = table.Column(type: "TEXT", nullable: false), + TipoAssenza = table.Column(type: "TEXT", nullable: false), + Stato = table.Column(type: "TEXT", nullable: false), + Note = table.Column(type: "TEXT", nullable: true), + CreatedAt = table.Column(type: "TEXT", nullable: true), + CreatedBy = table.Column(type: "TEXT", nullable: true), + UpdatedAt = table.Column(type: "TEXT", nullable: true), + UpdatedBy = table.Column(type: "TEXT", nullable: true), + CustomFieldsJson = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Assenze", x => x.Id); + table.ForeignKey( + name: "FK_Assenze_Dipendenti_DipendenteId", + column: x => x.DipendenteId, + principalTable: "Dipendenti", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Contratti", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DipendenteId = table.Column(type: "INTEGER", nullable: false), + DataInizio = table.Column(type: "TEXT", nullable: false), + DataFine = table.Column(type: "TEXT", nullable: true), + TipoContratto = table.Column(type: "TEXT", nullable: false), + Livello = table.Column(type: "TEXT", nullable: true), + RetribuzioneLorda = table.Column(type: "TEXT", precision: 18, scale: 2, nullable: false), + Note = table.Column(type: "TEXT", nullable: true), + Attivo = table.Column(type: "INTEGER", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: true), + CreatedBy = table.Column(type: "TEXT", nullable: true), + UpdatedAt = table.Column(type: "TEXT", nullable: true), + UpdatedBy = table.Column(type: "TEXT", nullable: true), + CustomFieldsJson = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Contratti", x => x.Id); + table.ForeignKey( + name: "FK_Contratti_Dipendenti_DipendenteId", + column: x => x.DipendenteId, + principalTable: "Dipendenti", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Pagamenti", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DipendenteId = table.Column(type: "INTEGER", nullable: false), + DataPagamento = table.Column(type: "TEXT", nullable: false), + ImportoNetto = table.Column(type: "TEXT", precision: 18, scale: 2, nullable: false), + Descrizione = table.Column(type: "TEXT", nullable: false), + Pagato = table.Column(type: "INTEGER", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: true), + CreatedBy = table.Column(type: "TEXT", nullable: true), + UpdatedAt = table.Column(type: "TEXT", nullable: true), + UpdatedBy = table.Column(type: "TEXT", nullable: true), + CustomFieldsJson = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Pagamenti", x => x.Id); + table.ForeignKey( + name: "FK_Pagamenti_Dipendenti_DipendenteId", + column: x => x.DipendenteId, + principalTable: "Dipendenti", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Rimborsi", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DipendenteId = table.Column(type: "INTEGER", nullable: false), + DataSpesa = table.Column(type: "TEXT", nullable: false), + Importo = table.Column(type: "TEXT", precision: 18, scale: 2, nullable: false), + Descrizione = table.Column(type: "TEXT", nullable: false), + Stato = table.Column(type: "TEXT", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: true), + CreatedBy = table.Column(type: "TEXT", nullable: true), + UpdatedAt = table.Column(type: "TEXT", nullable: true), + UpdatedBy = table.Column(type: "TEXT", nullable: true), + CustomFieldsJson = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Rimborsi", x => x.Id); + table.ForeignKey( + name: "FK_Rimborsi_Dipendenti_DipendenteId", + column: x => x.DipendenteId, + principalTable: "Dipendenti", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Assenze_DipendenteId", + table: "Assenze", + column: "DipendenteId"); + + migrationBuilder.CreateIndex( + name: "IX_Contratti_DipendenteId", + table: "Contratti", + column: "DipendenteId"); + + migrationBuilder.CreateIndex( + name: "IX_Dipendenti_CodiceFiscale", + table: "Dipendenti", + column: "CodiceFiscale", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Pagamenti_DipendenteId", + table: "Pagamenti", + column: "DipendenteId"); + + migrationBuilder.CreateIndex( + name: "IX_Rimborsi_DipendenteId", + table: "Rimborsi", + column: "DipendenteId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Assenze"); + + migrationBuilder.DropTable( + name: "Contratti"); + + migrationBuilder.DropTable( + name: "Pagamenti"); + + migrationBuilder.DropTable( + name: "Rimborsi"); + + migrationBuilder.DropTable( + name: "Dipendenti"); + } + } +} diff --git a/src/backend/Zentral.Infrastructure/Migrations/20251203190418_RenamePersonaleToHR.Designer.cs b/src/backend/Zentral.Infrastructure/Migrations/20251203190418_RenamePersonaleToHR.Designer.cs new file mode 100644 index 0000000..e16f59e --- /dev/null +++ b/src/backend/Zentral.Infrastructure/Migrations/20251203190418_RenamePersonaleToHR.Designer.cs @@ -0,0 +1,4657 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Zentral.Infrastructure.Data; + +#nullable disable + +namespace Zentral.Infrastructure.Migrations +{ + [DbContext(typeof(ZentralDbContext))] + [Migration("20251203190418_RenamePersonaleToHR")] + partial class RenamePersonaleToHR + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("Zentral.Domain.Entities.AppModule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BasePrice") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Dependencies") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Icon") + .HasColumnType("TEXT"); + + b.Property("IsAvailable") + .HasColumnType("INTEGER"); + + b.Property("IsCore") + .HasColumnType("INTEGER"); + + b.Property("MonthlyMultiplier") + .HasPrecision(5, 2) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RoutePath") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("SortOrder"); + + b.ToTable("AppModules"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Articolo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CategoriaId") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CodiceAlternativo") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Immagine") + .HasColumnType("BLOB"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("QtaDisponibile") + .HasColumnType("TEXT"); + + b.Property("QtaStdA") + .HasColumnType("TEXT"); + + b.Property("QtaStdB") + .HasColumnType("TEXT"); + + b.Property("QtaStdS") + .HasColumnType("TEXT"); + + b.Property("TipoMaterialeId") + .HasColumnType("INTEGER"); + + b.Property("UnitaMisura") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CategoriaId"); + + b.HasIndex("Codice") + .IsUnique(); + + b.HasIndex("TipoMaterialeId"); + + b.ToTable("Articoli"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.AutoCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EntityCode") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EntityName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("IsReadOnly") + .HasColumnType("INTEGER"); + + b.Property("LastResetMonth") + .HasColumnType("INTEGER"); + + b.Property("LastResetYear") + .HasColumnType("INTEGER"); + + b.Property("LastSequence") + .HasColumnType("INTEGER"); + + b.Property("ModuleCode") + .HasColumnType("TEXT"); + + b.Property("Pattern") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("ResetSequenceMonthly") + .HasColumnType("INTEGER"); + + b.Property("ResetSequenceYearly") + .HasColumnType("INTEGER"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EntityCode") + .IsUnique(); + + b.HasIndex("ModuleCode"); + + b.ToTable("AutoCodes"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Cliente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cap") + .HasColumnType("TEXT"); + + b.Property("Citta") + .HasColumnType("TEXT"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CodiceAlternativo") + .HasColumnType("TEXT"); + + b.Property("CodiceDestinatario") + .HasColumnType("TEXT"); + + b.Property("CodiceFiscale") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("PartitaIva") + .HasColumnType("TEXT"); + + b.Property("Pec") + .HasColumnType("TEXT"); + + b.Property("Provincia") + .HasColumnType("TEXT"); + + b.Property("RagioneSociale") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PartitaIva"); + + b.HasIndex("RagioneSociale"); + + b.ToTable("Clienti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.CodiceCategoria", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CoeffA") + .HasColumnType("TEXT"); + + b.Property("CoeffB") + .HasColumnType("TEXT"); + + b.Property("CoeffS") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("CodiciCategoria"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Configurazione", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Chiave") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("Valore") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Chiave") + .IsUnique(); + + b.ToTable("Configurazioni"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.CustomFieldDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DefaultValue") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EntityName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsRequired") + .HasColumnType("INTEGER"); + + b.Property("Label") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OptionsJson") + .HasColumnType("TEXT"); + + b.Property("Placeholder") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("ValidationRegex") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EntityName"); + + b.HasIndex("EntityName", "FieldName") + .IsUnique(); + + b.ToTable("CustomFieldDefinitions"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Evento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClienteId") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .HasColumnType("TEXT"); + + b.Property("Confermato") + .HasColumnType("INTEGER"); + + b.Property("CostoPersona") + .HasColumnType("TEXT"); + + b.Property("CostoTotale") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataEvento") + .HasColumnType("TEXT"); + + b.Property("DataScadenzaPreventivo") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("LocationId") + .HasColumnType("INTEGER"); + + b.Property("NoteAllestimento") + .HasColumnType("TEXT"); + + b.Property("NoteCliente") + .HasColumnType("TEXT"); + + b.Property("NoteCucina") + .HasColumnType("TEXT"); + + b.Property("NoteInterne") + .HasColumnType("TEXT"); + + b.Property("NumeroOspiti") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiAdulti") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiBambini") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiBuffet") + .HasColumnType("INTEGER"); + + b.Property("NumeroOspitiSeduti") + .HasColumnType("INTEGER"); + + b.Property("OraFine") + .HasColumnType("TEXT"); + + b.Property("OraInizio") + .HasColumnType("TEXT"); + + b.Property("Saldo") + .HasColumnType("TEXT"); + + b.Property("Stato") + .HasColumnType("INTEGER"); + + b.Property("TipoEventoId") + .HasColumnType("INTEGER"); + + b.Property("TotaleAcconti") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ClienteId"); + + b.HasIndex("Codice"); + + b.HasIndex("DataEvento"); + + b.HasIndex("LocationId"); + + b.HasIndex("Stato"); + + b.HasIndex("TipoEventoId"); + + b.ToTable("Eventi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAcconto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AConferma") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataPagamento") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Importo") + .HasColumnType("TEXT"); + + b.Property("MetodoPagamento") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Ordine") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiAcconti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAllegato", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Contenuto") + .HasColumnType("BLOB"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("NomeFile") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiAllegati"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAltroCosto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AliquotaIva") + .HasColumnType("TEXT"); + + b.Property("ApplicaIva") + .HasColumnType("INTEGER"); + + b.Property("CostoUnitario") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Ordine") + .HasColumnType("INTEGER"); + + b.Property("Quantita") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiAltriCosti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDegustazione", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completata") + .HasColumnType("INTEGER"); + + b.Property("CostoDegustazione") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataDegustazione") + .HasColumnType("TEXT"); + + b.Property("Detraibile") + .HasColumnType("INTEGER"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Luogo") + .HasColumnType("TEXT"); + + b.Property("Menu") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("NumeroPaganti") + .HasColumnType("INTEGER"); + + b.Property("NumeroPersone") + .HasColumnType("INTEGER"); + + b.Property("Ora") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiDegustazioni"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioOspiti", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CostoUnitario") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Numero") + .HasColumnType("INTEGER"); + + b.Property("Ordine") + .HasColumnType("INTEGER"); + + b.Property("Sconto") + .HasColumnType("TEXT"); + + b.Property("TipoOspiteId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.HasIndex("TipoOspiteId"); + + b.ToTable("EventiDettaglioOspiti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioPrelievo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticoloId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("QtaCalcolata") + .HasColumnType("TEXT"); + + b.Property("QtaEffettiva") + .HasColumnType("TEXT"); + + b.Property("QtaRichiesta") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticoloId"); + + b.HasIndex("EventoId"); + + b.ToTable("EventiDettaglioPrelievo"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioRisorsa", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Costo") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EventoId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OraFine") + .HasColumnType("TEXT"); + + b.Property("OraInizio") + .HasColumnType("TEXT"); + + b.Property("OreLavoro") + .HasColumnType("TEXT"); + + b.Property("RisorsaId") + .HasColumnType("INTEGER"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventoId"); + + b.HasIndex("RisorsaId"); + + b.ToTable("EventiDettaglioRisorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Assenza", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataFine") + .HasColumnType("TEXT"); + + b.Property("DataInizio") + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Stato") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TipoAssenza") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Assenze", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Contratto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataFine") + .HasColumnType("TEXT"); + + b.Property("DataInizio") + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Livello") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("RetribuzioneLorda") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("TipoContratto") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Contratti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Dipendente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CodiceFiscale") + .HasColumnType("TEXT"); + + b.Property("Cognome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataNascita") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CodiceFiscale") + .IsUnique(); + + b.ToTable("Dipendenti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Pagamento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataPagamento") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("ImportoNetto") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Pagato") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Pagamenti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Rimborso", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataSpesa") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Importo") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Stato") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Rimborsi", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cap") + .HasColumnType("TEXT"); + + b.Property("Citta") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DistanzaKm") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Provincia") + .HasColumnType("TEXT"); + + b.Property("Referente") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Nome"); + + b.ToTable("Location"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ModuleSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRenew") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("LastRenewalDate") + .HasColumnType("TEXT"); + + b.Property("ModuleId") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PaidPrice") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("SubscriptionType") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ModuleId") + .IsUnique(); + + b.ToTable("ModuleSubscriptions"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterials", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("IsActive"); + + b.ToTable("BillOfMaterials", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterialsComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BillOfMaterialsId") + .HasColumnType("INTEGER"); + + b.Property("ComponentArticleId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ScrapPercentage") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("BillOfMaterialsId"); + + b.HasIndex("ComponentArticleId"); + + b.ToTable("BillOfMaterialsComponents", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.MrpSuggestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("CalculationDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("IsProcessed") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SuggestionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("CalculationDate"); + + b.HasIndex("IsProcessed"); + + b.ToTable("MrpSuggestions", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCycle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("IsActive"); + + b.ToTable("ProductionCycles", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCyclePhase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("DurationPerUnitMinutes") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProductionCycleId") + .HasColumnType("INTEGER"); + + b.Property("Sequence") + .HasColumnType("INTEGER"); + + b.Property("SetupTimeMinutes") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WorkCenterId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProductionCycleId"); + + b.HasIndex("WorkCenterId"); + + b.ToTable("ProductionCyclePhases", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DueDate") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ParentProductionOrderId") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("ParentProductionOrderId"); + + b.HasIndex("StartDate"); + + b.HasIndex("Status"); + + b.ToTable("ProductionOrders", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("ConsumedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("ProductionOrderId") + .HasColumnType("INTEGER"); + + b.Property("RequiredQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("ProductionOrderId"); + + b.ToTable("ProductionOrderComponents", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderPhase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActualDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("EstimatedDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProductionOrderId") + .HasColumnType("INTEGER"); + + b.Property("QuantityCompleted") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("QuantityScrapped") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Sequence") + .HasColumnType("INTEGER"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WorkCenterId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProductionOrderId"); + + b.HasIndex("Status"); + + b.HasIndex("WorkCenterId"); + + b.ToTable("ProductionOrderPhases", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.WorkCenter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CostPerHour") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.ToTable("WorkCenters", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DestinationWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OrderDate") + .HasColumnType("TEXT"); + + b.Property("OrderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("TotalGross") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalNet") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalTax") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DestinationWarehouseId"); + + b.HasIndex("OrderDate"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SupplierId"); + + b.ToTable("PurchaseOrders", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DiscountPercent") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("PurchaseOrderId") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ReceivedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TaxRate") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseArticleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseOrderId"); + + b.HasIndex("WarehouseArticleId"); + + b.ToTable("PurchaseOrderLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Country") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("FiscalCode") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PaymentTerms") + .HasColumnType("TEXT"); + + b.Property("Pec") + .HasColumnType("TEXT"); + + b.Property("Phone") + .HasColumnType("TEXT"); + + b.Property("Province") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("VatNumber") + .HasColumnType("TEXT"); + + b.Property("Website") + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.HasIndex("Name"); + + b.HasIndex("VatNumber"); + + b.ToTable("Suppliers", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ReportFont", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("FileSize") + .HasColumnType("INTEGER"); + + b.Property("FontData") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("FontFamily") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FontStyle") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("MimeType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("FontFamily"); + + b.ToTable("ReportFonts"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ReportImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Categoria") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("FileSize") + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("INTEGER"); + + b.Property("ImageData") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("MimeType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Categoria"); + + b.ToTable("ReportImages"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ReportTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Categoria") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Orientation") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PageSize") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TemplateJson") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Thumbnail") + .HasColumnType("BLOB"); + + b.Property("ThumbnailMimeType") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Categoria"); + + b.HasIndex("Nome"); + + b.ToTable("ReportTemplates"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Risorsa", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cognome") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("TipoRisorsaId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TipoRisorsaId"); + + b.ToTable("Risorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("CustomerId") + .HasColumnType("INTEGER"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OrderDate") + .HasColumnType("TEXT"); + + b.Property("OrderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("TotalGross") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalNet") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalTax") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.HasIndex("OrderDate"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("SalesOrders", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DiscountPercent") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SalesOrderId") + .HasColumnType("INTEGER"); + + b.Property("ShippedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TaxRate") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseArticleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SalesOrderId"); + + b.HasIndex("WarehouseArticleId"); + + b.ToTable("SalesOrderLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoEvento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TipoPastoId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TipoPastoId"); + + b.ToTable("TipiEvento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoMateriale", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiMateriale"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoOspite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiOspite"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoPasto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiPasto"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoRisorsa", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Codice") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TipiRisorsa"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Utente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Cognome") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Nome") + .HasColumnType("TEXT"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("SolaLettura") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("Utenti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.VirtualDataset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("Categoria") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ConfigurationJson") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Categoria"); + + b.HasIndex("Nome") + .IsUnique(); + + b.ToTable("VirtualDatasets"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBarcode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("Barcode") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsPrimary") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("Barcode") + .IsUnique(); + + b.ToTable("ArticleBarcodes", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Certifications") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CurrentQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("ExpiryDate") + .HasColumnType("TEXT"); + + b.Property("InitialQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("LastQualityCheckDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ProductionDate") + .HasColumnType("TEXT"); + + b.Property("QualityStatus") + .HasColumnType("INTEGER"); + + b.Property("ReservedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierBatch") + .HasColumnType("TEXT"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("Status"); + + b.HasIndex("ArticleId", "BatchNumber") + .IsUnique(); + + b.ToTable("ArticleBatches", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("Attributes") + .HasColumnType("TEXT"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CurrentWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("CustomerId") + .HasColumnType("INTEGER"); + + b.Property("ManufacturerSerial") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ProductionDate") + .HasColumnType("TEXT"); + + b.Property("SalesReference") + .HasColumnType("TEXT"); + + b.Property("SerialNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SoldDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarrantyExpiryDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("BatchId"); + + b.HasIndex("CurrentWarehouseId"); + + b.HasIndex("Status"); + + b.HasIndex("ArticleId", "SerialNumber") + .IsUnique(); + + b.ToTable("ArticleSerials", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdjustmentMovementId") + .HasColumnType("INTEGER"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ConfirmedBy") + .HasColumnType("TEXT"); + + b.Property("ConfirmedDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("InventoryDate") + .HasColumnType("TEXT"); + + b.Property("NegativeDifferenceValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PositiveDifferenceValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AdjustmentMovementId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("InventoryDate"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("InventoryCounts", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCountLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CountedAt") + .HasColumnType("TEXT"); + + b.Property("CountedBy") + .HasColumnType("TEXT"); + + b.Property("CountedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("InventoryCountId") + .HasColumnType("INTEGER"); + + b.Property("LocationCode") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("SecondCountBy") + .HasColumnType("TEXT"); + + b.Property("SecondCountQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TheoreticalQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("BatchId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("InventoryCountId", "ArticleId", "WarehouseId", "BatchId") + .IsUnique(); + + b.ToTable("InventoryCountLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.MovementReason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsSystem") + .HasColumnType("INTEGER"); + + b.Property("MovementType") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("RequiresExternalReference") + .HasColumnType("INTEGER"); + + b.Property("RequiresValuation") + .HasColumnType("INTEGER"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("StockSign") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("UpdatesAverageCost") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.HasIndex("MovementType"); + + b.ToTable("MovementReasons", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("LastInventoryDate") + .HasColumnType("TEXT"); + + b.Property("LastMovementDate") + .HasColumnType("TEXT"); + + b.Property("LocationCode") + .HasColumnType("TEXT"); + + b.Property("OnOrderQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ReservedQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StockValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BatchId"); + + b.HasIndex("LocationCode"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ArticleId", "WarehouseId", "BatchId") + .IsUnique(); + + b.ToTable("StockLevels", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ConfirmedBy") + .HasColumnType("TEXT"); + + b.Property("ConfirmedDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("CustomerId") + .HasColumnType("INTEGER"); + + b.Property("DestinationWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("DocumentNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ExternalDocumentType") + .HasColumnType("INTEGER"); + + b.Property("ExternalReference") + .HasColumnType("TEXT"); + + b.Property("MovementDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ReasonId") + .HasColumnType("INTEGER"); + + b.Property("SourceWarehouseId") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("SupplierId") + .HasColumnType("INTEGER"); + + b.Property("TotalValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DestinationWarehouseId"); + + b.HasIndex("DocumentNumber") + .IsUnique(); + + b.HasIndex("ExternalReference"); + + b.HasIndex("MovementDate"); + + b.HasIndex("ReasonId"); + + b.HasIndex("SourceWarehouseId"); + + b.HasIndex("Status"); + + b.HasIndex("Type"); + + b.ToTable("StockMovements", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovementLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DestinationLocationCode") + .HasColumnType("TEXT"); + + b.Property("ExternalLineReference") + .HasColumnType("TEXT"); + + b.Property("LineNumber") + .HasColumnType("INTEGER"); + + b.Property("LineValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("MovementId") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SerialId") + .HasColumnType("INTEGER"); + + b.Property("SourceLocationCode") + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitOfMeasure") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("BatchId"); + + b.HasIndex("SerialId"); + + b.HasIndex("MovementId", "LineNumber") + .IsUnique(); + + b.ToTable("StockMovementLines", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("ClosedBy") + .HasColumnType("TEXT"); + + b.Property("ClosedDate") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("InboundQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("InboundValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("IsClosed") + .HasColumnType("INTEGER"); + + b.Property("Method") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OutboundQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("OutboundValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Period") + .HasColumnType("INTEGER"); + + b.Property("Quantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("TotalValue") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("ValuationDate") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("IsClosed"); + + b.HasIndex("ValuationDate"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("Period", "ArticleId", "WarehouseId") + .IsUnique(); + + b.ToTable("StockValuations", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuationLayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArticleId") + .HasColumnType("INTEGER"); + + b.Property("BatchId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("IsExhausted") + .HasColumnType("INTEGER"); + + b.Property("LayerDate") + .HasColumnType("TEXT"); + + b.Property("OriginalQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("RemainingQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SourceMovementId") + .HasColumnType("INTEGER"); + + b.Property("UnitCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("WarehouseId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("BatchId"); + + b.HasIndex("IsExhausted"); + + b.HasIndex("SourceMovementId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ArticleId", "WarehouseId", "LayerDate"); + + b.ToTable("StockValuationLayers", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AlternativeCode") + .HasColumnType("TEXT"); + + b.Property("Barcode") + .HasColumnType("TEXT"); + + b.Property("BaseSellingPrice") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Depth") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ExpiryWarningDays") + .HasColumnType("INTEGER"); + + b.Property("HasExpiry") + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("TEXT"); + + b.Property("Image") + .HasColumnType("BLOB"); + + b.Property("ImageMimeType") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsBatchManaged") + .HasColumnType("INTEGER"); + + b.Property("IsSerialManaged") + .HasColumnType("INTEGER"); + + b.Property("LastPurchaseCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("LeadTimeDays") + .HasColumnType("INTEGER"); + + b.Property("ManufacturerCode") + .HasColumnType("TEXT"); + + b.Property("MaximumStock") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("MinimumStock") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("ReorderQuantity") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("SecondaryUnitOfMeasure") + .HasColumnType("TEXT"); + + b.Property("ShortDescription") + .HasColumnType("TEXT"); + + b.Property("StandardCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("StockManagement") + .HasColumnType("INTEGER"); + + b.Property("UnitConversionFactor") + .HasPrecision(18, 6) + .HasColumnType("TEXT"); + + b.Property("UnitOfMeasure") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.Property("ValuationMethod") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .HasPrecision(18, 6) + .HasColumnType("TEXT"); + + b.Property("Weight") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("WeightedAverageCost") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Barcode"); + + b.HasIndex("CategoryId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.ToTable("WarehouseArticles", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AlternativeCode") + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Color") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DefaultValuationMethod") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("FullPath") + .HasColumnType("TEXT"); + + b.Property("Icon") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ParentCategoryId") + .HasColumnType("INTEGER"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("FullPath"); + + b.HasIndex("ParentCategoryId"); + + b.ToTable("WarehouseArticleCategories", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("AlternativeCode") + .HasColumnType("TEXT"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Country") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("PostalCode") + .HasColumnType("TEXT"); + + b.Property("Province") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("IsActive"); + + b.HasIndex("IsDefault"); + + b.ToTable("WarehouseLocations", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Articolo", b => + { + b.HasOne("Zentral.Domain.Entities.CodiceCategoria", "Categoria") + .WithMany("Articoli") + .HasForeignKey("CategoriaId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.TipoMateriale", "TipoMateriale") + .WithMany("Articoli") + .HasForeignKey("TipoMaterialeId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Categoria"); + + b.Navigation("TipoMateriale"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Evento", b => + { + b.HasOne("Zentral.Domain.Entities.Cliente", "Cliente") + .WithMany("Eventi") + .HasForeignKey("ClienteId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Location", "Location") + .WithMany("Eventi") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.TipoEvento", "TipoEvento") + .WithMany("Eventi") + .HasForeignKey("TipoEventoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Cliente"); + + b.Navigation("Location"); + + b.Navigation("TipoEvento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAcconto", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("Acconti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAllegato", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("Allegati") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoAltroCosto", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("AltriCosti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDegustazione", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("Degustazioni") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioOspiti", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("DettagliOspiti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.TipoOspite", "TipoOspite") + .WithMany("DettagliOspiti") + .HasForeignKey("TipoOspiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + + b.Navigation("TipoOspite"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioPrelievo", b => + { + b.HasOne("Zentral.Domain.Entities.Articolo", "Articolo") + .WithMany("DettagliPrelievo") + .HasForeignKey("ArticoloId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("DettagliPrelievo") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Articolo"); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.EventoDettaglioRisorsa", b => + { + b.HasOne("Zentral.Domain.Entities.Evento", "Evento") + .WithMany("DettagliRisorse") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Risorsa", "Risorsa") + .WithMany("DettagliRisorse") + .HasForeignKey("RisorsaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + + b.Navigation("Risorsa"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Assenza", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Assenze") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Contratto", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Contratti") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Pagamento", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Pagamenti") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Rimborso", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Rimborsi") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.ModuleSubscription", b => + { + b.HasOne("Zentral.Domain.Entities.AppModule", "Module") + .WithOne("Subscription") + .HasForeignKey("Zentral.Domain.Entities.ModuleSubscription", "ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterials", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterialsComponent", b => + { + b.HasOne("Zentral.Domain.Entities.Production.BillOfMaterials", "BillOfMaterials") + .WithMany("Components") + .HasForeignKey("BillOfMaterialsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "ComponentArticle") + .WithMany() + .HasForeignKey("ComponentArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BillOfMaterials"); + + b.Navigation("ComponentArticle"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.MrpSuggestion", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCycle", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCyclePhase", b => + { + b.HasOne("Zentral.Domain.Entities.Production.ProductionCycle", "ProductionCycle") + .WithMany("Phases") + .HasForeignKey("ProductionCycleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.WorkCenter", "WorkCenter") + .WithMany() + .HasForeignKey("WorkCenterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ProductionCycle"); + + b.Navigation("WorkCenter"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrder", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.ProductionOrder", "ParentProductionOrder") + .WithMany("ChildProductionOrders") + .HasForeignKey("ParentProductionOrderId"); + + b.Navigation("Article"); + + b.Navigation("ParentProductionOrder"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderComponent", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.ProductionOrder", "ProductionOrder") + .WithMany("Components") + .HasForeignKey("ProductionOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("ProductionOrder"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrderPhase", b => + { + b.HasOne("Zentral.Domain.Entities.Production.ProductionOrder", "ProductionOrder") + .WithMany("Phases") + .HasForeignKey("ProductionOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Production.WorkCenter", "WorkCenter") + .WithMany() + .HasForeignKey("WorkCenterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ProductionOrder"); + + b.Navigation("WorkCenter"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrder", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "DestinationWarehouse") + .WithMany() + .HasForeignKey("DestinationWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Purchases.Supplier", "Supplier") + .WithMany("PurchaseOrders") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DestinationWarehouse"); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrderLine", b => + { + b.HasOne("Zentral.Domain.Entities.Purchases.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PurchaseOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "WarehouseArticle") + .WithMany() + .HasForeignKey("WarehouseArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("WarehouseArticle"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Risorsa", b => + { + b.HasOne("Zentral.Domain.Entities.TipoRisorsa", "TipoRisorsa") + .WithMany("Risorse") + .HasForeignKey("TipoRisorsaId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("TipoRisorsa"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrder", b => + { + b.HasOne("Zentral.Domain.Entities.Cliente", "Customer") + .WithMany("SalesOrders") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrderLine", b => + { + b.HasOne("Zentral.Domain.Entities.Sales.SalesOrder", "SalesOrder") + .WithMany("Lines") + .HasForeignKey("SalesOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "WarehouseArticle") + .WithMany() + .HasForeignKey("WarehouseArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SalesOrder"); + + b.Navigation("WarehouseArticle"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoEvento", b => + { + b.HasOne("Zentral.Domain.Entities.TipoPasto", "TipoPasto") + .WithMany("TipiEvento") + .HasForeignKey("TipoPastoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("TipoPasto"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBarcode", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Barcodes") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Batches") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Serials") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("Serials") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "CurrentWarehouse") + .WithMany() + .HasForeignKey("CurrentWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("CurrentWarehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCount", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.StockMovement", "AdjustmentMovement") + .WithMany() + .HasForeignKey("AdjustmentMovementId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("AdjustmentMovement"); + + b.Navigation("Category"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCountLine", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.InventoryCount", "InventoryCount") + .WithMany("Lines") + .HasForeignKey("InventoryCountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("InventoryCount"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockLevel", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("StockLevels") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("StockLevels") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany("StockLevels") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovement", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "DestinationWarehouse") + .WithMany("DestinationMovements") + .HasForeignKey("DestinationWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Zentral.Domain.Entities.Warehouse.MovementReason", "Reason") + .WithMany("Movements") + .HasForeignKey("ReasonId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "SourceWarehouse") + .WithMany("SourceMovements") + .HasForeignKey("SourceWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("DestinationWarehouse"); + + b.Navigation("Reason"); + + b.Navigation("SourceWarehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovementLine", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("MovementLines") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("MovementLines") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.StockMovement", "Movement") + .WithMany("Lines") + .HasForeignKey("MovementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleSerial", "Serial") + .WithMany("MovementLines") + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("Movement"); + + b.Navigation("Serial"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuation", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockValuationLayer", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Zentral.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.StockMovement", "SourceMovement") + .WithMany() + .HasForeignKey("SourceMovementId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("SourceMovement"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", "Category") + .WithMany("Articles") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.HasOne("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", "ParentCategory") + .WithMany("ChildCategories") + .HasForeignKey("ParentCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ParentCategory"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.AppModule", b => + { + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Articolo", b => + { + b.Navigation("DettagliPrelievo"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Cliente", b => + { + b.Navigation("Eventi"); + + b.Navigation("SalesOrders"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.CodiceCategoria", b => + { + b.Navigation("Articoli"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Evento", b => + { + b.Navigation("Acconti"); + + b.Navigation("Allegati"); + + b.Navigation("AltriCosti"); + + b.Navigation("Degustazioni"); + + b.Navigation("DettagliOspiti"); + + b.Navigation("DettagliPrelievo"); + + b.Navigation("DettagliRisorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Dipendente", b => + { + b.Navigation("Assenze"); + + b.Navigation("Contratti"); + + b.Navigation("Pagamenti"); + + b.Navigation("Rimborsi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Location", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.BillOfMaterials", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionCycle", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Production.ProductionOrder", b => + { + b.Navigation("ChildProductionOrders"); + + b.Navigation("Components"); + + b.Navigation("Phases"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Purchases.Supplier", b => + { + b.Navigation("PurchaseOrders"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Risorsa", b => + { + b.Navigation("DettagliRisorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Sales.SalesOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoEvento", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoMateriale", b => + { + b.Navigation("Articoli"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoOspite", b => + { + b.Navigation("DettagliOspiti"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoPasto", b => + { + b.Navigation("TipiEvento"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.TipoRisorsa", b => + { + b.Navigation("Risorse"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.Navigation("MovementLines"); + + b.Navigation("Serials"); + + b.Navigation("StockLevels"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.Navigation("MovementLines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.InventoryCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.MovementReason", b => + { + b.Navigation("Movements"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.StockMovement", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.Navigation("Barcodes"); + + b.Navigation("Batches"); + + b.Navigation("MovementLines"); + + b.Navigation("Serials"); + + b.Navigation("StockLevels"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.Navigation("Articles"); + + b.Navigation("ChildCategories"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.Warehouse.WarehouseLocation", b => + { + b.Navigation("DestinationMovements"); + + b.Navigation("SourceMovements"); + + b.Navigation("StockLevels"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/backend/Zentral.Infrastructure/Migrations/20251203190418_RenamePersonaleToHR.cs b/src/backend/Zentral.Infrastructure/Migrations/20251203190418_RenamePersonaleToHR.cs new file mode 100644 index 0000000..58803d8 --- /dev/null +++ b/src/backend/Zentral.Infrastructure/Migrations/20251203190418_RenamePersonaleToHR.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Zentral.Infrastructure.Migrations +{ + /// + public partial class RenamePersonaleToHR : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/backend/Zentral.Infrastructure/Migrations/ZentralDbContextModelSnapshot.cs b/src/backend/Zentral.Infrastructure/Migrations/ZentralDbContextModelSnapshot.cs index 0c95057..21dd8f6 100644 --- a/src/backend/Zentral.Infrastructure/Migrations/ZentralDbContextModelSnapshot.cs +++ b/src/backend/Zentral.Infrastructure/Migrations/ZentralDbContextModelSnapshot.cs @@ -940,6 +940,254 @@ namespace Zentral.Infrastructure.Migrations b.ToTable("EventiDettaglioRisorse"); }); + modelBuilder.Entity("Zentral.Domain.Entities.HR.Assenza", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataFine") + .HasColumnType("TEXT"); + + b.Property("DataInizio") + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Stato") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TipoAssenza") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Assenze", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Contratto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attivo") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataFine") + .HasColumnType("TEXT"); + + b.Property("DataInizio") + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Livello") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("RetribuzioneLorda") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("TipoContratto") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Contratti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Dipendente", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CodiceFiscale") + .HasColumnType("TEXT"); + + b.Property("Cognome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataNascita") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Indirizzo") + .HasColumnType("TEXT"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Ruolo") + .HasColumnType("TEXT"); + + b.Property("Telefono") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CodiceFiscale") + .IsUnique(); + + b.ToTable("Dipendenti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Pagamento", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataPagamento") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("ImportoNetto") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Pagato") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Pagamenti", (string)null); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Rimborso", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + + b.Property("DataSpesa") + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DipendenteId") + .HasColumnType("INTEGER"); + + b.Property("Importo") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Stato") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedBy") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DipendenteId"); + + b.ToTable("Rimborsi", (string)null); + }); + modelBuilder.Entity("Zentral.Domain.Entities.Location", b => { b.Property("Id") @@ -3697,6 +3945,50 @@ namespace Zentral.Infrastructure.Migrations b.Navigation("Risorsa"); }); + modelBuilder.Entity("Zentral.Domain.Entities.HR.Assenza", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Assenze") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Contratto", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Contratti") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Pagamento", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Pagamenti") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + + modelBuilder.Entity("Zentral.Domain.Entities.HR.Rimborso", b => + { + b.HasOne("Zentral.Domain.Entities.HR.Dipendente", "Dipendente") + .WithMany("Rimborsi") + .HasForeignKey("DipendenteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dipendente"); + }); + modelBuilder.Entity("Zentral.Domain.Entities.ModuleSubscription", b => { b.HasOne("Zentral.Domain.Entities.AppModule", "Module") @@ -4219,6 +4511,17 @@ namespace Zentral.Infrastructure.Migrations b.Navigation("DettagliRisorse"); }); + modelBuilder.Entity("Zentral.Domain.Entities.HR.Dipendente", b => + { + b.Navigation("Assenze"); + + b.Navigation("Contratti"); + + b.Navigation("Pagamenti"); + + b.Navigation("Rimborsi"); + }); + modelBuilder.Entity("Zentral.Domain.Entities.Location", b => { b.Navigation("Eventi"); diff --git a/src/frontend/public/locales/en/translation.json b/src/frontend/public/locales/en/translation.json index 6eb7a24..e7ce6e7 100644 --- a/src/frontend/public/locales/en/translation.json +++ b/src/frontend/public/locales/en/translation.json @@ -47,6 +47,7 @@ "purchases": "Purchases", "sales": "Sales", "production": "Production", + "hr": "Human Resources", "reports": "Reports", "modules": "Modules", "autoCodes": "Auto Codes", @@ -264,6 +265,14 @@ "stock": "Stock", "categories": "Categories" }, + "hr": { + "title": "Human Resources", + "dipendenti": "Employees", + "contratti": "Contracts", + "assenze": "Absences", + "pagamenti": "Payments", + "rimborsi": "Reimbursements" + }, "admin": { "title": "Module Management", "subtitle": "Configure active modules and manage subscriptions", @@ -356,6 +365,14 @@ "4": "Certifications and audits", "5": "Quality statistics" }, + "hr": { + "0": "Employee management", + "1": "Contract management", + "2": "Absence and leave register", + "3": "Payroll and salary management", + "4": "Expense reports and reimbursements", + "5": "Personnel cost analysis" + }, "default": "Complete module features" } }, @@ -1337,5 +1354,45 @@ "process": "Process / Create Order" } } + }, + "personale": { + "dipendentiTitle": "Employee Management", + "newDipendente": "New Employee", + "editDipendente": "Edit Employee", + "nome": "First Name", + "cognome": "Last Name", + "codiceFiscale": "Tax Code", + "email": "Email", + "telefono": "Phone", + "ruolo": "Role", + "indirizzo": "Address", + "citta": "City", + "cap": "ZIP Code", + "dataAssunzione": "Hiring Date", + "dipartimento": "Department", + "contrattiTitle": "Contract Management", + "newContratto": "New Contract", + "editContratto": "Edit Contract", + "dipendente": "Employee", + "tipoContratto": "Contract Type", + "dataInizio": "Start Date", + "dataFine": "End Date", + "retribuzione": "Salary", + "attivo": "Active", + "assenzeTitle": "Absence Management", + "newAssenza": "New Absence", + "editAssenza": "Edit Absence", + "tipoAssenza": "Absence Type", + "stato": "Status", + "pagamentiTitle": "Payment Management", + "newPagamento": "New Payment", + "editPagamento": "Edit Payment", + "data": "Date", + "importo": "Amount", + "causale": "Reason", + "rimborsiTitle": "Reimbursement Management", + "newRimborso": "New Reimbursement", + "editRimborso": "Edit Reimbursement", + "descrizione": "Description" } } \ No newline at end of file diff --git a/src/frontend/public/locales/it/translation.json b/src/frontend/public/locales/it/translation.json index 0a6d047..72c9370 100644 --- a/src/frontend/public/locales/it/translation.json +++ b/src/frontend/public/locales/it/translation.json @@ -43,6 +43,7 @@ "purchases": "Acquisti", "sales": "Vendite", "production": "Produzione", + "hr": "Gestione Personale", "reports": "Report", "modules": "Moduli", "autoCodes": "Codici Auto", @@ -260,6 +261,14 @@ "stock": "Giacenze", "categories": "Categorie" }, + "hr": { + "title": "Gestione Personale", + "dipendenti": "Dipendenti", + "contratti": "Contratti", + "assenze": "Assenze", + "pagamenti": "Pagamenti", + "rimborsi": "Rimborsi" + }, "admin": { "title": "Gestione Moduli", "subtitle": "Configura i moduli attivi e gestisci le subscription", @@ -353,6 +362,14 @@ "4": "Certificazioni e audit", "5": "Statistiche qualità" }, + "hr": { + "0": "Gestione anagrafica dipendenti", + "1": "Gestione contratti", + "2": "Registro assenze e ferie", + "3": "Gestione pagamenti e stipendi", + "4": "Note spese e rimborsi", + "5": "Analisi costi personale" + }, "default": "Funzionalità complete del modulo" } }, @@ -1390,5 +1407,45 @@ } } } + }, + "personale": { + "dipendentiTitle": "Gestione Dipendenti", + "newDipendente": "Nuovo Dipendente", + "editDipendente": "Modifica Dipendente", + "nome": "Nome", + "cognome": "Cognome", + "codiceFiscale": "Codice Fiscale", + "email": "Email", + "telefono": "Telefono", + "ruolo": "Ruolo", + "indirizzo": "Indirizzo", + "citta": "Città", + "cap": "CAP", + "dataAssunzione": "Data Assunzione", + "dipartimento": "Dipartimento", + "contrattiTitle": "Gestione Contratti", + "newContratto": "Nuovo Contratto", + "editContratto": "Modifica Contratto", + "dipendente": "Dipendente", + "tipoContratto": "Tipo Contratto", + "dataInizio": "Data Inizio", + "dataFine": "Data Fine", + "retribuzione": "Retribuzione", + "attivo": "Attivo", + "assenzeTitle": "Gestione Assenze", + "newAssenza": "Nuova Assenza", + "editAssenza": "Modifica Assenza", + "tipoAssenza": "Tipo Assenza", + "stato": "Stato", + "pagamentiTitle": "Gestione Pagamenti", + "newPagamento": "Nuovo Pagamento", + "editPagamento": "Modifica Pagamento", + "data": "Data", + "importo": "Importo", + "causale": "Causale", + "rimborsiTitle": "Gestione Rimborsi", + "newRimborso": "Nuovo Rimborso", + "editRimborso": "Modifica Rimborso", + "descrizione": "Descrizione" } } \ No newline at end of file diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 29cb786..4a00db0 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -7,13 +7,7 @@ import { AppLanguageProvider } from "./contexts/LanguageContext"; import Layout from "./components/Layout"; import Dashboard from "./pages/Dashboard"; -import EventiPage from "./pages/EventiPage"; -import EventoDetailPage from "./pages/EventoDetailPage"; -import ClientiPage from "./pages/ClientiPage"; -import LocationPage from "./pages/LocationPage"; -import ArticoliPage from "./pages/ArticoliPage"; -import RisorsePage from "./pages/RisorsePage"; -import CalendarioPage from "./pages/CalendarioPage"; + import ReportTemplatesPage from "./pages/ReportTemplatesPage"; import ReportEditorPage from "./pages/ReportEditorPage"; import ModulesAdminPage from "./pages/ModulesAdminPage"; @@ -24,6 +18,8 @@ import WarehouseRoutes from "./modules/warehouse/routes"; import PurchasesRoutes from "./modules/purchases/routes"; import SalesRoutes from "./modules/sales/routes"; import ProductionRoutes from "./modules/production/routes"; +import EventsRoutes from "./modules/events/routes"; +import HRRoutes from "./modules/hr/routes"; import { ModuleGuard } from "./components/ModuleGuard"; import { useRealTimeUpdates } from "./hooks/useRealTimeUpdates"; import { CollaborationProvider } from "./contexts/CollaborationContext"; @@ -62,13 +58,7 @@ function App() { }> } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> + } @@ -131,6 +121,24 @@ function App() { } /> + {/* Events Module */} + + + + } + /> + {/* HR Module */} + + + + } + /> diff --git a/src/frontend/src/components/Sidebar.tsx b/src/frontend/src/components/Sidebar.tsx index 0fa87e7..7419afb 100644 --- a/src/frontend/src/components/Sidebar.tsx +++ b/src/frontend/src/components/Sidebar.tsx @@ -36,6 +36,8 @@ import { Timeline as TimelineIcon, PrecisionManufacturing as ManufacturingIcon, Category as CategoryIcon, + AttachMoney as AttachMoneyIcon, + Receipt as ReceiptIcon, } from '@mui/icons-material'; import { useLocation } from 'react-router-dom'; import { useLanguage } from '../contexts/LanguageContext'; @@ -62,6 +64,8 @@ export default function Sidebar({ onClose }: { onClose?: () => void }) { purchases: false, sales: false, production: false, + events: false, + hr: false, admin: false, }); @@ -85,10 +89,7 @@ export default function Sidebar({ onClose }: { onClose?: () => void }) { icon: , children: [ { id: 'dashboard', label: t('menu.dashboard'), icon: , path: '/' }, - { id: 'calendar', label: t('menu.calendar'), icon: , path: '/calendario' }, - { id: 'events', label: t('menu.events'), icon: , path: '/eventi' }, { id: 'clients', label: t('menu.clients'), icon: , path: '/clienti' }, - { id: 'location', label: t('menu.location'), icon: , path: '/location' }, { id: 'articles', label: t('menu.articles'), icon: , path: '/articoli' }, { id: 'resources', label: t('menu.resources'), icon: , path: '/risorse' }, ], @@ -140,6 +141,30 @@ export default function Sidebar({ onClose }: { onClose?: () => void }) { { id: 'prod-mrp', label: 'MRP', icon: , path: '/production/mrp' }, ], }, + { + id: 'events', + label: t('menu.events'), + icon: , + moduleCode: 'events', + children: [ + { id: 'ev-list', label: t('menu.events'), icon: , path: '/events/list' }, + { id: 'ev-calendar', label: t('menu.calendar'), icon: , path: '/events/calendar' }, + { id: 'ev-locations', label: t('menu.location'), icon: , path: '/events/locations' }, + ], + }, + { + id: 'hr', + label: t('modules.hr.title'), + icon: , + moduleCode: 'hr', + children: [ + { id: 'hr-dipendenti', label: t('modules.hr.dipendenti'), icon: , path: '/hr/dipendenti' }, + { id: 'hr-contratti', label: t('modules.hr.contratti'), icon: , path: '/hr/contratti' }, + { id: 'hr-assenze', label: t('modules.hr.assenze'), icon: , path: '/hr/assenze' }, + { id: 'hr-pagamenti', label: t('modules.hr.pagamenti'), icon: , path: '/hr/pagamenti' }, + { id: 'hr-rimborsi', label: t('modules.hr.rimborsi'), icon: , path: '/hr/rimborsi' }, + ], + }, { id: 'admin', label: 'Amministrazione', diff --git a/src/frontend/src/pages/CalendarioPage.tsx b/src/frontend/src/modules/events/pages/CalendarioPage.tsx similarity index 95% rename from src/frontend/src/pages/CalendarioPage.tsx rename to src/frontend/src/modules/events/pages/CalendarioPage.tsx index 0fb98aa..6f6677f 100644 --- a/src/frontend/src/pages/CalendarioPage.tsx +++ b/src/frontend/src/modules/events/pages/CalendarioPage.tsx @@ -18,7 +18,7 @@ import interactionPlugin from "@fullcalendar/interaction"; import { useNavigate } from "react-router-dom"; import dayjs from "dayjs"; import { useTranslation } from "react-i18next"; -import { eventiService } from "../services/eventiService"; +import { eventiService } from "../../../services/eventiService"; export default function CalendarioPage() { const navigate = useNavigate(); @@ -53,7 +53,7 @@ export default function CalendarioPage() { const handleCreateEvent = () => { // Naviga alla pagina nuovo evento con la data preselezionata - navigate("/eventi/0", { state: { dataEvento: newEventDialog.date } }); + navigate("/events/list/0", { state: { dataEvento: newEventDialog.date } }); setNewEventDialog({ open: false, date: "", formattedDate: "" }); }; @@ -62,7 +62,7 @@ export default function CalendarioPage() { }; const handleEventClick = (info: any) => { - navigate(`/eventi/${info.event.id}`); + navigate(`/events/list/${info.event.id}`); }; const handleDatesSet = (info: any) => { diff --git a/src/frontend/src/modules/events/pages/DashboardPage.tsx b/src/frontend/src/modules/events/pages/DashboardPage.tsx new file mode 100644 index 0000000..166bff6 --- /dev/null +++ b/src/frontend/src/modules/events/pages/DashboardPage.tsx @@ -0,0 +1,430 @@ +import { useState } from "react"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; +import { + Grid, + Paper, + Typography, + Box, + Card, + CardContent, + List, + ListItem, + ListItemText, + Chip, + Button, + Dialog, + DialogTitle, + DialogContent, + DialogContentText, + DialogActions, + Alert, + CircularProgress, +} from "@mui/material"; +import { + Event as EventIcon, + People as PeopleIcon, + CheckCircle as ConfirmedIcon, + PendingActions as PendingIcon, + PlayArrow as GenerateIcon, + DeleteSweep as ClearIcon, +} from "@mui/icons-material"; +import { useNavigate } from "react-router-dom"; +import dayjs from "dayjs"; +import { useTranslation, Trans } from "react-i18next"; +import { eventiService } from "../services/eventiService"; +import { demoService, DemoDataResult } from "../services/demoService"; +import { StatoEvento } from "../types"; + +const StatCard = ({ + title, + value, + icon, + color, +}: { + title: string; + value: number; + icon: React.ReactNode; + color: string; +}) => ( + + + + + + {title} + + {value} + + {icon} + + + +); + +const getStatoLabel = (stato: StatoEvento, t: any) => { + switch (stato) { + case StatoEvento.Scheda: + return t("status.scheda"); + case StatoEvento.Preventivo: + return t("status.preventivo"); + case StatoEvento.Confermato: + return t("status.confermato"); + default: + return t("common.unknown"); + } +}; + +const getStatoColor = (stato: StatoEvento) => { + switch (stato) { + case StatoEvento.Scheda: + return "default"; + case StatoEvento.Preventivo: + return "warning"; + case StatoEvento.Confermato: + return "success"; + default: + return "default"; + } +}; + +export default function Dashboard() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + const { t } = useTranslation(); + const [demoDialog, setDemoDialog] = useState<"generate" | "clear" | null>( + null, + ); + const [loading, setLoading] = useState(false); + const [result, setResult] = useState(null); + const [error, setError] = useState(null); + + const { data: eventi = [] } = useQuery({ + queryKey: ["eventi"], + queryFn: () => eventiService.getAll(), + }); + + const handleGenerateDemo = async () => { + setLoading(true); + setError(null); + try { + const res = await demoService.generateDemoData(); + setResult(res); + queryClient.invalidateQueries(); + } catch (err: any) { + setError( + err.response?.data?.error || t("dashboard.generateError"), + ); + } finally { + setLoading(false); + } + }; + + const handleClearDemo = async () => { + setLoading(true); + setError(null); + try { + const res = await demoService.clearDemoData(); + setResult(res); + queryClient.invalidateQueries(); + } catch (err: any) { + setError( + err.response?.data?.error || t("dashboard.clearError"), + ); + } finally { + setLoading(false); + } + }; + + const handleCloseDialog = () => { + setDemoDialog(null); + setResult(null); + setError(null); + }; + + const oggi = dayjs().startOf("day"); + const prossimi30Giorni = oggi.add(30, "day"); + + const eventiProssimi = eventi + .filter( + (e) => + dayjs(e.dataEvento).isAfter(oggi) && + dayjs(e.dataEvento).isBefore(prossimi30Giorni), + ) + .sort((a, b) => dayjs(a.dataEvento).diff(dayjs(b.dataEvento))); + + const eventiConfermati = eventi.filter( + (e) => e.stato === StatoEvento.Confermato, + ).length; + const eventiPreventivo = eventi.filter( + (e) => e.stato === StatoEvento.Preventivo, + ).length; + const eventiOggi = eventi.filter((e) => + dayjs(e.dataEvento).isSame(oggi, "day"), + ).length; + + return ( + + + {t("dashboard.title")} + + + + + + + + + } + color="#1976d2" + /> + + + } + color="#4caf50" + /> + + + } + color="#ff9800" + /> + + + } + color="#9c27b0" + /> + + + + + + + + {t("dashboard.upcomingEvents")} + + + {eventiProssimi.slice(0, 10).map((evento) => ( + navigate(`/eventi/${evento.id}`)} + sx={{ + cursor: "pointer", + "&:hover": { bgcolor: "action.hover" }, + }} + > + + + {dayjs(evento.dataEvento).format("DD/MM/YYYY")} + + - + {evento.cliente?.ragioneSociale} + + } + /> + + + ))} + {eventiProssimi.length === 0 && ( + + + + )} + + + + + + + + {t("dashboard.expiringQuotes")} + + + {eventi + .filter( + (e) => + e.stato === StatoEvento.Preventivo && + e.dataScadenzaPreventivo, + ) + .sort((a, b) => + dayjs(a.dataScadenzaPreventivo).diff( + dayjs(b.dataScadenzaPreventivo), + ), + ) + .slice(0, 5) + .map((evento) => ( + navigate(`/eventi/${evento.id}`)} + sx={{ + cursor: "pointer", + "&:hover": { bgcolor: "action.hover" }, + }} + > + + + + ))} + {eventi.filter((e) => e.stato === StatoEvento.Preventivo) + .length === 0 && ( + + + + )} + + + + + + {/* Dialog Genera Dati Demo */} + + {t("dashboard.generateDialogTitle")} + + {!result && !error && ( + + }} /> + + )} + {loading && ( + + + + )} + {result && ( + + {result.message} + + )} + {error && ( + + {error} + + )} + + + + {!result && ( + + )} + + + + {/* Dialog Pulisci Database */} + + {t("dashboard.clearDialogTitle")} + + {!result && !error && ( + + {t("dashboard.clearDialogWarning")} + + )} + {!result && !error && ( + + }} /> + + )} + {loading && ( + + + + )} + {result && ( + + {t("dashboard.clearSuccess", { + events: result.eventiCreati, + clients: result.clientiCreati, + locations: result.locationCreate, + resources: result.risorseCreate, + articles: result.articoliCreati + })} + + )} + {error && ( + + {error} + + )} + + + + {!result && ( + + )} + + + + ); +} diff --git a/src/frontend/src/pages/EventiPage.tsx b/src/frontend/src/modules/events/pages/EventiPage.tsx similarity index 97% rename from src/frontend/src/pages/EventiPage.tsx rename to src/frontend/src/modules/events/pages/EventiPage.tsx index 2d34f5d..13a7608 100644 --- a/src/frontend/src/pages/EventiPage.tsx +++ b/src/frontend/src/modules/events/pages/EventiPage.tsx @@ -29,9 +29,9 @@ import { } from '@mui/icons-material'; import dayjs from 'dayjs'; import { useTranslation } from 'react-i18next'; -import { eventiService } from '../services/eventiService'; -import { lookupService } from '../services/lookupService'; -import { Evento, StatoEvento } from '../types'; +import { eventiService } from '../../../services/eventiService'; +import { lookupService } from '../../../services/lookupService'; +import { Evento, StatoEvento } from '../../../types'; const getStatoLabel = (stato: StatoEvento, t: any) => { switch (stato) { @@ -150,10 +150,10 @@ export default function EventiPage() { sortable: false, renderCell: (params) => ( - navigate(`/eventi/${params.row.id}`)}> + navigate(`/events/list/${params.row.id}`)}> - navigate(`/eventi/${params.row.id}`)}> + navigate(`/events/list/${params.row.id}`)}> duplicaMutation.mutate(params.row.id)}> diff --git a/src/frontend/src/pages/EventoDetailPage.tsx b/src/frontend/src/modules/events/pages/EventoDetailPage.tsx similarity index 98% rename from src/frontend/src/pages/EventoDetailPage.tsx rename to src/frontend/src/modules/events/pages/EventoDetailPage.tsx index bf26463..b36d6b5 100644 --- a/src/frontend/src/pages/EventoDetailPage.tsx +++ b/src/frontend/src/modules/events/pages/EventoDetailPage.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { useParams, useNavigate, useLocation } from "react-router-dom"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; -import { signalRService } from "../services/signalr"; +import { signalRService } from "../../../services/signalr"; import { Box, Typography, @@ -42,16 +42,16 @@ import { } from "@mui/icons-material"; import { useTranslation } from "react-i18next"; import dayjs from "dayjs"; -import { eventiService } from "../services/eventiService"; -import { lookupService } from "../services/lookupService"; -import EventoCostiPanel from "../components/EventoCostiPanel"; +import { eventiService } from "../../../services/eventiService"; +import { lookupService } from "../../../services/lookupService"; +import EventoCostiPanel from "../../../components/EventoCostiPanel"; import { Evento, StatoEvento, EventoDettaglioOspiti, EventoDettaglioPrelievo, EventoDettaglioRisorsa, -} from "../types"; +} from "../../../types"; interface TabPanelProps { children?: React.ReactNode; @@ -147,7 +147,7 @@ export default function EventoDetailPage() { const createMutation = useMutation({ mutationFn: (data: Partial) => eventiService.create(data), onSuccess: (newEvento) => { - navigate(`/eventi/${newEvento.id}`); + navigate(`/events/list/${newEvento.id}`); }, }); @@ -206,7 +206,7 @@ export default function EventoDetailPage() { const duplicaMutation = useMutation({ mutationFn: () => eventiService.duplica(eventoId), onSuccess: (newEvento) => { - navigate(`/eventi/${newEvento.id}`); + navigate(`/events/list/${newEvento.id}`); }, }); @@ -362,7 +362,7 @@ export default function EventoDetailPage() { > navigate("/eventi")} + onClick={() => navigate("/events/list")} sx={{ color: statoInfo.textColor }} > diff --git a/src/frontend/src/pages/LocationPage.tsx b/src/frontend/src/modules/events/pages/LocationPage.tsx similarity index 98% rename from src/frontend/src/pages/LocationPage.tsx rename to src/frontend/src/modules/events/pages/LocationPage.tsx index c3a19ed..dc36422 100644 --- a/src/frontend/src/pages/LocationPage.tsx +++ b/src/frontend/src/modules/events/pages/LocationPage.tsx @@ -16,8 +16,8 @@ import { import { DataGrid, GridColDef } from '@mui/x-data-grid'; import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; -import { locationService } from '../services/lookupService'; -import { Location } from '../types'; +import { locationService } from '../../../services/lookupService'; +import { Location } from '../../../types'; export default function LocationPage() { const queryClient = useQueryClient(); diff --git a/src/frontend/src/modules/events/routes.tsx b/src/frontend/src/modules/events/routes.tsx new file mode 100644 index 0000000..2a4b70d --- /dev/null +++ b/src/frontend/src/modules/events/routes.tsx @@ -0,0 +1,17 @@ +import { Routes, Route, Navigate } from "react-router-dom"; +import EventiPage from "./pages/EventiPage"; +import EventoDetailPage from "./pages/EventoDetailPage"; +import CalendarioPage from "./pages/CalendarioPage"; +import LocationPage from "./pages/LocationPage"; + +export default function EventsRoutes() { + return ( + + } /> + } /> + } /> + } /> + } /> + + ); +} diff --git a/src/frontend/src/modules/hr/pages/AssenzePage.tsx b/src/frontend/src/modules/hr/pages/AssenzePage.tsx new file mode 100644 index 0000000..cddf02e --- /dev/null +++ b/src/frontend/src/modules/hr/pages/AssenzePage.tsx @@ -0,0 +1,281 @@ +import { useState } from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + Box, + Typography, + Button, + Paper, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Grid, + MenuItem, +} from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import axios from 'axios'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import dayjs from 'dayjs'; + +// Interfaces +interface Dipendente { + id: number; + nome: string; + cognome: string; +} + +interface Assenza { + id: number; + dipendenteId: number; + dipendente?: Dipendente; + dataInizio: string; + dataFine: string; + tipoAssenza: string; + stato: string; + note?: string; +} + +const assenzeService = { + getAll: async (dipendenteId?: number) => { + const params = dipendenteId ? { dipendenteId } : {}; + const response = await axios.get('/api/hr/assenze', { params }); + return response.data; + }, + create: async (data: Partial) => { + const response = await axios.post('/api/hr/assenze', data); + return response.data; + }, + update: async (id: number, data: Partial) => { + const response = await axios.put(`/api/hr/assenze/${id}`, data); + return response.data; + }, + delete: async (id: number) => { + await axios.delete(`/api/hr/assenze/${id}`); + }, +}; + +const dipendentiService = { + getAll: async () => { + const response = await axios.get('/api/hr/dipendenti'); + return response.data; + }, +}; + +export default function AssenzePage() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + const [openDialog, setOpenDialog] = useState(false); + const [editingId, setEditingId] = useState(null); + const [formData, setFormData] = useState>({ stato: 'Richiesta' }); + + const { data: assenze = [], isLoading } = useQuery({ + queryKey: ['assenze'], + queryFn: () => assenzeService.getAll(), + }); + + const { data: dipendenti = [] } = useQuery({ + queryKey: ['dipendenti'], + queryFn: () => dipendentiService.getAll(), + }); + + const createMutation = useMutation({ + mutationFn: (data: Partial) => assenzeService.create(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['assenze'] }); + handleCloseDialog(); + }, + }); + + const updateMutation = useMutation({ + mutationFn: ({ id, data }: { id: number; data: Partial }) => assenzeService.update(id, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['assenze'] }); + handleCloseDialog(); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (id: number) => assenzeService.delete(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['assenze'] }), + }); + + const handleCloseDialog = () => { + setOpenDialog(false); + setEditingId(null); + setFormData({ stato: 'Richiesta' }); + }; + + const handleEdit = (assenza: Assenza) => { + setFormData(assenza); + setEditingId(assenza.id); + setOpenDialog(true); + }; + + const handleSubmit = () => { + if (editingId) { + updateMutation.mutate({ id: editingId, data: formData }); + } else { + createMutation.mutate(formData); + } + }; + + const columns: GridColDef[] = [ + { + field: 'dipendente', + headerName: t('personale.dipendente'), + width: 200, + valueGetter: (params: any) => params?.nome && params?.cognome ? `${params.cognome} ${params.nome}` : '', + }, + { field: 'tipoAssenza', headerName: t('personale.tipoAssenza'), width: 150 }, + { + field: 'dataInizio', + headerName: t('personale.dataInizio'), + width: 120, + valueFormatter: (params: any) => params?.value ? dayjs(params.value).format('DD/MM/YYYY') : '', + }, + { + field: 'dataFine', + headerName: t('personale.dataFine'), + width: 120, + valueFormatter: (params: any) => params?.value ? dayjs(params.value).format('DD/MM/YYYY') : '', + }, + { field: 'stato', headerName: t('personale.stato'), width: 120 }, + { + field: 'actions', + headerName: t('common.actions'), + width: 120, + sortable: false, + renderCell: (params) => ( + + handleEdit(params.row)}> + + + { + if (confirm(t('common.deleteConfirm'))) { + deleteMutation.mutate(params.row.id); + } + }} + > + + + + ), + }, + ]; + + return ( + + + {t('personale.assenzeTitle')} + + + + + + + + + {editingId ? t('personale.editAssenza') : t('personale.newAssenza')} + + + + setFormData({ ...formData, dipendenteId: Number(e.target.value) })} + required + > + {dipendenti?.map((d) => ( + + {d.nome} {d.cognome} + + ))} + + + + setFormData({ ...formData, tipoAssenza: e.target.value })} + required + > + Ferie + Malattia + Permesso + Altro + + + + setFormData({ ...formData, stato: e.target.value })} + required + > + Richiesta + Approvata + Rifiutata + + + + setFormData({ ...formData, dataInizio: newValue ? newValue.toISOString() : undefined })} + slotProps={{ textField: { fullWidth: true, required: true } }} + /> + + + setFormData({ ...formData, dataFine: newValue ? newValue.toISOString() : undefined })} + slotProps={{ textField: { fullWidth: true, required: true } }} + /> + + + setFormData({ ...formData, note: e.target.value })} + /> + + + + + + + + + + ); +} diff --git a/src/frontend/src/modules/hr/pages/ContrattiPage.tsx b/src/frontend/src/modules/hr/pages/ContrattiPage.tsx new file mode 100644 index 0000000..4b6b37b --- /dev/null +++ b/src/frontend/src/modules/hr/pages/ContrattiPage.tsx @@ -0,0 +1,292 @@ +import { useState } from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + Box, + Typography, + Button, + Paper, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Grid, + MenuItem, +} from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import axios from 'axios'; +import dayjs from 'dayjs'; + +// Interfaces +interface Dipendente { + id: number; + nome: string; + cognome: string; +} + +interface Contratto { + id: number; + dipendenteId: number; + dipendente?: Dipendente; + dataInizio: string; + dataFine?: string; + tipoContratto: string; + livello?: string; + retribuzioneLorda: number; + oreSettimanali?: number; + note?: string; + attivo: boolean; +} + +const contrattiService = { + getAll: async (dipendenteId?: number) => { + const params = dipendenteId ? { dipendenteId } : {}; + const response = await axios.get('/api/hr/contratti', { params }); + return response.data; + }, + create: async (data: Partial) => { + const response = await axios.post('/api/hr/contratti', data); + return response.data; + }, + update: async (id: number, data: Partial) => { + const response = await axios.put(`/api/hr/contratti/${id}`, data); + return response.data; + }, + delete: async (id: number) => { + await axios.delete(`/api/hr/contratti/${id}`); + }, +}; + +const dipendentiService = { + getAll: async () => { + const response = await axios.get('/api/hr/dipendenti'); + return response.data; + }, +}; + +export default function ContrattiPage() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + const [openDialog, setOpenDialog] = useState(false); + const [editingId, setEditingId] = useState(null); + const [formData, setFormData] = useState>({ attivo: true }); + + const { data: contratti = [], isLoading } = useQuery({ + queryKey: ['contratti'], + queryFn: () => contrattiService.getAll(), + }); + + const { data: dipendenti = [] } = useQuery({ + queryKey: ['dipendenti'], + queryFn: () => dipendentiService.getAll(), + }); + + const createMutation = useMutation({ + mutationFn: (data: Partial) => contrattiService.create(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['contratti'] }); + handleCloseDialog(); + }, + }); + + const updateMutation = useMutation({ + mutationFn: ({ id, data }: { id: number; data: Partial }) => contrattiService.update(id, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['contratti'] }); + handleCloseDialog(); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (id: number) => contrattiService.delete(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['contratti'] }), + }); + + const handleCloseDialog = () => { + setOpenDialog(false); + setEditingId(null); + setFormData({ attivo: true }); + }; + + const handleEdit = (contratto: Contratto) => { + setFormData(contratto); + setEditingId(contratto.id); + setOpenDialog(true); + }; + + const handleSubmit = () => { + if (editingId) { + updateMutation.mutate({ id: editingId, data: formData }); + } else { + createMutation.mutate(formData); + } + }; + + const columns: GridColDef[] = [ + { + field: 'dipendente', + headerName: t('personale.dipendente'), + width: 200, + valueGetter: (params: any) => params?.nome && params?.cognome ? `${params.cognome} ${params.nome}` : '', + }, + { field: 'tipoContratto', headerName: t('personale.tipoContratto'), width: 150 }, + { + field: 'dataInizio', + headerName: t('personale.dataInizio'), + width: 120, + valueFormatter: (params: any) => params?.value ? dayjs(params.value).format('DD/MM/YYYY') : '', + }, + { + field: 'dataFine', + headerName: t('personale.dataFine'), + width: 120, + valueFormatter: (params: any) => params?.value ? dayjs(params.value).format('DD/MM/YYYY') : '', + }, + { field: 'retribuzioneLorda', headerName: t('personale.retribuzione'), width: 120, type: 'number' }, + { field: 'attivo', headerName: t('personale.attivo'), width: 100, type: 'boolean' }, + { + field: 'actions', + headerName: t('common.actions'), + width: 120, + sortable: false, + renderCell: (params) => ( + + handleEdit(params.row)}> + + + { + if (confirm(t('common.deleteConfirm'))) { + deleteMutation.mutate(params.row.id); + } + }} + > + + + + ), + }, + ]; + + return ( + + + {t('personale.contrattiTitle')} + + + + + + + + + {editingId ? t('personale.editContratto') : t('personale.newContratto')} + + + + setFormData({ ...formData, dipendenteId: Number(e.target.value) })} + > + {dipendenti?.map((d) => ( + + {d.nome} {d.cognome} + + ))} + + + + setFormData({ ...formData, tipoContratto: e.target.value })} + /> + + + setFormData({ ...formData, livello: e.target.value })} + /> + + + setFormData({ ...formData, dataInizio: new Date(e.target.value).toISOString() })} + /> + + + setFormData({ ...formData, dataFine: e.target.value ? new Date(e.target.value).toISOString() : undefined })} + /> + + + setFormData({ ...formData, retribuzioneLorda: Number(e.target.value) })} + /> + + + setFormData({ ...formData, oreSettimanali: Number(e.target.value) })} + /> + + + setFormData({ ...formData, note: e.target.value })} + /> + + + + + + + + + + ); +} diff --git a/src/frontend/src/modules/hr/pages/DipendentiPage.tsx b/src/frontend/src/modules/hr/pages/DipendentiPage.tsx new file mode 100644 index 0000000..5368b08 --- /dev/null +++ b/src/frontend/src/modules/hr/pages/DipendentiPage.tsx @@ -0,0 +1,277 @@ +import { useState } from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + Box, + Typography, + Button, + Paper, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Grid, +} from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import axios from 'axios'; + +// Interfaces +interface Dipendente { + id: number; + nome: string; + cognome: string; + codiceFiscale?: string; + email?: string; + telefono?: string; + ruolo?: string; + dataNascita?: string; + indirizzo?: string; + citta?: string; + cap?: string; + dataAssunzione?: string; + dipartimento?: string; +} + +const dipendentiService = { + getAll: async (search?: string) => { + const params = search ? { search } : {}; + const response = await axios.get('/api/hr/dipendenti', { params }); + return response.data; + }, + get: async (id: number) => { + const response = await axios.get(`/api/hr/dipendenti/${id}`); + return response.data; + }, + create: async (data: Partial) => { + const response = await axios.post('/api/hr/dipendenti', data); + return response.data; + }, + update: async (id: number, data: Partial) => { + const response = await axios.put(`/api/hr/dipendenti/${id}`, data); + return response.data; + }, + delete: async (id: number) => { + await axios.delete(`/api/hr/dipendenti/${id}`); + }, +}; + +export default function DipendentiPage() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + const [openDialog, setOpenDialog] = useState(false); + const [editingId, setEditingId] = useState(null); + const [formData, setFormData] = useState>({}); + const [search, setSearch] = useState(''); + + const { data: dipendenti = [], isLoading } = useQuery({ + queryKey: ['dipendenti', search], + queryFn: () => dipendentiService.getAll(search), + }); + + const createMutation = useMutation({ + mutationFn: (data: Partial) => dipendentiService.create(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['dipendenti'] }); + handleCloseDialog(); + }, + }); + + const updateMutation = useMutation({ + mutationFn: ({ id, data }: { id: number; data: Partial }) => dipendentiService.update(id, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['dipendenti'] }); + handleCloseDialog(); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (id: number) => dipendentiService.delete(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['dipendenti'] }), + }); + + const handleCloseDialog = () => { + setOpenDialog(false); + setEditingId(null); + setFormData({}); + }; + + const handleEdit = (dipendente: Dipendente) => { + setFormData(dipendente); + setEditingId(dipendente.id); + setOpenDialog(true); + }; + + const handleSubmit = () => { + if (editingId) { + updateMutation.mutate({ id: editingId, data: formData }); + } else { + createMutation.mutate(formData); + } + }; + + const columns: GridColDef[] = [ + { field: 'nome', headerName: t('personale.nome'), width: 150 }, + { field: 'cognome', headerName: t('personale.cognome'), width: 150 }, + { field: 'ruolo', headerName: t('personale.ruolo'), width: 150 }, + { field: 'email', headerName: t('personale.email'), width: 200 }, + { field: 'telefono', headerName: t('personale.telefono'), width: 150 }, + { + field: 'actions', + headerName: t('common.actions'), + width: 150, + sortable: false, + renderCell: (params) => ( + + handleEdit(params.row)}> + + + { + if (confirm(t('common.deleteConfirm'))) { + deleteMutation.mutate(params.row.id); + } + }} + > + + + + ), + }, + ]; + + return ( + + + {t('personale.dipendentiTitle')} + + + + + + + + + {editingId ? t('personale.editDipendente') : t('personale.newDipendente')} + + + + setFormData({ ...formData, nome: e.target.value })} + /> + + + setFormData({ ...formData, cognome: e.target.value })} + /> + + + setFormData({ ...formData, codiceFiscale: e.target.value })} + /> + + + setFormData({ ...formData, email: e.target.value })} + /> + + + setFormData({ ...formData, telefono: e.target.value })} + /> + + + setFormData({ ...formData, indirizzo: e.target.value })} + /> + + + setFormData({ ...formData, citta: e.target.value })} + /> + + + setFormData({ ...formData, cap: e.target.value })} + /> + + + setFormData({ ...formData, dataAssunzione: new Date(e.target.value).toISOString() })} + /> + + + setFormData({ ...formData, ruolo: e.target.value })} + /> + + + setFormData({ ...formData, dipartimento: e.target.value })} + /> + + + + + + + + + + ); +} diff --git a/src/frontend/src/modules/hr/pages/PagamentiPage.tsx b/src/frontend/src/modules/hr/pages/PagamentiPage.tsx new file mode 100644 index 0000000..f5f6456 --- /dev/null +++ b/src/frontend/src/modules/hr/pages/PagamentiPage.tsx @@ -0,0 +1,256 @@ +import { useState } from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + Box, + Typography, + Button, + Paper, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Grid, + MenuItem, +} from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import axios from 'axios'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import dayjs from 'dayjs'; + +// Interfaces +interface Dipendente { + id: number; + nome: string; + cognome: string; +} + +interface Pagamento { + id: number; + dipendenteId: number; + dipendente?: Dipendente; + data: string; + importo: number; + causale: string; + note?: string; +} + +const pagamentiService = { + getAll: async (dipendenteId?: number) => { + const params = dipendenteId ? { dipendenteId } : {}; + const response = await axios.get('/api/hr/pagamenti', { params }); + return response.data; + }, + create: async (data: Partial) => { + const response = await axios.post('/api/hr/pagamenti', data); + return response.data; + }, + update: async (id: number, data: Partial) => { + const response = await axios.put(`/api/hr/pagamenti/${id}`, data); + return response.data; + }, + delete: async (id: number) => { + await axios.delete(`/api/hr/pagamenti/${id}`); + }, +}; + +const dipendentiService = { + getAll: async () => { + const response = await axios.get('/api/hr/dipendenti'); + return response.data; + }, +}; + +export default function PagamentiPage() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + const [openDialog, setOpenDialog] = useState(false); + const [editingId, setEditingId] = useState(null); + const [formData, setFormData] = useState>({}); + + const { data: pagamenti = [], isLoading } = useQuery({ + queryKey: ['pagamenti'], + queryFn: () => pagamentiService.getAll(), + }); + + const { data: dipendenti = [] } = useQuery({ + queryKey: ['dipendenti'], + queryFn: () => dipendentiService.getAll(), + }); + + const createMutation = useMutation({ + mutationFn: (data: Partial) => pagamentiService.create(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['pagamenti'] }); + handleCloseDialog(); + }, + }); + + const updateMutation = useMutation({ + mutationFn: ({ id, data }: { id: number; data: Partial }) => pagamentiService.update(id, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['pagamenti'] }); + handleCloseDialog(); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (id: number) => pagamentiService.delete(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['pagamenti'] }), + }); + + const handleCloseDialog = () => { + setOpenDialog(false); + setEditingId(null); + setFormData({}); + }; + + const handleEdit = (pagamento: Pagamento) => { + setFormData(pagamento); + setEditingId(pagamento.id); + setOpenDialog(true); + }; + + const handleSubmit = () => { + if (editingId) { + updateMutation.mutate({ id: editingId, data: formData }); + } else { + createMutation.mutate(formData); + } + }; + + const columns: GridColDef[] = [ + { + field: 'dipendente', + headerName: t('personale.dipendente'), + width: 200, + valueGetter: (params: any) => params?.nome && params?.cognome ? `${params.cognome} ${params.nome}` : '', + }, + { + field: 'data', + headerName: t('personale.data'), + width: 120, + valueFormatter: (params: any) => params?.value ? dayjs(params.value).format('DD/MM/YYYY') : '', + }, + { field: 'importo', headerName: t('personale.importo'), width: 120, type: 'number' }, + { field: 'causale', headerName: t('personale.causale'), width: 200 }, + { + field: 'actions', + headerName: t('common.actions'), + width: 120, + sortable: false, + renderCell: (params) => ( + + handleEdit(params.row)}> + + + { + if (confirm(t('common.deleteConfirm'))) { + deleteMutation.mutate(params.row.id); + } + }} + > + + + + ), + }, + ]; + + return ( + + + {t('personale.pagamentiTitle')} + + + + + + + + + {editingId ? t('personale.editPagamento') : t('personale.newPagamento')} + + + + setFormData({ ...formData, dipendenteId: Number(e.target.value) })} + required + > + {dipendenti?.map((d) => ( + + {d.nome} {d.cognome} + + ))} + + + + setFormData({ ...formData, data: newValue ? newValue.toISOString() : undefined })} + slotProps={{ textField: { fullWidth: true, required: true } }} + /> + + + setFormData({ ...formData, importo: Number(e.target.value) })} + required + /> + + + setFormData({ ...formData, causale: e.target.value })} + required + /> + + + setFormData({ ...formData, note: e.target.value })} + /> + + + + + + + + + + ); +} diff --git a/src/frontend/src/modules/hr/pages/RimborsiPage.tsx b/src/frontend/src/modules/hr/pages/RimborsiPage.tsx new file mode 100644 index 0000000..0b6b81b --- /dev/null +++ b/src/frontend/src/modules/hr/pages/RimborsiPage.tsx @@ -0,0 +1,273 @@ +import { useState } from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + Box, + Typography, + Button, + Paper, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Grid, + MenuItem, +} from '@mui/material'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import axios from 'axios'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import dayjs from 'dayjs'; + +// Interfaces +interface Dipendente { + id: number; + nome: string; + cognome: string; +} + +interface Rimborso { + id: number; + dipendenteId: number; + dipendente?: Dipendente; + data: string; + importo: number; + descrizione: string; + stato: string; + note?: string; +} + +const rimborsiService = { + getAll: async (dipendenteId?: number) => { + const params = dipendenteId ? { dipendenteId } : {}; + const response = await axios.get('/api/hr/rimborsi', { params }); + return response.data; + }, + create: async (data: Partial) => { + const response = await axios.post('/api/hr/rimborsi', data); + return response.data; + }, + update: async (id: number, data: Partial) => { + const response = await axios.put(`/api/hr/rimborsi/${id}`, data); + return response.data; + }, + delete: async (id: number) => { + await axios.delete(`/api/hr/rimborsi/${id}`); + }, +}; + +const dipendentiService = { + getAll: async () => { + const response = await axios.get('/api/hr/dipendenti'); + return response.data; + }, +}; + +export default function RimborsiPage() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + const [openDialog, setOpenDialog] = useState(false); + const [editingId, setEditingId] = useState(null); + const [formData, setFormData] = useState>({ stato: 'Richiesto' }); + + const { data: rimborsi = [], isLoading } = useQuery({ + queryKey: ['rimborsi'], + queryFn: () => rimborsiService.getAll(), + }); + + const { data: dipendenti = [] } = useQuery({ + queryKey: ['dipendenti'], + queryFn: () => dipendentiService.getAll(), + }); + + const createMutation = useMutation({ + mutationFn: (data: Partial) => rimborsiService.create(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['rimborsi'] }); + handleCloseDialog(); + }, + }); + + const updateMutation = useMutation({ + mutationFn: ({ id, data }: { id: number; data: Partial }) => rimborsiService.update(id, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['rimborsi'] }); + handleCloseDialog(); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (id: number) => rimborsiService.delete(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['rimborsi'] }), + }); + + const handleCloseDialog = () => { + setOpenDialog(false); + setEditingId(null); + setFormData({ stato: 'Richiesto' }); + }; + + const handleEdit = (rimborso: Rimborso) => { + setFormData(rimborso); + setEditingId(rimborso.id); + setOpenDialog(true); + }; + + const handleSubmit = () => { + if (editingId) { + updateMutation.mutate({ id: editingId, data: formData }); + } else { + createMutation.mutate(formData); + } + }; + + const columns: GridColDef[] = [ + { + field: 'dipendente', + headerName: t('personale.dipendente'), + width: 200, + valueGetter: (params: any) => params?.nome && params?.cognome ? `${params.cognome} ${params.nome}` : '', + }, + { + field: 'data', + headerName: t('personale.data'), + width: 120, + valueFormatter: (params: any) => params?.value ? dayjs(params.value).format('DD/MM/YYYY') : '', + }, + { field: 'importo', headerName: t('personale.importo'), width: 120, type: 'number' }, + { field: 'descrizione', headerName: t('personale.descrizione'), width: 200 }, + { field: 'stato', headerName: t('personale.stato'), width: 120 }, + { + field: 'actions', + headerName: t('common.actions'), + width: 120, + sortable: false, + renderCell: (params) => ( + + handleEdit(params.row)}> + + + { + if (confirm(t('common.deleteConfirm'))) { + deleteMutation.mutate(params.row.id); + } + }} + > + + + + ), + }, + ]; + + return ( + + + {t('personale.rimborsiTitle')} + + + + + + + + + {editingId ? t('personale.editRimborso') : t('personale.newRimborso')} + + + + setFormData({ ...formData, dipendenteId: Number(e.target.value) })} + required + > + {dipendenti?.map((d) => ( + + {d.nome} {d.cognome} + + ))} + + + + setFormData({ ...formData, data: newValue ? newValue.toISOString() : undefined })} + slotProps={{ textField: { fullWidth: true, required: true } }} + /> + + + setFormData({ ...formData, importo: Number(e.target.value) })} + required + /> + + + setFormData({ ...formData, descrizione: e.target.value })} + required + /> + + + setFormData({ ...formData, stato: e.target.value })} + required + > + Richiesto + Approvato + Rimborsato + Rifiutato + + + + setFormData({ ...formData, note: e.target.value })} + /> + + + + + + + + + + ); +} diff --git a/src/frontend/src/modules/hr/routes.tsx b/src/frontend/src/modules/hr/routes.tsx new file mode 100644 index 0000000..8ec0e71 --- /dev/null +++ b/src/frontend/src/modules/hr/routes.tsx @@ -0,0 +1,19 @@ +import { Routes, Route, Navigate } from "react-router-dom"; +import DipendentiPage from "./pages/DipendentiPage"; +import ContrattiPage from "./pages/ContrattiPage"; +import AssenzePage from "./pages/AssenzePage"; +import PagamentiPage from "./pages/PagamentiPage"; +import RimborsiPage from "./pages/RimborsiPage"; + +export default function HRRoutes() { + return ( + + } /> + } /> + } /> + } /> + } /> + } /> + + ); +} diff --git a/src/frontend/src/pages/ClientiPage.tsx b/src/frontend/src/modules/sales/pages/ClientiPage.tsx similarity index 100% rename from src/frontend/src/pages/ClientiPage.tsx rename to src/frontend/src/modules/sales/pages/ClientiPage.tsx diff --git a/src/frontend/src/pages/ArticoliPage.tsx b/src/frontend/src/modules/warehouse/pages/ArticoliPage.tsx similarity index 100% rename from src/frontend/src/pages/ArticoliPage.tsx rename to src/frontend/src/modules/warehouse/pages/ArticoliPage.tsx diff --git a/src/frontend/src/pages/Dashboard.tsx b/src/frontend/src/pages/Dashboard.tsx index 166bff6..9e50f89 100644 --- a/src/frontend/src/pages/Dashboard.tsx +++ b/src/frontend/src/pages/Dashboard.tsx @@ -1,430 +1,21 @@ -import { useState } from "react"; -import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { - Grid, - Paper, - Typography, - Box, - Card, - CardContent, - List, - ListItem, - ListItemText, - Chip, - Button, - Dialog, - DialogTitle, - DialogContent, - DialogContentText, - DialogActions, - Alert, - CircularProgress, -} from "@mui/material"; -import { - Event as EventIcon, - People as PeopleIcon, - CheckCircle as ConfirmedIcon, - PendingActions as PendingIcon, - PlayArrow as GenerateIcon, - DeleteSweep as ClearIcon, -} from "@mui/icons-material"; -import { useNavigate } from "react-router-dom"; -import dayjs from "dayjs"; -import { useTranslation, Trans } from "react-i18next"; -import { eventiService } from "../services/eventiService"; -import { demoService, DemoDataResult } from "../services/demoService"; -import { StatoEvento } from "../types"; - -const StatCard = ({ - title, - value, - icon, - color, -}: { - title: string; - value: number; - icon: React.ReactNode; - color: string; -}) => ( - - - - - - {title} - - {value} - - {icon} - - - -); - -const getStatoLabel = (stato: StatoEvento, t: any) => { - switch (stato) { - case StatoEvento.Scheda: - return t("status.scheda"); - case StatoEvento.Preventivo: - return t("status.preventivo"); - case StatoEvento.Confermato: - return t("status.confermato"); - default: - return t("common.unknown"); - } -}; - -const getStatoColor = (stato: StatoEvento) => { - switch (stato) { - case StatoEvento.Scheda: - return "default"; - case StatoEvento.Preventivo: - return "warning"; - case StatoEvento.Confermato: - return "success"; - default: - return "default"; - } -}; +import { Box, Typography, Grid, Paper } from '@mui/material'; export default function Dashboard() { - const navigate = useNavigate(); - const queryClient = useQueryClient(); - const { t } = useTranslation(); - const [demoDialog, setDemoDialog] = useState<"generate" | "clear" | null>( - null, - ); - const [loading, setLoading] = useState(false); - const [result, setResult] = useState(null); - const [error, setError] = useState(null); - - const { data: eventi = [] } = useQuery({ - queryKey: ["eventi"], - queryFn: () => eventiService.getAll(), - }); - - const handleGenerateDemo = async () => { - setLoading(true); - setError(null); - try { - const res = await demoService.generateDemoData(); - setResult(res); - queryClient.invalidateQueries(); - } catch (err: any) { - setError( - err.response?.data?.error || t("dashboard.generateError"), - ); - } finally { - setLoading(false); - } - }; - - const handleClearDemo = async () => { - setLoading(true); - setError(null); - try { - const res = await demoService.clearDemoData(); - setResult(res); - queryClient.invalidateQueries(); - } catch (err: any) { - setError( - err.response?.data?.error || t("dashboard.clearError"), - ); - } finally { - setLoading(false); - } - }; - - const handleCloseDialog = () => { - setDemoDialog(null); - setResult(null); - setError(null); - }; - - const oggi = dayjs().startOf("day"); - const prossimi30Giorni = oggi.add(30, "day"); - - const eventiProssimi = eventi - .filter( - (e) => - dayjs(e.dataEvento).isAfter(oggi) && - dayjs(e.dataEvento).isBefore(prossimi30Giorni), - ) - .sort((a, b) => dayjs(a.dataEvento).diff(dayjs(b.dataEvento))); - - const eventiConfermati = eventi.filter( - (e) => e.stato === StatoEvento.Confermato, - ).length; - const eventiPreventivo = eventi.filter( - (e) => e.stato === StatoEvento.Preventivo, - ).length; - const eventiOggi = eventi.filter((e) => - dayjs(e.dataEvento).isSame(oggi, "day"), - ).length; - return ( - - {t("dashboard.title")} - - - - - - - - - } - color="#1976d2" - /> - - - } - color="#4caf50" - /> - - - } - color="#ff9800" - /> - - - } - color="#9c27b0" - /> - - - + + Dashboard + - + - - {t("dashboard.upcomingEvents")} + Welcome to Zentral + + Select a module from the menu to get started. - - {eventiProssimi.slice(0, 10).map((evento) => ( - navigate(`/eventi/${evento.id}`)} - sx={{ - cursor: "pointer", - "&:hover": { bgcolor: "action.hover" }, - }} - > - - - {dayjs(evento.dataEvento).format("DD/MM/YYYY")} - - - - {evento.cliente?.ragioneSociale} - - } - /> - - - ))} - {eventiProssimi.length === 0 && ( - - - - )} - - - - - - - - {t("dashboard.expiringQuotes")} - - - {eventi - .filter( - (e) => - e.stato === StatoEvento.Preventivo && - e.dataScadenzaPreventivo, - ) - .sort((a, b) => - dayjs(a.dataScadenzaPreventivo).diff( - dayjs(b.dataScadenzaPreventivo), - ), - ) - .slice(0, 5) - .map((evento) => ( - navigate(`/eventi/${evento.id}`)} - sx={{ - cursor: "pointer", - "&:hover": { bgcolor: "action.hover" }, - }} - > - - - - ))} - {eventi.filter((e) => e.stato === StatoEvento.Preventivo) - .length === 0 && ( - - - - )} - - - {/* Dialog Genera Dati Demo */} - - {t("dashboard.generateDialogTitle")} - - {!result && !error && ( - - }} /> - - )} - {loading && ( - - - - )} - {result && ( - - {result.message} - - )} - {error && ( - - {error} - - )} - - - - {!result && ( - - )} - - - - {/* Dialog Pulisci Database */} - - {t("dashboard.clearDialogTitle")} - - {!result && !error && ( - - {t("dashboard.clearDialogWarning")} - - )} - {!result && !error && ( - - }} /> - - )} - {loading && ( - - - - )} - {result && ( - - {t("dashboard.clearSuccess", { - events: result.eventiCreati, - clients: result.clientiCreati, - locations: result.locationCreate, - resources: result.risorseCreate, - articles: result.articoliCreati - })} - - )} - {error && ( - - {error} - - )} - - - - {!result && ( - - )} - - ); } diff --git a/src/frontend/src/pages/RisorsePage.tsx b/src/frontend/src/pages/RisorsePage.tsx deleted file mode 100644 index 54d9e59..0000000 --- a/src/frontend/src/pages/RisorsePage.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import { useState } from 'react'; -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { - Box, - Typography, - Button, - Paper, - IconButton, - Dialog, - DialogTitle, - DialogContent, - DialogActions, - TextField, - Grid, - FormControl, - InputLabel, - Select, - MenuItem, -} from '@mui/material'; -import { DataGrid, GridColDef } from '@mui/x-data-grid'; -import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; -import { useTranslation } from 'react-i18next'; -import { risorseService, lookupService } from '../services/lookupService'; -import { Risorsa } from '../types'; - -export default function RisorsePage() { - const queryClient = useQueryClient(); - const { t } = useTranslation(); - const [openDialog, setOpenDialog] = useState(false); - const [editingId, setEditingId] = useState(null); - const [formData, setFormData] = useState>({ attivo: true }); - - const { data: risorse = [], isLoading } = useQuery({ - queryKey: ['risorse'], - queryFn: () => risorseService.getAll(), - }); - - const { data: tipiRisorsa = [] } = useQuery({ - queryKey: ['lookup', 'tipi-risorsa'], - queryFn: () => lookupService.getTipiRisorsa(), - }); - - const createMutation = useMutation({ - mutationFn: (data: Partial) => risorseService.create(data), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['risorse'] }); - handleCloseDialog(); - }, - }); - - const updateMutation = useMutation({ - mutationFn: ({ id, data }: { id: number; data: Partial }) => risorseService.update(id, data), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['risorse'] }); - handleCloseDialog(); - }, - }); - - const deleteMutation = useMutation({ - mutationFn: (id: number) => risorseService.delete(id), - onSuccess: () => queryClient.invalidateQueries({ queryKey: ['risorse'] }), - }); - - const handleCloseDialog = () => { - setOpenDialog(false); - setEditingId(null); - setFormData({ attivo: true }); - }; - - const handleEdit = (risorsa: Risorsa) => { - setFormData(risorsa); - setEditingId(risorsa.id); - setOpenDialog(true); - }; - - const handleSubmit = () => { - if (editingId) { - updateMutation.mutate({ id: editingId, data: formData }); - } else { - createMutation.mutate(formData); - } - }; - - const columns: GridColDef[] = [ - { field: 'nome', headerName: t('resources.name'), width: 150 }, - { field: 'cognome', headerName: t('resources.surname'), width: 150 }, - { - field: 'tipoRisorsa', - headerName: t('resources.type'), - width: 150, - valueGetter: (value: any) => value?.descrizione || '', - }, - { field: 'telefono', headerName: t('resources.phone'), width: 130 }, - { field: 'email', headerName: t('resources.email'), flex: 1, minWidth: 200 }, - { - field: 'actions', - headerName: t('common.actions'), - width: 120, - sortable: false, - renderCell: (params) => ( - - handleEdit(params.row)}> - - - { - if (confirm(t('resources.deleteConfirm'))) { - deleteMutation.mutate(params.row.id); - } - }} - > - - - - ), - }, - ]; - - return ( - - - {t('resources.title')} - - - - - - - - - {editingId ? t('resources.editResource') : t('resources.newResource')} - - - - setFormData({ ...formData, nome: e.target.value })} - /> - - - setFormData({ ...formData, cognome: e.target.value })} - /> - - - - {t('resources.resourceType')} - - - - - setFormData({ ...formData, telefono: e.target.value })} - /> - - - setFormData({ ...formData, email: e.target.value })} - /> - - - setFormData({ ...formData, note: e.target.value })} - /> - - - - - - - - - - ); -}