feat(domain): add all domain entities with legacy database mapping

Entities mapped to legacy database tables using [Table] and [Column] attributes:
- EmailAccount → TBDD_EMAIL_ACCOUNT (OAuth2 and password auth support)
- EmailProfile → TBEMLP_POLL_PROFILES (polling configuration)
- EmailProcess → TBEMLP_POLL_PROCESS (process definitions)
- ProcessStep → TBEMLP_POLL_STEPS (indexing steps)
- IndexingStep → TBEMLP_POLL_INDEXING_STEPS (DMS indexing fields)
- EmailHistory → TBEMLP_HISTORY (processed emails)
- EmailAttachment → TBEMLP_HISTORY_ATTACHMENT (email attachments)
- EmailOutbox → TBEMLP_EMAIL_OUT (outgoing email queue)

All entities follow Clean Architecture and DDD principles.
Database schema is read-only - no migrations will modify existing tables.
SNAKE_CASE columns mapped to PascalCase properties.
This commit is contained in:
2026-07-07 18:59:10 +02:00
parent 18bb07cd93
commit c97073775b
8 changed files with 688 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
using DigitalData.EmailProfiler.Domain.Enums;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBDD_EMAIL_ACCOUNT")]
public class EmailAccount : BaseEntity, IAggregateRoot
{
[Key]
[Column("EMAIL_ACCOUNT_ID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("ACCOUNT_NAME", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string AccountName { get; set; } = string.Empty;
// IMAP Configuration
[Column("IMAP_SERVER", TypeName = "varchar(200)")]
[Required]
[MaxLength(200)]
public string ImapServer { get; set; } = string.Empty;
[Column("IMAP_PORT")]
[Required]
public int ImapPort { get; set; }
[Column("IMAP_USE_SSL")]
public bool ImapUseSsl { get; set; } = true;
// SMTP Configuration
[Column("SMTP_SERVER", TypeName = "varchar(200)")]
[Required]
[MaxLength(200)]
public string SmtpServer { get; set; } = string.Empty;
[Column("SMTP_PORT")]
[Required]
public int SmtpPort { get; set; }
[Column("SMTP_USE_SSL")]
public bool SmtpUseSsl { get; set; } = true;
// Authentication
[Column("USERNAME", TypeName = "varchar(200)")]
[Required]
[MaxLength(200)]
public string Username { get; set; } = string.Empty;
[Column("PASSWORD", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? EncryptedPassword { get; set; }
[Column("USE_OAUTH2")]
public bool UseOAuth2 { get; set; }
// OAuth2 (nullable)
[Column("CLIENT_ID", TypeName = "varchar(200)")]
[MaxLength(200)]
public string? ClientId { get; set; }
[Column("TENANT_ID", TypeName = "varchar(200)")]
[MaxLength(200)]
public string? TenantId { get; set; }
[Column("CLIENT_SECRET", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? EncryptedClientSecret { get; set; }
// Status
[Column("ACTIVE")]
public bool IsActive { get; set; } = true;
[Column("SEQUENCE")]
public int? Sequence { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit fields
[Column("ADDED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? AddedWho { get; set; }
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
[Column("CHANGED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? ChangedWho { get; set; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; set; }
// Navigation properties
public virtual ICollection<EmailProfile> Profiles { get; set; } = new List<EmailProfile>();
// Domain methods
public AuthenticationType GetAuthenticationType() => UseOAuth2 ? AuthenticationType.OAuth2 : AuthenticationType.UsernamePassword;
public void Activate() => IsActive = true;
public void Deactivate() => IsActive = false;
}

View File

@@ -0,0 +1,93 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
using DigitalData.EmailProfiler.Domain.Enums;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_HISTORY_ATTACHMENT")]
public class EmailAttachment : BaseEntity
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("EMAIL_HISTORY_ID")]
[Required]
public int EmailHistoryId { get; set; }
// File information
[Column("ORIGINAL_FILE_NAME", TypeName = "varchar(500)")]
[Required]
[MaxLength(500)]
public string OriginalFileName { get; set; } = string.Empty;
[Column("SAVED_FILE_NAME", TypeName = "varchar(500)")]
[Required]
[MaxLength(500)]
public string SavedFileName { get; set; } = string.Empty;
[Column("FILE_PATH", TypeName = "varchar(1000)")]
[Required]
[MaxLength(1000)]
public string FilePath { get; set; } = string.Empty;
[Column("FILE_SIZE")]
public long FileSize { get; set; }
[Column("EXTENSION", TypeName = "varchar(20)")]
[MaxLength(20)]
public string Extension { get; set; } = string.Empty;
// Attachment hierarchy
[Column("IS_EMBEDDED_FILE")]
public bool IsEmbeddedFile { get; set; }
[Column("PARENT_ATTACHMENT_ID")]
public int? ParentAttachmentId { get; set; }
[Column("ATTACHMENT_POSITION")]
public int AttachmentPosition { get; set; }
// Validation
[Column("STATUS", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? Status { get; set; }
[Column("VALIDATION_ERROR_CODE")]
public int? ValidationErrorCode { get; set; }
[Column("VALIDATION_ERROR_MESSAGE", TypeName = "nvarchar(max)")]
public string? ValidationErrorMessage { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit field
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
// Navigation properties
[ForeignKey("EmailHistoryId")]
public virtual EmailHistory? EmailHistory { get; set; }
[ForeignKey("ParentAttachmentId")]
public virtual EmailAttachment? ParentAttachment { get; set; }
public virtual ICollection<EmailAttachment> EmbeddedFiles { get; set; } = new List<EmailAttachment>();
// Domain methods
public void MarkAsValid()
{
Status = AttachmentStatus.Valid.ToString();
}
public void MarkAsCorrupt(ErrorCode errorCode, string message)
{
Status = AttachmentStatus.Corrupt.ToString();
ValidationErrorCode = (int)errorCode;
ValidationErrorMessage = message;
}
}

View File

@@ -0,0 +1,112 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
using DigitalData.EmailProfiler.Domain.Enums;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_HISTORY")]
public class EmailHistory : BaseEntity
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("PROFILE_ID")]
public int? ProfileId { get; set; }
[Column("WORK_PROCESS", TypeName = "varchar(100)")]
[MaxLength(100)]
public string? WorkProcess { get; set; }
// Email identification
[Column("EMAIL_MSGID")]
[Required]
public int EmailMessageId { get; set; }
[Column("EMAIL_MSGID_HASH", TypeName = "varchar(100)")]
[MaxLength(100)]
public string? MessageIdHash { get; set; }
[Column("EMAIL_MSGID_ORIGINAL", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? OriginalMessageId { get; set; }
[Column("IMAP_UID")]
public int? ImapUid { get; set; }
// Email metadata
[Column("EMAIL_SENDER", TypeName = "varchar(200)")]
[MaxLength(200)]
public string? SenderAddress { get; set; }
[Column("EMAIL_SUBJECT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Subject { get; set; }
[Column("EMAIL_DATE")]
public DateTime? EmailDate { get; set; }
[Column("EMAIL_BODY", TypeName = "nvarchar(max)")]
public string? EmailBodyHtml { get; set; }
[Column("EMAIL_BODY_TEXT", TypeName = "nvarchar(max)")]
public string? EmailBodyText { get; set; }
[Column("EMAIL_SUBSTRING1", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? EmailSubstring1 { get; set; }
[Column("EMAIL_SUBSTRING2", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? EmailSubstring2 { get; set; }
// Processing
[Column("PROCESSED_DATE")]
public DateTime? ProcessedDate { get; set; }
[Column("STATUS", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? Status { get; set; }
[Column("ERROR_CODE")]
public int? ErrorCodeValue { get; set; }
[Column("ERROR_MESSAGE", TypeName = "nvarchar(max)")]
public string? ErrorMessage { get; set; }
// windream
[Column("WINDREAM_DOCUMENT_ID", TypeName = "varchar(100)")]
[MaxLength(100)]
public string? WindreamDocumentId { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit field
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
// Navigation properties
[ForeignKey("ProfileId")]
public virtual EmailProfile? Profile { get; set; }
public virtual ICollection<EmailAttachment> Attachments { get; set; } = new List<EmailAttachment>();
// Domain methods
public void MarkAsProcessed()
{
Status = EmailStatus.Processed.ToString();
ProcessedDate = DateTime.UtcNow;
}
public void MarkAsFailed(ErrorCode errorCode, string message)
{
Status = EmailStatus.Failed.ToString();
ErrorCodeValue = (int)errorCode;
ErrorMessage = message;
ProcessedDate = DateTime.UtcNow;
}
}

View File

@@ -0,0 +1,60 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_EMAIL_OUT")]
public class EmailOutbox : BaseEntity
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("EMAIL_ACCOUNT_ID")]
[Required]
public int EmailAccountId { get; set; }
[Column("RECIPIENT", TypeName = "varchar(200)")]
[Required]
[MaxLength(200)]
public string Recipient { get; set; } = string.Empty;
[Column("SUBJECT", TypeName = "nvarchar(500)")]
[Required]
[MaxLength(500)]
public string Subject { get; set; } = string.Empty;
[Column("BODY", TypeName = "nvarchar(max)")]
[Required]
public string Body { get; set; } = string.Empty;
[Column("IS_HTML")]
public bool IsHtml { get; set; } = true;
[Column("SENT")]
public bool Sent { get; set; }
[Column("SENT_DATE")]
public DateTime? SentDate { get; set; }
[Column("RETRY_COUNT")]
public int RetryCount { get; set; }
[Column("REFERENCE_STRING", TypeName = "varchar(200)")]
[MaxLength(200)]
public string? ReferenceId { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit field
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
// Navigation properties
[ForeignKey("EmailAccountId")]
public virtual EmailAccount? EmailAccount { get; set; }
}

View File

@@ -0,0 +1,114 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
using DigitalData.EmailProfiler.Domain.Enums;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_POLL_PROCESS")]
public class EmailProcess : BaseEntity
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("PROCESS_NAME", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string ProcessName { get; set; } = string.Empty;
[Column("STEP_NAME", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string StepName { get; set; } = string.Empty;
[Column("PROFILE_ID")]
public int? ProfileId { get; set; }
// Configuration
[Column("COPY_2_HDD")]
public bool CopyToHdd { get; set; }
[Column("DELETE_MAIL")]
public bool DeleteEmailAfterProcessing { get; set; }
// Paths
[Column("PATH_EMAIL_TEMP", TypeName = "varchar(500)")]
[Required]
[MaxLength(500)]
public string TempPath { get; set; } = string.Empty;
[Column("PATH_EMAIL_ERRORS", TypeName = "varchar(500)")]
[Required]
[MaxLength(500)]
public string ErrorPath { get; set; } = string.Empty;
[Column("PATH_ORIGINAL", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? ArchivePath { get; set; }
// windream
[Column("WM_IMPORT")]
public bool EnableWindreamImport { get; set; }
[Column("WM_OBJEKTTYPE", TypeName = "varchar(100)")]
[MaxLength(100)]
public string? WindreamObjectType { get; set; }
[Column("WM_VECTOR_LOG", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? WindreamVectorLog { get; set; }
[Column("WM_PATH", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? WindreamPath { get; set; }
[Column("WM_FILE_NAME", TypeName = "varchar(200)")]
[MaxLength(200)]
public string? WindreamFileName { get; set; }
[Column("WM_REFERENCE_INDEX", TypeName = "varchar(100)")]
[MaxLength(100)]
public string? WindreamReferenceIndex { get; set; }
[Column("WM_IDX_BODY_TEXT", TypeName = "varchar(100)")]
[MaxLength(100)]
public string? WindreamIndexBodyText { get; set; }
[Column("WM_IDX_BODY_SUBSTR_LENGTH")]
public int WindreamIndexBodySubstrLength { get; set; }
[Column("ALLOW_XML_RECEIPTS")]
public bool? AllowXmlReceipts { get; set; }
// Status
[Column("ACTIVE")]
public bool IsActive { get; set; } = true;
[Column("SEQUENCE")]
public int? Sequence { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit fields
[Column("ADDED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? AddedWho { get; set; }
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
[Column("CHANGED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? ChangedWho { get; set; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; set; }
// Navigation properties
public virtual ICollection<ProcessStep> Steps { get; set; } = new List<ProcessStep>();
public virtual ICollection<EmailProfile> Profiles { get; set; } = new List<EmailProfile>();
}

View File

@@ -0,0 +1,88 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_POLL_PROFILES")]
public class EmailProfile : BaseEntity, IAggregateRoot
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("PROFILE_NAME", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string ProfileName { get; set; } = string.Empty;
[Column("POLL_TYPE", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string PollType { get; set; } = "IMAP";
[Column("EMAIL_CONF_ID")]
[Required]
public int EmailAccountId { get; set; }
[Column("PROCESS_ID")]
public int? ProcessId { get; set; }
// Polling Configuration
[Column("POLL_INTERVAL")]
public int PollIntervalMinutes { get; set; } = 5;
[Column("LAST_TICK")]
public DateTime? LastPollTime { get; set; }
// Validation
[Column("VALIDATION_SQL", TypeName = "nvarchar(1024)")]
[MaxLength(1024)]
public string? ValidationSql { get; set; }
// Status
[Column("ACTIVE")]
public bool IsActive { get; set; }
[Column("SEQUENCE")]
public int? Sequence { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit fields
[Column("ADDED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? AddedWho { get; set; }
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
[Column("CHANGED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? ChangedWho { get; set; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; set; }
// Navigation properties
[ForeignKey("EmailAccountId")]
public virtual EmailAccount? EmailAccount { get; set; }
[ForeignKey("ProcessId")]
public virtual EmailProcess? EmailProcess { get; set; }
public virtual ICollection<EmailHistory> EmailHistories { get; set; } = new List<EmailHistory>();
// Domain methods
public void UpdateLastPollTime() => LastPollTime = DateTime.UtcNow;
public bool ShouldPoll()
{
if (!IsActive) return false;
if (!LastPollTime.HasValue) return true;
return DateTime.UtcNow >= LastPollTime.Value.AddMinutes(PollIntervalMinutes);
}
}

View File

@@ -0,0 +1,56 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_POLL_INDEXING_STEPS")]
public class IndexingStep : BaseEntity
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("STEP_ID")]
[Required]
public int StepId { get; set; }
[Column("INDEXNAME", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string IndexName { get; set; } = string.Empty;
[Column("INDEXVALUE", TypeName = "varchar(100)")]
[Required]
[MaxLength(100)]
public string IndexValue { get; set; } = string.Empty;
[Column("ACTIVE")]
public bool IsActive { get; set; } = true;
[Column("USE_FOR_DIRECT_ANSWER")]
public bool UseForDirectAnswer { get; set; }
[Column("SEQUENCE")]
public int? Sequence { get; set; }
// Audit fields
[Column("ADDED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? AddedWho { get; set; }
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
[Column("CHANGED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? ChangedWho { get; set; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; set; }
// Navigation properties
[ForeignKey("StepId")]
public virtual ProcessStep? ProcessStep { get; set; }
}

View File

@@ -0,0 +1,58 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DigitalData.EmailProfiler.Domain.Common;
namespace DigitalData.EmailProfiler.Domain.Entities;
[Table("TBEMLP_POLL_STEPS")]
public class ProcessStep : BaseEntity
{
[Key]
[Column("GUID", Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("PROCESS_ID")]
[Required]
public int ProcessId { get; set; }
[Column("STEP_NAME", TypeName = "varchar(50)")]
[Required]
[MaxLength(50)]
public string StepName { get; set; } = string.Empty;
[Column("KEYWORDS_BODY", TypeName = "varchar(1000)")]
[MaxLength(1000)]
public string? KeywordsBody { get; set; }
[Column("ACTIVE")]
public bool IsActive { get; set; } = true;
[Column("SEQUENCE")]
public int? Sequence { get; set; }
[Column("COMMENT", TypeName = "varchar(500)")]
[MaxLength(500)]
public string? Comment { get; set; }
// Audit fields
[Column("ADDED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? AddedWho { get; set; }
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
[Column("CHANGED_WHO", TypeName = "varchar(50)")]
[MaxLength(50)]
public string? ChangedWho { get; set; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; set; }
// Navigation properties
[ForeignKey("ProcessId")]
public virtual EmailProcess? EmailProcess { get; set; }
public virtual ICollection<IndexingStep> IndexingSteps { get; set; } = new List<IndexingStep>();
}