Analyse Results
This commit is contained in:
779
Versuche/Versuch 03/Ergenisse/software/SwRS_DataModel.md
Normal file
779
Versuche/Versuch 03/Ergenisse/software/SwRS_DataModel.md
Normal file
@@ -0,0 +1,779 @@
|
||||
# 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/
|
||||
Reference in New Issue
Block a user