Directory_Refactor #128

Merged
ashutosh.nehete merged 22 commits from Directory_Refactor into Document_Manager 2025-09-09 11:03:46 +00:00
4 changed files with 355 additions and 147 deletions
Showing only changes of commit 4af6891821 - Show all commits

View File

@ -144,63 +144,47 @@ namespace Marco.Pms.Services.Controllers
public async Task<IActionResult> CreateContactNote([FromBody] CreateContactNoteDto noteDto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _directoryService.CreateContactNote(noteDto, tenantId, loggedInEmployee); ;
if (response.StatusCode == 200)
var response = await _directoryService.CreateContactNoteAsync(noteDto, tenantId, loggedInEmployee); ;
if (response.Success)
{
return Ok(response);
}
else if (response.StatusCode == 404)
{
return NotFound(response);
}
else
{
return BadRequest(response);
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Directory_Notes", Response = response.Data };
await _signalR.SendNotificationAsync(notification);
}
return StatusCode(response.StatusCode, response);
}
[HttpGet("notes/{ContactId}")]
public async Task<IActionResult> GetNoteListByContactId(Guid contactId, [FromQuery] bool active = true)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _directoryService.GetNoteListByContactId(contactId, active, tenantId, loggedInEmployee);
if (response.StatusCode == 200)
{
return Ok(response);
}
else if (response.StatusCode == 404)
{
return NotFound(response);
}
else
{
return BadRequest(response);
}
var response = await _directoryService.GetNoteListByContactIdAsync(contactId, active, tenantId, loggedInEmployee);
return StatusCode(response.StatusCode, response);
}
[HttpPut("note/{id}")]
public async Task<IActionResult> UpdateContactNote(Guid id, [FromBody] UpdateContactNoteDto noteDto)
{
var response = await _directoryService.UpdateContactNote(id, noteDto);
if (response.StatusCode == 200)
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _directoryService.UpdateContactNoteAsync(id, noteDto, tenantId, loggedInEmployee);
if (response.Success)
{
return Ok(response);
}
else if (response.StatusCode == 404)
{
return NotFound(response);
}
else
{
return BadRequest(response);
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Directory_Notes", Response = response.Data };
await _signalR.SendNotificationAsync(notification);
}
return StatusCode(response.StatusCode, response);
}
[HttpDelete("note/{id}")]
public async Task<IActionResult> DeleteContactNote(Guid id, [FromQuery] bool? active)
public async Task<IActionResult> DeleteContactNote(Guid id, [FromQuery] bool active = false)
{
var response = await _directoryService.DeleteContactNote(id, active ?? false);
return Ok(response);
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _directoryService.DeleteContactNoteAsync(id, active, tenantId, loggedInEmployee);
if (response.Success)
{
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Directory_Notes", Response = response.Data };
await _signalR.SendNotificationAsync(notification);
}
return StatusCode(response.StatusCode, response);
}
#endregion

View File

@ -274,6 +274,8 @@ namespace Marco.Pms.Services.MappingProfiles
dest => dest.OrganizationName,
opt => opt.MapFrom(src => src.Contact != null ? src.Contact.Organization : string.Empty)
);
CreateMap<CreateContactNoteDto, ContactNote>();
CreateMap<UpdateContactNoteDto, ContactNote>();
#endregion
}

View File

