fix(domain): use DateTime.Now instead of DateTime.UtcNow for legacy compatibility
CRITICAL FIX: Replace all DateTime.UtcNow with DateTime.Now throughout the application. Reason: Legacy VB.NET system uses local server time, and database stores all timestamps as local time. Using UTC breaks compatibility and causes incorrect time comparisons. Changes: - EmailProcessedEvent: ProcessedDate now uses DateTime.Now - EmailHistory.MarkAsProcessed(): ProcessedDate now uses DateTime.Now - EmailHistory.MarkAsFailed(): ProcessedDate now uses DateTime.Now - EmailProfile.UpdateLastPollTime(): LastPollTime now uses DateTime.Now - EmailProfile.ShouldPoll(): Poll interval comparison now uses DateTime.Now Documentation: - Added critical note to agents.md about DateTime usage - Includes examples and detailed explanation for future developers This ensures all date/time operations remain compatible with legacy database.
This commit is contained in:
24
agents.md
24
agents.md
@@ -33,7 +33,29 @@ The `MessageIdGenerator` in `Domain.Services` must use **exactly the same algori
|
|||||||
|
|
||||||
**Algorithm**: SHA256 hash of `{originalMessageId}|{sender}|{date:yyyyMMddHHmmss}|{subject}`
|
**Algorithm**: SHA256 hash of `{originalMessageId}|{sender}|{date:yyyyMMddHHmmss}|{subject}`
|
||||||
|
|
||||||
### 3. No Commits Without Permission
|
### 3. DateTime Usage - ALWAYS Use Local Time
|
||||||
|
**CRITICAL**: Always use `DateTime.Now` instead of `DateTime.UtcNow` throughout the entire application.
|
||||||
|
|
||||||
|
**Reason**: The legacy system uses local server time, and the database stores all timestamps as local time. Using UTC would break compatibility and cause incorrect time comparisons.
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
```csharp
|
||||||
|
// ✅ CORRECT
|
||||||
|
profile.CreatedDate = DateTime.Now;
|
||||||
|
var lastPoll = DateTime.Now.AddMinutes(-profile.PollIntervalMinutes);
|
||||||
|
|
||||||
|
// ❌ WRONG - DO NOT USE
|
||||||
|
profile.CreatedDate = DateTime.UtcNow; // NEVER USE UTC
|
||||||
|
var lastPoll = DateTime.UtcNow.AddMinutes(-profile.PollIntervalMinutes); // NEVER USE UTC
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important**: This applies to:
|
||||||
|
- All entity audit fields (CreatedDate, ModifiedDate, LastPollDate, etc.)
|
||||||
|
- All date comparisons in business logic
|
||||||
|
- All timestamps in logs and error messages
|
||||||
|
- All date parameters in queries
|
||||||
|
|
||||||
|
### 4. No Commits Without Permission
|
||||||
**NEVER** commit changes to git automatically. Always wait for explicit user instruction to commit.
|
**NEVER** commit changes to git automatically. Always wait for explicit user instruction to commit.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class EmailHistory : BaseEntity
|
|||||||
public void MarkAsProcessed()
|
public void MarkAsProcessed()
|
||||||
{
|
{
|
||||||
Status = EmailStatus.Processed.ToString();
|
Status = EmailStatus.Processed.ToString();
|
||||||
ProcessedDate = DateTime.UtcNow;
|
ProcessedDate = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkAsFailed(ErrorCode errorCode, string message)
|
public void MarkAsFailed(ErrorCode errorCode, string message)
|
||||||
@@ -107,6 +107,6 @@ public class EmailHistory : BaseEntity
|
|||||||
Status = EmailStatus.Failed.ToString();
|
Status = EmailStatus.Failed.ToString();
|
||||||
ErrorCodeValue = (int)errorCode;
|
ErrorCodeValue = (int)errorCode;
|
||||||
ErrorMessage = message;
|
ErrorMessage = message;
|
||||||
ProcessedDate = DateTime.UtcNow;
|
ProcessedDate = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,12 +77,12 @@ public class EmailProfile : BaseEntity, IAggregateRoot
|
|||||||
public virtual ICollection<EmailHistory> EmailHistories { get; set; } = new List<EmailHistory>();
|
public virtual ICollection<EmailHistory> EmailHistories { get; set; } = new List<EmailHistory>();
|
||||||
|
|
||||||
// Domain methods
|
// Domain methods
|
||||||
public void UpdateLastPollTime() => LastPollTime = DateTime.UtcNow;
|
public void UpdateLastPollTime() => LastPollTime = DateTime.Now;
|
||||||
|
|
||||||
public bool ShouldPoll()
|
public bool ShouldPoll()
|
||||||
{
|
{
|
||||||
if (!IsActive) return false;
|
if (!IsActive) return false;
|
||||||
if (!LastPollTime.HasValue) return true;
|
if (!LastPollTime.HasValue) return true;
|
||||||
return DateTime.UtcNow >= LastPollTime.Value.AddMinutes(PollIntervalMinutes);
|
return DateTime.Now >= LastPollTime.Value.AddMinutes(PollIntervalMinutes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,20 +3,11 @@ using DigitalData.EmailProfiler.Domain.Enums;
|
|||||||
|
|
||||||
namespace DigitalData.EmailProfiler.Domain.Events;
|
namespace DigitalData.EmailProfiler.Domain.Events;
|
||||||
|
|
||||||
public class EmailProcessedEvent : INotification
|
public class EmailProcessedEvent(int emailHistoryId, int profileId, string messageId, EmailStatus status) : INotification
|
||||||
{
|
{
|
||||||
public int EmailHistoryId { get; }
|
public int EmailHistoryId { get; } = emailHistoryId;
|
||||||
public int ProfileId { get; }
|
public int ProfileId { get; } = profileId;
|
||||||
public string MessageId { get; }
|
public string MessageId { get; } = messageId;
|
||||||
public EmailStatus Status { get; }
|
public EmailStatus Status { get; } = status;
|
||||||
public DateTime ProcessedDate { get; }
|
public DateTime ProcessedDate { get; } = DateTime.Now;
|
||||||
|
|
||||||
public EmailProcessedEvent(int emailHistoryId, int profileId, string messageId, EmailStatus status)
|
|
||||||
{
|
|
||||||
EmailHistoryId = emailHistoryId;
|
|
||||||
ProfileId = profileId;
|
|
||||||
MessageId = messageId;
|
|
||||||
Status = status;
|
|
||||||
ProcessedDate = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user