From 3ab215b4011efeb55811d3f3aa8ddb8b7c6d2023 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Sat, 17 May 2025 12:09:54 +0530 Subject: [PATCH] added an API to get list of contacts by bucket id and added project- contact mapping table --- .../ApplicationDbContextModelSnapshot.cs | 56 +++++++++++++- Marco.Pms.Model/Directory/Contact.cs | 2 +- .../Directory/ContactProjectMapping.cs | 20 +++++ .../Dtos/Directory/CreateContactDto.cs | 2 +- .../Dtos/Directory/UpdateContactDto.cs | 2 +- Marco.Pms.Model/Mapper/DirectoryMapper.cs | 3 - .../ViewModels/Directory/ContactVM.cs | 3 +- Marco.Pms.Services/Helpers/DirectoryHelper.cs | 77 ++++++++++++++++--- 8 files changed, 145 insertions(+), 20 deletions(-) create mode 100644 Marco.Pms.Model/Directory/ContactProjectMapping.cs diff --git a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs index a66cb99..b80c716 100644 --- a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs @@ -320,9 +320,6 @@ namespace Marco.Pms.DataAccess.Migrations .IsRequired() .HasColumnType("longtext"); - b.Property("ProjectId") - .HasColumnType("char(36)"); - b.Property("TenantId") .HasColumnType("char(36)"); @@ -478,6 +475,32 @@ namespace Marco.Pms.DataAccess.Migrations b.ToTable("ContactsPhones"); }); + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactProjectMappings"); + }); + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => { b.Property("Id") @@ -2541,6 +2564,33 @@ namespace Marco.Pms.DataAccess.Migrations b.Navigation("Contact"); }); + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => { b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") diff --git a/Marco.Pms.Model/Directory/Contact.cs b/Marco.Pms.Model/Directory/Contact.cs index 87d7698..ecdd622 100644 --- a/Marco.Pms.Model/Directory/Contact.cs +++ b/Marco.Pms.Model/Directory/Contact.cs @@ -9,7 +9,7 @@ namespace Marco.Pms.Model.Directory public class Contact : TenantRelation { public Guid Id { get; set; } - public Guid? ProjectId { get; set; } + //public Guid? ProjectId { get; set; } public string Name { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public string Organization { get; set; } = string.Empty; diff --git a/Marco.Pms.Model/Directory/ContactProjectMapping.cs b/Marco.Pms.Model/Directory/ContactProjectMapping.cs new file mode 100644 index 0000000..0f965fe --- /dev/null +++ b/Marco.Pms.Model/Directory/ContactProjectMapping.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Marco.Pms.Model.Projects; +using Marco.Pms.Model.Utilities; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; + +namespace Marco.Pms.Model.Directory +{ + public class ContactProjectMapping : TenantRelation + { + public Guid Id { get; set; } + public Guid ProjectId { get; set; } + [ValidateNever] + [ForeignKey("ProjectId")] + public Project? Project { get; set; } + public Guid ContactId { get; set; } + [ValidateNever] + [ForeignKey("ContactId")] + public Contact? Contact { get; set; } + } +} \ No newline at end of file diff --git a/Marco.Pms.Model/Dtos/Directory/CreateContactDto.cs b/Marco.Pms.Model/Dtos/Directory/CreateContactDto.cs index cadd7e2..577f405 100644 --- a/Marco.Pms.Model/Dtos/Directory/CreateContactDto.cs +++ b/Marco.Pms.Model/Dtos/Directory/CreateContactDto.cs @@ -2,7 +2,7 @@ { public class CreateContactDto { - public Guid? ProjectId { get; set; } + public List? ProjectIds { get; set; } public string? Name { get; set; } public List? ContactPhones { get; set; } public List? ContactEmails { get; set; } diff --git a/Marco.Pms.Model/Dtos/Directory/UpdateContactDto.cs b/Marco.Pms.Model/Dtos/Directory/UpdateContactDto.cs index ccf5345..c648db0 100644 --- a/Marco.Pms.Model/Dtos/Directory/UpdateContactDto.cs +++ b/Marco.Pms.Model/Dtos/Directory/UpdateContactDto.cs @@ -3,7 +3,7 @@ public class UpdateContactDto { public Guid Id { get; set; } - public Guid? ProjectId { get; set; } + public List? ProjectIds { get; set; } public string? Name { get; set; } public List? ContactPhones { get; set; } public List? ContactEmails { get; set; } diff --git a/Marco.Pms.Model/Mapper/DirectoryMapper.cs b/Marco.Pms.Model/Mapper/DirectoryMapper.cs index 8197c94..2807e9a 100644 --- a/Marco.Pms.Model/Mapper/DirectoryMapper.cs +++ b/Marco.Pms.Model/Mapper/DirectoryMapper.cs @@ -13,7 +13,6 @@ namespace Marco.Pms.Model.Mapper return new Contact { - ProjectId = createContactDto.ProjectId, Name = createContactDto.Name ?? string.Empty, ContactCategoryId = createContactDto.ContactCategoryId, Description = createContactDto.Description ?? string.Empty, @@ -30,7 +29,6 @@ namespace Marco.Pms.Model.Mapper return new Contact { Id = updateContactDto.Id, - ProjectId = updateContactDto.ProjectId, Name = updateContactDto.Name ?? string.Empty, ContactCategoryId = updateContactDto.ContactCategoryId, CreatedAt = contact.CreatedAt, @@ -46,7 +44,6 @@ namespace Marco.Pms.Model.Mapper return new ContactVM { Id = contact.Id, - ProjectId = contact.ProjectId, Name = contact.Name, ContactCategory = contact.ContactCategory != null ? contact.ContactCategory.ToContactCategoryVMFromContactCategoryMaster() : null, Description = contact.Description ?? string.Empty, diff --git a/Marco.Pms.Model/ViewModels/Directory/ContactVM.cs b/Marco.Pms.Model/ViewModels/Directory/ContactVM.cs index b1abb3b..d394f73 100644 --- a/Marco.Pms.Model/ViewModels/Directory/ContactVM.cs +++ b/Marco.Pms.Model/ViewModels/Directory/ContactVM.cs @@ -5,11 +5,12 @@ namespace Marco.Pms.Model.ViewModels.Directory public class ContactVM { public Guid Id { get; set; } - public Guid? ProjectId { get; set; } + public List? ProjectIds { get; set; } public string? Name { get; set; } public List? ContactPhones { get; set; } public List? ContactEmails { get; set; } public ContactCategoryVM? ContactCategory { get; set; } + public List? BucketIds { get; set; } public string? Description { get; set; } public string? Organization { get; set; } public string? Address { get; set; } diff --git a/Marco.Pms.Services/Helpers/DirectoryHelper.cs b/Marco.Pms.Services/Helpers/DirectoryHelper.cs index 157c62d..c856172 100644 --- a/Marco.Pms.Services/Helpers/DirectoryHelper.cs +++ b/Marco.Pms.Services/Helpers/DirectoryHelper.cs @@ -31,14 +31,19 @@ namespace Marco.Pms.Services.Helpers { Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + List? employeeBuckets = await _context.EmployeeBucketMappings.Where(eb => eb.EmployeeId == LoggedInEmployee.Id).ToListAsync(); + List bucketIds = employeeBuckets.Select(c => c.BucketId).ToList(); List? contactBuckets = await _context.ContactBucketMappings.Where(cb => bucketIds.Contains(cb.BucketId)).ToListAsync(); List contactIds = contactBuckets.Select(cb => cb.ContactId).ToList(); var contacts = await _context.Contacts.Include(c => c.ContactCategory).Where(c => contactIds.Contains(c.Id) && c.TenantId == tenantId && c.IsActive).ToListAsync(); + var phoneNo = await _context.ContactsPhones.Where(p => contactIds.Contains(p.ContactId)).ToListAsync(); var Emails = await _context.ContactsEmails.Where(E => contactIds.Contains(E.ContactId)).ToListAsync(); var Tags = await _context.ContactTagMappings.Where(t => contactIds.Contains(t.ContactId)).ToListAsync(); + var contactProjects = await _context.ContactProjectMappings.Where(p => contactIds.Contains(p.ContactId)).ToListAsync(); + List TagIds = Tags.Select(t => t.ContactTagtId).ToList(); var TagList = await _context.ContactTagMasters.Where(t => TagIds.Contains(t.Id)).ToListAsync(); @@ -56,9 +61,10 @@ namespace Marco.Pms.Services.Helpers var phones = phoneNo.Where(p => p.ContactId == contact.Id).ToList(); var emails = Emails.Where(e => e.ContactId == contact.Id).ToList(); var tagMappingss = Tags.Where(t => t.ContactId == contact.Id).ToList(); + var projectMapping = contactProjects.Where(p => p.ContactId == contact.Id).ToList(); + var bucketMapping = contactBuckets.Where(b => b.ContactId == contact.Id).ToList(); - - if (emails != null) + if (emails != null && emails.Count > 0) { foreach (var email in emails) { @@ -68,7 +74,7 @@ namespace Marco.Pms.Services.Helpers } } - if (phones != null) + if (phones != null && phones.Count > 0) { foreach (var phone in phones) { @@ -78,7 +84,7 @@ namespace Marco.Pms.Services.Helpers } } - if (tagMappingss != null) + if (tagMappingss != null && tagMappingss.Count > 0) { foreach (var tagMapping in tagMappingss) { @@ -91,9 +97,17 @@ namespace Marco.Pms.Services.Helpers } } - - contactVM = contact.ToContactVMFromContact(); + + if (projectMapping != null && projectMapping.Count > 0) + { + contactVM.ProjectIds = projectMapping.Select(p => p.ProjectId).ToList(); + } + if (bucketMapping != null && bucketMapping.Count > 0) + { + contactVM.BucketIds = bucketMapping.Select(p => p.BucketId).ToList(); + } + contactVM.ContactEmails = contactEmailVms; contactVM.ContactPhones = contactPhoneVms; contactVM.Tags = conatctTagVms; @@ -220,6 +234,8 @@ namespace Marco.Pms.Services.Helpers var tags = await _context.ContactTagMasters.Where(t => t.TenantId == tenantId).ToListAsync(); var tagNames = tags.Select(t => t.Name.ToLower()).ToList(); var buckets = await _context.Buckets.Where(b => b.TenantId == tenantId).Select(b => b.Id).ToListAsync(); + var projects = await _context.Projects.Where(p => p.TenantId == tenantId).Select(p => p.Id).ToListAsync(); + if (createContact.ContactPhones != null) { @@ -242,6 +258,7 @@ namespace Marco.Pms.Services.Helpers _context.ContactsEmails.AddRange(emails); _logger.LogInfo("{count} email addresses are saved in contact with ID {ContactId} by employee with ID {LoggedEmployeeId}", emails.Count, contact.Id, LoggedInEmployee.Id); } + if (createContact.BucketIds != null) { foreach (var bucket in createContact.BucketIds) @@ -257,8 +274,29 @@ namespace Marco.Pms.Services.Helpers } } _context.ContactBucketMappings.AddRange(contactBucketMappings); - _logger.LogInfo("Contact with ID {ContactId} added to {count} number of buckets by employee with ID {LoggedEmployeeId}", contact.Id, LoggedInEmployee.Id); + _logger.LogInfo("Contact with ID {ContactId} added to {count} number of buckets by employee with ID {LoggedEmployeeId}", contact.Id, contactBucketMappings.Count, LoggedInEmployee.Id); } + + if (createContact.ProjectIds != null) + { + List projectMappings = new List(); + foreach (var projectId in createContact.ProjectIds) + { + if (projects.Contains(projectId)) + { + ContactProjectMapping projectMapping = new ContactProjectMapping + { + ProjectId = projectId, + ContactId = contact.Id, + TenantId = tenantId + }; + projectMappings.Add(projectMapping); + } + } + _context.ContactProjectMappings.AddRange(projectMappings); + _logger.LogInfo("Contact with ID {ContactId} added to {count} number of project by employee with ID {LoggedEmployeeId}", contact.Id, projectMappings.Count, LoggedInEmployee.Id); + } + if (createContact.Tags != null) { foreach (var tag in createContact.Tags) @@ -276,7 +314,8 @@ namespace Marco.Pms.Services.Helpers { var newtag = new ContactTagMaster { - Name = tag.Name + Name = tag.Name, + TenantId = tenantId }; _context.ContactTagMasters.Add(newtag); ContactTagMapping tagMapping = new ContactTagMapping @@ -287,12 +326,20 @@ namespace Marco.Pms.Services.Helpers contactTagMappings.Add(tagMapping); } } + _context.ContactTagMappings.AddRange(contactTagMappings); + _logger.LogInfo("{count} number of tags added to Contact with ID {ContactId} by employee with ID {LoggedEmployeeId}", contactTagMappings.Count, contact.Id, LoggedInEmployee.Id); } await _context.SaveChangesAsync(); ContactVM contactVM = new ContactVM(); List phoneVMs = new List(); + + contact = await _context.Contacts.Include(c => c.ContactCategory).FirstOrDefaultAsync(c => c.Id == contact.Id) ?? new Contact(); + var tagIds = contactTagMappings.Select(t => t.ContactTagtId).ToList(); + tags = await _context.ContactTagMasters.Where(t => t.TenantId == tenantId && tagIds.Contains(t.Id)).ToListAsync(); + List contactProjects = await _context.ContactProjectMappings.Where(cp => cp.ContactId == contact.Id).ToListAsync(); + List bucketMappings = await _context.ContactBucketMappings.Where(cb => cb.ContactId == contact.Id).ToListAsync(); foreach (var phone in phones) { ContactPhoneVM phoneVM = phone.ToContactPhoneVMFromContactPhone(); @@ -318,6 +365,8 @@ namespace Marco.Pms.Services.Helpers contactVM.ContactPhones = phoneVMs; contactVM.ContactEmails = emailVMs; contactVM.Tags = tagVMs; + contactVM.ProjectIds = contactProjects.Select(cp => cp.ProjectId).ToList(); + contactVM.BucketIds = bucketMappings.Select(cb => cb.BucketId).ToList(); return ApiResponse.SuccessResponse(contactVM, "Contact Created Successfully", 200); } @@ -496,7 +545,8 @@ namespace Marco.Pms.Services.Helpers ContactTagMaster contactTag = new ContactTagMaster { Name = tag.Name, - Description = "" + Description = "", + TenantId = tenantId }; _context.ContactTagMasters.Add(contactTag); @@ -509,7 +559,7 @@ namespace Marco.Pms.Services.Helpers } foreach (var contactTag in contactTags) { - if (!updatedTagIds.Contains(contactTag.ContactTagtId)) + if (!updatedTagIds.Contains(contactTag.Id)) { _context.ContactTagMappings.Remove(contactTag); } @@ -532,6 +582,10 @@ namespace Marco.Pms.Services.Helpers phones = await _context.ContactsPhones.AsNoTracking().Where(p => p.ContactId == contact.Id).ToListAsync(); emails = await _context.ContactsEmails.AsNoTracking().Where(p => p.ContactId == contact.Id).ToListAsync(); contactTags = await _context.ContactTagMappings.AsNoTracking().Where(m => m.ContactId == contact.Id).ToListAsync(); + contactBuckets = await _context.ContactBucketMappings.AsNoTracking().Where(cb => cb.ContactId == contact.Id).ToListAsync(); + contactProjects = await _context.ContactProjectMappings.AsNoTracking().Where(cp => cp.ContactId == contact.Id).ToListAsync(); + tagIds = contactTags.Select(t => t.ContactTagtId).Distinct().ToList(); + tags = await _context.ContactTagMasters.Where(t => tagIds.Contains(t.Id)).ToListAsync(); ContactVM contactVM = new ContactVM(); List phoneVMs = new List(); @@ -560,6 +614,9 @@ namespace Marco.Pms.Services.Helpers contactVM.ContactPhones = phoneVMs; contactVM.ContactEmails = emailVMs; contactVM.Tags = tagVMs; + contactVM.BucketIds = contactBuckets.Select(cb => cb.BucketId).ToList(); + contactVM.ProjectIds = contactProjects.Select(cp => cp.ProjectId).ToList(); + _logger.LogInfo("Conatct {ContactId} has been updated by employee {EmployeeId}", contact.Id, LoggedInEmployee.Id); return ApiResponse.SuccessResponse(contactVM, "Contact Updated Successfully", 200); }