Added the service project details API and pagination in list of infra projects
This commit is contained in:
parent
bfe9c03147
commit
a32515fc84
@ -209,8 +209,12 @@ namespace Marco.Pms.DataAccess.Data
|
||||
#region ======================================================= Service Project =======================================================
|
||||
public DbSet<ServiceProject> ServiceProjects { get; set; }
|
||||
public DbSet<ServiceProjectServiceMapping> ServiceProjectServiceMapping { get; set; }
|
||||
#region ======================================================= Job =======================================================
|
||||
#endregion
|
||||
|
||||
//#region ======================================================= Job =======================================================
|
||||
//public DbSet<JobTicket> JobTickets { get; set; }
|
||||
//public DbSet<JobStatus> JobStatus { get; set; }
|
||||
|
||||
//#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
@ -1266,6 +1270,26 @@ namespace Marco.Pms.DataAccess.Data
|
||||
}
|
||||
);
|
||||
|
||||
//modelBuilder.Entity<JobStatus>().HasData(
|
||||
// new JobStatus
|
||||
// {
|
||||
// Id = Guid.Parse(""),
|
||||
// Name = "",
|
||||
// DisplayName = ""
|
||||
// },
|
||||
// new JobStatus
|
||||
// {
|
||||
// Id = Guid.Parse(""),
|
||||
// Name = "",
|
||||
// DisplayName = ""
|
||||
// },
|
||||
// new JobStatus
|
||||
// {
|
||||
// Id = Guid.Parse(""),
|
||||
// Name = "",
|
||||
// DisplayName = ""
|
||||
// });
|
||||
|
||||
modelBuilder.Entity<Module>().HasData(
|
||||
new Module
|
||||
{
|
||||
|
||||
9
Marco.Pms.Model/ServiceProject/JobStatus.cs
Normal file
9
Marco.Pms.Model/ServiceProject/JobStatus.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Marco.Pms.Model.ServiceProject
|
||||
{
|
||||
public class JobStatus
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
39
Marco.Pms.Model/ServiceProject/JobTicket.cs
Normal file
39
Marco.Pms.Model/ServiceProject/JobTicket.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Marco.Pms.Model.ServiceProject
|
||||
{
|
||||
public class JobTicket : TenantRelation
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public Guid ProjectId { get; set; }
|
||||
|
||||
[ValidateNever]
|
||||
[ForeignKey("ProjectId")]
|
||||
public ServiceProject? Project { get; set; }
|
||||
public Guid StatusId { get; set; }
|
||||
|
||||
[ValidateNever]
|
||||
[ForeignKey("StatusId")]
|
||||
public JobStatus? Status { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime DueDate { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public Guid CreatedById { get; set; }
|
||||
|
||||
[ValidateNever]
|
||||
[ForeignKey("CreatedById")]
|
||||
public Employee? CreatedBy { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public Guid? UpdatedById { get; set; }
|
||||
|
||||
[ValidateNever]
|
||||
[ForeignKey("UpdatedById")]
|
||||
public Employee? UpdatedBy { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Model.ViewModels.Organization;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.ServiceProject
|
||||
{
|
||||
public class ServiceProjectDetailsVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? ShortName { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public DateTime AssignedDate { get; set; }
|
||||
public StatusMaster? Status { get; set; }
|
||||
public BasicOrganizationVm? Client { get; set; }
|
||||
public List<ServiceMasterVM>? Services { get; set; }
|
||||
public int NumberOfJobs { get; set; }
|
||||
public string? ContactName { get; set; }
|
||||
public string? ContactPhone { get; set; }
|
||||
public string? ContactEmail { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
/// <returns>An ApiResponse containing a list of projects or an error.</returns>
|
||||
|
||||
[HttpGet("list")]
|
||||
public async Task<IActionResult> GetAllProjects()
|
||||
public async Task<IActionResult> GetAllProjects([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20)
|
||||
{
|
||||
// --- Input Validation and Initial Setup ---
|
||||
if (!ModelState.IsValid)
|
||||
@ -70,7 +70,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request data provided.", errors, 400));
|
||||
}
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _projectServices.GetAllProjectsAsync(tenantId, loggedInEmployee);
|
||||
var response = await _projectServices.GetAllProjectsAsync(pageNumber, pageSize, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,19 @@ namespace Marco.Pms.Services.Controllers
|
||||
var response = await _serviceProject.GetServiceProjectListAsync(pageNumber, pageSize, loggedInEmploee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
|
||||
}
|
||||
|
||||
[HttpGet("details/{id}")]
|
||||
public async Task<IActionResult> GetServiceProjectDetails(Guid id)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||
}
|
||||
Employee loggedInEmploee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _serviceProject.GetServiceProjectDetailsAsync(id, loggedInEmploee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -195,6 +195,7 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
|
||||
CreateMap<ServiceProjectDto, ServiceProject>();
|
||||
CreateMap<ServiceProject, ServiceProjectVM>();
|
||||
CreateMap<ServiceProject, ServiceProjectDetailsVM>();
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Employee =======================================================
|
||||
|
||||
@ -97,7 +97,7 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> GetAllProjectsAsync(Guid tenantId, Employee loggedInEmployee)
|
||||
public async Task<ApiResponse<object>> GetAllProjectsAsync(int pageNumber, int pageSize, Guid tenantId, Employee loggedInEmployee)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -144,9 +144,25 @@ namespace Marco.Pms.Services.Service
|
||||
_logger.LogInfo("Cache HIT. All {ProjectCount} projects found in cache.", projectIds.Count);
|
||||
}
|
||||
|
||||
var totalEntites = responseVms.Count;
|
||||
var totalPages = (int)Math.Ceiling((double)totalEntites / pageSize);
|
||||
|
||||
responseVms = responseVms
|
||||
.OrderBy(p => p.Name)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize).ToList();
|
||||
|
||||
// --- Step 4: Return the combined result ---
|
||||
|
||||
var response = new
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
TotalPages = totalPages,
|
||||
TotalEntites = totalEntites,
|
||||
Data = responseVms,
|
||||
};
|
||||
_logger.LogInfo("Successfully retrieved a total of {ProjectCount} projects.", responseVms.Count);
|
||||
return ApiResponse<object>.SuccessResponse(responseVms, "Projects retrieved successfully.", 200);
|
||||
return ApiResponse<object>.SuccessResponse(response, "Projects retrieved successfully.", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
public interface IProjectServices
|
||||
{
|
||||
Task<ApiResponse<object>> GetAllProjectsBasicAsync(bool provideAll, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetAllProjectsAsync(Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetAllProjectsAsync(int pageNumber, int pageSize, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectAsync(Guid id, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectDetailsAsync(Guid id, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectDetailsOldAsync(Guid id, Guid tenantId, Employee loggedInEmployee);
|
||||
|
||||
@ -6,9 +6,9 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
{
|
||||
public interface IServiceProject
|
||||
{
|
||||
|
||||
Task<ApiResponse<object>> CreateServiceProjectAsync(ServiceProjectDto serviceProject, Employee loggedInEmployee, Guid TenantId);
|
||||
Task<ApiResponse<object>> GetServiceProjectListAsync(int pageNumber, int pageSize, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> GetServiceProjectDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> CreateServiceProjectAsync(ServiceProjectDto serviceProject, Employee loggedInEmployee, Guid TenantId);
|
||||
Task<ApiResponse<object>> UpdateServiceProjectAsync(Guid id, ServiceProjectDto serviceProject, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> DeActivateServiceProjectAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||
}
|
||||
|
||||
@ -40,7 +40,90 @@ namespace Marco.Pms.Services.Service
|
||||
_dbContextFactory = dbContextFactory;
|
||||
}
|
||||
|
||||
#region =================================================================== Service Project Functions ===================================================================
|
||||
public async Task<ApiResponse<object>> GetServiceProjectListAsync(int pageNumber, int pageSize, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var serviceProjectQuery = _context.ServiceProjects
|
||||
.Include(sp => sp.Client)
|
||||
.Include(sp => sp.Status)
|
||||
.Include(sp => sp.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(sp => sp.TenantId == tenantId && sp.IsActive);
|
||||
|
||||
var totalEntites = await serviceProjectQuery.CountAsync();
|
||||
var totalPages = (int)Math.Ceiling((double)totalEntites / pageSize);
|
||||
|
||||
var serviceProjects = await serviceProjectQuery
|
||||
.OrderByDescending(e => e.CreatedAt)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
var serviceProjectIds = serviceProjects.Select(sp => sp.Id).ToList();
|
||||
var serviceProjectServiceMappings = await _context.ServiceProjectServiceMapping
|
||||
.Include(sps => sps.Service)
|
||||
.Where(sps => serviceProjectIds.Contains(sps.ProjectId) &&
|
||||
sps.Service != null &&
|
||||
sps.TenantId == tenantId)
|
||||
.ToListAsync();
|
||||
|
||||
var serviceProjectVMs = serviceProjects.Select(sp =>
|
||||
{
|
||||
var services = serviceProjectServiceMappings.Where(sps => sps.ProjectId == sp.Id).Select(sps => sps.Service!).ToList();
|
||||
var result = _mapper.Map<ServiceProjectVM>(sp);
|
||||
result.Services = _mapper.Map<List<ServiceMasterVM>>(services);
|
||||
return result;
|
||||
}).ToList();
|
||||
|
||||
var response = new
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
TotalPages = totalPages,
|
||||
TotalEntites = totalEntites,
|
||||
Data = serviceProjectVMs,
|
||||
};
|
||||
|
||||
_logger.LogInfo("Successfully retrieved a total of {ProjectCount} projects.", serviceProjectVMs.Count);
|
||||
return ApiResponse<object>.SuccessResponse(serviceProjectVMs, "Projects retrieved successfully.", 200);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// --- Step 5: Graceful Error Handling ---
|
||||
_logger.LogError(ex, "An unexpected error occurred in GetAllProjects for tenant {TenantId}.", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
||||
}
|
||||
|
||||
}
|
||||
public async Task<ApiResponse<object>> GetServiceProjectDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
var serviceProject = await _context.ServiceProjects
|
||||
.Include(sp => sp.Client)
|
||||
.Include(sp => sp.Status)
|
||||
.Include(sp => sp.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Include(sp => sp.UpdatedBy).ThenInclude(e => e!.JobRole)
|
||||
.FirstOrDefaultAsync(sp => sp.Id == id && sp.TenantId == tenantId);
|
||||
if (serviceProject == null)
|
||||
{
|
||||
return ApiResponse<object>.ErrorResponse("Service Project not found", "Service Project not found", 404);
|
||||
}
|
||||
var services = await _context.ServiceProjectServiceMapping
|
||||
.Include(sps => sps.Service)
|
||||
.Where(sps => sps.ProjectId == serviceProject.Id &&
|
||||
sps.Service != null &&
|
||||
sps.TenantId == tenantId)
|
||||
.Select(sps => sps.Service!)
|
||||
.ToListAsync();
|
||||
//var numberOfJobs = await _context.JobTickets.Where(jt => jt.ProjectId == serviceProject.Id && jt.TenantId == tenantId).CountAsync();
|
||||
|
||||
var response = _mapper.Map<ServiceProjectDetailsVM>(serviceProject);
|
||||
response.Services = _mapper.Map<List<ServiceMasterVM>>(services);
|
||||
//response.NumberOfJobs = numberOfJobs;
|
||||
response.NumberOfJobs = 0;
|
||||
return ApiResponse<object>.SuccessResponse(response, "Service Project Details fetched successfully", 200);
|
||||
}
|
||||
public async Task<ApiResponse<object>> CreateServiceProjectAsync(ServiceProjectDto model, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
var serviceIds = model.Services.Where(s => s.IsActive).Select(s => s.ServiceId).ToList();
|
||||
@ -116,51 +199,6 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public async Task<ApiResponse<object>> GetServiceProjectListAsync(int pageNumber, int pageSize, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var serviceProjectQuery = _context.ServiceProjects
|
||||
.Include(sp => sp.Client)
|
||||
.Include(sp => sp.Status)
|
||||
.Include(sp => sp.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(sp => sp.TenantId == tenantId && sp.IsActive);
|
||||
|
||||
var serviceProjects = await serviceProjectQuery
|
||||
.OrderByDescending(e => e.CreatedAt)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
var serviceProjectIds = serviceProjects.Select(sp => sp.Id).ToList();
|
||||
var serviceProjectServiceMappings = await _context.ServiceProjectServiceMapping
|
||||
.Include(sps => sps.Service)
|
||||
.Where(sps => serviceProjectIds.Contains(sps.ProjectId) &&
|
||||
sps.Service != null &&
|
||||
sps.TenantId == tenantId)
|
||||
.ToListAsync();
|
||||
|
||||
var serviceProjectVMs = serviceProjects.Select(sp =>
|
||||
{
|
||||
var services = serviceProjectServiceMappings.Where(sps => sps.ProjectId == sp.Id).Select(sps => sps.Service!).ToList();
|
||||
var result = _mapper.Map<ServiceProjectVM>(sp);
|
||||
result.Services = _mapper.Map<List<ServiceMasterVM>>(services);
|
||||
return result;
|
||||
}).ToList();
|
||||
|
||||
_logger.LogInfo("Successfully retrieved a total of {ProjectCount} projects.", serviceProjectVMs.Count);
|
||||
return ApiResponse<object>.SuccessResponse(serviceProjectVMs, "Projects retrieved successfully.", 200);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// --- Step 5: Graceful Error Handling ---
|
||||
_logger.LogError(ex, "An unexpected error occurred in GetAllProjects for tenant {TenantId}.", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
||||
}
|
||||
|
||||
}
|
||||
public async Task<ApiResponse<object>> UpdateServiceProjectAsync(Guid id, ServiceProjectDto model, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
@ -314,5 +352,12 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Expense Functions ===================================================================
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Expense Functions ===================================================================
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,13 +18,6 @@
|
||||
"SenderEmail": "marcoioitsoft@gmail.com",
|
||||
"Password": "qrtq wfuj hwpp fhqr"
|
||||
},
|
||||
//"SmtpSettings": {
|
||||
// "SmtpServer": "mail.marcoaiot.com",
|
||||
// "Port": 587,
|
||||
// "SenderName": "MarcoAIOT",
|
||||
// "SenderEmail": "ashutosh.nehete@marcoaiot.com",
|
||||
// "Password": "Reset@123"
|
||||
//},
|
||||
"AppSettings": {
|
||||
"WebFrontendUrl": "http://localhost:5173",
|
||||
"ImagesBaseUrl": "http://localhost:5173"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user