From 362b306c48bb0bd14fc6b62e7e5267c82f3b85d5 Mon Sep 17 00:00:00 2001 From: MahanCh Date: Thu, 21 Aug 2025 11:05:26 +0330 Subject: [PATCH] feat: add InstitutionContractWorkshopDetail and related mappings for workshop management --- .../InstitutionContract.cs | 37 ++++++++++ .../CreateInstitutionContractTemp.cs | 2 - CompanyManagment.EFCore/CompanyContext.cs | 1 + .../Mapping/InstitutionContractMapping.cs | 12 ++-- ...nstitutionContractWorkshopDetailMapping.cs | 33 +++++++++ .../Mapping/WorkshopMapping.cs | 4 +- .../InstitutionContractRepository.cs | 70 ++++++++++++++----- 7 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 CompanyManagment.EFCore/Mapping/InstitutionContractWorkshopDetailMapping.cs diff --git a/Company.Domain/InstitutionContractAgg/InstitutionContract.cs b/Company.Domain/InstitutionContractAgg/InstitutionContract.cs index c3f8a0f3..e1955fc4 100644 --- a/Company.Domain/InstitutionContractAgg/InstitutionContract.cs +++ b/Company.Domain/InstitutionContractAgg/InstitutionContract.cs @@ -192,6 +192,7 @@ public class InstitutionContractWorkshopDetail:EntityBase PersonnelCount = personnelCount; WorkshopCreated = false; Price = price; + Employers = []; } /// @@ -228,11 +229,34 @@ public class InstitutionContractWorkshopDetail:EntityBase /// public long InstitutionContractId { get; private set; } + /// + /// Navigation property to InstitutionContract + /// + public InstitutionContract InstitutionContract { get; private set; } + public double Price { get; set; } + private InstitutionContractWorkshopDetail() { } + public List Employers { get; private set; } = new(); + + public void SetEmployers(List employerIds) + { + Employers.Clear(); + foreach (var employerId in employerIds) + { + Employers.Add(new InstitutionContractWorkshopDetailEmployer(id, employerId)); + } + } + public void AddEmployer(long employerId) + { + if (Employers.Exists(x => x.EmployerId == employerId)) + return; + + Employers.Add(new InstitutionContractWorkshopDetailEmployer(id, employerId)); + } public void Edit(bool hasAttendancePlan, bool hasUnofficialPayslipPlan, bool hasContractSettlementPlan) { @@ -281,4 +305,17 @@ public class InstitutionContractInstallment public long InstitutionContractId { get; private set; } public InstitutionContract InstitutionContract { get; private set; } +} +public class InstitutionContractWorkshopDetailEmployer : EntityBase +{ + public long InstitutionContractWorkshopDetailId { get; private set; } + public long EmployerId { get; private set; } + + public InstitutionContractWorkshopDetailEmployer(long institutionContractWorkshopDetailId, long employerId) + { + InstitutionContractWorkshopDetailId = institutionContractWorkshopDetailId; + EmployerId = employerId; + } + + private InstitutionContractWorkshopDetailEmployer() { } } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/TemporaryClientRegistration/CreateInstitutionContractTemp.cs b/CompanyManagment.App.Contracts/TemporaryClientRegistration/CreateInstitutionContractTemp.cs index 1263db19..21a72843 100644 --- a/CompanyManagment.App.Contracts/TemporaryClientRegistration/CreateInstitutionContractTemp.cs +++ b/CompanyManagment.App.Contracts/TemporaryClientRegistration/CreateInstitutionContractTemp.cs @@ -69,8 +69,6 @@ public class CreateInstitutionContractTemp /// public InstitutionContractTempStatus RegistrationStatus { get; set; } - - /// /// آی دی پیامک ارسال شده /// diff --git a/CompanyManagment.EFCore/CompanyContext.cs b/CompanyManagment.EFCore/CompanyContext.cs index c4e46245..54c9b07f 100644 --- a/CompanyManagment.EFCore/CompanyContext.cs +++ b/CompanyManagment.EFCore/CompanyContext.cs @@ -271,6 +271,7 @@ public class CompanyContext : DbContext public DbSet InsuranceJobAndJobsSet { get; set; } public DbSet InstitutionContractContactInfos { get; set; } public DbSet InstitutionContractSet { get; set; } + public DbSet InstitutionContractWorkshopDetails { get; set; } public DbSet FileEmployerSet { get; set; } public DbSet FileEmployeeSet { get; set; } public DbSet RepresentativeSet { get; set; } diff --git a/CompanyManagment.EFCore/Mapping/InstitutionContractMapping.cs b/CompanyManagment.EFCore/Mapping/InstitutionContractMapping.cs index 4112f73c..69e94747 100644 --- a/CompanyManagment.EFCore/Mapping/InstitutionContractMapping.cs +++ b/CompanyManagment.EFCore/Mapping/InstitutionContractMapping.cs @@ -30,13 +30,11 @@ public class InstitutionContractMapping : IEntityTypeConfiguration x.HasValueAddedTax).HasMaxLength(10); builder.Property(x => x.Status).HasConversion().HasMaxLength(122); - builder.OwnsMany(x => x.WorkshopDetails, workshopDetail => - { - workshopDetail.HasKey(x => x.id); - workshopDetail.WithOwner().HasForeignKey(x => x.InstitutionContractId); - workshopDetail.Property(x => x.WorkshopName).HasMaxLength(100); - workshopDetail.Property(x => x.WorkshopId).IsRequired(false); - }); + + // Configure simple relationship with WorkshopDetails for Include() support + builder.HasMany(x => x.WorkshopDetails) + .WithOne(x => x.InstitutionContract) + .HasForeignKey(x => x.InstitutionContractId); builder.HasMany(x => x.Installments) .WithOne(x => x.InstitutionContract) diff --git a/CompanyManagment.EFCore/Mapping/InstitutionContractWorkshopDetailMapping.cs b/CompanyManagment.EFCore/Mapping/InstitutionContractWorkshopDetailMapping.cs new file mode 100644 index 00000000..859084ff --- /dev/null +++ b/CompanyManagment.EFCore/Mapping/InstitutionContractWorkshopDetailMapping.cs @@ -0,0 +1,33 @@ +using Company.Domain.InstitutionContractAgg; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace CompanyManagment.EFCore.Mapping; + +public class InstitutionContractWorkshopDetailMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("InstitutionContractWorkshopDetail"); + builder.HasKey(x => x.id); + + builder.Property(x => x.WorkshopName).HasMaxLength(100); + builder.Property(x => x.WorkshopId).IsRequired(false); + + // Configure relationship with InstitutionContract + builder.HasOne(x => x.InstitutionContract) + .WithMany(x => x.WorkshopDetails) + .HasForeignKey(x => x.InstitutionContractId); + + // Configure OwnsMany relationship with Employers + builder.OwnsMany(x => x.Employers, employer => + { + employer.ToTable("InstitutionContractWorkshopDetailEmployers"); + employer.HasKey(x => x.id); + employer.WithOwner().HasForeignKey(x => x.InstitutionContractWorkshopDetailId); + employer.Property(x => x.EmployerId).IsRequired(); + employer.HasIndex(x => new { x.InstitutionContractWorkshopDetailId, x.EmployerId }) + .IsUnique(); + }); + } +} diff --git a/CompanyManagment.EFCore/Mapping/WorkshopMapping.cs b/CompanyManagment.EFCore/Mapping/WorkshopMapping.cs index 9a334aa6..86790d9d 100644 --- a/CompanyManagment.EFCore/Mapping/WorkshopMapping.cs +++ b/CompanyManagment.EFCore/Mapping/WorkshopMapping.cs @@ -43,9 +43,7 @@ partial class WorkshopMapping : IEntityTypeConfiguration builder.Property(x => x.CutContractEndOfYear).HasConversion(x => x.ToString() , x => ((IsActive)Enum.Parse(typeof(IsActive), x))).HasMaxLength(5); - - builder.Property(x => x.RegistrationStatus).HasConversion().HasMaxLength(50); - builder.HasQueryFilter(x => x.RegistrationStatus == WorkshopRegistrationStatus.Registered); + //builder.HasOne(x => x.Employer) // .WithMany(x => x.Workshops) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 311f41ad..8f939e98 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1416,39 +1416,72 @@ public class InstitutionContractRepository : RepositoryBase + /// دریافت لیست اقلام گردش کار ثبت نام + /// + /// شناسه قرارداد نهاد + /// لیست اقلام گردش کار ثبت نام public async Task> RegistrationWorkflowItems(long institutionContractId) { + // دریافت قرارداد نهاد همراه با جزئیات کارگاه‌ها var institutionContract = await _context.InstitutionContractSet .Include(x => x.WorkshopDetails) .FirstOrDefaultAsync(x => x.id == institutionContractId); + if (institutionContract == null) throw new NotFoundException("قرارداد مؤسسه یافت نشد"); + // استخراج شناسه‌های کارگاه‌هایی که ایجاد شده‌اند + var workshopIds = institutionContract.WorkshopDetails + .Where(x => x.WorkshopId != null) + .Select(x => x.WorkshopId.Value) + .ToList(); - var workshopIds = institutionContract.WorkshopDetails.Where(x => x.WorkshopId != null) - .Select(x => x.WorkshopId.Value).ToList(); + // دریافت کارگاه‌ها همراه با کارفرمایان در یک کوئری + var workshopsTask = _context.Workshops + .Where(x => workshopIds.Contains(x.id)).ToListAsync(); - var workshops = await _context.Workshops.IgnoreQueryFilters() - .Where(x => workshopIds.Contains(x.id)) - .Include(workshop => workshop.WorkshopEmployers) - .ThenInclude(workshopEmployer => workshopEmployer.Employer) + // استخراج تمامی شناسه‌های کارفرمایان از جزئیات کارگاه‌ها + var allEmployerIds = institutionContract.WorkshopDetails + .SelectMany(x => x.Employers.Select(e => e.EmployerId)) + .Distinct() + .ToList(); + + // دریافت اطلاعات کارفرمایان در یک کوئری واحد + var employersTask = _context.Employers + .Where(e => allEmployerIds.Contains(e.id)) + .Select(e => new { e.id, e.FullName }) .ToListAsync(); - var items = institutionContract.WorkshopDetails.Select(x => + // انتظار برای تکمیل هر دو کوئری به صورت موازی + await Task.WhenAll(workshopsTask, employersTask); + + var workshops = await workshopsTask; + var employersDict = (await employersTask).ToDictionary(e => e.id, e => e); + + // ساخت نتیجه نهایی با استفاده از داده‌های از پیش بارگذاری شده + var items = institutionContract.WorkshopDetails.Select(workshopDetail => { - var workshop = workshops.FirstOrDefault(w => w.id == x.WorkshopId); + // پیدا کردن کارگاه مرتبط + var workshop = workshops.FirstOrDefault(w => w.id == workshopDetail.WorkshopId); + + // ساخت لیست کارفرمایان این جزئیات کارگاه + var employers = workshopDetail.Employers + .Where(e => employersDict.ContainsKey(e.EmployerId)) + .Select(e => new RegistrationWorkflowItemsEmployerViewModel + { + Id = e.EmployerId, + FullName = employersDict[e.EmployerId].FullName + }) + .ToList(); + return new RegistrationWorkflowItemsViewModel { - Price = x.Price, + Price = workshopDetail.Price, IsDone = workshop != null, - PersonnelCount = x.PersonnelCount, - WorkshopName = x.WorkshopName, - Employers = workshop?.WorkshopEmployers.Select(we => we.Employer).Select(we => - new RegistrationWorkflowItemsEmployerViewModel - { - Id = x.id, - FullName = we.FullName, - }).ToList() ?? [], + PersonnelCount = workshopDetail.PersonnelCount, + WorkshopName = workshopDetail.WorkshopName, + Employers = employers, }; }).ToList(); @@ -1523,4 +1556,5 @@ public class InstitutionContractRepository : RepositoryBase