using CMSMicroservice.Domain.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace CMSMicroservice.Infrastructure.Persistence.Configurations; /// /// تنظیمات Entity Framework برای حرکات انبار /// public class StockMovementConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { // ========== تنظیمات پایه ========== builder.HasQueryFilter(s => !s.IsDeleted); builder.Ignore(entity => entity.DomainEvents); builder.HasKey(entity => entity.Id); builder.Property(entity => entity.Id).UseIdentityColumn(); // ========== فیلدهای اصلی ========== // نوع حرکت (enum به int) builder.Property(e => e.MovementType) .IsRequired() .HasConversion(); // مقدار تغییر (می‌تواند منفی باشد) builder.Property(e => e.Quantity) .IsRequired(); // موجودی قبل و بعد builder.Property(e => e.QuantityBefore) .IsRequired(); builder.Property(e => e.QuantityAfter) .IsRequired(); // ========== فیلدهای اختیاری ========== // شناسه سفارش معمولی builder.Property(e => e.OrderId) .IsRequired(false); // شناسه سفارش تخفیفی builder.Property(e => e.DiscountOrderId) .IsRequired(false); // شماره مرجع builder.Property(e => e.ReferenceNumber) .IsRequired(false) .HasMaxLength(100); // یادداشت builder.Property(e => e.Note) .IsRequired(false) .HasMaxLength(500); // کاربر انجام‌دهنده builder.Property(e => e.PerformedByUserId) .IsRequired(false); // ========== روابط ========== // رابطه با InventoryItem (اجباری) builder.HasOne(e => e.InventoryItem) .WithMany(i => i.StockMovements) .HasForeignKey(e => e.InventoryItemId) .IsRequired() .OnDelete(DeleteBehavior.Cascade); // ========== Index ها ========== // Index روی InventoryItemId برای جستجوی حرکات یک آیتم builder.HasIndex(e => e.InventoryItemId) .HasDatabaseName("IX_StockMovements_InventoryItemId"); // Index روی MovementType برای فیلتر بر اساس نوع حرکت builder.HasIndex(e => e.MovementType) .HasDatabaseName("IX_StockMovements_MovementType"); // Index روی Created برای مرتب‌سازی زمانی builder.HasIndex(e => e.Created) .HasDatabaseName("IX_StockMovements_Created"); // Index ترکیبی برای گزارش‌گیری builder.HasIndex(e => new { e.InventoryItemId, e.MovementType, e.Created }) .HasDatabaseName("IX_StockMovements_Item_Type_Date"); // Index روی OrderId برای ردیابی حرکات مرتبط با سفارش builder.HasIndex(e => e.OrderId) .HasDatabaseName("IX_StockMovements_OrderId") .HasFilter("[OrderId] IS NOT NULL"); // Index روی DiscountOrderId برای ردیابی حرکات مرتبط با سفارش تخفیفی builder.HasIndex(e => e.DiscountOrderId) .HasDatabaseName("IX_StockMovements_DiscountOrderId") .HasFilter("[DiscountOrderId] IS NOT NULL"); // Index روی ReferenceNumber برای جستجوی سریع با شماره مرجع builder.HasIndex(e => e.ReferenceNumber) .HasDatabaseName("IX_StockMovements_ReferenceNumber") .HasFilter("[ReferenceNumber] IS NOT NULL"); // ========== محدودیت‌ها ========== // محدودیت: QuantityAfter باید برابر QuantityBefore + Quantity باشد builder.HasCheckConstraint("CK_StockMovement_QuantityAfter_Calculation", "QuantityAfter = QuantityBefore + Quantity"); // محدودیت: QuantityBefore و QuantityAfter نمی‌توانند منفی باشند builder.HasCheckConstraint("CK_StockMovement_QuantityBefore_NonNegative", "QuantityBefore >= 0"); builder.HasCheckConstraint("CK_StockMovement_QuantityAfter_NonNegative", "QuantityAfter >= 0"); } }