779 lines
24 KiB
Markdown
779 lines
24 KiB
Markdown
# 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<AccountAddress> Addresses { get; set; }
|
|
public virtual IList<AccountTypeToAccount> 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<AccountAddressContact> 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<ReceiptItemBase> 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<ServiceOrder> ServiceOrders { get; set; }
|
|
public virtual IList<AssetContract> 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<TEntity> inheritance
|
|
- **Configuration**: Table name, column mappings, relationships
|
|
|
|
**Example Mapping Implementation**:
|
|
```csharp
|
|
// File: src/backend/Centron.DAO/Mappings/Accounts/AccountMaps.cs
|
|
public class AccountMaps : ClassMap<Account>
|
|
{
|
|
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<Receipt>
|
|
{
|
|
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<ValidationResult> Validate(ValidationContext context)
|
|
{
|
|
var results = new List<ValidationResult>();
|
|
|
|
// 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<bool> 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<AccountAddress>();
|
|
|
|
// 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<AccountDTO>(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<Result<bool>> 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/ |