Added the serviceId in project allocation
This commit is contained in:
parent
9b59a4d6b6
commit
7d85cb5f4c
6133
Marco.Pms.DataAccess/Migrations/20250920105816_Added_Service_FK_In_ProjectAllocation.Designer.cs
generated
Normal file
6133
Marco.Pms.DataAccess/Migrations/20250920105816_Added_Service_FK_In_ProjectAllocation.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Marco.Pms.DataAccess.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Added_Service_FK_In_ProjectAllocation : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "ServiceId",
|
||||
table: "ProjectAllocations",
|
||||
type: "char(36)",
|
||||
nullable: true,
|
||||
collation: "ascii_general_ci");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "logoImage",
|
||||
table: "Organizations",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Organizations",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("4e3a6d31-c640-40f7-8d67-6c109fcdb9ea"),
|
||||
column: "logoImage",
|
||||
value: null);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ProjectAllocations_ServiceId",
|
||||
table: "ProjectAllocations",
|
||||
column: "ServiceId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ProjectAllocations_ServiceMasters_ServiceId",
|
||||
table: "ProjectAllocations",
|
||||
column: "ServiceId",
|
||||
principalTable: "ServiceMasters",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ProjectAllocations_ServiceMasters_ServiceId",
|
||||
table: "ProjectAllocations");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_ProjectAllocations_ServiceId",
|
||||
table: "ProjectAllocations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ServiceId",
|
||||
table: "ProjectAllocations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "logoImage",
|
||||
table: "Organizations");
|
||||
}
|
||||
}
|
||||
}
|
@ -3643,6 +3643,9 @@ namespace Marco.Pms.DataAccess.Migrations
|
||||
b.Property<Guid?>("UpdatedById")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("logoImage")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Organizations");
|
||||
@ -3918,6 +3921,9 @@ namespace Marco.Pms.DataAccess.Migrations
|
||||
b.Property<DateTime?>("ReAllocationDate")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<Guid?>("ServiceId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
@ -3927,6 +3933,8 @@ namespace Marco.Pms.DataAccess.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("ProjectAllocations");
|
||||
@ -5858,6 +5866,10 @@ namespace Marco.Pms.DataAccess.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Marco.Pms.Model.Master.ServiceMaster", "Service")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
@ -5868,6 +5880,8 @@ namespace Marco.Pms.DataAccess.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Service");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
public required string ContactPerson { get; set; }
|
||||
public required string Address { get; set; }
|
||||
public required string ContactNumber { get; set; }
|
||||
public string? logoImage { get; set; }
|
||||
public required List<Guid> ServiceIds { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
{
|
||||
public class ProjectAllocationDot
|
||||
{
|
||||
public Guid EmpID { get; set; }
|
||||
public Guid EmployeeId { get; set; }
|
||||
public Guid JobRoleId { get; set; }
|
||||
public Guid ProjectId { get; set; }
|
||||
public Guid ServiceId { get; set; }
|
||||
public bool Status { get; set; }
|
||||
}
|
||||
|
||||
@ -13,6 +14,7 @@
|
||||
{
|
||||
public Guid ProjectId { get; set; }
|
||||
public Guid JobRoleId { get; set; }
|
||||
public Guid ServiceId { get; set; }
|
||||
public bool Status { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ namespace Marco.Pms.Model.Mapper
|
||||
return new ProjectAllocation
|
||||
{
|
||||
AllocationDate = DateTime.Now,
|
||||
EmployeeId = model.EmpID,
|
||||
EmployeeId = model.EmployeeId,
|
||||
JobRoleId = model.JobRoleId,
|
||||
TenantId = TenantId,
|
||||
ProjectId = model.ProjectId
|
||||
@ -65,7 +65,7 @@ namespace Marco.Pms.Model.Mapper
|
||||
}
|
||||
|
||||
|
||||
public static ProjectAllocation ToProjectAllocationFromProjectsAllocationDto(this ProjectsAllocationDto model, Guid TenantId,Guid employeeId)
|
||||
public static ProjectAllocation ToProjectAllocationFromProjectsAllocationDto(this ProjectsAllocationDto model, Guid TenantId, Guid employeeId)
|
||||
{
|
||||
return new ProjectAllocation
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string ContactNumber { get; set; } = string.Empty;
|
||||
public double SPRID { get; set; }
|
||||
public string? logoImage { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public Guid? CreatedById { get; set; }
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Marco.Pms.Model.Projects
|
||||
{
|
||||
@ -21,9 +22,15 @@ namespace Marco.Pms.Model.Projects
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
public Guid ProjectId { get; set; }
|
||||
|
||||
[ForeignKey("ProjectId")]
|
||||
[ValidateNever]
|
||||
public Project? Project { get; set; }
|
||||
public Guid? ServiceId { get; set; }
|
||||
|
||||
[ForeignKey("ServiceId")]
|
||||
[ValidateNever]
|
||||
public ServiceMaster? Service { get; set; }
|
||||
|
||||
|
||||
public DateTime AllocationDate { get; set; }
|
||||
|
@ -11,6 +11,7 @@ namespace Marco.Pms.Model.ViewModels.Organization
|
||||
public string? Address { get; set; }
|
||||
public string? ContactNumber { get; set; }
|
||||
public double SPRID { get; set; }
|
||||
public string? logoImage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||
|
@ -219,7 +219,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
}
|
||||
|
||||
[HttpGet("allocation/{projectId}")]
|
||||
public async Task<IActionResult> GetProjectAllocation(Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] bool includeInactive = false)
|
||||
public async Task<IActionResult> GetProjectAllocation(Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] Guid? serviceId, [FromQuery] bool includeInactive = false)
|
||||
{
|
||||
// --- Step 1: Input Validation ---
|
||||
if (!ModelState.IsValid)
|
||||
@ -231,7 +231,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
|
||||
// --- Step 2: Prepare data without I/O ---
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _projectServices.GetProjectAllocationAsync(projectId, organizationId, includeInactive, tenantId, loggedInEmployee);
|
||||
var response = await _projectServices.GetProjectAllocationAsync(projectId, organizationId, serviceId, includeInactive, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
|
@ -161,8 +161,7 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
CreateMap<ProjectAllocationDot, ProjectAllocation>()
|
||||
.ForMember(
|
||||
dest => dest.EmployeeId,
|
||||
// Explicitly and safely convert string ProjectStatusId to Guid ProjectStatusId
|
||||
opt => opt.MapFrom(src => src.EmpID));
|
||||
opt => opt.MapFrom(src => src.EmployeeId));
|
||||
CreateMap<ProjectsAllocationDto, ProjectAllocation>();
|
||||
CreateMap<ProjectAllocation, ProjectAllocationVM>();
|
||||
|
||||
|
@ -562,7 +562,7 @@ namespace Marco.Pms.Services.Service
|
||||
/// <param name="tenantId">The ID of the current tenant.</param>
|
||||
/// <param name="loggedInEmployee">The current authenticated employee for permission checks.</param>
|
||||
/// <returns>An ApiResponse containing allocation details or an appropriate error.</returns>
|
||||
public async Task<ApiResponse<object>> GetProjectAllocationAsync(Guid projectId, Guid? organizationId, bool includeInactive, Guid tenantId, Employee loggedInEmployee)
|
||||
public async Task<ApiResponse<object>> GetProjectAllocationAsync(Guid projectId, Guid? organizationId, Guid? serviceId, bool includeInactive, Guid tenantId, Employee loggedInEmployee)
|
||||
{
|
||||
// --- Step 1: Input Validation ---
|
||||
if (projectId == Guid.Empty)
|
||||
@ -595,7 +595,8 @@ namespace Marco.Pms.Services.Service
|
||||
.ThenInclude(e => e!.JobRole)
|
||||
.Include(pa => pa.Employee)
|
||||
.ThenInclude(e => e!.Organization)
|
||||
.Where(pa => pa.ProjectId == projectId && pa.TenantId == tenantId);
|
||||
.Include(pa => pa.Service)
|
||||
.Where(pa => pa.ProjectId == projectId && pa.TenantId == tenantId && pa.Service != null);
|
||||
|
||||
// Conditionally apply the filter for active allocations.
|
||||
if (!includeInactive)
|
||||
@ -628,6 +629,8 @@ namespace Marco.Pms.Services.Service
|
||||
|
||||
OrganizationName = pa.Employee.Organization!.Name,
|
||||
|
||||
ServiceName = pa.Service!.Name,
|
||||
|
||||
// Simplified JobRoleId logic: Use the allocation's role if it exists, otherwise fall back to the employee's default role.
|
||||
JobRoleId = pa.JobRoleId ?? pa.Employee.JobRoleId
|
||||
})
|
||||
@ -679,8 +682,8 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
|
||||
// --- Step 2: Fetch all relevant existing data in ONE database call ---
|
||||
var employeeProjectPairs = allocationsDto.Select(a => new { a.EmpID, a.ProjectId }).ToList();
|
||||
List<Guid> employeeIds = allocationsDto.Select(a => a.EmpID).Distinct().ToList();
|
||||
var employeeProjectPairs = allocationsDto.Select(a => new { a.EmployeeId, a.ProjectId }).ToList();
|
||||
List<Guid> employeeIds = allocationsDto.Select(a => a.EmployeeId).Distinct().ToList();
|
||||
|
||||
// Fetch all currently active allocations for the employees and projects in this batch.
|
||||
// We use a dictionary for fast O(1) lookups inside the loop.
|
||||
@ -695,7 +698,7 @@ namespace Marco.Pms.Services.Service
|
||||
// --- Step 3: Process logic IN MEMORY ---
|
||||
foreach (var dto in allocationsDto)
|
||||
{
|
||||
var key = (dto.EmpID, dto.ProjectId);
|
||||
var key = (dto.EmployeeId, dto.ProjectId);
|
||||
existingAllocations.TryGetValue(key, out var existingAllocation);
|
||||
|
||||
if (dto.Status == false) // User wants to DEACTIVATE the allocation
|
||||
@ -726,8 +729,8 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
try
|
||||
{
|
||||
await _cache.ClearAllProjectIds(dto.EmpID);
|
||||
_logger.LogInfo("Successfully completed cache invalidation for employee {EmployeeId}.", dto.EmpID);
|
||||
await _cache.ClearAllProjectIds(dto.EmployeeId);
|
||||
_logger.LogInfo("Successfully completed cache invalidation for employee {EmployeeId}.", dto.EmployeeId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
Task<ApiResponse<object>> CreateProjectAsync(CreateProjectDto projectDto, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> UpdateProjectAsync(Guid id, UpdateProjectDto updateProjectDto, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetEmployeeByProjectIdAsync(Guid projectId, Guid? organizationId, bool includeInactive, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectAllocationAsync(Guid projectId, Guid? organizationId, bool includeInactive, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectAllocationAsync(Guid projectId, Guid? organizationId, Guid? serviceId, bool includeInactive, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<List<ProjectAllocationVM>>> ManageAllocationAsync(List<ProjectAllocationDot> projectAllocationDots, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectsByEmployeeAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<List<ProjectAllocationVM>>> AssigneProjectsToEmployeeAsync(List<ProjectsAllocationDto> projectAllocationDtos, Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||
|
Loading…
x
Reference in New Issue
Block a user