adde functionality to delete workItems from cache
This commit is contained in:
parent
f4ca7670e3
commit
560d2f2d4d
@ -90,18 +90,18 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
|
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid from Date while featching attendance logs");
|
_logger.LogWarning("User sent Invalid from Date while featching attendance logs");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||||
}
|
}
|
||||||
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
|
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid to Date while featching attendance logs");
|
_logger.LogWarning("User sent Invalid to Date while featching attendance logs");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (employeeId == Guid.Empty)
|
if (employeeId == Guid.Empty)
|
||||||
{
|
{
|
||||||
_logger.LogError("The employee Id sent by user is empty");
|
_logger.LogWarning("The employee Id sent by user is empty");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Employee ID is required and must not be Empty.", "Employee ID is required and must not be empty.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Employee ID is required and must not be Empty.", "Employee ID is required and must not be empty.", 400));
|
||||||
}
|
}
|
||||||
List<Attendance> attendances = await _context.Attendes.Where(c => c.EmployeeID == employeeId && c.TenantId == TenantId && c.AttendanceDate.Date >= fromDate && c.AttendanceDate.Date <= toDate).ToListAsync();
|
List<Attendance> attendances = await _context.Attendes.Where(c => c.EmployeeID == employeeId && c.TenantId == TenantId && c.AttendanceDate.Date >= fromDate && c.AttendanceDate.Date <= toDate).ToListAsync();
|
||||||
@ -161,18 +161,18 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
|
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid fromDate while featching attendance logs");
|
_logger.LogWarning("User sent Invalid fromDate while featching attendance logs");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||||
}
|
}
|
||||||
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
|
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid toDate while featching attendance logs");
|
_logger.LogWarning("User sent Invalid toDate while featching attendance logs");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectId == Guid.Empty)
|
if (projectId == Guid.Empty)
|
||||||
{
|
{
|
||||||
_logger.LogError("The project Id sent by user is less than or equal to zero");
|
_logger.LogWarning("The project Id sent by user is less than or equal to zero");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,13 +276,13 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (date != null && DateTime.TryParse(date, out forDate) == false)
|
if (date != null && DateTime.TryParse(date, out forDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid Date while featching attendance logs");
|
_logger.LogWarning("User sent Invalid Date while featching attendance logs");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||||
|
|
||||||
}
|
}
|
||||||
if (projectId == Guid.Empty)
|
if (projectId == Guid.Empty)
|
||||||
{
|
{
|
||||||
_logger.LogError("The project Id sent by user is less than or equal to zero");
|
_logger.LogWarning("The project Id sent by user is less than or equal to zero");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +425,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("User sent Invalid Date while marking attendance");
|
_logger.LogWarning("User sent Invalid Date while marking attendance \n {Error}", string.Join(",", errors));
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,14 +439,14 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (recordAttendanceDot.MarkTime == null)
|
if (recordAttendanceDot.MarkTime == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid Mark Time while marking attendance");
|
_logger.LogWarning("User sent Invalid Mark Time while marking attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime);
|
DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime);
|
||||||
if (recordAttendanceDot.Comment == null)
|
if (recordAttendanceDot.Comment == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("User sent Invalid comment while marking attendance");
|
_logger.LogWarning("User sent Invalid comment while marking attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +480,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} sent regularization request but it check-out time is earlier than check-out");
|
_logger.LogWarning("Employee {EmployeeId} sent regularization request but it check-out time is earlier than check-out");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Check-out time must be later than check-in time", "Check-out time must be later than check-in time", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Check-out time must be later than check-in time", "Check-out time must be later than check-in time", 400));
|
||||||
}
|
}
|
||||||
// do nothing
|
// do nothing
|
||||||
@ -585,7 +585,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await transaction.RollbackAsync(); // Rollback on failure
|
await transaction.RollbackAsync(); // Rollback on failure
|
||||||
_logger.LogError("{Error} while marking attendance", ex.Message);
|
_logger.LogError(ex, "An Error occured while marking attendance");
|
||||||
var response = new
|
var response = new
|
||||||
{
|
{
|
||||||
message = ex.Message,
|
message = ex.Message,
|
||||||
@ -604,7 +604,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||||
_logger.LogError("Invalid attendance model received.");
|
_logger.LogWarning("Invalid attendance model received. \n {Error}", string.Join(",", errors));
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +780,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await transaction.RollbackAsync();
|
await transaction.RollbackAsync();
|
||||||
_logger.LogError("Error while recording attendance : {Error}", ex.Message);
|
_logger.LogError(ex, "Error while recording attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Something went wrong", ex.Message, 500));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Something went wrong", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
using System.Net;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using Marco.Pms.DataAccess.Data;
|
|
||||||
using Marco.Pms.Model.Authentication;
|
using Marco.Pms.Model.Authentication;
|
||||||
using Marco.Pms.Model.Dtos.Authentication;
|
using Marco.Pms.Model.Dtos.Authentication;
|
||||||
using Marco.Pms.Model.Dtos.Util;
|
using Marco.Pms.Model.Dtos.Util;
|
||||||
@ -15,6 +11,10 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MarcoBMS.Services.Controllers
|
namespace MarcoBMS.Services.Controllers
|
||||||
{
|
{
|
||||||
@ -110,7 +110,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unexpected error during login : {Error}", ex.Message);
|
_logger.LogError(ex, "Unexpected error during login");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unexpected error occurred while verifying MPIN : {Error}", ex.Message);
|
_logger.LogError(ex, "Unexpected error occurred while verifying MPIN");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unexpected error during logout : {Error}", ex.Message);
|
_logger.LogError(ex, "Unexpected error during logout");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error occurred", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error occurred", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +351,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(user.UserName))
|
if (string.IsNullOrWhiteSpace(user.UserName))
|
||||||
{
|
{
|
||||||
_logger.LogError("Username missing for user ID: {UserId}", user.Id);
|
_logger.LogWarning("Username missing for user ID: {UserId}", user.Id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Username not found.", "Username not found.", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Username not found.", "Username not found.", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +370,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("An unexpected error occurred during token refresh. : {Error}", ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred during token refresh.");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error occurred.", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error occurred.", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error while sending password reset email to: {Error}", ex.Message);
|
_logger.LogError(ex, "Error while sending password reset email to");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Error sending password reset email.", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Error sending password reset email.", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error while sending reset password success email to user: {Error}", ex.Message);
|
_logger.LogError(ex, "Error while sending reset password success email to user");
|
||||||
// Continue, do not fail because of email issue
|
// Continue, do not fail because of email issue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +547,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("An unexpected error occurred while sending OTP to {Email} : {Error}", generateOTP.Email ?? "", ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred while sending OTP to {Email}", generateOTP.Email ?? "");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("An unexpected error occurred.", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("An unexpected error occurred.", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,7 +638,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("An unexpected error occurred during OTP login for email {Email} : {Error}", verifyOTP.Email ?? string.Empty, ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred during OTP login for email {Email}", verifyOTP.Email ?? string.Empty);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error", ex.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Unexpected error", ex.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -719,7 +719,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
var errors = result.Errors.Select(e => e.Description).ToList();
|
var errors = result.Errors.Select(e => e.Description).ToList();
|
||||||
_logger.LogError("Password reset failed for user {Email}. Errors: {Errors}", changePassword.Email, string.Join("; ", errors));
|
_logger.LogWarning("Password reset failed for user {Email}. Errors: {Errors}", changePassword.Email, string.Join("; ", errors));
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Failed to change password", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Failed to change password", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,7 +732,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception exp)
|
catch (Exception exp)
|
||||||
{
|
{
|
||||||
_logger.LogError("An unexpected error occurred while changing password : {Error}", exp.Message);
|
_logger.LogError(exp, "An unexpected error occurred while changing password");
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("An unexpected error occurred.", exp.Message, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("An unexpected error occurred.", exp.Message, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -752,7 +752,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
// Validate employee and MPIN input
|
// Validate employee and MPIN input
|
||||||
if (requestEmployee == null || string.IsNullOrWhiteSpace(generateMPINDto.MPIN) || generateMPINDto.MPIN.Length != 6 || !generateMPINDto.MPIN.All(char.IsDigit))
|
if (requestEmployee == null || string.IsNullOrWhiteSpace(generateMPINDto.MPIN) || generateMPINDto.MPIN.Length != 6 || !generateMPINDto.MPIN.All(char.IsDigit))
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} provided invalid information to generate MPIN", loggedInEmployee.Id);
|
_logger.LogWarning("Employee {EmployeeId} provided invalid information to generate MPIN", loggedInEmployee.Id);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Provided invalid information", "Provided invalid information", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Provided invalid information", "Provided invalid information", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Number of pending regularization and pending check-out are fetched successfully for employee {EmployeeId}", LoggedInEmployee.Id);
|
_logger.LogInfo("Number of pending regularization and pending check-out are fetched successfully for employee {EmployeeId}", LoggedInEmployee.Id);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending regularization and pending check-out are fetched successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending regularization and pending check-out are fetched successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("No attendance entry was found for employee {EmployeeId}", LoggedInEmployee.Id);
|
_logger.LogWarning("No attendance entry was found for employee {EmployeeId}", LoggedInEmployee.Id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("No attendance entry was found for this employee", "No attendance entry was found for this employee", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("No attendance entry was found for this employee", "No attendance entry was found for this employee", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,14 +378,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
List<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
|
List<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
|
||||||
if (date != null && DateTime.TryParse(date, out currentDate) == false)
|
if (date != null && DateTime.TryParse(date, out currentDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError($"user send invalid date");
|
_logger.LogWarning($"user send invalid date");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
|
||||||
|
|
||||||
}
|
}
|
||||||
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
|
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
|
||||||
if (project == null)
|
if (project == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} was attempted to get project attendance for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
|
_logger.LogWarning("Employee {EmployeeId} was attempted to get project attendance for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
||||||
}
|
}
|
||||||
List<ProjectAllocation>? projectAllocation = await _context.ProjectAllocations.Where(p => p.ProjectId == projectId && p.IsActive && p.TenantId == tenantId).ToListAsync();
|
List<ProjectAllocation>? projectAllocation = await _context.ProjectAllocations.Where(p => p.ProjectId == projectId && p.IsActive && p.TenantId == tenantId).ToListAsync();
|
||||||
@ -431,14 +431,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
DateTime currentDate = DateTime.UtcNow;
|
DateTime currentDate = DateTime.UtcNow;
|
||||||
if (date != null && DateTime.TryParse(date, out currentDate) == false)
|
if (date != null && DateTime.TryParse(date, out currentDate) == false)
|
||||||
{
|
{
|
||||||
_logger.LogError($"user send invalid date");
|
_logger.LogWarning($"user send invalid date");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
|
||||||
|
|
||||||
}
|
}
|
||||||
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
|
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
|
||||||
if (project == null)
|
if (project == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} was attempted to get activities performed for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
|
_logger.LogWarning("Employee {EmployeeId} was attempted to get activities performed for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("User sent Invalid Date while marking attendance");
|
_logger.LogWarning("User sent Invalid Date while marking attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
var response = await _directoryHelper.CreateContact(createContact);
|
var response = await _directoryHelper.CreateContact(createContact);
|
||||||
@ -256,7 +256,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("User sent Invalid Date while marking attendance");
|
_logger.LogWarning("User sent Invalid Date while marking attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
var response = await _directoryHelper.CreateBucket(bucketDto);
|
var response = await _directoryHelper.CreateBucket(bucketDto);
|
||||||
|
@ -382,7 +382,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
Employee? existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id.Value);
|
Employee? existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id.Value);
|
||||||
if (existingEmployee == null)
|
if (existingEmployee == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("User tries to update employee {EmployeeId} but not found in database", model.Id);
|
_logger.LogWarning("User tries to update employee {EmployeeId} but not found in database", model.Id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found", 404));
|
||||||
}
|
}
|
||||||
byte[]? imageBytes = null;
|
byte[]? imageBytes = null;
|
||||||
@ -495,7 +495,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee with ID {EmploueeId} not found in database", id);
|
_logger.LogWarning("Employee with ID {EmploueeId} not found in database", id);
|
||||||
}
|
}
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Employee Suspended successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Employee Suspended successfully", 200));
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("{error}", errors);
|
_logger.LogWarning("{error}", errors);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
Guid tenantId = _userHelper.GetTenantId();
|
||||||
@ -66,7 +66,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var Image = attachmentDto;
|
var Image = attachmentDto;
|
||||||
if (string.IsNullOrEmpty(Image.Base64Data))
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
{
|
{
|
||||||
_logger.LogError("Base64 data is missing");
|
_logger.LogWarning("Base64 data is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("{error}", errors);
|
_logger.LogWarning("{error}", errors);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
Guid tenantId = _userHelper.GetTenantId();
|
||||||
@ -197,7 +197,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var Image = attachmentDto;
|
var Image = attachmentDto;
|
||||||
if (string.IsNullOrEmpty(Image.Base64Data))
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
{
|
{
|
||||||
_logger.LogError("Base64 data is missing");
|
_logger.LogWarning("Base64 data is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Ticket {TicketId} updated", updateTicketDto.Id);
|
_logger.LogInfo("Ticket {TicketId} updated", updateTicketDto.Id);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Updated Successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Updated Successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Ticket {TicketId} not Found in database", updateTicketDto.Id);
|
_logger.LogWarning("Ticket {TicketId} not Found in database", updateTicketDto.Id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +349,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("{error}", errors);
|
_logger.LogWarning("{error}", errors);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
if (ticket == null)
|
if (ticket == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Ticket {TicketId} not Found in database", addCommentDto.TicketId);
|
_logger.LogWarning("Ticket {TicketId} not Found in database", addCommentDto.TicketId);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var Image = attachmentDto;
|
var Image = attachmentDto;
|
||||||
if (string.IsNullOrEmpty(Image.Base64Data))
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
{
|
{
|
||||||
_logger.LogError("Base64 data is missing");
|
_logger.LogWarning("Base64 data is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("{error}", errors);
|
_logger.LogWarning("{error}", errors);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +451,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
if (ticket == null)
|
if (ticket == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Ticket {TicketId} not Found in database", updateCommentDto.TicketId);
|
_logger.LogWarning("Ticket {TicketId} not Found in database", updateCommentDto.TicketId);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +474,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var Image = attachmentDto;
|
var Image = attachmentDto;
|
||||||
if (string.IsNullOrEmpty(Image.Base64Data))
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
{
|
{
|
||||||
_logger.LogError("Base64 data is missing");
|
_logger.LogWarning("Base64 data is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("{error}", errors);
|
_logger.LogWarning("{error}", errors);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
if (tickets == null || tickets.Count > 0)
|
if (tickets == null || tickets.Count > 0)
|
||||||
{
|
{
|
||||||
_logger.LogError("Tickets not Found in database");
|
_logger.LogWarning("Tickets not Found in database");
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,12 +578,12 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(forumAttachmentDto.Base64Data))
|
if (string.IsNullOrEmpty(forumAttachmentDto.Base64Data))
|
||||||
{
|
{
|
||||||
_logger.LogError("Base64 data is missing");
|
_logger.LogWarning("Base64 data is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
if (forumAttachmentDto.TicketId == null)
|
if (forumAttachmentDto.TicketId == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("ticket ID is missing");
|
_logger.LogWarning("ticket ID is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("ticket ID is missing", "ticket ID is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("ticket ID is missing", "ticket ID is missing", 400));
|
||||||
}
|
}
|
||||||
var ticket = tickets.FirstOrDefault(t => t.Id == forumAttachmentDto.TicketId);
|
var ticket = tickets.FirstOrDefault(t => t.Id == forumAttachmentDto.TicketId);
|
||||||
|
@ -168,7 +168,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("activity updated successfully from tenant {tenantId}", tenantId);
|
_logger.LogInfo("activity updated successfully from tenant {tenantId}", tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity updated successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity updated successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Activity {ActivityId} not found", id);
|
_logger.LogWarning("Activity {ActivityId} not found", id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Ticket Status master {TicketStatusId} added successfully from tenant {tenantId}", statusMaster.Id, tenantId);
|
_logger.LogInfo("Ticket Status master {TicketStatusId} added successfully from tenant {tenantId}", statusMaster.Id, tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(statusVM, "Ticket Status master added successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(statusVM, "Ticket Status master added successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Sent Empty payload", "Sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Sent Empty payload", "Sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,10 +251,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Ticket Status master {TicketStatusId} updated successfully from tenant {tenantId}", statusMaster.Id, tenantId);
|
_logger.LogInfo("Ticket Status master {TicketStatusId} updated successfully from tenant {tenantId}", statusMaster.Id, tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(statusVM, "Ticket Status master updated successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(statusVM, "Ticket Status master updated successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Ticket Status master {TicketStatusId} not found in database", statusMasterDto.Id != null ? statusMasterDto.Id.Value : Guid.Empty);
|
_logger.LogWarning("Ticket Status master {TicketStatusId} not found in database", statusMasterDto.Id != null ? statusMasterDto.Id.Value : Guid.Empty);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Status master not found", "Ticket Status master not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Status master not found", "Ticket Status master not found", 404));
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Sent Empty payload", "Sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Sent Empty payload", "Sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Ticket Status {TickeStatusId} not found in database", id);
|
_logger.LogWarning("Ticket Status {TickeStatusId} not found in database", id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Status not found", "Ticket Status not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Status not found", "Ticket Status not found", 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket type master added successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket type master added successfully", 200));
|
||||||
|
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,10 +339,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Ticket Type master {TicketTypeId} updated successfully from tenant {tenantId}", typeMaster.Id, tenantId);
|
_logger.LogInfo("Ticket Type master {TicketTypeId} updated successfully from tenant {tenantId}", typeMaster.Id, tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket type master updated successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket type master updated successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Ticket type master {TicketTypeId} not found in database", typeMasterDto.Id != null ? typeMasterDto.Id.Value : Guid.Empty);
|
_logger.LogWarning("Ticket type master {TicketTypeId} not found in database", typeMasterDto.Id != null ? typeMasterDto.Id.Value : Guid.Empty);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket type master not found", "Ticket type master not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket type master not found", "Ticket type master not found", 404));
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,7 +369,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Ticket Type {TickeTypeId} not found in database", id);
|
_logger.LogWarning("Ticket Type {TickeTypeId} not found in database", id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Type not found", "Ticket Type not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Type not found", "Ticket Type not found", 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,7 +407,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket Priority master added successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket Priority master added successfully", 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
[HttpPost("ticket-priorities/edit/{id}")]
|
[HttpPost("ticket-priorities/edit/{id}")]
|
||||||
@ -427,10 +427,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Ticket Priority master {TicketPriorityId} updated successfully from tenant {tenantId}", typeMaster.Id, tenantId);
|
_logger.LogInfo("Ticket Priority master {TicketPriorityId} updated successfully from tenant {tenantId}", typeMaster.Id, tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket Priority master updated successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket Priority master updated successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Ticket Priority master {TicketPriorityId} not found in database", priorityMasterDto.Id != null ? priorityMasterDto.Id.Value : Guid.Empty);
|
_logger.LogWarning("Ticket Priority master {TicketPriorityId} not found in database", priorityMasterDto.Id != null ? priorityMasterDto.Id.Value : Guid.Empty);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Priority master not found", "Ticket Priority master not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Priority master not found", "Ticket Priority master not found", 404));
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +457,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Ticket Priority {TickePriorityId} not found in database", id);
|
_logger.LogWarning("Ticket Priority {TickePriorityId} not found in database", id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Priority not found", "Ticket Priority not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket Priority not found", "Ticket Priority not found", 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,7 +494,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket tag master added successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket tag master added successfully", 200));
|
||||||
|
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,10 +515,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Ticket Tag master {TicketTypeId} updated successfully from tenant {tenantId}", tagMaster.Id, tenantId);
|
_logger.LogInfo("Ticket Tag master {TicketTypeId} updated successfully from tenant {tenantId}", tagMaster.Id, tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket tag master updated successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(typeVM, "Ticket tag master updated successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Ticket tag master {TicketTypeId} not found in database", tagMasterDto.Id != null ? tagMasterDto.Id.Value : Guid.Empty);
|
_logger.LogWarning("Ticket tag master {TicketTypeId} not found in database", tagMasterDto.Id != null ? tagMasterDto.Id.Value : Guid.Empty);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket tag master not found", "Ticket tag master not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket tag master not found", "Ticket tag master not found", 404));
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,7 +545,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Ticket Tag {TickeTagId} not found in database", id);
|
_logger.LogWarning("Ticket Tag {TickeTagId} not found in database", id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Ticket tag not found", "Ticket tag not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket tag not found", "Ticket tag not found", 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -609,7 +609,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(workCategoryMasterVM, "Work category master added successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(workCategoryMasterVM, "Work category master added successfully", 200));
|
||||||
|
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,7 +624,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
if (workCategory.IsSystem)
|
if (workCategory.IsSystem)
|
||||||
{
|
{
|
||||||
_logger.LogError("User tries to update system-defined work category");
|
_logger.LogWarning("User tries to update system-defined work category");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Cannot update system-defined work", "Cannot update system-defined work", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Cannot update system-defined work", "Cannot update system-defined work", 400));
|
||||||
}
|
}
|
||||||
workCategory = workCategoryMasterDto.ToWorkCategoryMasterFromWorkCategoryMasterDto(tenantId);
|
workCategory = workCategoryMasterDto.ToWorkCategoryMasterFromWorkCategoryMasterDto(tenantId);
|
||||||
@ -635,10 +635,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Work category master {WorkCategoryId} updated successfully from tenant {tenantId}", workCategory.Id, tenantId);
|
_logger.LogInfo("Work category master {WorkCategoryId} updated successfully from tenant {tenantId}", workCategory.Id, tenantId);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(workCategoryMasterVM, "Work category master updated successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(workCategoryMasterVM, "Work category master updated successfully", 200));
|
||||||
}
|
}
|
||||||
_logger.LogError("Work category master {WorkCategoryId} not found in database", workCategoryMasterDto.Id ?? Guid.Empty);
|
_logger.LogWarning("Work category master {WorkCategoryId} not found in database", workCategoryMasterDto.Id ?? Guid.Empty);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Work category master not found", "Work category master not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Work category master not found", "Work category master not found", 404));
|
||||||
}
|
}
|
||||||
_logger.LogError("User sent empyt payload");
|
_logger.LogWarning("User sent empyt payload");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("User sent Empty payload", "User sent Empty payload", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +666,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Work category {WorkCategoryId} not found in database", id);
|
_logger.LogWarning("Work category {WorkCategoryId} not found in database", id);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Work category not found", "Work category not found", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Work category not found", "Work category not found", 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -689,7 +689,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("User sent Invalid Date while marking attendance");
|
_logger.LogWarning("User sent Invalid Date while marking attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
var response = await _masterHelper.CreateWorkStatus(createWorkStatusDto);
|
var response = await _masterHelper.CreateWorkStatus(createWorkStatusDto);
|
||||||
@ -803,7 +803,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
.SelectMany(v => v.Errors)
|
.SelectMany(v => v.Errors)
|
||||||
.Select(e => e.ErrorMessage)
|
.Select(e => e.ErrorMessage)
|
||||||
.ToList();
|
.ToList();
|
||||||
_logger.LogError("User sent Invalid Date while marking attendance");
|
_logger.LogWarning("User sent Invalid Date while marking attendance");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
var response = await _masterHelper.CreateContactTag(contactTagDto);
|
var response = await _masterHelper.CreateContactTag(contactTagDto);
|
||||||
|
@ -6,19 +6,18 @@ using Marco.Pms.Model.Mapper;
|
|||||||
using Marco.Pms.Model.MongoDBModels;
|
using Marco.Pms.Model.MongoDBModels;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Marco.Pms.Model.ViewModels.Employee;
|
|
||||||
using Marco.Pms.Model.ViewModels.Projects;
|
using Marco.Pms.Model.ViewModels.Projects;
|
||||||
using Marco.Pms.Services.Helpers;
|
using Marco.Pms.Services.Helpers;
|
||||||
using Marco.Pms.Services.Hubs;
|
|
||||||
using Marco.Pms.Services.Service;
|
using Marco.Pms.Services.Service;
|
||||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||||
using MarcoBMS.Services.Helpers;
|
using MarcoBMS.Services.Helpers;
|
||||||
using MarcoBMS.Services.Service;
|
using MarcoBMS.Services.Service;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
using Project = Marco.Pms.Model.Projects.Project;
|
||||||
|
|
||||||
namespace MarcoBMS.Services.Controllers
|
namespace MarcoBMS.Services.Controllers
|
||||||
{
|
{
|
||||||
@ -31,14 +30,20 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
private readonly UserHelper _userHelper;
|
private readonly UserHelper _userHelper;
|
||||||
private readonly ILoggingService _logger;
|
private readonly ILoggingService _logger;
|
||||||
private readonly IHubContext<MarcoHub> _signalR;
|
private readonly ISignalRService _signalR;
|
||||||
private readonly PermissionServices _permission;
|
private readonly PermissionServices _permission;
|
||||||
private readonly CacheUpdateHelper _cache;
|
private readonly CacheUpdateHelper _cache;
|
||||||
private readonly Guid tenantId;
|
private readonly Guid tenantId;
|
||||||
|
|
||||||
|
|
||||||
public ProjectController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger,
|
public ProjectController(
|
||||||
IHubContext<MarcoHub> signalR, CacheUpdateHelper cache, PermissionServices permission, IProjectServices projectServices)
|
ApplicationDbContext context,
|
||||||
|
UserHelper userHelper,
|
||||||
|
ILoggingService logger,
|
||||||
|
ISignalRService signalR,
|
||||||
|
CacheUpdateHelper cache,
|
||||||
|
PermissionServices permission,
|
||||||
|
IProjectServices projectServices)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_userHelper = userHelper;
|
_userHelper = userHelper;
|
||||||
@ -174,7 +179,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (response.Success)
|
if (response.Success)
|
||||||
{
|
{
|
||||||
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Create_Project", Response = response.Data };
|
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Create_Project", Response = response.Data };
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
}
|
}
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
@ -204,7 +209,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (response.Success)
|
if (response.Success)
|
||||||
{
|
{
|
||||||
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Update_Project", Response = response.Data };
|
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Update_Project", Response = response.Data };
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
}
|
}
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
@ -213,90 +218,38 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
#region =================================================================== Project Allocation APIs ===================================================================
|
#region =================================================================== Project Allocation APIs ===================================================================
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet("employees/get/{projectid?}/{includeInactive?}")]
|
||||||
[Route("employees/get/{projectid?}/{includeInactive?}")]
|
public async Task<IActionResult> GetEmployeeByProjectId(Guid? projectId, bool includeInactive = false)
|
||||||
public async Task<IActionResult> GetEmployeeByProjectID(Guid? projectid, bool includeInactive = false)
|
|
||||||
{
|
{
|
||||||
|
// --- Step 1: Input Validation ---
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var errors = ModelState.Values
|
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||||
.SelectMany(v => v.Errors)
|
_logger.LogWarning("Get employee list by ProjectId called with invalid model state \n Errors: {Errors}", string.Join(", ", errors));
|
||||||
.Select(e => e.ErrorMessage)
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request data provided.", errors, 400));
|
||||||
.ToList();
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectid != null)
|
// --- Step 2: Prepare data without I/O ---
|
||||||
{
|
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
// Fetch assigned project
|
var response = await _projectServices.GetEmployeeByProjectIdAsync(projectId, includeInactive, tenantId, loggedInEmployee);
|
||||||
List<Employee> result = new List<Employee>();
|
return StatusCode(response.StatusCode, response);
|
||||||
|
|
||||||
if ((bool)includeInactive)
|
|
||||||
{
|
|
||||||
|
|
||||||
result = await (from rpm in _context.Employees.Include(c => c.JobRole)
|
|
||||||
join fp in _context.ProjectAllocations.Where(c => c.TenantId == tenantId && c.ProjectId == projectid)
|
|
||||||
on rpm.Id equals fp.EmployeeId
|
|
||||||
select rpm).ToListAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = await (from rpm in _context.Employees.Include(c => c.JobRole)
|
|
||||||
join fp in _context.ProjectAllocations.Where(c => c.TenantId == tenantId && c.ProjectId == projectid && c.IsActive)
|
|
||||||
on rpm.Id equals fp.EmployeeId
|
|
||||||
select rpm).ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<EmployeeVM> resultVM = new List<EmployeeVM>();
|
|
||||||
foreach (Employee employee in result)
|
|
||||||
{
|
|
||||||
EmployeeVM vm = employee.ToEmployeeVMFromEmployee();
|
|
||||||
resultVM.Add(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(resultVM, "Success.", 200));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Invalid Input Parameter", 404));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet("allocation/{projectId}")]
|
||||||
[Route("allocation/{projectId}")]
|
|
||||||
public async Task<IActionResult> GetProjectAllocation(Guid? projectId)
|
public async Task<IActionResult> GetProjectAllocation(Guid? projectId)
|
||||||
{
|
{
|
||||||
|
// --- Step 1: Input Validation ---
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var errors = ModelState.Values
|
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||||
.SelectMany(v => v.Errors)
|
_logger.LogWarning("Get employee list by ProjectId called with invalid model state \n Errors: {Errors}", string.Join(", ", errors));
|
||||||
.Select(e => e.ErrorMessage)
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request data provided.", errors, 400));
|
||||||
.ToList();
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var employees = await _context.ProjectAllocations
|
// --- Step 2: Prepare data without I/O ---
|
||||||
.Where(c => c.TenantId == tenantId && c.ProjectId == projectId && c.Employee != null)
|
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
.Include(e => e.Employee)
|
var response = await _projectServices.GetProjectAllocationAsync(projectId, tenantId, loggedInEmployee);
|
||||||
.Select(e => new
|
return StatusCode(response.StatusCode, response);
|
||||||
{
|
|
||||||
ID = e.Id,
|
|
||||||
EmployeeId = e.EmployeeId,
|
|
||||||
ProjectId = e.ProjectId,
|
|
||||||
AllocationDate = e.AllocationDate,
|
|
||||||
ReAllocationDate = e.ReAllocationDate,
|
|
||||||
FirstName = e.Employee != null ? e.Employee.FirstName : string.Empty,
|
|
||||||
LastName = e.Employee != null ? e.Employee.LastName : string.Empty,
|
|
||||||
MiddleName = e.Employee != null ? e.Employee.MiddleName : string.Empty,
|
|
||||||
IsActive = e.IsActive,
|
|
||||||
JobRoleId = (e.JobRoleId != null ? e.JobRoleId : e.Employee != null ? e.Employee.JobRoleId : null)
|
|
||||||
}).ToListAsync();
|
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(employees, "Success.", 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("allocation")]
|
[HttpPost("allocation")]
|
||||||
@ -375,7 +328,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Assign_Project", ProjectIds = projectIds, EmployeeList = employeeIds };
|
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Assign_Project", ProjectIds = projectIds, EmployeeList = employeeIds };
|
||||||
|
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Data saved successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, "Data saved successfully", 200));
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -494,7 +447,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
await _cache.ClearAllProjectIds(employeeId);
|
await _cache.ClearAllProjectIds(employeeId);
|
||||||
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Assign_Project", ProjectIds = projectIds, EmployeeId = employeeId };
|
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Assign_Project", ProjectIds = projectIds, EmployeeId = employeeId };
|
||||||
|
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Data saved successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, "Data saved successfully", 200));
|
||||||
}
|
}
|
||||||
@ -799,7 +752,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "WorkItem", WorkAreaIds = workAreaIds, Message = message };
|
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "WorkItem", WorkAreaIds = workAreaIds, Message = message };
|
||||||
|
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(responseList, responseMessage, 200));
|
return Ok(ApiResponse<object>.SuccessResponse(responseList, responseMessage, 200));
|
||||||
}
|
}
|
||||||
@ -826,9 +779,15 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
|
|
||||||
workAreaIds.Add(task.WorkAreaId);
|
workAreaIds.Add(task.WorkAreaId);
|
||||||
|
var projectId = floor?.Building?.ProjectId;
|
||||||
|
|
||||||
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "WorkItem", WorkAreaIds = workAreaIds, Message = $"Task Deleted in Building: {floor?.Building?.Name}, on Floor: {floor?.FloorName}, in Area: {task.WorkArea?.AreaName} by {LoggedInEmployee.FirstName} {LoggedInEmployee.LastName}" };
|
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "WorkItem", WorkAreaIds = workAreaIds, Message = $"Task Deleted in Building: {floor?.Building?.Name}, on Floor: {floor?.FloorName}, in Area: {task.WorkArea?.AreaName} by {LoggedInEmployee.FirstName} {LoggedInEmployee.LastName}" };
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
|
await _cache.DeleteWorkItemByIdAsync(task.Id);
|
||||||
|
if (projectId != null)
|
||||||
|
{
|
||||||
|
await _cache.DeleteProjectByIdAsync(projectId.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -847,7 +806,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Task with ID {WorkItemId} not found ID database", id);
|
_logger.LogWarning("Task with ID {WorkItemId} not found ID database", id);
|
||||||
}
|
}
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Task deleted successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Task deleted successfully", 200));
|
||||||
}
|
}
|
||||||
@ -973,7 +932,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
message = $"{message} by {LoggedInEmployee.FirstName} {LoggedInEmployee.LastName}";
|
message = $"{message} by {LoggedInEmployee.FirstName} {LoggedInEmployee.LastName}";
|
||||||
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Infra", ProjectIds = projectIds, Message = message };
|
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Infra", ProjectIds = projectIds, Message = message };
|
||||||
|
|
||||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
await _signalR.SendNotificationAsync(notification);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(responseData, responseMessage, 200));
|
return Ok(ApiResponse<object>.SuccessResponse(responseData, responseMessage, 200));
|
||||||
}
|
}
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid details.", "Infra Details are not valid.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid details.", "Infra Details are not valid.", 400));
|
||||||
|
@ -106,7 +106,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Database Error: Failed to check existence of MailListId '{MailListId}' for TenantId: {TenantId}. : {Error}", mailDetailsDto.MailListId, tenantId, ex.Message);
|
_logger.LogError(ex, "Database Error: Failed to check existence of MailListId '{MailListId}' for TenantId: {TenantId}.", mailDetailsDto.MailListId, tenantId);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while validating mail template.", 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while validating mail template.", 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,13 +143,13 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (DbUpdateException dbEx)
|
catch (DbUpdateException dbEx)
|
||||||
{
|
{
|
||||||
_logger.LogError("Database Error: Failed to save new mail details for ProjectId: {ProjectId}, Recipient: '{Recipient}', TenantId: {TenantId}. : {Error}", newMailDetails.ProjectId, newMailDetails.Recipient, tenantId, dbEx.Message);
|
_logger.LogError(dbEx, "Database Error: Failed to save new mail details for ProjectId: {ProjectId}, Recipient: '{Recipient}', TenantId: {TenantId}.", newMailDetails.ProjectId, newMailDetails.Recipient, tenantId);
|
||||||
// Check for specific constraint violations if applicable (e.g., duplicate recipient for a project)
|
// Check for specific constraint violations if applicable (e.g., duplicate recipient for a project)
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while saving the mail details.", 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while saving the mail details.", 500));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unexpected Error: An unhandled exception occurred while adding mail details for ProjectId: {ProjectId}, Recipient: '{Recipient}', TenantId: {TenantId}. : {Error}", newMailDetails.ProjectId, newMailDetails.Recipient, tenantId, ex.Message);
|
_logger.LogError(ex, "Unexpected Error: An unhandled exception occurred while adding mail details for ProjectId: {ProjectId}, Recipient: '{Recipient}', TenantId: {TenantId}.", newMailDetails.ProjectId, newMailDetails.Recipient, tenantId);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An unexpected error occurred.", 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An unexpected error occurred.", 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Database Error: Failed to check for existing mail template with title '{Title}' for TenantId: {TenantId}.: {Error}", mailTemplateDto.Title, tenantId, ex.Message);
|
_logger.LogError(ex, "Database Error: Failed to check for existing mail template with title '{Title}' for TenantId: {TenantId}.", mailTemplateDto.Title, tenantId);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while checking for existing templates.", 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while checking for existing templates.", 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,12 +270,12 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
catch (DbUpdateException dbEx)
|
catch (DbUpdateException dbEx)
|
||||||
{
|
{
|
||||||
_logger.LogError("Database Error: Failed to save new mail template '{Title}' for TenantId: {TenantId}. : {Error}", mailTemplateDto.Title, tenantId, dbEx.Message);
|
_logger.LogError(dbEx, "Database Error: Failed to save new mail template '{Title}' for TenantId: {TenantId}. : {Error}", mailTemplateDto.Title, tenantId);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while saving the mail template.", 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while saving the mail template.", 500));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unexpected Error: An unhandled exception occurred while adding mail template '{Title}' for TenantId: {TenantId}. : {Error}", mailTemplateDto.Title, tenantId, ex.Message);
|
_logger.LogError(ex, "Unexpected Error: An unhandled exception occurred while adding mail template '{Title}' for TenantId: {TenantId}.", mailTemplateDto.Title, tenantId);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An unexpected error occurred.", 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Server Error", "An unexpected error occurred.", 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,7 +350,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
// 3. OPTIMIZATION: Make the process resilient.
|
// 3. OPTIMIZATION: Make the process resilient.
|
||||||
// If one task fails unexpectedly, log it and continue with others.
|
// If one task fails unexpectedly, log it and continue with others.
|
||||||
_logger.LogError("Failed to send report for project {ProjectId} : {Error}", mailGroup.ProjectId, ex.Message);
|
_logger.LogError(ex, "Failed to send report for project {ProjectId}", mailGroup.ProjectId);
|
||||||
Interlocked.Increment(ref failureCount);
|
Interlocked.Increment(ref failureCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -527,7 +527,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// It's good practice to log any unexpected errors within a concurrent task.
|
// It's good practice to log any unexpected errors within a concurrent task.
|
||||||
_logger.LogError("Failed to process project report for ProjectId {ProjectId} : {Error}", group.ProjectId, ex.Message);
|
_logger.LogError(ex, "Failed to process project report for ProjectId {ProjectId}", group.ProjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -118,8 +118,8 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
|
|
||||||
projectDetails.ProjectStatus = new StatusMasterMongoDB
|
projectDetails.ProjectStatus = new StatusMasterMongoDB
|
||||||
{
|
{
|
||||||
Id = status?.Id.ToString(),
|
Id = status!.Id.ToString(),
|
||||||
Status = status?.Status
|
Status = status.Status
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use fast in-memory lookups instead of .Where() in loops.
|
// Use fast in-memory lookups instead of .Where() in loops.
|
||||||
@ -797,7 +797,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error occured while fetching project report mail bodys: {Error}", ex.Message);
|
_logger.LogError(ex, "Error occured while fetching project report mail bodys");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,7 +809,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error occured while adding project report mail bodys: {Error}", ex.Message);
|
_logger.LogError(ex, "Error occured while adding project report mail bodys");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attemped to access a contacts, but do not have permission", LoggedInEmployee.Id);
|
_logger.LogWarning("Employee {EmployeeId} attemped to access a contacts, but do not have permission", LoggedInEmployee.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attemped to access a contacts with in bucket {BucketId}, but do not have permission", LoggedInEmployee.Id, id);
|
_logger.LogWarning("Employee {EmployeeId} attemped to access a contacts with in bucket {BucketId}, but do not have permission", LoggedInEmployee.Id, id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attemped to update a contact, but do not have permission", LoggedInEmployee.Id);
|
_logger.LogWarning("Employee {EmployeeId} attemped to update a contact, but do not have permission", LoggedInEmployee.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1169,7 +1169,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attemped to access a buckets list, but do not have permission", LoggedInEmployee.Id);
|
_logger.LogWarning("Employee {EmployeeId} attemped to access a buckets list, but do not have permission", LoggedInEmployee.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1204,7 +1204,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
var demo = !permissionIds.Contains(PermissionsMaster.DirectoryUser);
|
var demo = !permissionIds.Contains(PermissionsMaster.DirectoryUser);
|
||||||
if (!permissionIds.Contains(PermissionsMaster.DirectoryAdmin) && !permissionIds.Contains(PermissionsMaster.DirectoryAdmin) && !permissionIds.Contains(PermissionsMaster.DirectoryUser))
|
if (!permissionIds.Contains(PermissionsMaster.DirectoryAdmin) && !permissionIds.Contains(PermissionsMaster.DirectoryAdmin) && !permissionIds.Contains(PermissionsMaster.DirectoryUser))
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attemped to create a bucket, but do not have permission", LoggedInEmployee.Id);
|
_logger.LogWarning("Employee {EmployeeId} attemped to create a bucket, but do not have permission", LoggedInEmployee.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission", "You don't have permission", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1276,7 +1276,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
if (accessableBucket == null)
|
if (accessableBucket == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attempted to access bucket {BucketId} without the necessary permissions.", LoggedInEmployee.Id, bucket.Id);
|
_logger.LogWarning("Employee {EmployeeId} attempted to access bucket {BucketId} without the necessary permissions.", LoggedInEmployee.Id, bucket.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission to access this bucket", "You don't have permission to access this bucket", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission to access this bucket", "You don't have permission to access this bucket", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,7 +1342,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
if (accessableBucket == null)
|
if (accessableBucket == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attempted to access bucket {BucketId} without the necessary permissions.", LoggedInEmployee.Id, bucket.Id);
|
_logger.LogWarning("Employee {EmployeeId} attempted to access bucket {BucketId} without the necessary permissions.", LoggedInEmployee.Id, bucket.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission to access this bucket", "You don't have permission to access this bucket", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission to access this bucket", "You don't have permission to access this bucket", 401);
|
||||||
}
|
}
|
||||||
var employeeIds = await _context.Employees.Where(e => e.TenantId == tenantId && e.IsActive).Select(e => e.Id).ToListAsync();
|
var employeeIds = await _context.Employees.Where(e => e.TenantId == tenantId && e.IsActive).Select(e => e.Id).ToListAsync();
|
||||||
@ -1396,7 +1396,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
if (removededEmployee > 0)
|
if (removededEmployee > 0)
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} removed {conut} number of employees from bucket {BucketId}", LoggedInEmployee.Id, removededEmployee, bucketId);
|
_logger.LogWarning("Employee {EmployeeId} removed {conut} number of employees from bucket {BucketId}", LoggedInEmployee.Id, removededEmployee, bucketId);
|
||||||
}
|
}
|
||||||
return ApiResponse<object>.SuccessResponse(bucketVM, "Details updated successfully", 200);
|
return ApiResponse<object>.SuccessResponse(bucketVM, "Details updated successfully", 200);
|
||||||
}
|
}
|
||||||
@ -1443,7 +1443,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
if (accessableBucket == null)
|
if (accessableBucket == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Employee {EmployeeId} attempted to access bucket {BucketId} without the necessary permissions.", LoggedInEmployee.Id, bucket.Id);
|
_logger.LogWarning("Employee {EmployeeId} attempted to access bucket {BucketId} without the necessary permissions.", LoggedInEmployee.Id, bucket.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("You don't have permission to access this bucket", "You don't have permission to access this bucket", 401);
|
return ApiResponse<object>.ErrorResponse("You don't have permission to access this bucket", "You don't have permission to access this bucket", 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace MarcoBMS.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{Error}", ex.Message);
|
_logger.LogError(ex, "Error occured while fetching employee by application user ID {ApplicationUserId}", ApplicationUserID);
|
||||||
return new Employee();
|
return new Employee();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ namespace MarcoBMS.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{Error}", ex.Message);
|
_logger.LogError(ex, "Error occoured while filtering employees by string {SearchString} or project {ProjectId}", searchString, ProjectId ?? Guid.Empty);
|
||||||
return new List<EmployeeVM>();
|
return new List<EmployeeVM>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ namespace MarcoBMS.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{Error}", ex.Message);
|
_logger.LogError(ex, "Error occured while featching list of employee by project ID {ProjectId}", ProjectId ?? Guid.Empty);
|
||||||
return new List<EmployeeVM>();
|
return new List<EmployeeVM>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
_logger.LogInfo("Contact tag master {ConatctTagId} updated successfully by employee {EmployeeId}", contactTagVm.Id, LoggedInEmployee.Id);
|
_logger.LogInfo("Contact tag master {ConatctTagId} updated successfully by employee {EmployeeId}", contactTagVm.Id, LoggedInEmployee.Id);
|
||||||
return ApiResponse<object>.SuccessResponse(contactTagVm, "Contact Tag master updated successfully", 200);
|
return ApiResponse<object>.SuccessResponse(contactTagVm, "Contact Tag master updated successfully", 200);
|
||||||
}
|
}
|
||||||
_logger.LogError("Contact Tag master {ContactTagId} not found in database", id);
|
_logger.LogWarning("Contact Tag master {ContactTagId} not found in database", id);
|
||||||
return ApiResponse<object>.ErrorResponse("Contact Tag master not found", "Contact tag master not found", 404);
|
return ApiResponse<object>.ErrorResponse("Contact Tag master not found", "Contact tag master not found", 404);
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", LoggedInEmployee.Id);
|
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", LoggedInEmployee.Id);
|
||||||
@ -294,7 +294,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error occurred while fetching work status list : {Error}", ex.Message);
|
_logger.LogWarning("Error occurred while fetching work status list : {Error}", ex.Message);
|
||||||
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to fetch work status list", 500);
|
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to fetch work status list", 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,7 +343,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error occurred while creating work status : {Error}", ex.Message);
|
_logger.LogWarning("Error occurred while creating work status : {Error}", ex.Message);
|
||||||
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to create work status", 500);
|
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to create work status", 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,7 +403,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error occurred while updating work status ID: {Id} : {Error}", id, ex.Message);
|
_logger.LogError(ex, "Error occurred while updating work status ID: {Id}", id);
|
||||||
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to update the work status at this time", 500);
|
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to update the work status at this time", 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,7 +458,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error occurred while deleting WorkStatus Id: {Id} : {Error}", id, ex.Message);
|
_logger.LogError(ex, "Error occurred while deleting WorkStatus Id: {Id}", id);
|
||||||
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to delete work status", 500);
|
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to delete work status", 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,13 +289,13 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
// --- Input Validation ---
|
// --- Input Validation ---
|
||||||
if (projectId == Guid.Empty)
|
if (projectId == Guid.Empty)
|
||||||
{
|
{
|
||||||
_logger.LogError("Validation Error: Provided empty project ID while fetching project report.");
|
_logger.LogWarning("Validation Error: Provided empty project ID while fetching project report.");
|
||||||
return ApiResponse<object>.ErrorResponse("Provided empty Project ID.", "Provided empty Project ID.", 400);
|
return ApiResponse<object>.ErrorResponse("Provided empty Project ID.", "Provided empty Project ID.", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipientEmails == null || !recipientEmails.Any())
|
if (recipientEmails == null || !recipientEmails.Any())
|
||||||
{
|
{
|
||||||
_logger.LogError("Validation Error: No recipient emails provided for project ID {ProjectId}.", projectId);
|
_logger.LogWarning("Validation Error: No recipient emails provided for project ID {ProjectId}.", projectId);
|
||||||
return ApiResponse<object>.ErrorResponse("No recipient emails provided.", "No recipient emails provided.", 400);
|
return ApiResponse<object>.ErrorResponse("No recipient emails provided.", "No recipient emails provided.", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Email Sending Error: Failed to send project statistics email for project ID {ProjectId}. : {Error}", projectId, ex.Message);
|
_logger.LogError(ex, "Email Sending Error: Failed to send project statistics email for project ID {ProjectId}.", projectId);
|
||||||
return ApiResponse<object>.ErrorResponse("Failed to send email.", "An error occurred while sending the email.", 500);
|
return ApiResponse<object>.ErrorResponse("Failed to send email.", "An error occurred while sending the email.", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,14 +350,14 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (DbUpdateException dbEx)
|
catch (DbUpdateException dbEx)
|
||||||
{
|
{
|
||||||
_logger.LogError("Database Error: Failed to save mail logs for project ID {ProjectId}. : {Error}", projectId, dbEx.Message);
|
_logger.LogError(dbEx, "Database Error: Failed to save mail logs for project ID {ProjectId}.", projectId);
|
||||||
// Depending on your requirements, you might still return success here as the email was sent.
|
// Depending on your requirements, you might still return success here as the email was sent.
|
||||||
// Or return an error indicating the logging failed.
|
// Or return an error indicating the logging failed.
|
||||||
return ApiResponse<object>.ErrorResponse("Email sent, but failed to log activity.", "Email sent, but an error occurred while logging.", 500);
|
return ApiResponse<object>.ErrorResponse("Email sent, but failed to log activity.", "Email sent, but an error occurred while logging.", 500);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Unexpected Error: An unhandled exception occurred while processing project statistics for project ID {ProjectId}. : {Error}", projectId, ex.Message);
|
_logger.LogError(ex, "Unexpected Error: An unhandled exception occurred while processing project statistics for project ID {ProjectId}.", projectId);
|
||||||
return ApiResponse<object>.ErrorResponse("An unexpected error occurred.", "An unexpected error occurred.", 500);
|
return ApiResponse<object>.ErrorResponse("An unexpected error occurred.", "An unexpected error occurred.", 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ namespace MarcoBMS.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("An error occurred while fetching permissions for EmployeeId {EmployeeId} : {Error}", EmployeeId, ex.Message);
|
_logger.LogError(ex, "An error occurred while fetching permissions for EmployeeId {EmployeeId}", EmployeeId);
|
||||||
return new List<FeaturePermission>();
|
return new List<FeaturePermission>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ namespace MarcoBMS.Services.Helpers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("An error occurred while fetching permissions for RoleId {RoleId}: {Error}", roleId, ex.Message);
|
_logger.LogError(ex, "An error occurred while fetching permissions for RoleId {RoleId}", roleId);
|
||||||
// Return an empty list as a safe default to prevent downstream failures.
|
// Return an empty list as a safe default to prevent downstream failures.
|
||||||
return new List<FeaturePermission>();
|
return new List<FeaturePermission>();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Marco.Pms.Model.Dtos.Project;
|
using Marco.Pms.Model.Dtos.Project;
|
||||||
|
using Marco.Pms.Model.Employees;
|
||||||
using Marco.Pms.Model.Master;
|
using Marco.Pms.Model.Master;
|
||||||
using Marco.Pms.Model.MongoDBModels;
|
using Marco.Pms.Model.MongoDBModels;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
|
using Marco.Pms.Model.ViewModels.Employee;
|
||||||
using Marco.Pms.Model.ViewModels.Projects;
|
using Marco.Pms.Model.ViewModels.Projects;
|
||||||
|
|
||||||
namespace Marco.Pms.Services.MappingProfiles
|
namespace Marco.Pms.Services.MappingProfiles
|
||||||
{
|
{
|
||||||
public class ProjectMappingProfile : Profile
|
public class MappingProfile : Profile
|
||||||
{
|
{
|
||||||
public ProjectMappingProfile()
|
public MappingProfile()
|
||||||
{
|
{
|
||||||
|
#region ======================================================= Projects =======================================================
|
||||||
// Your mappings
|
// Your mappings
|
||||||
CreateMap<Project, ProjectVM>();
|
CreateMap<Project, ProjectVM>();
|
||||||
CreateMap<Project, ProjectInfoVM>();
|
CreateMap<Project, ProjectInfoVM>();
|
||||||
@ -40,6 +43,11 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
CreateMap<StatusMasterMongoDB, StatusMaster>();
|
CreateMap<StatusMasterMongoDB, StatusMaster>();
|
||||||
CreateMap<ProjectVM, Project>();
|
CreateMap<ProjectVM, Project>();
|
||||||
CreateMap<CreateProjectDto, Project>();
|
CreateMap<CreateProjectDto, Project>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Projects =======================================================
|
||||||
|
CreateMap<Employee, EmployeeVM>();
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -158,6 +158,7 @@ builder.Services.AddTransient<S3UploadService>();
|
|||||||
#region Customs Services
|
#region Customs Services
|
||||||
builder.Services.AddScoped<RefreshTokenService>();
|
builder.Services.AddScoped<RefreshTokenService>();
|
||||||
builder.Services.AddScoped<PermissionServices>();
|
builder.Services.AddScoped<PermissionServices>();
|
||||||
|
builder.Services.AddScoped<ISignalRService, SignalRService>();
|
||||||
builder.Services.AddScoped<IProjectServices, ProjectServices>();
|
builder.Services.AddScoped<IProjectServices, ProjectServices>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
void LogInfo(string? message, params object[]? args);
|
void LogInfo(string? message, params object[]? args);
|
||||||
void LogDebug(string? message, params object[]? args);
|
void LogDebug(string? message, params object[]? args);
|
||||||
void LogWarning(string? message, params object[]? args);
|
void LogWarning(string? message, params object[]? args);
|
||||||
void LogError(string? message, params object[]? args);
|
void LogError(Exception? ex, string? message, params object[]? args);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,16 @@ namespace MarcoBMS.Services.Service
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogError(string? message, params object[]? args)
|
public void LogError(Exception? ex, string? message, params object[]? args)
|
||||||
{
|
{
|
||||||
using (LogContext.PushProperty("LogLevel", "Error"))
|
using (LogContext.PushProperty("LogLevel", "Error"))
|
||||||
if (args != null)
|
if (args != null)
|
||||||
{
|
{
|
||||||
_logger.LogError(message, args);
|
_logger.LogError(ex, message, args);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError(message);
|
_logger.LogError(ex, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using AutoMapper.QueryableExtensions;
|
||||||
using Marco.Pms.DataAccess.Data;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Model.Activities;
|
using Marco.Pms.Model.Activities;
|
||||||
using Marco.Pms.Model.Dtos.Project;
|
using Marco.Pms.Model.Dtos.Project;
|
||||||
@ -7,12 +8,15 @@ using Marco.Pms.Model.Entitlements;
|
|||||||
using Marco.Pms.Model.MongoDBModels;
|
using Marco.Pms.Model.MongoDBModels;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
|
using Marco.Pms.Model.ViewModels.Employee;
|
||||||
using Marco.Pms.Model.ViewModels.Projects;
|
using Marco.Pms.Model.ViewModels.Projects;
|
||||||
using Marco.Pms.Services.Helpers;
|
using Marco.Pms.Services.Helpers;
|
||||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||||
using MarcoBMS.Services.Helpers;
|
using MarcoBMS.Services.Helpers;
|
||||||
using MarcoBMS.Services.Service;
|
using MarcoBMS.Services.Service;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Project = Marco.Pms.Model.Projects.Project;
|
||||||
|
|
||||||
namespace Marco.Pms.Services.Service
|
namespace Marco.Pms.Services.Service
|
||||||
{
|
{
|
||||||
@ -75,7 +79,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// --- Step 5: Graceful Error Handling ---
|
// --- Step 5: Graceful Error Handling ---
|
||||||
_logger.LogError("An unexpected error occurred in GetAllProjectsBasic for tenant {TenantId}. \n {Error}", tenantId, ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred in GetAllProjectsBasic for tenant {TenantId}.", tenantId);
|
||||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +138,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// --- Step 5: Graceful Error Handling ---
|
// --- Step 5: Graceful Error Handling ---
|
||||||
_logger.LogError("An unexpected error occurred in GetAllProjects for tenant {TenantId}. \n {Error}", tenantId, ex.Message);
|
_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);
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +182,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("An unexpected error occurred while getting project {ProjectId} : \n {Error}", id, ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred while getting project {ProjectId}", id);
|
||||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred.", null, 500);
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred.", null, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,7 +248,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// --- Step 5: Graceful Error Handling ---
|
// --- Step 5: Graceful Error Handling ---
|
||||||
_logger.LogError("An unexpected error occurred in Get Project Details for project {ProjectId} for tenant {TenantId}. \n {Error}", id, tenantId, ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred in Get Project Details for project {ProjectId} for tenant {TenantId}. ", id, tenantId);
|
||||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred. Please try again later.", null, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,7 +364,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Log the detailed exception
|
// Log the detailed exception
|
||||||
_logger.LogError("Failed to create project in database. Rolling back transaction. \n {Error}", ex.Message);
|
_logger.LogError(ex, "Failed to create project in database. Rolling back transaction.");
|
||||||
// Return a server error as the primary operation failed
|
// Return a server error as the primary operation failed
|
||||||
return ApiResponse<object>.ErrorResponse("An error occurred while saving the project.", ex.Message, 500);
|
return ApiResponse<object>.ErrorResponse("An error occurred while saving the project.", ex.Message, 500);
|
||||||
}
|
}
|
||||||
@ -379,7 +383,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
{
|
{
|
||||||
// The project was created successfully, but a side-effect failed.
|
// The project was created successfully, but a side-effect failed.
|
||||||
// Log this as a warning, as the primary operation succeeded. Don't return an error to the user.
|
// Log this as a warning, as the primary operation succeeded. Don't return an error to the user.
|
||||||
_logger.LogWarning("Project {ProjectId} was created, but a post-creation side-effect (caching/notification) failed. \n {Error}", project.Id, ex.Message);
|
_logger.LogError(ex, "Project {ProjectId} was created, but a post-creation side-effect (caching/notification) failed. ", project.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Return a success response to the user as soon as the critical data is saved.
|
// 4. Return a success response to the user as soon as the critical data is saved.
|
||||||
@ -435,7 +439,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
{
|
{
|
||||||
// --- Step 3: Handle Concurrency Conflicts ---
|
// --- Step 3: Handle Concurrency Conflicts ---
|
||||||
// This happens if another user modified the project after we fetched it.
|
// This happens if another user modified the project after we fetched it.
|
||||||
_logger.LogWarning("Concurrency conflict while updating project {ProjectId} \n {Error}", id, ex.Message);
|
_logger.LogError(ex, "Concurrency conflict while updating project {ProjectId} ", id);
|
||||||
return ApiResponse<object>.ErrorResponse("Conflict occurred.", "This project has been modified by someone else. Please refresh and try again.", 409);
|
return ApiResponse<object>.ErrorResponse("Conflict occurred.", "This project has been modified by someone else. Please refresh and try again.", 409);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,13 +462,216 @@ namespace Marco.Pms.Services.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// --- Step 6: Graceful Error Handling for Unexpected Errors ---
|
// --- Step 6: Graceful Error Handling for Unexpected Errors ---
|
||||||
_logger.LogError("An unexpected error occurred while updating project {ProjectId} \n {Error}", id, ex.Message);
|
_logger.LogError(ex, "An unexpected error occurred while updating project {ProjectId} ", id);
|
||||||
return ApiResponse<object>.ErrorResponse("An internal server error occurred.", null, 500);
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred.", null, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region =================================================================== Project Allocation APIs ===================================================================
|
||||||
|
|
||||||
|
public async Task<ApiResponse<object>> GetEmployeeByProjectID(Guid? projectid, bool includeInactive, Guid tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
if (projectid == null)
|
||||||
|
{
|
||||||
|
return ApiResponse<object>.ErrorResponse("Invalid Input Parameter", 404);
|
||||||
|
}
|
||||||
|
// Fetch assigned project
|
||||||
|
List<Employee> result = new List<Employee>();
|
||||||
|
|
||||||
|
var employeeQuery = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.Where(pa => pa.ProjectId == projectid && pa.TenantId == tenantId && pa.Employee != null);
|
||||||
|
|
||||||
|
if (includeInactive)
|
||||||
|
{
|
||||||
|
|
||||||
|
result = await employeeQuery.Select(pa => pa.Employee ?? new Employee()).ToListAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = await employeeQuery
|
||||||
|
.Where(pa => pa.IsActive)
|
||||||
|
.Select(pa => pa.Employee ?? new Employee()).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<EmployeeVM> resultVM = new List<EmployeeVM>();
|
||||||
|
foreach (Employee employee in result)
|
||||||
|
{
|
||||||
|
EmployeeVM vm = _mapper.Map<EmployeeVM>(employee);
|
||||||
|
resultVM.Add(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(resultVM, "Successfully fetched the list of employees for seleted project", 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a list of employees for a specific project.
|
||||||
|
/// This method is optimized to perform all filtering and mapping on the database server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projectId">The ID of the project.</param>
|
||||||
|
/// <param name="includeInactive">Whether to include employees from inactive allocations.</param>
|
||||||
|
/// <param name="tenantId">The ID of the current tenant.</param>
|
||||||
|
/// <param name="loggedInEmployee">The current authenticated employee (used for permission checks).</param>
|
||||||
|
/// <returns>An ApiResponse containing a list of employees or an error.</returns>
|
||||||
|
public async Task<ApiResponse<object>> GetEmployeeByProjectIdAsync(Guid? projectId, bool includeInactive, Guid tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
// --- Step 1: Input Validation ---
|
||||||
|
if (projectId == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("GetEmployeeByProjectID called with a null projectId.");
|
||||||
|
// 400 Bad Request is more appropriate for invalid input than 404 Not Found.
|
||||||
|
return ApiResponse<object>.ErrorResponse("Project ID is required.", "Invalid Input Parameter", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInfo("Fetching employees for ProjectID: {ProjectId}, IncludeInactive: {IncludeInactive}", projectId, includeInactive);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// --- CRITICAL: Security Check ---
|
||||||
|
// Before fetching data, you MUST verify the user has permission to see it.
|
||||||
|
// This is a placeholder for your actual permission logic.
|
||||||
|
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value);
|
||||||
|
var hasAllEmployeePermission = await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id);
|
||||||
|
var hasviewTeamPermission = await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id);
|
||||||
|
|
||||||
|
if (!(hasProjectPermission && (hasAllEmployeePermission || hasviewTeamPermission)))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Access DENIED for user {UserId} on project {ProjectId}.", loggedInEmployee.Id, projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to view this project's team.", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 2: Build a Single, Efficient IQueryable ---
|
||||||
|
// We start with the base query and conditionally add filters before executing it.
|
||||||
|
// This avoids code duplication and is highly performant.
|
||||||
|
var employeeQuery = _context.ProjectAllocations
|
||||||
|
.Where(pa => pa.ProjectId == projectId && pa.TenantId == tenantId);
|
||||||
|
|
||||||
|
// Conditionally apply the filter for active allocations.
|
||||||
|
if (!includeInactive)
|
||||||
|
{
|
||||||
|
employeeQuery = employeeQuery.Where(pa => pa.IsActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 3: Project Directly to the ViewModel on the Database Server ---
|
||||||
|
// This is the most significant performance optimization.
|
||||||
|
// Instead of fetching full Employee entities, we select only the data needed for the EmployeeVM.
|
||||||
|
// AutoMapper's ProjectTo is perfect for this, as it translates the mapping configuration into an efficient SQL SELECT statement.
|
||||||
|
var resultVM = await employeeQuery
|
||||||
|
.Where(pa => pa.Employee != null) // Safety check for data integrity
|
||||||
|
.Select(pa => pa.Employee) // Navigate to the Employee entity
|
||||||
|
.ProjectTo<EmployeeVM>(_mapper.ConfigurationProvider) // Let AutoMapper generate the SELECT
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
_logger.LogInfo("Successfully fetched {EmployeeCount} employees for project {ProjectId}.", resultVM.Count, projectId);
|
||||||
|
|
||||||
|
// Note: The original mapping loop is now completely gone, replaced by the single efficient query above.
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(resultVM, "Successfully fetched the list of employees for the selected project.", 200);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// --- Step 4: Graceful Error Handling ---
|
||||||
|
_logger.LogError(ex, "An error occurred while fetching employees for project {ProjectId}. ", projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred.", "Database Query Failed", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse<object>> GetProjectAllocation(Guid? projectId, Guid tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
var employees = await _context.ProjectAllocations
|
||||||
|
.Where(c => c.TenantId == tenantId && c.ProjectId == projectId && c.Employee != null)
|
||||||
|
.Include(e => e.Employee)
|
||||||
|
.Select(e => new
|
||||||
|
{
|
||||||
|
ID = e.Id,
|
||||||
|
EmployeeId = e.EmployeeId,
|
||||||
|
ProjectId = e.ProjectId,
|
||||||
|
AllocationDate = e.AllocationDate,
|
||||||
|
ReAllocationDate = e.ReAllocationDate,
|
||||||
|
FirstName = e.Employee != null ? e.Employee.FirstName : string.Empty,
|
||||||
|
LastName = e.Employee != null ? e.Employee.LastName : string.Empty,
|
||||||
|
MiddleName = e.Employee != null ? e.Employee.MiddleName : string.Empty,
|
||||||
|
IsActive = e.IsActive,
|
||||||
|
JobRoleId = (e.JobRoleId != null ? e.JobRoleId : e.Employee != null ? e.Employee.JobRoleId : null)
|
||||||
|
}).ToListAsync();
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(employees, "Success.", 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves project allocation details for a specific project.
|
||||||
|
/// This method is optimized for performance and includes security checks.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projectId">The ID of the project.</param>
|
||||||
|
/// <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 tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
// --- Step 1: Input Validation ---
|
||||||
|
if (projectId == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("GetProjectAllocation called with a null projectId.");
|
||||||
|
return ApiResponse<object>.ErrorResponse("Project ID is required.", "Invalid Input Parameter", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInfo("Fetching allocations for ProjectID: {ProjectId} for user {UserId}", projectId, loggedInEmployee.Id);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// --- Step 2: Security and Existence Checks ---
|
||||||
|
// Before fetching data, you MUST verify the user has permission to see it.
|
||||||
|
// This is a placeholder for your actual permission logic.
|
||||||
|
var hasPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value);
|
||||||
|
if (!hasPermission)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Access DENIED for user {UserId} on project {ProjectId}.", loggedInEmployee.Id, projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to view this project's team.", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 3: Execute a Single, Optimized Database Query ---
|
||||||
|
// This query projects directly to a new object on the database server, which is highly efficient.
|
||||||
|
var allocations = await _context.ProjectAllocations
|
||||||
|
// Filter down to the relevant records first.
|
||||||
|
.Where(pa => pa.ProjectId == projectId && pa.TenantId == tenantId && pa.Employee != null)
|
||||||
|
// Project directly to the final shape. This tells EF Core which columns to select.
|
||||||
|
// The redundant .Include() is removed as EF Core infers the JOIN from this Select.
|
||||||
|
.Select(pa => new
|
||||||
|
{
|
||||||
|
// Fields from ProjectAllocation
|
||||||
|
ID = pa.Id,
|
||||||
|
pa.EmployeeId,
|
||||||
|
pa.ProjectId,
|
||||||
|
pa.AllocationDate,
|
||||||
|
pa.ReAllocationDate,
|
||||||
|
pa.IsActive,
|
||||||
|
|
||||||
|
// Fields from the joined Employee table (no null checks needed due to the 'Where' clause)
|
||||||
|
FirstName = pa.Employee!.FirstName,
|
||||||
|
LastName = pa.Employee.LastName,
|
||||||
|
MiddleName = pa.Employee.MiddleName,
|
||||||
|
|
||||||
|
// 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
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
_logger.LogInfo("Successfully fetched {AllocationCount} allocations for project {ProjectId}.", allocations.Count, projectId);
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(allocations, "Project allocations retrieved successfully.", 200);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// --- Step 4: Graceful Error Handling ---
|
||||||
|
// Log the full exception for debugging, but return a generic, safe error message.
|
||||||
|
_logger.LogError(ex, "An error occurred while fetching allocations for project {ProjectId}.", projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred.", "Database query failed.", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Helper Functions ===================================================================
|
#region =================================================================== Helper Functions ===================================================================
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -661,7 +868,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Failed to update cache for project {ProjectId} : \n {Error}", projectId, ex.Message);
|
_logger.LogError(ex, "Failed to update cache for project {ProjectId} : ", projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map from the database entity to the response ViewModel.
|
// Map from the database entity to the response ViewModel.
|
||||||
@ -682,7 +889,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Background cache update failed for project {ProjectId} \n {Error}", project.Id, ex.Message);
|
_logger.LogError(ex, "Background cache update failed for project {ProjectId} ", project.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Text;
|
|
||||||
using Marco.Pms.DataAccess.Data;
|
|
||||||
using Marco.Pms.Model.Authentication;
|
using Marco.Pms.Model.Authentication;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
namespace MarcoBMS.Services.Service
|
namespace MarcoBMS.Services.Service
|
||||||
@ -94,7 +94,7 @@ namespace MarcoBMS.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{Error}", ex.Message);
|
_logger.LogError(ex, "Error occured while creating new JWT token for user {UserId}", userId);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ namespace MarcoBMS.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error creating MPIN token for userId: {UserId}, tenantId: {TenantId}, error : {Error}", userId, tenantId, ex.Message);
|
_logger.LogError(ex, "Error creating MPIN token for userId: {UserId}, tenantId: {TenantId}", userId, tenantId);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ namespace MarcoBMS.Services.Service
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Token is invalid
|
// Token is invalid
|
||||||
_logger.LogError($"Token validation failed: {ex.Message}");
|
_logger.LogError(ex, "Token validation failed");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{error} while uploading file to S3", ex.Message);
|
_logger.LogError(ex, "error occured while uploading file to S3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{error} while requesting presigned url from Amazon S3", ex.Message);
|
_logger.LogError(ex, "error occured while requesting presigned url from Amazon S3", ex.Message);
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError("{error} while deleting from Amazon S3", ex.Message);
|
_logger.LogError(ex, "error ocured while deleting from Amazon S3");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("Warning: Could not find MimeType, Type, or ContentType property in Definition.");
|
_logger.LogWarning("Warning: Could not find MimeType, Type, or ContentType property in Definition.");
|
||||||
return "application/octet-stream";
|
return "application/octet-stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,16 +211,16 @@ namespace Marco.Pms.Services.Service
|
|||||||
return "application/octet-stream"; // Default if type cannot be determined
|
return "application/octet-stream"; // Default if type cannot be determined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FormatException)
|
catch (FormatException fEx)
|
||||||
{
|
{
|
||||||
// Handle cases where the input string is not valid Base64
|
// Handle cases where the input string is not valid Base64
|
||||||
_logger.LogError("Invalid Base64 string.");
|
_logger.LogError(fEx, "Invalid Base64 string.");
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Handle other potential errors during decoding or inspection
|
// Handle other potential errors during decoding or inspection
|
||||||
_logger.LogError($"An error occurred: {ex.Message}");
|
_logger.LogError(ex, "errors during decoding or inspection");
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
Task<ApiResponse<object>> GetProjectDetailsOldAsync(Guid id, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetProjectDetailsOldAsync(Guid id, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<object>> CreateProjectAsync(CreateProjectDto projectDto, Guid tenantId, Employee loggedInEmployee);
|
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>> UpdateProjectAsync(Guid id, UpdateProjectDto updateProjectDto, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Task<ApiResponse<object>> GetEmployeeByProjectIdAsync(Guid? projectId, bool includeInactive, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Task<ApiResponse<object>> GetProjectAllocationAsync(Guid? projectId, Guid tenantId, Employee loggedInEmployee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||||
|
{
|
||||||
|
public interface ISignalRService
|
||||||
|
{
|
||||||
|
Task SendNotificationAsync(object notification);
|
||||||
|
}
|
||||||
|
}
|
29
Marco.Pms.Services/Service/SignalRService.cs
Normal file
29
Marco.Pms.Services/Service/SignalRService.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using Marco.Pms.Services.Hubs;
|
||||||
|
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||||
|
using MarcoBMS.Services.Service;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Services.Service
|
||||||
|
{
|
||||||
|
public class SignalRService : ISignalRService
|
||||||
|
{
|
||||||
|
private readonly IHubContext<MarcoHub> _signalR;
|
||||||
|
private readonly ILoggingService _logger;
|
||||||
|
public SignalRService(IHubContext<MarcoHub> signalR, ILoggingService logger)
|
||||||
|
{
|
||||||
|
_signalR = signalR ?? throw new ArgumentNullException(nameof(signalR));
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
public async Task SendNotificationAsync(object notification)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Exception occured during sending notification through signalR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user