Added IsArchive field in ob ticket table
This commit is contained in:
parent
d5a7ad0716
commit
bd2f9d953f
8909
Marco.Pms.DataAccess/Migrations/20251120051203_Added_IsArchive_In_JobTicket_Table.Designer.cs
generated
Normal file
8909
Marco.Pms.DataAccess/Migrations/20251120051203_Added_IsArchive_In_JobTicket_Table.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Marco.Pms.DataAccess.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Added_IsArchive_In_JobTicket_Table : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsArchive",
|
||||
table: "JobTickets",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsArchive",
|
||||
table: "JobTickets");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5494,6 +5494,9 @@ namespace Marco.Pms.DataAccess.Migrations
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsArchive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<Guid?>("ProjectBranchId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
|
||||
@ -12,5 +12,6 @@ namespace Marco.Pms.Model.Dtos.ServiceProject
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime DueDate { get; set; }
|
||||
public List<TagDto>? Tags { get; set; }
|
||||
public bool IsArchive { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ namespace Marco.Pms.Model.ServiceProject
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime DueDate { get; set; }
|
||||
public bool IsActive { get; set; } = true;
|
||||
public bool IsArchive { get; set; } = false;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public Guid CreatedById { get; set; }
|
||||
|
||||
|
||||
@ -7,5 +7,6 @@
|
||||
public string? Description { get; set; }
|
||||
public string? JobTicketUId { get; set; }
|
||||
public string? StatusName { get; set; }
|
||||
public bool IsArchive { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime DueDate { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public bool IsArchive { get; set; }
|
||||
public Guid? AttendanceId { get; set; }
|
||||
public TAGGING_MARK_TYPE? TaggingAction { get; set; }
|
||||
public TAGGING_MARK_TYPE? NextTaggingAction { get; set; }
|
||||
|
||||
@ -16,6 +16,7 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime DueDate { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public bool IsArchive { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public List<TagVM>? Tags { get; set; }
|
||||
|
||||
@ -187,10 +187,11 @@ namespace Marco.Pms.Services.Controllers
|
||||
#region =================================================================== Job Tickets Functions ===================================================================
|
||||
|
||||
[HttpGet("job/list")]
|
||||
public async Task<IActionResult> GetJobTicketsList([FromQuery] Guid? projectId, [FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20, [FromQuery] bool isActive = true)
|
||||
public async Task<IActionResult> GetJobTicketsList([FromQuery] Guid? projectId, [FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20, [FromQuery] bool isActive = true,
|
||||
[FromQuery] bool isArchive = false)
|
||||
{
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _serviceProject.GetJobTicketsListAsync(projectId, pageNumber, pageSize, isActive, loggedInEmployee, tenantId);
|
||||
var response = await _serviceProject.GetJobTicketsListAsync(projectId, pageNumber, pageSize, isActive, isArchive, loggedInEmployee, tenantId);
|
||||
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Job Tickets Functions ===================================================================
|
||||
Task<ApiResponse<object>> GetJobTicketsListAsync(Guid? projectId, int pageNumber, int pageSize, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> GetJobTicketsListAsync(Guid? projectId, int pageNumber, int pageSize, bool isActive, bool isArchive, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> GetJobTicketDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> GetJobTagListAsync(Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> CreateJobTicketAsync(CreateJobTicketDto model, Employee loggedInEmployee, Guid tenantId);
|
||||
|
||||
@ -1387,7 +1387,7 @@ namespace Marco.Pms.Services.Service
|
||||
/// <param name="tenantId">Tenant context.</param>
|
||||
/// <param name="loggedInEmployee">Employee requesting data.</param>
|
||||
/// <returns>Paged list of JobTicketVM plus metadata, or error response.</returns>
|
||||
public async Task<ApiResponse<object>> GetJobTicketsListAsync(Guid? projectId, int pageNumber, int pageSize, bool isActive, Employee loggedInEmployee, Guid tenantId)
|
||||
public async Task<ApiResponse<object>> GetJobTicketsListAsync(Guid? projectId, int pageNumber, int pageSize, bool isActive, bool isArchive, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
if (tenantId == Guid.Empty)
|
||||
{
|
||||
@ -1418,6 +1418,7 @@ namespace Marco.Pms.Services.Service
|
||||
.Where(jt =>
|
||||
jt.TenantId == tenantId &&
|
||||
jt.IsActive == isActive &&
|
||||
jt.IsArchive == isArchive &&
|
||||
jt.Project != null &&
|
||||
jt.Status != null &&
|
||||
jt.CreatedBy != null &&
|
||||
@ -1540,6 +1541,7 @@ namespace Marco.Pms.Services.Service
|
||||
jt.Id == id &&
|
||||
jt.TenantId == tenantId &&
|
||||
jt.IsActive &&
|
||||
!jt.IsArchive &&
|
||||
jt.Project != null &&
|
||||
jt.Status != null &&
|
||||
jt.CreatedBy != null &&
|
||||
@ -1548,7 +1550,7 @@ namespace Marco.Pms.Services.Service
|
||||
if (jobTicket == null)
|
||||
{
|
||||
_logger.LogWarning("Job ticket not found or inactive. JobTicketId: {JobTicketId}, TenantId: {TenantId}", id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job ticket not found or inactive.", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found. Please check the job details and try again.", "Job ticket not found or inactive.", 404);
|
||||
}
|
||||
|
||||
// Load all job statuses for status mappings in logs
|
||||
@ -1782,6 +1784,8 @@ namespace Marco.Pms.Services.Service
|
||||
jobTicket.StatusId = hasAssignees ? AssignedStatus : NewStatus;
|
||||
jobTicket.UIDPrefix = uIDPrefix;
|
||||
jobTicket.UIDPostfix = uIDPostfix;
|
||||
jobTicket.IsActive = true;
|
||||
jobTicket.IsArchive = false;
|
||||
jobTicket.CreatedAt = DateTime.UtcNow;
|
||||
jobTicket.CreatedById = loggedInEmployee.Id;
|
||||
jobTicket.TenantId = tenantId;
|
||||
@ -1946,12 +1950,12 @@ namespace Marco.Pms.Services.Service
|
||||
var jobTicket = await _context.JobTickets
|
||||
.Include(jt => jt.Project)
|
||||
.Include(jt => jt.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTicketId && jt.TenantId == tenantId);
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTicketId && jt.TenantId == tenantId && jt.IsActive && !jt.IsArchive);
|
||||
|
||||
if (jobTicket == null)
|
||||
{
|
||||
_logger.LogWarning("Job ticket {JobTicketId} not found for status change in tenant {TenantId}", model.JobTicketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job Not Found", "Job ticket not found.", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found. Please check the job details and try again.", "Job ticket not found.", 404);
|
||||
}
|
||||
|
||||
var jobStatusMapping = await GetJobStatusMappingAsync(jobTicket.StatusId, model.StatusId, jobTicket.ProjectId, loggedInEmployee.Id, tenantId);
|
||||
@ -2073,6 +2077,18 @@ namespace Marco.Pms.Services.Service
|
||||
};
|
||||
_context.StatusUpdateLogs.Add(updateLog);
|
||||
}
|
||||
if (jobTicket.IsArchive != model.IsArchive)
|
||||
{
|
||||
// Validate if job ticket status permits archiving
|
||||
if (model.IsArchive && jobTicket.StatusId != DoneStatus && jobTicket.StatusId != ClosedStatus)
|
||||
{
|
||||
_logger.LogWarning("Archiving failed: Job status not eligible. JobTicketId: {JobTicketId}, StatusId: {StatusId}", jobTicket.Id, jobTicket.StatusId);
|
||||
return ApiResponse<object>.ErrorResponse(
|
||||
"Archiving failed: Only jobs with status Done or Closed can be archived.",
|
||||
"Invalid status: Job not eligible for archiving.",
|
||||
400);
|
||||
}
|
||||
}
|
||||
|
||||
// Create BSON snapshot of existing entity for audit logging (MongoDB)
|
||||
BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(jobTicket);
|
||||
@ -2280,18 +2296,18 @@ namespace Marco.Pms.Services.Service
|
||||
.Include(jc => jc.JobTicket).ThenInclude(jt => jt!.Status)
|
||||
.Include(jc => jc.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Include(jc => jc.UpdatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(jc => jc.TenantId == tenantId && jc.JobTicket != null && jc.CreatedBy != null && jc.CreatedBy.JobRole != null);
|
||||
.Where(jc => jc.TenantId == tenantId && jc.JobTicket != null && !jc.JobTicket.IsArchive && jc.CreatedBy != null && jc.CreatedBy.JobRole != null);
|
||||
|
||||
// Filter by jobTicketId if provided after verifying existence
|
||||
if (jobTicketId.HasValue)
|
||||
{
|
||||
var jobTicketExists = await _context.JobTickets.AnyAsync(jt =>
|
||||
jt.Id == jobTicketId && jt.TenantId == tenantId);
|
||||
jt.Id == jobTicketId && jt.TenantId == tenantId && !jt.IsArchive);
|
||||
|
||||
if (!jobTicketExists)
|
||||
{
|
||||
_logger.LogWarning("Job ticket {JobTicketId} not found in tenant {TenantId} for comment listing", jobTicketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job ticket not found.", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found or is archived. Please check the job details and try again.", "Job ticket not found.", 404);
|
||||
}
|
||||
|
||||
commentQuery = commentQuery.Where(jc => jc.JobTicketId == jobTicketId.Value);
|
||||
@ -2398,12 +2414,12 @@ namespace Marco.Pms.Services.Service
|
||||
var jobTicket = await _context.JobTickets
|
||||
.Include(jt => jt.Status)
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTicketId && jt.TenantId == tenantId);
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTicketId && jt.TenantId == tenantId && !jt.IsArchive);
|
||||
|
||||
if (jobTicket == null)
|
||||
{
|
||||
_logger.LogWarning("Job ticket {JobTicketId} not found or inaccessible in tenant {TenantId}", model.JobTicketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job Not Found", "Job ticket not found or inaccessible.", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found or is archived. Please check the job details and try again.", "Job ticket not found or inaccessible.", 404);
|
||||
}
|
||||
|
||||
// Create new comment entity
|
||||
@ -2527,7 +2543,7 @@ namespace Marco.Pms.Services.Service
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.JobTickets
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(jc => jc.Id == model.JobTicketId && jc.TenantId == tenantId && jc.IsActive);
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTicketId && jt.TenantId == tenantId && !jt.IsArchive);
|
||||
});
|
||||
|
||||
await Task.WhenAll(jobCommentTask, jobTicketTask);
|
||||
@ -2537,7 +2553,7 @@ namespace Marco.Pms.Services.Service
|
||||
if (jobTicket == null)
|
||||
{
|
||||
_logger.LogWarning("Job ticket {JobTicketId} not found for updating comment {CommentId}", model.JobTicketId, id);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job not found", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found or is archived. Please check the job details and try again.", "The job could not be found. Please check the job details and try again.", 404);
|
||||
}
|
||||
if (jobComment == null)
|
||||
{
|
||||
@ -2725,12 +2741,12 @@ namespace Marco.Pms.Services.Service
|
||||
var jobTicket = await _context.JobTickets
|
||||
.AsNoTracking()
|
||||
.Include(jt => jt.Status)
|
||||
.FirstOrDefaultAsync(jt => jt.Id == jobTicketId && jt.TenantId == tenantId && jt.IsActive);
|
||||
.FirstOrDefaultAsync(jt => jt.Id == jobTicketId && jt.TenantId == tenantId && !jt.IsArchive);
|
||||
|
||||
if (jobTicket == null)
|
||||
{
|
||||
_logger.LogWarning("JobTicket not found. JobTicketId: {JobTicketId}, TenantId: {TenantId}", jobTicketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job is not found", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found. Please check the job details and try again.", "Job is not found", 404);
|
||||
}
|
||||
|
||||
var jobEmployeeMapping = await _context.JobEmployeeMappings
|
||||
@ -2876,7 +2892,7 @@ namespace Marco.Pms.Services.Service
|
||||
// Validate the existence and active status of the job ticket including its status related data
|
||||
var jobTicket = await _context.JobTickets
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(jt => jt.Id == jobTicketId && jt.TenantId == tenantId && jt.IsActive);
|
||||
.FirstOrDefaultAsync(jt => jt.Id == jobTicketId && jt.TenantId == tenantId && !jt.IsArchive);
|
||||
|
||||
if (jobTicket == null)
|
||||
{
|
||||
@ -2934,11 +2950,11 @@ namespace Marco.Pms.Services.Service
|
||||
var jobTicket = await _context.JobTickets
|
||||
.AsNoTracking()
|
||||
.Include(jt => jt.Status)
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTcketId && jt.TenantId == tenantId && jt.IsActive);
|
||||
.FirstOrDefaultAsync(jt => jt.Id == model.JobTcketId && jt.TenantId == tenantId && !jt.IsArchive);
|
||||
if (jobTicket == null)
|
||||
{
|
||||
_logger.LogWarning("JobTicket not found. JobTicketId: {JobTicketId}, TenantId: {TenantId}", model.JobTcketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job not found", 404);
|
||||
return ApiResponse<object>.ErrorResponse("The job could not be found. Please check the job details and try again.", "The job could not be found. Please check the job details and try again.", 404);
|
||||
}
|
||||
|
||||
// Check if the current user is part of the job team
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user