Implement Inventory Management Service with CRUD operations for warehouses and inventory items, stock operations, and bulk processing capabilities.
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 1m48s

This commit is contained in:
masoodafar-web
2026-01-02 00:45:37 +03:30
parent f0117eb1d5
commit 1cf501711f
50 changed files with 10699 additions and 101 deletions
@@ -0,0 +1,117 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
/// <summary>
/// تنظیمات Entity Framework برای حرکات انبار
/// </summary>
public class StockMovementConfiguration : IEntityTypeConfiguration<StockMovement>
{
public void Configure(EntityTypeBuilder<StockMovement> 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<int>();
// مقدار تغییر (می‌تواند منفی باشد)
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");
}
}