@ -8,6 +8,7 @@ using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.MongoDBModels.Utility;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Directory;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Projects;
@ -1549,151 +1550,372 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while fetching notes. Please try again later.", 500);
}
}
public async Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active, Guid tenantId, Employee loggedInEmployee)
{
var (hasAdminPermission, hasManagerPermission, hasUserPermission) = await CheckPermissionsAsync(loggedInEmployee.Id);
/// <summary>
/// Fetches all notes associated with a given contact, subject to permission checks and contact-bucket mappings.
/// </summary>
/// <param name="id">The contact ID.</param>
/// <param name="tenantId">The tenant ID of the current user.</param>
/// <param name="active">Whether to filter for active notes only.</param>
/// <param name="loggedInEmployee">The currently logged in employee object.</param>
/// <returns>Returns a list of contact notes wrapped in ApiResponse.</returns>
public async Task<ApiResponse<object>> GetNoteListByContactIdAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee)
{
// Step 1: Permission Validation
var (hasAdminPermission, hasManagerPermission, hasUserPermission) = await CheckPermissionsAsync(loggedInEmployee.Id);
if (!hasAdminPermission && !hasManagerPermission && !hasUserPermission)
{
_logger.LogWarning("Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId} Do not have permission", loggedInEmployee.Id, tenantId);
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
_logger.LogWarning(
"Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId}. No permissions granted.",
loggedInEmployee.Id, tenantId);
return ApiResponse<object>.ErrorResponse(
"Access Denied",
"You don't have access to view notes.",
StatusCodes.Status403Forbidden);
}
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == id && c.IsActive && c.TenantId == tenantId);
// Step 2: Validate Contact Exists
Contact? contact = await _context.Contacts
.AsNoTracking() // optimization: no tracking needed
.FirstOrDefaultAsync(c => c.Id == id && c.IsActive && c.TenantId == tenantId);
if (contact == null)
{
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to fetch a list notes from contact with ID {ContactId}, but the contact was not found in the database.", loggedInEmployee.Id, id);
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
_logger.LogWarning(
"Employee {EmployeeId} attempted to fetch notes for Contact {ContactId}, but the contact was not found. TenantId: {TenantId}",
loggedInEmployee.Id, id, tenantId);
return ApiResponse<object>.ErrorResponse(
"Contact not found",
"Contact not found",
StatusCodes.Status404NotFound);
}
if (!hasAdminPermission && (hasManagerPermission || hasUserPermission))
// Step 3: Bucket-level Security Checks (Non-admin users)
if (!hasAdminPermission)
{
var bucketIds = await _context.EmployeeBucketMappings.Where(em => em.EmployeeId == loggedInEmployee.Id).Select(em => em.BucketId).ToListAsync();
var hasContactAccess = await _context.ContactBucketMappings.AnyAsync(cb => bucketIds.Contains(cb.BucketId) && cb.ContactId == contact.Id);
var employeeBucketIds = await _context.EmployeeBucketMappings
.AsNoTracking()
.Where(em => em.EmployeeId == loggedInEmployee.Id)
.Select(em => em.BucketId)
.ToListAsync();
bool hasContactAccess = await _context.ContactBucketMappings
.AsNoTracking()
.AnyAsync(cb => employeeBucketIds.Contains(cb.BucketId) && cb.ContactId == contact.Id);
if (!hasContactAccess)
{
_logger.LogWarning("Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId} Do not have access of bucket", loggedInEmployee.Id, tenantId);
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
_logger.LogWarning(
"Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId}. No bucket access for ContactId {ContactId}",
loggedInEmployee.Id, tenantId, contact.Id);
return ApiResponse<object>.ErrorResponse(
"Access Denied",
"You don't have access to view notes.",
StatusCodes.Status403Forbidden);
}
}
// Step 4: Fetch Notes
var notesQuery = _context.ContactNotes
.Include(n => n.Createdby)
.Include(n => n.Createdby) // Eager load creator
.ThenInclude(e => e!.JobRole)
.Include(n => n.UpdatedBy)
.Include(n => n.UpdatedBy) // Eager load updater
.ThenInclude(e => e!.JobRole)
.Where(n => n.ContactId == contact.Id && n.TenantId == tenantId);
if (active)
{
notesQuery = notesQuery.Where(n => n.IsActive);
}
List<ContactNote> notes = await notesQuery.ToListAsync();
var noteIds = notes.Select(n => n.Id).ToList();
List<DirectoryUpdateLog>? updateLogs = await _context.DirectoryUpdateLogs
.Include(l => l.Employee)
.ThenInclude(e => e!.JobRole)
.Where(l => noteIds.Contains(l.RefereanceId))
List<ContactNote> notes = await notesQuery
.AsNoTracking() // reduce EF overhead
.ToListAsync();
// Step 5: Fetch Update Logs in one DB call
var noteIds = notes.Select(n => n.Id).ToList();
List<DirectoryUpdateLog> updateLogs = new();
if (noteIds.Count > 0) // only fetch logs if needed
{
updateLogs = await _context.DirectoryUpdateLogs
.Include(l => l.Employee)
.ThenInclude(e => e!.JobRole)
.AsNoTracking()
.Where(l => noteIds.Contains(l.RefereanceId))
.ToListAsync();
}
// Step 6: Map Entities to ViewModels
List<ContactNoteVM> noteVMs = _mapper.Map<List<ContactNoteVM>>(notes);
_logger.LogInfo("{count} contact-notes record from contact {ContactId} fetched by Employee {EmployeeId}", noteVMs.Count, id, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(noteVMs, $"{noteVMs.Count} contact-notes record fetched successfully", 200);
// Step 7: Final Log + Response
_logger.LogInfo(
"Employee {EmployeeId} successfully fetched {Count} notes for Contact {ContactId} in Tenant {TenantId}",
loggedInEmployee.Id, noteVMs.Count, id, tenantId);
return ApiResponse<object>.SuccessResponse(
noteVMs,
$"{noteVMs.Count} contact-notes record(s) fetched successfully",
StatusCodes.Status200OK);
}
public async Task<ApiResponse<object>> CreateContactNote(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee)
/// <summary>
/// Creates a note for a given contact under the specified tenant.
/// Ensures that the contact exists and belongs to the tenant before adding the note.
/// </summary>
/// <param name="noteDto">The DTO containing the note details.</param>
/// <param name="tenantId">The tenant identifier to which the contact belongs.</param>
/// <param name="loggedInEmployee">The logged-in employee attempting the action.</param>
/// <returns>ApiResponse containing the created note details or error information.</returns>
public async Task<ApiResponse<object>> CreateContactNoteAsync(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee)
{
if (noteDto != null)
// Validate request payload
if (noteDto == null)
{
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.IsActive && c.TenantId == tenantId);
if (contact != null)
{
ContactNote note = noteDto.ToContactNoteFromCreateContactNoteDto(tenantId, loggedInEmployee.Id);
_context.ContactNotes.Add(note);
await _context.SaveChangesAsync();
ContactNoteVM noteVM = note.ToContactNoteVMFromContactNote();
_logger.LogInfo("Employee {EmployeeId} Added note at contact {ContactId}", loggedInEmployee.Id, contact.Id);
return ApiResponse<object>.SuccessResponse(noteVM, "Note added successfully", 200);
_logger.LogWarning(
"Employee {EmployeeId} attempted to create a note with an empty payload.",
loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Empty payload.", "Request body cannot be null.", 400);
}
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to add a note to contact with ID {ContactId}, but the contact was not found in the database.", loggedInEmployee.Id, noteDto.ContactId);
try
{
// Check if the contact exists and is active for this tenant
Contact? contact = await _context.Contacts
.AsNoTracking() // optimization for read-only query
.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.IsActive && c.TenantId == tenantId);
if (contact == null)
{
_logger.LogWarning(
"Employee {EmployeeId} attempted to add a note to Contact {ContactId}, but it was not found for tenant {TenantId}.",
loggedInEmployee.Id, noteDto.ContactId, tenantId);
return ApiResponse<object>.ErrorResponse("Contact not found.", "The specified contact does not exist.", 404);
}
// Map DTO -> Entity using AutoMapper
ContactNote note = _mapper.Map<ContactNote>(noteDto);
note.CreatedById = loggedInEmployee.Id;
note.TenantId = tenantId;
// Save new note
await _context.ContactNotes.AddAsync(note);
await _context.SaveChangesAsync();
// Map Entity -> ViewModel
ContactNoteVM noteVM = _mapper.Map<ContactNoteVM>(note);
_logger.LogInfo(
"Employee {EmployeeId} successfully added a note (NoteId: {NoteId}) to Contact {ContactId} for Tenant {TenantId}.",
loggedInEmployee.Id, note.Id, contact.Id, tenantId);
return ApiResponse<object>.SuccessResponse(noteVM, "Note added successfully.", 200);
}
catch (Exception ex)
{
// Log unexpected errors to troubleshoot
_logger.LogError(
ex,
"Unexpected error occurred while Employee {EmployeeId} attempted to add a note for Contact {ContactId} in Tenant {TenantId}.",
loggedInEmployee.Id, noteDto.ContactId, tenantId);
return ApiResponse<object>.ErrorResponse("An unexpected error occurred.", ex.Message, 500);
}
}
/// <summary>
/// Updates an existing contact note and logs changes
/// both in relational DB (SQL) and update logs (possibly MongoDB).
/// </summary>
/// <param name="id">The note ID that needs to be updated.</param>
/// <param name="noteDto">DTO with updated note data.</param>
/// <returns>Standardized ApiResponse with updated note or error details.</returns>
public async Task<ApiResponse<object>> UpdateContactNoteAsync(Guid id, UpdateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee)
{
// Validation: check null payload or mismatched ID
if (noteDto == null || id != noteDto.Id)
{
_logger.LogWarning("Employee {EmployeeId} sent invalid or null payload. RouteId: {RouteId}, PayloadId: {PayloadId}",
loggedInEmployee.Id, id, noteDto?.Id ?? Guid.Empty);
return ApiResponse<object>.ErrorResponse("Invalid or empty payload", "Invalid or empty payload", 400);
}
// Check if the contact belongs to this tenant
Contact? contact = await _context.Contacts
.AsNoTracking()
.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.TenantId == tenantId);
if (contact == null)
{
_logger.LogWarning("Employee {EmployeeId} attempted to update note {NoteId} for Contact {ContactId}, but the contact was not found in Tenant {TenantId}.",
loggedInEmployee.Id, noteDto.Id, noteDto.ContactId, tenantId);
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
}
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("User Send empty Payload", "User Send empty Payload", 400);
}
public async Task<ApiResponse<object>> UpdateContactNote(Guid id, UpdateContactNoteDto noteDto)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (noteDto != null && id == noteDto.Id)
{
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.TenantId == tenantId);
if (contact != null)
{
// Fetch the contact note to be updated
ContactNote? contactNote = await _context.ContactNotes
.Include(cn => cn.Createdby)
.ThenInclude(e => e!.JobRole)
.Include(cn => cn.Contact)
.FirstOrDefaultAsync(n => n.Id == noteDto.Id && n.ContactId == contact.Id && n.IsActive);
if (contactNote != null)
.FirstOrDefaultAsync(n =>
n.Id == noteDto.Id &&
n.ContactId == contact.Id &&
n.IsActive);
if (contactNote == null)
{
contactNote.Note = noteDto.Note;
contactNote.UpdatedById = LoggedInEmployee.Id;
contactNote.UpdatedAt = DateTime.UtcNow;
_logger.LogWarning("Employee {EmployeeId} attempted to update Note {NoteId} for Contact {ContactId}, but the note was not found or inactive.",
loggedInEmployee.Id, noteDto.Id, noteDto.ContactId);
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = LoggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
ContactNoteVM noteVM = contactNote.ToContactNoteVMFromContactNote();
noteVM.UpdatedAt = DateTime.UtcNow;
noteVM.UpdatedBy = LoggedInEmployee.ToBasicEmployeeVMFromEmployee();
_logger.LogInfo("Employee {EmployeeId} updated note {NoteId} at contact {ContactId}", LoggedInEmployee.Id, noteVM.Id, contact.Id);
return ApiResponse<object>.SuccessResponse(noteVM, "Note updated successfully", 200);
}
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to update a note {NoteId} to contact with ID {ContactId}, but the Note was not found in the database.", LoggedInEmployee.Id, noteDto.Id, noteDto.ContactId);
return ApiResponse<object>.ErrorResponse("Note not found", "Note not found", 404);
}
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to update a note {NoteId} to contact with ID {ContactId}, but the contact was not found in the database.", LoggedInEmployee.Id, noteDto.Id, noteDto.ContactId);
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
}
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", LoggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("User Send empty Payload", "User Send empty Payload", 400);
}
public async Task<ApiResponse<object>> DeleteContactNote(Guid id, bool active)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
ContactNote? note = await _context.ContactNotes.FirstOrDefaultAsync(n => n.Id == id && n.TenantId == tenantId);
if (note != null)
{
note.IsActive = active;
note.UpdatedById = LoggedInEmployee.Id;
note.UpdatedAt = DateTime.UtcNow;
// Capture old state for change-log before updating
var oldObject = _updateLogsHelper.EntityToBsonDocument(contactNote);
// Apply updates
contactNote.Note = noteDto.Note;
contactNote.UpdatedById = loggedInEmployee.Id;
contactNote.UpdatedAt = DateTime.UtcNow;
// Save change log into relational logs
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = LoggedInEmployee.Id,
UpdatedById = loggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
// Wrap in try-catch for robustness
try
{
await _context.SaveChangesAsync();
_logger.LogInfo("Employee {EmployeeId} deleted note {NoteId}", LoggedInEmployee.Id, id);
// Map to ViewModel for output
ContactNoteVM noteVM = _mapper.Map<ContactNoteVM>(contactNote);
noteVM.UpdatedAt = contactNote.UpdatedAt;
noteVM.UpdatedBy = _mapper.Map<BasicEmployeeVM>(loggedInEmployee);
// Push audit log asynchronously (Mongo / NoSQL Logs)
await _updateLogsHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = contactNote.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = oldObject,
UpdatedAt = DateTime.UtcNow
}, contactNoteCollection);
// Success log
_logger.LogInfo("Employee {EmployeeId} successfully updated Note {NoteId} for Contact {ContactId} at {UpdatedAt}",
loggedInEmployee.Id, noteVM.Id, contact.Id, noteVM.UpdatedAt);
return ApiResponse<object>.SuccessResponse(noteVM, "Note updated successfully", 200);
}
catch (DbUpdateException ex)
{
_logger.LogError(ex, "Database Exception occurred while updating Note {NoteId} for Contact {ContactId} by Employee {EmployeeId}",
noteDto.Id, noteDto.ContactId, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Failed to update note", "An unexpected error occurred while saving note.", 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred while updating Note {NoteId} for Contact {ContactId} by Employee {EmployeeId}",
noteDto.Id, noteDto.ContactId, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Failed to update note", "An unexpected error occurred while saving note.", 500);
}
}
_logger.LogWarning("Employee {EmployeeId} tries to delete contact note {NoteId} but not found in database", LoggedInEmployee.Id, id);
return ApiResponse<object>.SuccessResponse(new { }, "Note deleted successfully", 200);
/// <summary>
/// Soft deletes (or restores) a contact note by updating its active status.
/// Also pushes an update log entry in SQL and Mongo (audit trail).
/// </summary>
/// <param name="id">ID of the contact note to delete/restore.</param>
/// <param name="active">Flag to set note as active or inactive.</param>
/// <param name="tenantId">Tenant identifier of the logged-in user.</param>
/// <param name="loggedInEmployee">The employee performing this action.</param>
/// <returns>ApiResponse with success or error details.</returns>
public async Task<ApiResponse<object>> DeleteContactNoteAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee)
{
// Lookup note within the tenant
ContactNote? note = await _context.ContactNotes
.FirstOrDefaultAsync(n => n.Id == id && n.TenantId == tenantId);
if (note == null)
{
// Log missing resource
_logger.LogWarning("Employee {EmployeeId} attempted to delete Note {NoteId}, but it was not found in Tenant {TenantId}",
loggedInEmployee.Id, id, tenantId);
return ApiResponse<object>.ErrorResponse("Note not found", "Note not found", 404);
}
// Capture old state for audit logging
var oldObject = _updateLogsHelper.EntityToBsonDocument(note);
// Update note metadata
var currentTime = DateTime.UtcNow;
note.IsActive = active; // soft delete (false) or restore (true)
note.UpdatedById = loggedInEmployee.Id;
note.UpdatedAt = currentTime;
// Add relational update log entry
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = loggedInEmployee.Id,
UpdateAt = currentTime
});
try
{
// Save SQL changes
await _context.SaveChangesAsync();
// Push audit log (Mongo / NoSQL)
await _updateLogsHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = note.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = oldObject,
UpdatedAt = currentTime
}, contactNoteCollection);
// Log success — distinguish delete vs restore
if (!active)
{
_logger.LogInfo("Employee {EmployeeId} soft deleted Note {NoteId} at {Timestamp}",
loggedInEmployee.Id, id, currentTime);
}
else
{
_logger.LogInfo("Employee {EmployeeId} restored Note {NoteId} at {Timestamp}",
loggedInEmployee.Id, id, currentTime);
}
return ApiResponse<object>.SuccessResponse(new { },
active ? "Note restored successfully" : "Note deleted successfully",
200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while updating Note {NoteId} (delete/restore) in Tenant {TenantId} by Employee {EmployeeId}",
id, tenantId, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Failed to delete note",
"An unexpected error occurred while deleting/restoring the note.",
500);
}
}
#endregion
#region =================================================================== Bucket APIs ===================================================================

View File

@ -21,10 +21,10 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> CreateContactNote(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> UpdateContactNote(Guid id, UpdateContactNoteDto noteDto);
Task<ApiResponse<object>> DeleteContactNote(Guid id, bool active);
Task<ApiResponse<object>> GetNoteListByContactIdAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> CreateContactNoteAsync(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> UpdateContactNoteAsync(Guid id, UpdateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> DeleteContactNoteAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> GetBucketListAsync(Guid tenantId, Employee loggedInEmployee);