From 5a8740269b0cc6b4711ecb57335ac4e261d5d13e Mon Sep 17 00:00:00 2001 From: dnviti Date: Sat, 29 Nov 2025 17:53:34 +0100 Subject: [PATCH] feat: Implement a comprehensive custom fields system with backend management and frontend rendering capabilities. --- frontend/src/App.tsx | 5 + .../customFields/CustomFieldsRenderer.tsx | 195 + frontend/src/pages/ClientiPage.tsx | 97 +- frontend/src/pages/CustomFieldsAdminPage.tsx | 302 ++ frontend/src/services/customFieldService.ts | 24 + frontend/src/types/customFields.ts | 32 + frontend/src/types/index.ts | 1 + .../CustomFieldDefinitionsController.cs | 153 + src/Apollinare.API/Program.cs | 2 + .../Services/CustomFieldService.cs | 91 + src/Apollinare.API/apollinare.db-shm | Bin 32768 -> 32768 bytes src/Apollinare.API/apollinare.db-wal | Bin 181312 -> 177192 bytes src/Apollinare.Domain/Entities/BaseEntity.cs | 5 + .../Entities/CustomFieldDefinition.cs | 19 + .../Enums/CustomFieldType.cs | 15 + .../Data/AppollinareDbContext.cs | 10 + ...29161359_AddCustomFieldsSystem.Designer.cs | 3303 +++++++++++++++++ .../20251129161359_AddCustomFieldsSystem.cs | 472 +++ .../AppollinareDbContextModelSnapshot.cs | 193 + 19 files changed, 4881 insertions(+), 38 deletions(-) create mode 100644 frontend/src/components/customFields/CustomFieldsRenderer.tsx create mode 100644 frontend/src/pages/CustomFieldsAdminPage.tsx create mode 100644 frontend/src/services/customFieldService.ts create mode 100644 frontend/src/types/customFields.ts create mode 100644 src/Apollinare.API/Controllers/CustomFieldDefinitionsController.cs create mode 100644 src/Apollinare.API/Services/CustomFieldService.cs create mode 100644 src/Apollinare.Domain/Entities/CustomFieldDefinition.cs create mode 100644 src/Apollinare.Domain/Enums/CustomFieldType.cs create mode 100644 src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.Designer.cs create mode 100644 src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.cs diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index bb7c2cb..4c9de96 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -20,6 +20,7 @@ import ReportEditorPage from "./pages/ReportEditorPage"; import ModulesAdminPage from "./pages/ModulesAdminPage"; import ModulePurchasePage from "./pages/ModulePurchasePage"; import AutoCodesAdminPage from "./pages/AutoCodesAdminPage"; +import CustomFieldsAdminPage from "./pages/CustomFieldsAdminPage"; import WarehouseRoutes from "./modules/warehouse/routes"; import { ModuleGuard } from "./components/ModuleGuard"; import { useRealTimeUpdates } from "./hooks/useRealTimeUpdates"; @@ -101,6 +102,10 @@ function App() { path="admin/auto-codes" element={} /> + } + /> {/* Warehouse Module */} void; + readOnly?: boolean; +} + +export const CustomFieldsRenderer: React.FC = ({ entityName, values, onChange, readOnly = false }) => { + const [definitions, setDefinitions] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + const loadDefinitions = async () => { + try { + const defs = await customFieldService.getByEntity(entityName); + setDefinitions(defs); + } catch (error) { + console.error("Failed to load custom fields", error); + } finally { + setLoading(false); + } + }; + loadDefinitions(); + }, [entityName]); + + if (loading) return null; + if (definitions.length === 0) return null; + + return ( + + + Campi Personalizzati + + + {definitions.map(def => ( + + onChange(def.fieldName, val)} + readOnly={readOnly} + /> + + ))} + + + ); +}; + +const FieldRenderer: React.FC<{ + definition: CustomFieldDefinition; + value: any; + onChange: (value: any) => void; + readOnly: boolean; +}> = ({ definition, value, onChange, readOnly }) => { + + const handleChange = (e: React.ChangeEvent) => { + onChange(e.target.value); + }; + + switch (definition.type) { + case CustomFieldType.Text: + case CustomFieldType.Email: + case CustomFieldType.Url: + return ( + + ); + + case CustomFieldType.Number: + return ( + + ); + + case CustomFieldType.TextArea: + return ( + + ); + + case CustomFieldType.Boolean: + return ( + onChange(e.target.checked)} + disabled={readOnly} + /> + } + label={definition.label} + /> + ); + + case CustomFieldType.Date: + return ( + onChange(newValue ? newValue.toISOString() : null)} + disabled={readOnly} + slotProps={{ textField: { fullWidth: true, required: definition.isRequired, helperText: definition.description, size: 'small' } }} + /> + ); + + case CustomFieldType.Select: + let options: string[] = []; + try { + options = definition.optionsJson ? JSON.parse(definition.optionsJson) : []; + } catch (e) { + console.error("Invalid options JSON", e); + } + return ( + + {options.map((opt) => ( + + {opt} + + ))} + + ); + + case CustomFieldType.Color: + return ( + + ); + + default: + return null; + } +}; diff --git a/frontend/src/pages/ClientiPage.tsx b/frontend/src/pages/ClientiPage.tsx index 0f9e92f..19a26de 100644 --- a/frontend/src/pages/ClientiPage.tsx +++ b/frontend/src/pages/ClientiPage.tsx @@ -11,7 +11,7 @@ import { DialogContent, DialogActions, TextField, - Grid, + } from "@mui/material"; import { DataGrid, GridColDef } from "@mui/x-data-grid"; import { @@ -21,12 +21,15 @@ import { } from "@mui/icons-material"; import { clientiService } from "../services/lookupService"; import { Cliente } from "../types"; +import { CustomFieldsRenderer } from "../components/customFields/CustomFieldsRenderer"; +import { CustomFieldValues } from "../types/customFields"; export default function ClientiPage() { const queryClient = useQueryClient(); const [openDialog, setOpenDialog] = useState(false); const [editingId, setEditingId] = useState(null); const [formData, setFormData] = useState>({ attivo: true }); + const [customFields, setCustomFields] = useState({}); const { data: clienti = [], isLoading } = useQuery({ queryKey: ["clienti"], @@ -59,22 +62,33 @@ export default function ClientiPage() { setOpenDialog(false); setEditingId(null); setFormData({ attivo: true }); + setCustomFields({}); }; const handleEdit = (cliente: Cliente) => { setFormData(cliente); setEditingId(cliente.id); + try { + setCustomFields(cliente.customFieldsJson ? JSON.parse(cliente.customFieldsJson) : {}); + } catch (e) { + setCustomFields({}); + } setOpenDialog(true); }; const handleSubmit = () => { + const dataWithCustomFields = { + ...formData, + customFieldsJson: JSON.stringify(customFields) + }; + if (editingId) { // In modifica, non inviamo il codice (non modificabile) - const { codice: _codice, ...updateData } = formData; + const { codice: _codice, ...updateData } = dataWithCustomFields; updateMutation.mutate({ id: editingId, data: updateData }); } else { // In creazione, non inviamo il codice (generato automaticamente) - const { codice: _codice, ...createData } = formData; + const { codice: _codice, ...createData } = dataWithCustomFields; createMutation.mutate(createData); } }; @@ -162,8 +176,8 @@ export default function ClientiPage() { {editingId ? "Modifica Cliente" : "Nuovo Cliente"} - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + setCustomFields(prev => ({ ...prev, [field]: value }))} + /> + + diff --git a/frontend/src/pages/CustomFieldsAdminPage.tsx b/frontend/src/pages/CustomFieldsAdminPage.tsx new file mode 100644 index 0000000..84f3061 --- /dev/null +++ b/frontend/src/pages/CustomFieldsAdminPage.tsx @@ -0,0 +1,302 @@ + +import React, { useState, useEffect } from 'react'; +import { + Box, + Button, + Card, + CardContent, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + FormControl, + + InputLabel, + MenuItem, + Select, + TextField, + Typography, + FormControlLabel, + Checkbox, + Snackbar, + Alert +} from '@mui/material'; +import { DataGrid, GridColDef, GridActionsCellItem } from '@mui/x-data-grid'; +import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; +import { CustomFieldDefinition, CustomFieldType } from '../types/customFields'; +import { customFieldService } from '../services/customFieldService'; + +const ENTITIES = [ + { value: 'Cliente', label: 'Clienti' }, + { value: 'Articolo', label: 'Articoli (Catering)' }, + { value: 'Evento', label: 'Eventi' }, + { value: 'WarehouseArticle', label: 'Articoli Magazzino' }, + { value: 'WarehouseLocation', label: 'Magazzini' }, + { value: 'Risorsa', label: 'Risorse (Staff)' } +]; + +const FIELD_TYPES = [ + { value: CustomFieldType.Text, label: 'Testo' }, + { value: CustomFieldType.Number, label: 'Numero' }, + { value: CustomFieldType.Date, label: 'Data' }, + { value: CustomFieldType.Boolean, label: 'Booleano (Sì/No)' }, + { value: CustomFieldType.Select, label: 'Lista a discesa' }, + { value: CustomFieldType.TextArea, label: 'Area di testo' }, + { value: CustomFieldType.Color, label: 'Colore' }, + { value: CustomFieldType.Url, label: 'URL' }, + { value: CustomFieldType.Email, label: 'Email' } +]; + +const CustomFieldsAdminPage: React.FC = () => { + const [selectedEntity, setSelectedEntity] = useState(ENTITIES[0].value); + const [fields, setFields] = useState([]); + const [loading, setLoading] = useState(false); + const [dialogOpen, setDialogOpen] = useState(false); + const [currentField, setCurrentField] = useState>({}); + const [snackbar, setSnackbar] = useState<{ open: boolean, message: string, severity: 'success' | 'error' }>({ + open: false, + message: '', + severity: 'success' + }); + + const showSnackbar = (message: string, severity: 'success' | 'error') => { + setSnackbar({ open: true, message, severity }); + }; + + const handleCloseSnackbar = () => setSnackbar({ ...snackbar, open: false }); + + const loadFields = async () => { + setLoading(true); + try { + const data = await customFieldService.getByEntity(selectedEntity); + setFields(data); + } catch (error) { + showSnackbar('Errore nel caricamento dei campi', 'error'); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + loadFields(); + }, [selectedEntity]); + + const handleSave = async () => { + try { + if (currentField.id) { + await customFieldService.update(currentField.id, currentField as CustomFieldDefinition); + showSnackbar('Campo aggiornato con successo', 'success'); + } else { + await customFieldService.create({ + ...currentField, + entityName: selectedEntity, + isActive: true, + sortOrder: fields.length + 1 + } as CustomFieldDefinition); + showSnackbar('Campo creato con successo', 'success'); + } + setDialogOpen(false); + loadFields(); + } catch (error) { + showSnackbar('Errore nel salvataggio', 'error'); + } + }; + + const handleDelete = async (id: number) => { + if (window.confirm('Sei sicuro di voler eliminare questo campo?')) { + try { + await customFieldService.delete(id); + showSnackbar('Campo eliminato', 'success'); + loadFields(); + } catch (error) { + showSnackbar('Errore durante l\'eliminazione', 'error'); + } + } + }; + + const columns: GridColDef[] = [ + { field: 'label', headerName: 'Etichetta', flex: 1 }, + { field: 'fieldName', headerName: 'Nome Interno', flex: 1 }, + { + field: 'type', + headerName: 'Tipo', + width: 150, + valueFormatter: (params) => FIELD_TYPES.find(t => t.value === params.value)?.label + }, + { + field: 'isRequired', + headerName: 'Obbligatorio', + width: 120, + type: 'boolean' + }, + { + field: 'sortOrder', + headerName: 'Ordine', + width: 100, + type: 'number', + editable: true + }, + { + field: 'actions', + type: 'actions', + headerName: 'Azioni', + width: 100, + getActions: (params) => [ + } + label="Modifica" + onClick={() => { + setCurrentField(params.row); + setDialogOpen(true); + }} + />, + } + label="Elimina" + onClick={() => handleDelete(params.row.id)} + />, + ], + }, + ]; + + return ( + + + Gestione Campi Personalizzati + + + + + + + + Entità + + + + + + + + + + +
+ +
+ + setDialogOpen(false)} maxWidth="sm" fullWidth> + {currentField.id ? 'Modifica Campo' : 'Nuovo Campo'} + + + setCurrentField({ ...currentField, label: e.target.value })} + required + /> + setCurrentField({ ...currentField, fieldName: e.target.value })} + required + helperText="Deve essere univoco per l'entità. Usa solo lettere minuscole e underscore." + disabled={!!currentField.id} + /> + + Tipo + + + + {currentField.type === CustomFieldType.Select && ( + setCurrentField({ ...currentField, optionsJson: e.target.value })} + placeholder='["Opzione 1", "Opzione 2"]' + helperText="Inserisci un array JSON valido di stringhe" + /> + )} + + setCurrentField({ ...currentField, description: e.target.value })} + /> + + setCurrentField({ ...currentField, isRequired: e.target.checked })} + /> + } + label="Obbligatorio" + /> + + setCurrentField({ ...currentField, sortOrder: parseInt(e.target.value) })} + /> + + + + + + + + + + + {snackbar.message} + + +
+ ); +}; + +export default CustomFieldsAdminPage; + diff --git a/frontend/src/services/customFieldService.ts b/frontend/src/services/customFieldService.ts new file mode 100644 index 0000000..3170c3b --- /dev/null +++ b/frontend/src/services/customFieldService.ts @@ -0,0 +1,24 @@ +import api from './api'; +import { CustomFieldDefinition } from '../types/customFields'; + +export const customFieldService = { + getAll: async () => { + const response = await api.get('/custom-fields'); + return response.data; + }, + getByEntity: async (entityName: string) => { + const response = await api.get(`/custom-fields/entity/${entityName}`); + return response.data; + }, + create: async (definition: Omit) => { + const response = await api.post('/custom-fields', definition); + return response.data; + }, + update: async (id: number, definition: CustomFieldDefinition) => { + const response = await api.put(`/custom-fields/${id}`, definition); + return response.data; + }, + delete: async (id: number) => { + await api.delete(`/custom-fields/${id}`); + } +}; diff --git a/frontend/src/types/customFields.ts b/frontend/src/types/customFields.ts new file mode 100644 index 0000000..435dee5 --- /dev/null +++ b/frontend/src/types/customFields.ts @@ -0,0 +1,32 @@ +export enum CustomFieldType { + Text = 0, + Number = 1, + Date = 2, + Boolean = 3, + Select = 4, + MultiSelect = 5, + TextArea = 6, + Color = 7, + Url = 8, + Email = 9 +} + +export interface CustomFieldDefinition { + id: number; + entityName: string; + fieldName: string; + label: string; + type: CustomFieldType; + isRequired: boolean; + defaultValue?: string; + optionsJson?: string; + sortOrder: number; + description?: string; + isActive: boolean; + validationRegex?: string; + placeholder?: string; +} + +export interface CustomFieldValues { + [key: string]: any; +} diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 939c149..c37e6ae 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -10,6 +10,7 @@ export interface BaseEntity { createdBy?: string; updatedAt?: string; updatedBy?: string; + customFieldsJson?: string; } export interface Cliente extends BaseEntity { diff --git a/src/Apollinare.API/Controllers/CustomFieldDefinitionsController.cs b/src/Apollinare.API/Controllers/CustomFieldDefinitionsController.cs new file mode 100644 index 0000000..fbc9420 --- /dev/null +++ b/src/Apollinare.API/Controllers/CustomFieldDefinitionsController.cs @@ -0,0 +1,153 @@ +using Apollinare.API.Services; +using Apollinare.Domain.Entities; +using Apollinare.Domain.Enums; +using Microsoft.AspNetCore.Mvc; + +namespace Apollinare.API.Controllers; + +[ApiController] +[Route("api/custom-fields")] +public class CustomFieldDefinitionsController : ControllerBase +{ + private readonly CustomFieldService _service; + private readonly ILogger _logger; + + public CustomFieldDefinitionsController(CustomFieldService service, ILogger logger) + { + _service = service; + _logger = logger; + } + + [HttpGet] + public async Task>> GetAll() + { + var defs = await _service.GetAllDefinitionsAsync(); + return Ok(defs.Select(ToDto).ToList()); + } + + [HttpGet("entity/{entityName}")] + public async Task>> GetByEntity(string entityName) + { + var defs = await _service.GetDefinitionsByEntityAsync(entityName); + return Ok(defs.Select(ToDto).ToList()); + } + + [HttpGet("{id:int}")] + public async Task> Get(int id) + { + var def = await _service.GetDefinitionAsync(id); + if (def == null) return NotFound(); + return Ok(ToDto(def)); + } + + [HttpPost] + public async Task> Create(CustomFieldDefinitionDto dto) + { + try + { + var entity = new CustomFieldDefinition + { + EntityName = dto.EntityName, + FieldName = dto.FieldName, + Label = dto.Label, + Type = dto.Type, + IsRequired = dto.IsRequired, + DefaultValue = dto.DefaultValue, + OptionsJson = dto.OptionsJson, + SortOrder = dto.SortOrder, + Description = dto.Description, + IsActive = dto.IsActive, + ValidationRegex = dto.ValidationRegex, + Placeholder = dto.Placeholder + }; + + var created = await _service.CreateDefinitionAsync(entity); + return CreatedAtAction(nameof(Get), new { id = created.Id }, ToDto(created)); + } + catch (ArgumentException ex) + { + return BadRequest(new { error = ex.Message }); + } + } + + [HttpPut("{id:int}")] + public async Task> Update(int id, CustomFieldDefinitionDto dto) + { + try + { + var entity = new CustomFieldDefinition + { + EntityName = dto.EntityName, + FieldName = dto.FieldName, + Label = dto.Label, + Type = dto.Type, + IsRequired = dto.IsRequired, + DefaultValue = dto.DefaultValue, + OptionsJson = dto.OptionsJson, + SortOrder = dto.SortOrder, + Description = dto.Description, + IsActive = dto.IsActive, + ValidationRegex = dto.ValidationRegex, + Placeholder = dto.Placeholder + }; + + var updated = await _service.UpdateDefinitionAsync(id, entity); + return Ok(ToDto(updated)); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id:int}")] + public async Task Delete(int id) + { + try + { + await _service.DeleteDefinitionAsync(id); + return NoContent(); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + private static CustomFieldDefinitionDto ToDto(CustomFieldDefinition entity) + { + return new CustomFieldDefinitionDto + { + Id = entity.Id, + EntityName = entity.EntityName, + FieldName = entity.FieldName, + Label = entity.Label, + Type = entity.Type, + IsRequired = entity.IsRequired, + DefaultValue = entity.DefaultValue, + OptionsJson = entity.OptionsJson, + SortOrder = entity.SortOrder, + Description = entity.Description, + IsActive = entity.IsActive, + ValidationRegex = entity.ValidationRegex, + Placeholder = entity.Placeholder + }; + } +} + +public class CustomFieldDefinitionDto +{ + public int Id { get; set; } + public required string EntityName { get; set; } + public required string FieldName { get; set; } + public required string Label { get; set; } + public CustomFieldType Type { get; set; } + public bool IsRequired { get; set; } + public string? DefaultValue { get; set; } + public string? OptionsJson { get; set; } + public int SortOrder { get; set; } + public string? Description { get; set; } + public bool IsActive { get; set; } + public string? ValidationRegex { get; set; } + public string? Placeholder { get; set; } +} diff --git a/src/Apollinare.API/Program.cs b/src/Apollinare.API/Program.cs index c6478dd..7fa626d 100644 --- a/src/Apollinare.API/Program.cs +++ b/src/Apollinare.API/Program.cs @@ -1,5 +1,6 @@ using Apollinare.API.Hubs; using Apollinare.API.Services; +// Trigger rebuild using Apollinare.API.Services.Reports; using Apollinare.API.Modules.Warehouse.Services; using Apollinare.Infrastructure.Data; @@ -20,6 +21,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddSingleton(); // Warehouse Module Services diff --git a/src/Apollinare.API/Services/CustomFieldService.cs b/src/Apollinare.API/Services/CustomFieldService.cs new file mode 100644 index 0000000..da4767b --- /dev/null +++ b/src/Apollinare.API/Services/CustomFieldService.cs @@ -0,0 +1,91 @@ +using Apollinare.Domain.Entities; +using Apollinare.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; + +namespace Apollinare.API.Services; + +public class CustomFieldService +{ + private readonly AppollinareDbContext _context; + private readonly ILogger _logger; + + public CustomFieldService(AppollinareDbContext context, ILogger logger) + { + _context = context; + _logger = logger; + } + + public async Task> GetAllDefinitionsAsync() + { + return await _context.CustomFieldDefinitions + .OrderBy(x => x.EntityName) + .ThenBy(x => x.SortOrder) + .ToListAsync(); + } + + public async Task> GetDefinitionsByEntityAsync(string entityName) + { + return await _context.CustomFieldDefinitions + .Where(x => x.EntityName == entityName && x.IsActive) + .OrderBy(x => x.SortOrder) + .ToListAsync(); + } + + public async Task GetDefinitionAsync(int id) + { + return await _context.CustomFieldDefinitions.FindAsync(id); + } + + public async Task CreateDefinitionAsync(CustomFieldDefinition definition) + { + // Check for duplicate field name in the same entity + var exists = await _context.CustomFieldDefinitions + .AnyAsync(x => x.EntityName == definition.EntityName && x.FieldName == definition.FieldName); + + if (exists) + { + throw new ArgumentException($"Field '{definition.FieldName}' already exists for entity '{definition.EntityName}'"); + } + + definition.CreatedAt = DateTime.UtcNow; + _context.CustomFieldDefinitions.Add(definition); + await _context.SaveChangesAsync(); + return definition; + } + + public async Task UpdateDefinitionAsync(int id, CustomFieldDefinition updatedDef) + { + var existing = await _context.CustomFieldDefinitions.FindAsync(id); + if (existing == null) + { + throw new KeyNotFoundException($"CustomFieldDefinition with ID {id} not found"); + } + + existing.Label = updatedDef.Label; + existing.Type = updatedDef.Type; + existing.IsRequired = updatedDef.IsRequired; + existing.DefaultValue = updatedDef.DefaultValue; + existing.OptionsJson = updatedDef.OptionsJson; + existing.SortOrder = updatedDef.SortOrder; + existing.Description = updatedDef.Description; + existing.IsActive = updatedDef.IsActive; + existing.ValidationRegex = updatedDef.ValidationRegex; + existing.Placeholder = updatedDef.Placeholder; + existing.UpdatedAt = DateTime.UtcNow; + + await _context.SaveChangesAsync(); + return existing; + } + + public async Task DeleteDefinitionAsync(int id) + { + var existing = await _context.CustomFieldDefinitions.FindAsync(id); + if (existing == null) + { + throw new KeyNotFoundException($"CustomFieldDefinition with ID {id} not found"); + } + + _context.CustomFieldDefinitions.Remove(existing); + await _context.SaveChangesAsync(); + } +} diff --git a/src/Apollinare.API/apollinare.db-shm b/src/Apollinare.API/apollinare.db-shm index fc0c2551563cfbf5f48a503bf3f2112ed52b0881..99ddfc3898d9bda2b095ce2fd55ce271faa95461 100644 GIT binary patch literal 32768 zcmeI*IZgvX5QX6~`(pOZHj9n1%_b58Cj>;0!668_05>26BFITN1{o3J5FCPl1YTJn zIbsG0xkdM1^0P#I-KTHmy^4JZ@Jq*7AWl)AF1_-^-=wsNYRE0;=D52z{Y zN?qAd8cI{q$A%RD@B6-A-+kR5*6)#WtmL^?8-)M@2q1s}0tg_000IagfB*srAbv(2xJQsI;X2-_l55m55I+fvI9TAhRP%0Ck;^uq$%KMY*7e= z5m>i|PIKD{vpB0JE-)Q<{<<}7t8*e^n2nUJ8fIZuMIg99%{HuM+rjsdy@6tO3mpg~ zE-;h${AMG`3#1D$o9^gLp1i=ERctkR1pwj_@OK~Nsrfuj^dJzWz=ADDIamInM)S8O z-Z>cE{EM~{-Au6#8=bL#tc>4+XLW0?I?T0nS`N#%zHR4A=sx ztOLH2(y9zHNLSI--MRl;^`(=}&AI3N7SJi)eK227m7G~&P1ozZ*`M35)vMC&-+JM5 zqul&dyKG$D)W0;(ixKyGZC_sZzHPN`w!K{F{h;zr`KEkVc9lJ4U#Tko{kpQLY$@By zj^e-ZJ^r2N|7YJ{Q8ttVrKTJzN6HW7r*f>ED5uJq@=N)xl$DSFt`%MVzSs5M{45p% z2q1s}0tg_000IagfB*srAb-5u{w*-mo3wWTDF@5!@g5}vA<@cG>zKh*u!Sa!a&1>U5%w{*2OlCE~><`D$^e_vP#geg!7b8MzYKmv0p zAP}s;e6W*eZScGm?76+qTHC4acfnRt-5<>%5TC$ee5I+300IagfB*srAdo772c085 ArvLx| diff --git a/src/Apollinare.API/apollinare.db-wal b/src/Apollinare.API/apollinare.db-wal index 7a1b5751afccbd43e36e34e1f5429fdc96bbe355..856b57f9c621ed6e6628aef2ad44a65351c81176 100644 GIT binary patch literal 177192 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 l0!RP}AOR$R1dsp{Kmter2_ONT0I>@&x?O + /// Stores custom field values as JSON: {"birthday": "2023-01-01", "vip_status": "gold"} + /// + public string? CustomFieldsJson { get; set; } } diff --git a/src/Apollinare.Domain/Entities/CustomFieldDefinition.cs b/src/Apollinare.Domain/Entities/CustomFieldDefinition.cs new file mode 100644 index 0000000..e2aa4e9 --- /dev/null +++ b/src/Apollinare.Domain/Entities/CustomFieldDefinition.cs @@ -0,0 +1,19 @@ +using Apollinare.Domain.Enums; + +namespace Apollinare.Domain.Entities; + +public class CustomFieldDefinition : BaseEntity +{ + public required string EntityName { get; set; } // e.g. "Cliente", "WarehouseArticle" + public required string FieldName { get; set; } // Internal name, e.g. "birthday" + public required string Label { get; set; } // Display name, e.g. "Birthday" + public CustomFieldType Type { get; set; } + public bool IsRequired { get; set; } + public string? DefaultValue { get; set; } + public string? OptionsJson { get; set; } // For Select/MultiSelect: ["Option A", "Option B"] + public int SortOrder { get; set; } + public string? Description { get; set; } + public bool IsActive { get; set; } = true; + public string? ValidationRegex { get; set; } + public string? Placeholder { get; set; } +} diff --git a/src/Apollinare.Domain/Enums/CustomFieldType.cs b/src/Apollinare.Domain/Enums/CustomFieldType.cs new file mode 100644 index 0000000..7db8ea7 --- /dev/null +++ b/src/Apollinare.Domain/Enums/CustomFieldType.cs @@ -0,0 +1,15 @@ +namespace Apollinare.Domain.Enums; + +public enum CustomFieldType +{ + Text = 0, + Number = 1, + Date = 2, + Boolean = 3, + Select = 4, + MultiSelect = 5, + TextArea = 6, + Color = 7, + Url = 8, + Email = 9 +} diff --git a/src/Apollinare.Infrastructure/Data/AppollinareDbContext.cs b/src/Apollinare.Infrastructure/Data/AppollinareDbContext.cs index 0c49e4c..c11d2a9 100644 --- a/src/Apollinare.Infrastructure/Data/AppollinareDbContext.cs +++ b/src/Apollinare.Infrastructure/Data/AppollinareDbContext.cs @@ -44,6 +44,9 @@ public class AppollinareDbContext : DbContext // Auto Code system public DbSet AutoCodes => Set(); + // Custom Fields system + public DbSet CustomFieldDefinitions => Set(); + // Warehouse module entities public DbSet WarehouseLocations => Set(); public DbSet WarehouseArticles => Set(); @@ -284,6 +287,13 @@ public class AppollinareDbContext : DbContext entity.HasIndex(e => e.ModuleCode); }); + // CustomFieldDefinition + modelBuilder.Entity(entity => + { + entity.HasIndex(e => new { e.EntityName, e.FieldName }).IsUnique(); + entity.HasIndex(e => e.EntityName); + }); + // =============================================== // WAREHOUSE MODULE ENTITIES // =============================================== diff --git a/src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.Designer.cs b/src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.Designer.cs new file mode 100644 index 0000000..6fc86ed --- /dev/null +++ b/src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.Designer.cs @@ -0,0 +1,3303 @@ +// +using System; +using Apollinare.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Apollinare.Infrastructure.Migrations +{ + [DbContext(typeof(AppollinareDbContext))] + [Migration("20251129161359_AddCustomFieldsSystem")] + partial class AddCustomFieldsSystem + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.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("Apollinare.Domain.Entities.Articolo", b => + { + b.HasOne("Apollinare.Domain.Entities.CodiceCategoria", "Categoria") + .WithMany("Articoli") + .HasForeignKey("CategoriaId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.TipoMateriale", "TipoMateriale") + .WithMany("Articoli") + .HasForeignKey("TipoMaterialeId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Categoria"); + + b.Navigation("TipoMateriale"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Evento", b => + { + b.HasOne("Apollinare.Domain.Entities.Cliente", "Cliente") + .WithMany("Eventi") + .HasForeignKey("ClienteId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Location", "Location") + .WithMany("Eventi") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.TipoEvento", "TipoEvento") + .WithMany("Eventi") + .HasForeignKey("TipoEventoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Cliente"); + + b.Navigation("Location"); + + b.Navigation("TipoEvento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoAcconto", b => + { + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("Acconti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoAllegato", b => + { + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("Allegati") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoAltroCosto", b => + { + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("AltriCosti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoDegustazione", b => + { + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("Degustazioni") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoDettaglioOspiti", b => + { + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("DettagliOspiti") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.TipoOspite", "TipoOspite") + .WithMany("DettagliOspiti") + .HasForeignKey("TipoOspiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + + b.Navigation("TipoOspite"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoDettaglioPrelievo", b => + { + b.HasOne("Apollinare.Domain.Entities.Articolo", "Articolo") + .WithMany("DettagliPrelievo") + .HasForeignKey("ArticoloId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("DettagliPrelievo") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Articolo"); + + b.Navigation("Evento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.EventoDettaglioRisorsa", b => + { + b.HasOne("Apollinare.Domain.Entities.Evento", "Evento") + .WithMany("DettagliRisorse") + .HasForeignKey("EventoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Risorsa", "Risorsa") + .WithMany("DettagliRisorse") + .HasForeignKey("RisorsaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Evento"); + + b.Navigation("Risorsa"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.ModuleSubscription", b => + { + b.HasOne("Apollinare.Domain.Entities.AppModule", "Module") + .WithOne("Subscription") + .HasForeignKey("Apollinare.Domain.Entities.ModuleSubscription", "ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Risorsa", b => + { + b.HasOne("Apollinare.Domain.Entities.TipoRisorsa", "TipoRisorsa") + .WithMany("Risorse") + .HasForeignKey("TipoRisorsaId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("TipoRisorsa"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.TipoEvento", b => + { + b.HasOne("Apollinare.Domain.Entities.TipoPasto", "TipoPasto") + .WithMany("TipiEvento") + .HasForeignKey("TipoPastoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("TipoPasto"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.ArticleBarcode", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Barcodes") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Batches") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("Serials") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("Serials") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", "CurrentWarehouse") + .WithMany() + .HasForeignKey("CurrentWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("CurrentWarehouse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.InventoryCount", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.StockMovement", "AdjustmentMovement") + .WithMany() + .HasForeignKey("AdjustmentMovementId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticleCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("AdjustmentMovement"); + + b.Navigation("Category"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.InventoryCountLine", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.InventoryCount", "InventoryCount") + .WithMany("Lines") + .HasForeignKey("InventoryCountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.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("Apollinare.Domain.Entities.Warehouse.StockLevel", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("StockLevels") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("StockLevels") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany("StockLevels") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Batch"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.StockMovement", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", "DestinationWarehouse") + .WithMany("DestinationMovements") + .HasForeignKey("DestinationWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.MovementReason", "Reason") + .WithMany("Movements") + .HasForeignKey("ReasonId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", "SourceWarehouse") + .WithMany("SourceMovements") + .HasForeignKey("SourceWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("DestinationWarehouse"); + + b.Navigation("Reason"); + + b.Navigation("SourceWarehouse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.StockMovementLine", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany("MovementLines") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany("MovementLines") + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.StockMovement", "Movement") + .WithMany("Lines") + .HasForeignKey("MovementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.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("Apollinare.Domain.Entities.Warehouse.StockValuation", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Article"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.StockValuationLayer", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.ArticleBatch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.Domain.Entities.Warehouse.StockMovement", "SourceMovement") + .WithMany() + .HasForeignKey("SourceMovementId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Apollinare.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("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticleCategory", "Category") + .WithMany("Articles") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.HasOne("Apollinare.Domain.Entities.Warehouse.WarehouseArticleCategory", "ParentCategory") + .WithMany("ChildCategories") + .HasForeignKey("ParentCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ParentCategory"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.AppModule", b => + { + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Articolo", b => + { + b.Navigation("DettagliPrelievo"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Cliente", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.CodiceCategoria", b => + { + b.Navigation("Articoli"); + }); + + modelBuilder.Entity("Apollinare.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("Apollinare.Domain.Entities.Location", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Risorsa", b => + { + b.Navigation("DettagliRisorse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.TipoEvento", b => + { + b.Navigation("Eventi"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.TipoMateriale", b => + { + b.Navigation("Articoli"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.TipoOspite", b => + { + b.Navigation("DettagliOspiti"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.TipoPasto", b => + { + b.Navigation("TipiEvento"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.TipoRisorsa", b => + { + b.Navigation("Risorse"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.ArticleBatch", b => + { + b.Navigation("MovementLines"); + + b.Navigation("Serials"); + + b.Navigation("StockLevels"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.ArticleSerial", b => + { + b.Navigation("MovementLines"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.InventoryCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.MovementReason", b => + { + b.Navigation("Movements"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.StockMovement", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.WarehouseArticle", b => + { + b.Navigation("Barcodes"); + + b.Navigation("Batches"); + + b.Navigation("MovementLines"); + + b.Navigation("Serials"); + + b.Navigation("StockLevels"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.WarehouseArticleCategory", b => + { + b.Navigation("Articles"); + + b.Navigation("ChildCategories"); + }); + + modelBuilder.Entity("Apollinare.Domain.Entities.Warehouse.WarehouseLocation", b => + { + b.Navigation("DestinationMovements"); + + b.Navigation("SourceMovements"); + + b.Navigation("StockLevels"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.cs b/src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.cs new file mode 100644 index 0000000..3364516 --- /dev/null +++ b/src/Apollinare.Infrastructure/Migrations/20251129161359_AddCustomFieldsSystem.cs @@ -0,0 +1,472 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Apollinare.Infrastructure.Migrations +{ + /// + public partial class AddCustomFieldsSystem : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "WarehouseLocations", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "WarehouseArticles", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "WarehouseArticleCategories", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "VirtualDatasets", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Utenti", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "TipiRisorsa", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "TipiPasto", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "TipiOspite", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "TipiMateriale", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "TipiEvento", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "StockValuations", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "StockValuationLayers", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "StockMovements", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "StockMovementLines", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "StockLevels", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Risorse", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ReportTemplates", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ReportImages", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ReportFonts", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "MovementReasons", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ModuleSubscriptions", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Location", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "InventoryCounts", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "InventoryCountLines", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiDettaglioRisorse", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiDettaglioPrelievo", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiDettaglioOspiti", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiDegustazioni", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiAltriCosti", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiAllegati", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "EventiAcconti", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Eventi", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Configurazioni", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "CodiciCategoria", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Clienti", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "AutoCodes", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "Articoli", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ArticleSerials", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ArticleBatches", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "ArticleBarcodes", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "CustomFieldsJson", + table: "AppModules", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateTable( + name: "CustomFieldDefinitions", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EntityName = table.Column(type: "TEXT", nullable: false), + FieldName = table.Column(type: "TEXT", nullable: false), + Label = table.Column(type: "TEXT", nullable: false), + Type = table.Column(type: "INTEGER", nullable: false), + IsRequired = table.Column(type: "INTEGER", nullable: false), + DefaultValue = table.Column(type: "TEXT", nullable: true), + OptionsJson = table.Column(type: "TEXT", nullable: true), + SortOrder = table.Column(type: "INTEGER", nullable: false), + Description = table.Column(type: "TEXT", nullable: true), + IsActive = table.Column(type: "INTEGER", nullable: false), + ValidationRegex = table.Column(type: "TEXT", nullable: true), + Placeholder = 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_CustomFieldDefinitions", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_CustomFieldDefinitions_EntityName", + table: "CustomFieldDefinitions", + column: "EntityName"); + + migrationBuilder.CreateIndex( + name: "IX_CustomFieldDefinitions_EntityName_FieldName", + table: "CustomFieldDefinitions", + columns: new[] { "EntityName", "FieldName" }, + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CustomFieldDefinitions"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "WarehouseLocations"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "WarehouseArticles"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "WarehouseArticleCategories"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "VirtualDatasets"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Utenti"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "TipiRisorsa"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "TipiPasto"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "TipiOspite"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "TipiMateriale"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "TipiEvento"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "StockValuations"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "StockValuationLayers"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "StockMovements"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "StockMovementLines"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "StockLevels"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Risorse"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ReportTemplates"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ReportImages"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ReportFonts"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "MovementReasons"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ModuleSubscriptions"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Location"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "InventoryCounts"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "InventoryCountLines"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiDettaglioRisorse"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiDettaglioPrelievo"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiDettaglioOspiti"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiDegustazioni"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiAltriCosti"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiAllegati"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "EventiAcconti"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Eventi"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Configurazioni"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "CodiciCategoria"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Clienti"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "AutoCodes"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "Articoli"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ArticleSerials"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ArticleBatches"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "ArticleBarcodes"); + + migrationBuilder.DropColumn( + name: "CustomFieldsJson", + table: "AppModules"); + } + } +} diff --git a/src/Apollinare.Infrastructure/Migrations/AppollinareDbContextModelSnapshot.cs b/src/Apollinare.Infrastructure/Migrations/AppollinareDbContextModelSnapshot.cs index 82e8df1..a4eac8c 100644 --- a/src/Apollinare.Infrastructure/Migrations/AppollinareDbContextModelSnapshot.cs +++ b/src/Apollinare.Infrastructure/Migrations/AppollinareDbContextModelSnapshot.cs @@ -37,6 +37,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Dependencies") .HasColumnType("TEXT"); @@ -107,6 +110,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -168,6 +174,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Description") .HasColumnType("TEXT"); @@ -263,6 +272,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Email") .HasColumnType("TEXT"); @@ -331,6 +343,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -362,6 +377,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .HasColumnType("TEXT"); @@ -382,6 +400,76 @@ namespace Apollinare.Infrastructure.Migrations b.ToTable("Configurazioni"); }); + modelBuilder.Entity("Apollinare.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("Apollinare.Domain.Entities.Evento", b => { b.Property("Id") @@ -409,6 +497,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("DataEvento") .HasColumnType("TEXT"); @@ -504,6 +595,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("DataPagamento") .HasColumnType("TEXT"); @@ -553,6 +647,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("EventoId") .HasColumnType("INTEGER"); @@ -600,6 +697,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -644,6 +744,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("DataDegustazione") .HasColumnType("TEXT"); @@ -699,6 +802,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("EventoId") .HasColumnType("INTEGER"); @@ -747,6 +853,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("EventoId") .HasColumnType("INTEGER"); @@ -792,6 +901,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("EventoId") .HasColumnType("INTEGER"); @@ -849,6 +961,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("DistanzaKm") .HasColumnType("TEXT"); @@ -902,6 +1017,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("EndDate") .HasColumnType("TEXT"); @@ -956,6 +1074,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("FileSize") .HasColumnType("INTEGER"); @@ -1011,6 +1132,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("FileSize") .HasColumnType("INTEGER"); @@ -1064,6 +1188,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .HasColumnType("TEXT"); @@ -1122,6 +1249,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Email") .HasColumnType("TEXT"); @@ -1170,6 +1300,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -1209,6 +1342,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -1243,6 +1379,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -1277,6 +1416,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -1311,6 +1453,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .IsRequired() .HasColumnType("TEXT"); @@ -1344,6 +1489,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Email") .HasColumnType("TEXT"); @@ -1397,6 +1545,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Descrizione") .HasColumnType("TEXT"); @@ -1447,6 +1598,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Description") .HasColumnType("TEXT"); @@ -1505,6 +1659,9 @@ namespace Apollinare.Infrastructure.Migrations .HasPrecision(18, 4) .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("ExpiryDate") .HasColumnType("TEXT"); @@ -1583,6 +1740,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CurrentWarehouseId") .HasColumnType("INTEGER"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("CustomerId") .HasColumnType("INTEGER"); @@ -1666,6 +1826,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Description") .IsRequired() .HasColumnType("TEXT"); @@ -1751,6 +1914,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("InventoryCountId") .HasColumnType("INTEGER"); @@ -1814,6 +1980,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Description") .IsRequired() .HasColumnType("TEXT"); @@ -1881,6 +2050,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("LastInventoryDate") .HasColumnType("TEXT"); @@ -1951,6 +2123,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("CustomerId") .HasColumnType("INTEGER"); @@ -2038,6 +2213,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("DestinationLocationCode") .HasColumnType("TEXT"); @@ -2116,6 +2294,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("InboundQuantity") .HasPrecision(18, 4) .HasColumnType("TEXT"); @@ -2202,6 +2383,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("IsExhausted") .HasColumnType("INTEGER"); @@ -2276,6 +2460,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Depth") .HasColumnType("TEXT"); @@ -2417,6 +2604,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("DefaultValuationMethod") .HasColumnType("INTEGER"); @@ -2494,6 +2684,9 @@ namespace Apollinare.Infrastructure.Migrations b.Property("CreatedBy") .HasColumnType("TEXT"); + b.Property("CustomFieldsJson") + .HasColumnType("TEXT"); + b.Property("Description") .HasColumnType("TEXT");