feat(expense): add Expense + MonthlyStatement entities and EF config
This commit is contained in:
@@ -17,6 +17,8 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
|
||||
public DbSet<Ministry> Ministries => Set<Ministry>();
|
||||
public DbSet<ExpenseCategoryGroup> ExpenseCategoryGroups => Set<ExpenseCategoryGroup>();
|
||||
public DbSet<ExpenseSubCategory> ExpenseSubCategories => Set<ExpenseSubCategory>();
|
||||
public DbSet<Expense> Expenses => Set<Expense>();
|
||||
public DbSet<MonthlyStatement> MonthlyStatements => Set<MonthlyStatement>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
@@ -172,5 +174,55 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
|
||||
entity.HasOne(e => e.Group).WithMany(g => g.SubCategories)
|
||||
.HasForeignKey(e => e.GroupId).OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
// ── Expense ──────────────────────────────────────────────────────────
|
||||
builder.Entity<Expense>(entity =>
|
||||
{
|
||||
entity.HasQueryFilter(e => !e.IsDeleted);
|
||||
|
||||
entity.Property(e => e.Type).HasMaxLength(30).IsRequired();
|
||||
entity.Property(e => e.Status).HasMaxLength(30).HasDefaultValue("Draft");
|
||||
entity.Property(e => e.Amount).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.Description).HasMaxLength(500).IsRequired();
|
||||
entity.Property(e => e.VendorName).HasMaxLength(200);
|
||||
entity.Property(e => e.CheckNumber).HasMaxLength(50);
|
||||
entity.Property(e => e.ReceiptBlobPath).HasMaxLength(500);
|
||||
entity.Property(e => e.ReviewNotes).HasMaxLength(500);
|
||||
entity.Property(e => e.SubmittedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.ReviewedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.PaidBy).HasMaxLength(450);
|
||||
entity.Property(e => e.CreatedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.DeletedBy).HasMaxLength(450);
|
||||
|
||||
entity.HasIndex(e => e.MinistryId);
|
||||
entity.HasIndex(e => e.Status).HasFilter("\"IsDeleted\" = false");
|
||||
entity.HasIndex(e => e.ExpenseDate);
|
||||
|
||||
entity.HasOne(e => e.Ministry).WithMany()
|
||||
.HasForeignKey(e => e.MinistryId).OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne(e => e.CategoryGroup).WithMany()
|
||||
.HasForeignKey(e => e.CategoryGroupId).OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne(e => e.SubCategory).WithMany()
|
||||
.HasForeignKey(e => e.SubCategoryId).OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne(e => e.Member).WithMany()
|
||||
.HasForeignKey(e => e.MemberId).OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
// ── MonthlyStatement ─────────────────────────────────────────────────
|
||||
builder.Entity<MonthlyStatement>(entity =>
|
||||
{
|
||||
entity.Property(e => e.OpeningBalance).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.TotalGiving).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.TotalOtherIncome).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.TotalExpenses).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.CalculatedClosingBalance).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.BankStatementBalance).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.Difference).HasColumnType("decimal(18,2)");
|
||||
entity.Property(e => e.FinalizedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.CreatedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
|
||||
entity.HasIndex(e => new { e.Year, e.Month }).IsUnique();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using ROLAC.API.Entities.Base;
|
||||
namespace ROLAC.API.Entities;
|
||||
|
||||
public class Expense : SoftDeleteEntity
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int MinistryId { get; set; }
|
||||
public int CategoryGroupId { get; set; }
|
||||
public int SubCategoryId { get; set; }
|
||||
public string Type { get; set; } = "StaffReimbursement"; // VendorPayment | StaffReimbursement
|
||||
public string Status { get; set; } = "Draft"; // see state machine
|
||||
public decimal Amount { get; set; }
|
||||
public string Description { get; set; } = null!;
|
||||
public string? VendorName { get; set; }
|
||||
public int? MemberId { get; set; }
|
||||
public string? CheckNumber { get; set; }
|
||||
public DateOnly ExpenseDate { get; set; }
|
||||
public string? ReceiptBlobPath { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public string? SubmittedBy { get; set; }
|
||||
public DateTimeOffset? SubmittedAt { get; set; }
|
||||
public string? ReviewedBy { get; set; }
|
||||
public DateTimeOffset? ReviewedAt { get; set; }
|
||||
public string? ReviewNotes { get; set; }
|
||||
public DateTimeOffset? PaidAt { get; set; }
|
||||
public string? PaidBy { get; set; }
|
||||
|
||||
public Ministry? Ministry { get; set; }
|
||||
public ExpenseCategoryGroup? CategoryGroup { get; set; }
|
||||
public ExpenseSubCategory? SubCategory { get; set; }
|
||||
public Member? Member { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using ROLAC.API.Entities.Base;
|
||||
namespace ROLAC.API.Entities;
|
||||
|
||||
public class MonthlyStatement : AuditableEntity
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int Year { get; set; }
|
||||
public int Month { get; set; }
|
||||
public decimal OpeningBalance { get; set; }
|
||||
public decimal TotalGiving { get; set; }
|
||||
public decimal TotalOtherIncome { get; set; }
|
||||
public decimal TotalExpenses { get; set; }
|
||||
public decimal CalculatedClosingBalance { get; set; }
|
||||
public decimal BankStatementBalance { get; set; }
|
||||
public decimal Difference { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public bool IsFinalized { get; set; }
|
||||
public DateTimeOffset? FinalizedAt { get; set; }
|
||||
public string? FinalizedBy { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user