Sms & Email

This commit is contained in:
2026-10-20 10:45:03 +05:30
parent a40e463e8b
commit 0e423b806c
29 changed files with 13845 additions and 26 deletions
@@ -0,0 +1,79 @@
using ERPCore.Domain.Enums;
namespace ERPCore.Domain.Entities;
/// <summary>
/// Day-end owner report settings — a singleton row, same shape as <see cref="SalesConfig"/>
/// (docs/DAY_END_OWNER_REPORT_PLAN.md §3.1). When <see cref="Enabled"/>, OwnerReportJob sends the
/// day's figures to every active <see cref="OwnerReportRecipient"/> at <see cref="SendAtLocalTime"/>.
/// </summary>
public class OwnerReportConfig
{
/// <summary>Always 1 - the singleton row's id.</summary>
public const int SingletonId = 1;
public int ConfigId { get; set; }
/// <summary>Master switch — nothing is sent automatically while off ("Send test now" still works).</summary>
public bool Enabled { get; set; }
public bool SmsEnabled { get; set; } = true;
public bool EmailEnabled { get; set; } = true;
/// <summary>Local time of day (DayEndReport:TimeZone) after which the day's report goes out.</summary>
public TimeOnly SendAtLocalTime { get; set; } = new(21, 0);
/// <summary>Adds one summary row per active branch when branching is switched on.</summary>
public bool IncludeBranchBreakdown { get; set; } = true;
public DateTime? UpdatedAt { get; set; }
public int? UpdatedBy { get; set; }
public User? UpdatedByUser { get; set; }
public uint RowVersion { get; set; }
}
/// <summary>Someone who receives the day-end report — by SMS, email or both.</summary>
public class OwnerReportRecipient
{
public int RecipientId { get; set; }
public string Name { get; set; } = string.Empty;
/// <summary>Normalised to +94XXXXXXXXX (Sri Lankan rule, see PhoneRules).</summary>
public string? Mobile { get; set; }
public string? Email { get; set; }
public bool IsActive { get; set; } = true;
}
/// <summary>
/// One send of one day's report on one channel to one recipient — the send log, and the guard
/// against sending twice: (BusinessDate, Channel, RecipientId, IsTest) is unique for automatic
/// sends, so a restart or a second server instance can't send the same day again.
/// </summary>
public class OwnerReportDispatch
{
public long DispatchId { get; set; }
public DateOnly BusinessDate { get; set; }
public OwnerReportChannel Channel { get; set; }
public int? RecipientId { get; set; }
public OwnerReportRecipient? Recipient { get; set; }
/// <summary>Number / email address at send time — kept even if the recipient is edited later.</summary>
public string Destination { get; set; } = string.Empty;
public string RecipientName { get; set; } = string.Empty;
public OwnerReportDispatchStatus Status { get; set; }
public int Attempts { get; set; }
public string? Error { get; set; }
/// <summary>Test sends ("Send test now") — never block or count as the day's automatic send.</summary>
public bool IsTest { get; set; }
/// <summary>For tests: a unique token so repeated tests don't collide on the unique index.</summary>
public string DedupeKey { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public DateTime? SentAt { get; set; }
public DateTime? NextAttemptAt { get; set; }
}
@@ -0,0 +1,16 @@
namespace ERPCore.Domain.Enums;
/// <summary>How the day-end owner report is delivered (docs/DAY_END_OWNER_REPORT_PLAN.md).</summary>
public enum OwnerReportChannel
{
Sms,
Email,
}
/// <summary>State of one owner-report send.</summary>
public enum OwnerReportDispatchStatus
{
Pending,
Sent,
Failed,
}