using AutoMapper; using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Master; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Services.Service.ServiceInterfaces; using MarcoBMS.Services.Service; using Microsoft.EntityFrameworkCore; namespace Marco.Pms.Services.Service { public class MasterService : IMasterService { private readonly ApplicationDbContext _context; private readonly ILoggingService _logger; private readonly PermissionServices _permission; private readonly IMapper _mapper; public MasterService( ApplicationDbContext context, ILoggingService logger, PermissionServices permission, IMapper mapper) { _context = context; _logger = logger; _permission = permission; _mapper = mapper; } #region =================================================================== Expenses Type APIs =================================================================== public async Task> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId) { try { // Validation if employee is taking action in same tenant if (tenantId != loggedInEmployee.TenantId) { _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of expense type from different tenant", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); } // Featching the list of Expenses Type. var typeList = await _context.ExpensesTypeMaster.Where(et => et.TenantId == tenantId).ToListAsync(); var response = _mapper.Map>(typeList); _logger.LogInfo("{Count} records of expense type have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id); return ApiResponse.SuccessResponse(response, $"{response.Count} records of expense type have been fetched successfully.", 200); } catch (Exception ex) { _logger.LogError(ex, "Error occured while fetching list of expense type list by employee {EmployeeId}", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); } } public async Task> CreateExpenseTypeAsync(ExpensesTypeMasterDto dto, Employee loggedInEmployee, Guid tenantId) { var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) { _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Upload expenses for this project", 403); } var expensesType = _mapper.Map(dto); _context.ExpensesTypeMaster.Add(expensesType); await _context.SaveChangesAsync(); _logger.LogInfo("New Expense Type {ExpensesTypeId} was added by employee {EmployeeId}", expensesType.Id, loggedInEmployee.Id); var response = _mapper.Map(expensesType); return ApiResponse.SuccessResponse(response, "Expense type craeted Successfully", 201); } #endregion #region =================================================================== Expenses Status APIs =================================================================== public async Task> GetExpenseStatusListAsync(Employee loggedInEmployee, Guid tenantId) { try { // Validation if employee is taking action in same tenant if (tenantId != loggedInEmployee.TenantId) { _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of expense status from different tenant", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); } // Featching the list of Expenses Status. var statusList = await _context.ExpensesStatusMaster.Where(es => es.TenantId == tenantId).ToListAsync(); var response = _mapper.Map>(statusList); var statusIds = statusList.Select(s => s.Id).ToList(); var permissionStatusMapping = await _context.StatusPermissionMapping .Where(ps => statusIds.Contains(ps.StatusId)) .GroupBy(ps => ps.StatusId) .Select(g => new { StatusId = g.Key, PermissionIds = g.Select(ps => ps.PermissionId).ToList() }).ToListAsync(); foreach (var status in response) { status.PermissionIds = permissionStatusMapping.Where(ps => ps.StatusId == status.Id).Select(ps => ps.PermissionIds).FirstOrDefault(); } _logger.LogInfo("{Count} records of expense status have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id); return ApiResponse.SuccessResponse(response, $"{response.Count} records of expense status have been fetched successfully.", 200); } catch (Exception ex) { _logger.LogError(ex, "Error occured while fetching list of expense sattus list by employee {EmployeeId}", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); } } #endregion #region =================================================================== Payment mode APIs =================================================================== public async Task> GetPaymentModeListAsync(Employee loggedInEmployee, Guid tenantId) { try { // Validation if employee is taking action in same tenant if (tenantId != loggedInEmployee.TenantId) { _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of payment modes from different tenant", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); } // Featching the list of Payment Modes. var paymentModes = await _context.PaymentModeMatser.Where(pm => pm.TenantId == tenantId).ToListAsync(); var response = _mapper.Map>(paymentModes); _logger.LogInfo("{Count} records of payment modes have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id); return ApiResponse.SuccessResponse(response, $"{response.Count} records of payment modes have been fetched successfully.", 200); } catch (Exception ex) { _logger.LogError(ex, "Error occured while featching list of payment modes list by employee {EmployeeId}", loggedInEmployee.Id); return ApiResponse.ErrorResponse("Internal Error occured while featching list of payment modes list", ExceptionMapper(ex), 500); } } #endregion #region =================================================================== Helper Function =================================================================== private static object ExceptionMapper(Exception ex) { return new { Message = ex.Message, StackTrace = ex.StackTrace, Source = ex.Source, InnerException = new { Message = ex.InnerException?.Message, StackTrace = ex.InnerException?.StackTrace, Source = ex.InnerException?.Source, } }; } #endregion } }