feat(giving): add GivingCategory, OfferingSession, Giving entities + EF config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-05-28 16:16:24 -07:00
parent 3974cec967
commit 999f8a80f9
4 changed files with 111 additions and 0 deletions
+53
View File
@@ -11,6 +11,9 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
public DbSet<RefreshToken> RefreshTokens => Set<RefreshToken>();
public DbSet<Member> Members => Set<Member>();
public DbSet<FamilyUnit> FamilyUnits => Set<FamilyUnit>();
public DbSet<GivingCategory> GivingCategories => Set<GivingCategory>();
public DbSet<OfferingSession> OfferingSessions => Set<OfferingSession>();
public DbSet<Giving> Givings => Set<Giving>();
protected override void OnModelCreating(ModelBuilder builder)
{
@@ -89,5 +92,55 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
entity.HasOne(e => e.FamilyUnit).WithMany()
.HasForeignKey(e => e.FamilyUnitId).OnDelete(DeleteBehavior.SetNull);
});
// ── GivingCategory ───────────────────────────────────────────────────
builder.Entity<GivingCategory>(entity =>
{
entity.Property(e => e.Name_en).HasMaxLength(200).IsRequired();
entity.Property(e => e.Name_zh).HasMaxLength(200);
entity.Property(e => e.Description_en).HasMaxLength(500);
entity.Property(e => e.Description_zh).HasMaxLength(500);
entity.Property(e => e.CreatedBy).HasMaxLength(450);
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
});
// ── OfferingSession ──────────────────────────────────────────────────
builder.Entity<OfferingSession>(entity =>
{
entity.Property(e => e.Status).HasMaxLength(20).HasDefaultValue("Draft");
entity.Property(e => e.CashTotal).HasColumnType("decimal(18,2)");
entity.Property(e => e.CheckTotal).HasColumnType("decimal(18,2)");
entity.Property(e => e.SystemTotal).HasColumnType("decimal(18,2)");
entity.Property(e => e.Difference).HasColumnType("decimal(18,2)");
entity.Property(e => e.SubmittedBy).HasMaxLength(450);
entity.Property(e => e.ReconciledBy).HasMaxLength(450);
entity.Property(e => e.CreatedBy).HasMaxLength(450);
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
entity.HasIndex(e => e.SessionDate).IsUnique();
});
// ── Giving ───────────────────────────────────────────────────────────
builder.Entity<Giving>(entity =>
{
entity.Property(e => e.Amount).HasColumnType("decimal(18,2)");
entity.Property(e => e.PaymentMethod).HasMaxLength(20).IsRequired();
entity.Property(e => e.CheckNumber).HasMaxLength(50);
entity.Property(e => e.ZelleReferenceCode).HasMaxLength(100);
entity.Property(e => e.PayPalTransactionId).HasMaxLength(100);
entity.Property(e => e.Notes).HasMaxLength(500);
entity.Property(e => e.CreatedBy).HasMaxLength(450);
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
entity.HasIndex(e => new { e.MemberId, e.GivingDate });
entity.HasIndex(e => e.OfferingSessionId).HasFilter("\"OfferingSessionId\" IS NOT NULL");
entity.HasIndex(e => e.GivingDate);
entity.HasOne(e => e.GivingCategory).WithMany()
.HasForeignKey(e => e.GivingCategoryId).OnDelete(DeleteBehavior.Restrict);
entity.HasOne(e => e.Member).WithMany()
.HasForeignKey(e => e.MemberId).OnDelete(DeleteBehavior.SetNull);
entity.HasOne(e => e.OfferingSession).WithMany(s => s.Givings)
.HasForeignKey(e => e.OfferingSessionId).OnDelete(DeleteBehavior.Cascade);
});
}
}
+23
View File
@@ -0,0 +1,23 @@
using ROLAC.API.Entities.Base;
namespace ROLAC.API.Entities;
public class Giving : AuditableEntity
{
public int Id { get; set; }
public int? MemberId { get; set; }
public int GivingCategoryId { get; set; }
public int? OfferingSessionId { get; set; }
public decimal Amount { get; set; }
public string PaymentMethod { get; set; } = "Cash"; // Cash|Check|Zelle|PayPal|Other
public string? CheckNumber { get; set; }
public string? ZelleReferenceCode { get; set; }
public string? PayPalTransactionId{ get; set; }
public DateOnly GivingDate { get; set; }
public bool IsAnonymous { get; set; }
public string? Notes { get; set; }
public Member? Member { get; set; }
public GivingCategory? GivingCategory { get; set; }
public OfferingSession? OfferingSession { get; set; }
}
+14
View File
@@ -0,0 +1,14 @@
using ROLAC.API.Entities.Base;
namespace ROLAC.API.Entities;
public class GivingCategory : AuditableEntity
{
public int Id { get; set; }
public string Name_en { get; set; } = null!;
public string? Name_zh { get; set; }
public string? Description_en { get; set; }
public string? Description_zh { get; set; }
public bool IsActive { get; set; } = true;
public int SortOrder { get; set; }
}
+21
View File
@@ -0,0 +1,21 @@
using ROLAC.API.Entities.Base;
namespace ROLAC.API.Entities;
public class OfferingSession : AuditableEntity
{
public int Id { get; set; }
public DateOnly SessionDate { get; set; }
public string Status { get; set; } = "Draft"; // Draft | Submitted | Reconciled
public decimal CashTotal { get; set; }
public decimal CheckTotal { get; set; }
public decimal SystemTotal { get; set; }
public decimal Difference { get; set; }
public string? Notes { get; set; }
public DateTimeOffset? SubmittedAt { get; set; }
public string? SubmittedBy { get; set; }
public DateTimeOffset? ReconciledAt { get; set; }
public string? ReconciledBy { get; set; }
public List<Giving> Givings { get; set; } = [];
}