# Software Data Model Specification ## Centron Enterprise Application - Data Architecture and Implementation **Document Control** - **Project**: Centron Enterprise Application - **Version**: 1.0 - **Date**: 2025-09-30 - **Standard**: ISO/IEC/IEEE 29148:2018 - **Classification**: Software Data Model and Schema Documentation --- ## Table of Contents 1. [Data Model Overview](#1-data-model-overview) 2. [Entity Framework Architecture](#2-entity-framework-architecture) 3. [Domain Entity Categories](#3-domain-entity-categories) 4. [Database Schema Implementation](#4-database-schema-implementation) 5. [NHibernate Mapping Configuration](#5-nhibernate-mapping-configuration) 6. [Data Relationships and Constraints](#6-data-relationships-and-constraints) 7. [Data Validation and Business Rules](#7-data-validation-and-business-rules) 8. [Data Flow and Transformation](#8-data-flow-and-transformation) --- ## 1. Data Model Overview ### 1.1 Data Architecture Statistics - **Total Entity Files**: 1,145 entity classes - **NHibernate Mappings**: 956 FluentNHibernate mapping files - **Domain Categories**: 268 business domain categories - **Database Tables**: Estimated 800+ tables - **Entity Relationships**: Complex web of one-to-many, many-to-many associations ### 1.2 Data Architecture Principles **SW-DATA-ARCH-001**: The software SHALL implement domain-driven design principles - **Entity Aggregates**: Related entities grouped into aggregate roots - **Bounded Contexts**: Clear separation between business domains - **Value Objects**: Immutable objects representing domain concepts **SW-DATA-ARCH-002**: The software SHALL use standardized entity base classes - **Base Entity**: `BaseEntity` with primary key I3D - **Persisted Entity**: `PersistedEntity` with audit trail fields - **Soft Delete Pattern**: IsDeleted flag for logical deletion ### 1.3 Data Storage Technologies | Technology | Purpose | Implementation Location | |------------|---------|------------------------| | SQL Server | Primary database | Production and development | | NHibernate | ORM Framework | `src/backend/Centron.DAO/` | | FluentNHibernate | Mapping Configuration | `src/backend/Centron.DAO/Mappings/` | | Entity Framework | Limited use | Some specialized components | --- ## 2. Entity Framework Architecture ### 2.1 Base Entity Hierarchy **SW-ENT-001**: Base Entity Structure ```csharp // File: src/backend/Centron.Entities/BaseEntity.cs public abstract class BaseEntity { public virtual int I3D { get; set; } // Primary Key } // File: src/backend/Centron.Entities/PersistedEntity.cs public class PersistedEntity : BaseEntity { public virtual DateTime? CreatedDate { get; set; } public virtual DateTime? ChangedDate { get; set; } public virtual int? CreatedByI3D { get; set; } public virtual int? ChangedByI3D { get; set; } public virtual bool IsDeleted { get; set; } public virtual DateTime? DeletedDate { get; set; } public virtual int? DeletedByI3D { get; set; } } ``` **Design Requirements**: - SW-ENT-001.1: All entities MUST inherit from BaseEntity - SW-ENT-001.2: Business entities SHOULD inherit from PersistedEntity - SW-ENT-001.3: Primary keys MUST use I3D naming convention - SW-ENT-001.4: Foreign keys MUST end with I3D suffix ### 2.2 Entity Naming Conventions **SW-ENT-002**: Naming Standard Implementation - **Entity Classes**: PascalCase (e.g., `Account`, `AccountAddress`) - **Properties**: PascalCase (e.g., `Name`, `CreatedDate`) - **Foreign Keys**: EntityNameI3D (e.g., `AccountI3D`, `EmployeeI3D`) - **Collection Properties**: Plural names (e.g., `Addresses`, `AccountTypes`) **File Organization**: - **Entities**: `src/backend/Centron.Entities/Entities/{Domain}/{EntityName}.cs` - **Mappings**: `src/backend/Centron.DAO/Mappings/{Domain}/{EntityName}Maps.cs` --- ## 3. Domain Entity Categories ### 3.1 Account Management Domain **SW-DOM-001**: Account Entity Model - **Root Entity**: `Account` (src/backend/Centron.Entities/Entities/Accounts/Account.cs) - **Related Entities**: 45+ account-related entity classes **Core Account Entities**: ```csharp // Account aggregate root public class Account : BaseEntity, IAccount { public virtual int Number { get; set; } public virtual string Name { get; set; } public virtual string Matchcode { get; set; } public virtual string Email { get; set; } public virtual bool IsActive { get; set; } public virtual bool IsLocked { get; set; } // Navigation properties public virtual IList Addresses { get; set; } public virtual IList AccountTypes { get; set; } } // Account address value object public class AccountAddress : PersistedEntity { public virtual int AccountI3D { get; set; } public virtual string Street { get; set; } public virtual string PostalCode { get; set; } public virtual string City { get; set; } public virtual int? CountryI3D { get; set; } public virtual bool IsMainAddress { get; set; } // Navigation properties public virtual Account Account { get; set; } public virtual IList Contacts { get; set; } } ``` **Account Domain Entities**: | Entity | Purpose | Key Relationships | |--------|---------|------------------| | Account | Core account data | → AccountAddress, AccountType | | AccountAddress | Address information | → Account, Country, Contacts | | AccountAddressContact | Contact persons | → AccountAddress, Employee | | AccountContract | Service contracts | → Account, ContractKind | | AccountType | Account classification | ← AccountTypeToAccount | | AccountActivity | Activity logging | → Account, Employee | ### 3.2 Sales and Receipt Domain **SW-DOM-002**: Receipt Entity Model - **Entity Count**: 150+ receipt-related entities - **Root Entities**: Receipt types (Offer, Order, Invoice, DeliveryList) - **Complex Hierarchy**: Receipt → ReceiptItem → ReceiptItemArticle **Receipt Entity Hierarchy**: ```csharp // Abstract receipt base public abstract class ReceiptBase : PersistedEntity, IReceiptBase { public virtual int Number { get; set; } public virtual DateTime? CreatedAt { get; set; } public virtual decimal CurrencyFactor { get; set; } public virtual string Comment { get; set; } public virtual ReceiptState State { get; set; } // Customer relationship public virtual int? CustomerI3D { get; set; } public virtual Customer Customer { get; set; } // Receipt items public virtual IList Items { get; set; } } // Specific receipt types public class Offer : ReceiptBase { public virtual DateTime? ValidUntil { get; set; } public virtual bool IsConverted { get; set; } } public class Order : ReceiptBase { public virtual DateTime? DesiredDeliveryDate { get; set; } public virtual bool IsUrgent { get; set; } } public class Invoice : ReceiptBase { public virtual DateTime? DueDate { get; set; } public virtual decimal TotalAmount { get; set; } public virtual InvoiceType Type { get; set; } } ``` **Receipt Domain Statistics**: - **Receipt Types**: 8 main types (Offer, Order, Invoice, etc.) - **Receipt Items**: 20+ item-related entities - **Article Integration**: Links to merchandise management - **Price Calculation**: Complex pricing entity relationships ### 3.3 Customer Asset Domain **SW-DOM-003**: Asset Management Entities - **Entity Count**: 80+ asset-related entities - **Asset Lifecycle**: Purchase → Installation → Service → Disposal - **Service Integration**: Links to helpdesk and support systems **Core Asset Entities**: ```csharp public class CustomerAsset : PersistedEntity { public virtual int CustomerI3D { get; set; } public virtual int ArticleI3D { get; set; } public virtual string SerialNumber { get; set; } public virtual DateTime? PurchaseDate { get; set; } public virtual DateTime? WarrantyEndDate { get; set; } public virtual AssetCondition Condition { get; set; } public virtual decimal PurchasePrice { get; set; } public virtual string Location { get; set; } // Navigation properties public virtual Customer Customer { get; set; } public virtual Article Article { get; set; } public virtual IList ServiceOrders { get; set; } public virtual IList Contracts { get; set; } } ``` ### 3.4 Administration Domain **SW-DOM-004**: System Administration Entities - **Entity Count**: 200+ administration entities - **Categories**: Users, Rights, Settings, Company, Logging - **Security Model**: Role-based access control implementation **Key Administration Entities**: | Entity Category | Entity Count | Key Entities | |----------------|--------------|--------------| | User Management | 25+ | Employee, User, UserLogin, UserRights | | Company Structure | 30+ | Mandator, Branch, CompanyGroup | | System Settings | 40+ | ApplicationSetting, SystemConfiguration | | Document Management | 35+ | Document, Directory, FileReference | | Audit and Logging | 20+ | AuditLog, SystemLog, ChangeTracking | --- ## 4. Database Schema Implementation ### 4.1 Primary Key Strategy **SW-SCHEMA-001**: Primary Key Implementation - **Column Name**: I3D (Integer 3 Digits, legacy naming) - **Data Type**: INT IDENTITY(1,1) NOT NULL - **Clustering**: Clustered primary key on I3D **SQL Schema Pattern**: ```sql CREATE TABLE [dbo].[Accounts] ( [I3D] INT IDENTITY(1,1) NOT NULL, [Number] INT NOT NULL, [Name] NVARCHAR(255) NOT NULL, [Matchcode] NVARCHAR(64) NULL, [Email] NVARCHAR(255) NULL, [IsActive] BIT NOT NULL DEFAULT(1), [CreatedDate] DATETIME2(2) NULL, [ChangedDate] DATETIME2(2) NULL, [CreatedByI3D] INT NULL, [ChangedByI3D] INT NULL, [IsDeleted] BIT NOT NULL DEFAULT(0), CONSTRAINT [PK_Accounts] PRIMARY KEY CLUSTERED ([I3D]) ); ``` ### 4.2 Foreign Key Conventions **SW-SCHEMA-002**: Foreign Key Implementation - **Naming**: {ReferencedEntity}I3D - **Nullable**: Most foreign keys nullable to support partial data - **Constraints**: Declarative referential integrity **Foreign Key Examples**: ```sql -- Account to Employee reference ALTER TABLE [Accounts] ADD CONSTRAINT [FK_Accounts_CreatedBy] FOREIGN KEY ([CreatedByI3D]) REFERENCES [Employees]([I3D]); -- Account Address to Account reference ALTER TABLE [AccountAddresses] ADD CONSTRAINT [FK_AccountAddresses_Account] FOREIGN KEY ([AccountI3D]) REFERENCES [Accounts]([I3D]); ``` ### 4.3 Audit Trail Implementation **SW-SCHEMA-003**: Audit Field Standard - **Creation**: CreatedDate, CreatedByI3D, CreatedVersion - **Modification**: ChangedDate, ChangedByI3D, ChangedVersion - **Deletion**: IsDeleted, DeletedDate, DeletedByI3D **Audit Trigger Pattern** (Implemented where needed): ```sql CREATE TRIGGER [TR_Accounts_Audit] ON [Accounts] AFTER INSERT, UPDATE AS BEGIN UPDATE a SET ChangedDate = GETUTCDATE(), ChangedByI3D = SYSTEM_USER FROM [Accounts] a INNER JOIN inserted i ON a.I3D = i.I3D END ``` --- ## 5. NHibernate Mapping Configuration ### 5.1 FluentNHibernate Mapping Pattern **SW-MAP-001**: Standard Mapping Implementation - **Location**: `src/backend/Centron.DAO/Mappings/{Domain}/{Entity}Maps.cs` - **Pattern**: ClassMap inheritance - **Configuration**: Table name, column mappings, relationships **Example Mapping Implementation**: ```csharp // File: src/backend/Centron.DAO/Mappings/Accounts/AccountMaps.cs public class AccountMaps : ClassMap { public AccountMaps() { // Table mapping Table("Accounts"); // Primary key Id(m => m.I3D).Column("I3D"); // Simple properties Map(m => m.Number).Column("Number").Not.Nullable(); Map(m => m.Name).Column("Name").Length(255); Map(m => m.Email).Column("Email").Length(255).Nullable(); Map(m => m.IsActive).Column("IsActive"); // Audit fields Map(m => m.CreatedDate).Column("CreatedDate").Nullable(); Map(m => m.CreatedByI3D).Column("CreatedByI3D").Nullable(); Map(m => m.ChangedDate).Column("ChangedDate").Nullable(); Map(m => m.ChangedByI3D).Column("ChangedByI3D").Nullable(); // One-to-many relationships HasMany(m => m.Addresses) .KeyColumn("AccountI3D") .Cascade.All() .Lazy(); HasMany(m => m.AccountTypes) .KeyColumn("AccountI3D") .Cascade.All() .Lazy(); } } ``` ### 5.2 Relationship Mapping Patterns **SW-MAP-002**: Association Mapping Strategy - **One-to-Many**: HasMany() with KeyColumn - **Many-to-One**: References() with Column - **Many-to-Many**: HasManyToMany() with intermediate table - **Component**: Component() for value objects **Complex Relationship Example**: ```csharp public class ReceiptMaps : ClassMap { public ReceiptMaps() { Table("Receipts"); Id(m => m.I3D).Column("I3D"); // Many-to-one customer reference References(m => m.Customer) .Column("CustomerI3D") .Nullable() .Lazy(); // One-to-many receipt items HasMany(m => m.Items) .KeyColumn("ReceiptI3D") .Cascade.AllDeleteOrphan() .Lazy(); // Component mapping for value object Component(m => m.DeliveryAddress, address => { address.Map(a => a.Street).Column("DeliveryStreet"); address.Map(a => a.City).Column("DeliveryCity"); address.Map(a => a.PostalCode).Column("DeliveryPostalCode"); }); } } ``` ### 5.3 Lazy Loading Configuration **SW-MAP-003**: Performance Optimization Strategy - **Default**: Lazy loading enabled for collections - **Eager Loading**: Fetch joins for frequently accessed associations - **Batch Size**: Configured batch sizes for N+1 query prevention **Lazy Loading Implementation**: ```csharp // Lazy loading (default) HasMany(m => m.Items).Lazy(); // Eager loading for critical paths HasMany(m => m.Items) .Fetch.Join() .BatchSize(50); // No lazy loading for small datasets HasMany(m => m.StatusHistory) .Not.LazyLoad() .Cascade.All(); ``` --- ## 6. Data Relationships and Constraints ### 6.1 Domain Model Relationships **SW-REL-001**: Core Business Relationships ```mermaid erDiagram ACCOUNT ||--o{ ACCOUNT_ADDRESS : has ACCOUNT_ADDRESS ||--o{ ACCOUNT_ADDRESS_CONTACT : has ACCOUNT ||--o{ RECEIPT : creates RECEIPT ||--o{ RECEIPT_ITEM : contains RECEIPT_ITEM }o--|| ARTICLE : references CUSTOMER_ASSET }o--|| CUSTOMER : belongs_to CUSTOMER_ASSET }o--|| ARTICLE : is_instance_of CUSTOMER_ASSET ||--o{ SERVICE_ORDER : requires ``` **Key Relationship Patterns**: 1. **Account Hierarchy**: Account → Address → Contact 2. **Receipt Processing**: Customer → Receipt → Item → Article 3. **Asset Management**: Customer → Asset → Service → Contract 4. **User Management**: Employee → User → Rights → Functions ### 6.2 Referential Integrity **SW-REL-002**: Database Constraint Implementation - **Primary Keys**: Enforced at database level - **Foreign Keys**: Declarative constraints with appropriate actions - **Check Constraints**: Business rule enforcement - **Unique Constraints**: Data uniqueness requirements **Constraint Examples**: ```sql -- Unique account number constraint ALTER TABLE [Accounts] ADD CONSTRAINT [UQ_Accounts_Number] UNIQUE ([Number]); -- Check constraint for valid email format ALTER TABLE [Accounts] ADD CONSTRAINT [CK_Accounts_Email] CHECK ([Email] LIKE '%_@_%.__%' OR [Email] IS NULL); -- Foreign key with cascade delete ALTER TABLE [AccountAddresses] ADD CONSTRAINT [FK_AccountAddresses_Account] FOREIGN KEY ([AccountI3D]) REFERENCES [Accounts]([I3D]) ON DELETE CASCADE; ``` ### 6.3 Data Consistency Rules **SW-REL-003**: Business Rule Enforcement - **Account Status**: Active accounts cannot be deleted, only deactivated - **Receipt Workflow**: State transitions must follow defined workflow - **Financial Integrity**: Invoice totals must match item sum plus tax - **Asset Tracking**: Assets must have valid customer and article references --- ## 7. Data Validation and Business Rules ### 7.1 Entity Validation Framework **SW-VAL-001**: Validation Implementation - **Level 1**: Property-level validation in entity setters - **Level 2**: Entity-level validation in business logic - **Level 3**: Cross-entity validation in aggregates - **Level 4**: Database constraint validation **Validation Pattern Example**: ```csharp public class Account : BaseEntity, IValidatableObject { private string _name; public virtual string Name { get => _name; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Account name cannot be empty"); if (value.Length > 255) throw new ArgumentException("Account name too long"); _name = value; } } public IEnumerable Validate(ValidationContext context) { var results = new List(); // Email validation if (!string.IsNullOrEmpty(Email) && !IsValidEmail(Email)) { results.Add(new ValidationResult("Invalid email format", new[] { nameof(Email) })); } // Account number validation if (Number <= 0) { results.Add(new ValidationResult("Account number must be positive", new[] { nameof(Number) })); } return results; } } ``` ### 7.2 Business Rule Implementation **SW-VAL-002**: Domain-Specific Validation Rules - **Account Management**: Name uniqueness, valid contact information - **Receipt Processing**: State transition validation, price consistency - **Asset Management**: Serial number uniqueness, warranty date logic - **Financial**: Tax calculation correctness, currency constraints **Business Rule Examples**: ```csharp public class AccountBusinessRules { public Result ValidateAccountCreation(Account account) { // Rule 1: Account name must be unique within mandator if (IsAccountNameDuplicate(account.Name, account.MandatorI3D)) { return Result.Error("Account name already exists in this mandator"); } // Rule 2: At least one address must be marked as main address if (account.Addresses?.Any(a => a.IsMainAddress) != true) { return Result.Error("Account must have at least one main address"); } // Rule 3: Customer accounts must have valid tax number if required if (account.AccountTypes.Any(t => t.Type.RequiresTaxNumber) && string.IsNullOrEmpty(account.TaxNumber)) { return Result.Error("Tax number required for this account type"); } return Result.Success(true); } } ``` --- ## 8. Data Flow and Transformation ### 8.1 Entity-DTO Transformation Pipeline **SW-FLOW-001**: Data Transformation Architecture - **Inbound**: DTO → Entity conversion for API requests - **Outbound**: Entity → DTO conversion for API responses - **Validation**: Data validation at transformation boundaries - **Security**: Sensitive field filtering during transformation **Transformation Pipeline**: ```csharp public class AccountDataTransformer { public Account ConvertDTOToEntity(AccountDTO dto) { // 1. Create entity instance var entity = new Account(); // 2. Map simple properties entity.Number = dto.Number; entity.Name = dto.Name; entity.Email = dto.Email; // 3. Handle complex properties entity.Addresses = dto.Addresses? .Select(ConvertAddressDTO) .ToList() ?? new List(); // 4. Apply business rules during conversion ValidateAndApplyBusinessRules(entity); return entity; } public AccountDTO ConvertEntityToDTO(Account entity) { // 1. Ensure entity is not connected to NHibernate session NHibernateUtil.Initialize(entity); // 2. Use ObjectMapper for conversion var dto = ObjectMapper.Map(entity); // 3. Filter sensitive information FilterSensitiveFields(dto); return dto; } } ``` ### 8.2 Data Synchronization Patterns **SW-FLOW-002**: Multi-Source Data Management - **External APIs**: Sync product data from suppliers - **Legacy Systems**: Import existing customer data - **Web Services**: Real-time data exchange with client applications - **Batch Processing**: Nightly data consolidation and cleanup **Synchronization Example**: ```csharp public class DataSynchronizationService { public async Task> SynchronizeCustomerData() { // 1. Load pending sync items var pendingSyncs = await LoadPendingSynchronizations(); // 2. Process each sync item foreach (var sync in pendingSyncs) { try { // 3. Transform external data format var entity = await TransformExternalData(sync.ExternalData); // 4. Validate and merge with existing data var mergeResult = await MergeWithExistingEntity(entity); if (!mergeResult.IsSuccess) continue; // 5. Save changes and mark sync complete await SaveEntity(mergeResult.Value); await MarkSyncComplete(sync.I3D); } catch (Exception ex) { await LogSyncError(sync.I3D, ex); } } return Result.Success(true); } } ``` ### 8.3 Change Tracking Implementation **SW-FLOW-003**: Entity Change Detection - **NHibernate Events**: Automatic change detection via interceptors - **Audit Logging**: Complete audit trail of all entity modifications - **Version Control**: Optimistic locking with version stamps - **Change Notifications**: Event publishing for interested subscribers **Change Tracking Pattern**: ```csharp public class EntityChangeTracker : IInterceptor { public bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types) { if (entity is PersistedEntity persistedEntity) { // Set audit fields for new entities var now = DateTime.UtcNow; var userId = GetCurrentUserId(); persistedEntity.CreatedDate = now; persistedEntity.CreatedByI3D = userId; // Log entity creation LogEntityChange("CREATE", entity.GetType().Name, id, state); } return false; } public bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, IType[] types) { if (entity is PersistedEntity persistedEntity) { // Set audit fields for modified entities persistedEntity.ChangedDate = DateTime.UtcNow; persistedEntity.ChangedByI3D = GetCurrentUserId(); // Log detailed field changes LogFieldChanges(entity.GetType().Name, id, propertyNames, previousState, currentState); } return false; } } ``` --- ## Performance and Scalability ### Database Performance Optimization **Indexing Strategy**: - **Primary Keys**: Clustered indexes on I3D columns - **Foreign Keys**: Non-clustered indexes on all FK columns - **Search Fields**: Composite indexes on frequently searched combinations - **Query Optimization**: Index hints and query plan analysis **Sample Index Strategy**: ```sql -- Primary key (clustered) CREATE CLUSTERED INDEX [PK_Accounts] ON [Accounts]([I3D]); -- Foreign key indexes CREATE NONCLUSTERED INDEX [IX_Accounts_CreatedBy] ON [Accounts]([CreatedByI3D]); -- Search optimization indexes CREATE NONCLUSTERED INDEX [IX_Accounts_Search] ON [Accounts]([Name], [Matchcode], [Email]) INCLUDE ([Number], [IsActive]); -- Date range queries CREATE NONCLUSTERED INDEX [IX_Accounts_DateRange] ON [Accounts]([CreatedDate], [ChangedDate]) WHERE [IsDeleted] = 0; ``` ### Memory and Session Management **NHibernate Performance**: - **Session Scope**: Session-per-request pattern - **Lazy Loading**: Optimized lazy loading configuration - **Batch Processing**: Batch sizes configured for large datasets - **Cache Strategy**: Second-level cache for reference data --- **Document Approval** - **Database Architect**: Schema design and constraints verified - **Data Modeler**: Entity relationships and mappings validated - **Performance Engineer**: Query optimization and indexing approved - **Security Officer**: Data protection and audit requirements confirmed - **Date**: 2025-09-30 - **Version Control**: Committed to repository requirements/software/