Added all get lsit for Expenses-Type, Expenses-Status and payment-mode

This commit is contained in:
ashutosh.nehete 2025-07-19 15:02:48 +05:30
parent cc2e545442
commit 8e69219e73
7 changed files with 206 additions and 42 deletions

View File

@ -10,6 +10,7 @@ using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Forum;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Helpers;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Authorization;
@ -27,12 +28,14 @@ namespace Marco.Pms.Services.Controllers
private readonly UserHelper _userHelper;
private readonly ILoggingService _logger;
private readonly MasterHelper _masterHelper;
public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, MasterHelper masterHelper)
private readonly IMasterService _masterService;
public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, MasterHelper masterHelper, IMasterService masterService)
{
_context = context;
_userHelper = userHelper;
_logger = logger;
_masterHelper = masterHelper;
_masterService = masterService;
}
// -------------------------------- Activity --------------------------------
@ -846,5 +849,41 @@ namespace Marco.Pms.Services.Controllers
var response = await _masterHelper.DeleteContactTag(id);
return Ok(response);
}
#region =================================================================== Expenses Type APIs ===================================================================
[HttpGet("expenses-types")]
public async Task<IActionResult> GetExpenseTypeList()
{
var response = await _masterService.GetExpenseTypeListAsync();
return StatusCode(response.StatusCode, response);
}
public async Task<IActionResult> CreateExpenseType(ExpensesTypeMasterDto dto)
{
var response = await _masterService.GetExpenseTypeListAsync();
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Expenses Status APIs ===================================================================
[HttpGet("expenses-status")]
public async Task<IActionResult> GetExpenseStatusList()
{
var response = await _masterService.GetExpenseStatusListAsync();
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Payment mode APIs ===================================================================
[HttpGet("payment-modes")]
public async Task<IActionResult> GetPaymentModeList()
{
var response = await _masterService.GetPaymentModeListAsync();
return StatusCode(response.StatusCode, response);
}
#endregion
}
}

View File

@ -19,20 +19,21 @@ namespace Marco.Pms.Services.Helpers
private readonly ApplicationDbContext _context;
private readonly ILoggingService _logger;
private readonly UserHelper _userHelper;
private readonly PermissionServices _permissionService;
private readonly PermissionServices _permission;
private readonly Guid tenantId;
public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permissionServices)
public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permission)
{
_context = context;
_logger = logger;
_userHelper = userHelper;
_permissionService = permissionServices;
_permission = permission;
tenantId = userHelper.GetTenantId();
}
// -------------------------------- Contact Category --------------------------------
#region =================================================================== Contact Category APIs ===================================================================
public async Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactCategoryDto != null)
{
@ -55,7 +56,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> UpdateContactCategory(Guid id, UpdateContactCategoryDto contactCategoryDto)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactCategoryDto != null && id == contactCategoryDto.Id)
{
@ -86,7 +86,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> GetContactCategoriesList()
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var categoryList = await _context.ContactCategoryMasters.Where(c => c.TenantId == tenantId).ToListAsync();
@ -101,7 +100,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> GetContactCategoryById(Guid id)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var category = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
@ -117,7 +115,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> DeleteContactCategory(Guid id)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
ContactCategoryMaster? contactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (contactCategory != null)
@ -148,14 +145,12 @@ namespace Marco.Pms.Services.Helpers
_logger.LogWarning("Employee {EmployeeId} tries to delete Category {CategoryId} but not found in database", LoggedInEmployee.Id, id);
return ApiResponse<object>.SuccessResponse(new { }, "Category deleted successfully", 200);
}
#endregion
// -------------------------------- Contact Tag --------------------------------
#region =================================================================== Contact Tag APIs ===================================================================
public async Task<ApiResponse<Object>> GetContactTags()
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var taglist = await _context.ContactTagMasters.Where(t => t.TenantId == tenantId).ToListAsync();
@ -170,7 +165,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> CreateContactTag(CreateContactTagDto contactTagDto)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactTagDto != null)
{
@ -193,7 +187,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> UpdateContactTag(Guid id, UpdateContactTagDto contactTagDto)
{
var tenantId = _userHelper.GetTenantId();
Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactTagDto != null && contactTagDto.Id == id)
{
@ -226,7 +219,6 @@ namespace Marco.Pms.Services.Helpers
}
public async Task<ApiResponse<object>> DeleteContactTag(Guid id)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
ContactTagMaster? contactTag = await _context.ContactTagMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (contactTag != null)
@ -252,19 +244,21 @@ namespace Marco.Pms.Services.Helpers
return ApiResponse<object>.SuccessResponse(new { }, "Tag deleted successfully", 200);
}
// -------------------------------- Work Status --------------------------------
#endregion
#region =================================================================== Work Status APIs ===================================================================
public async Task<ApiResponse<object>> GetWorkStatusList()
{
_logger.LogInfo("GetWorkStatusList called.");
try
{
// Step 1: Get tenant and logged-in employee info
Guid tenantId = _userHelper.GetTenantId();
// Step 1: Get logged-in employee info
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permission to view master data
bool hasViewPermission = await _permissionService.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id);
bool hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id);
if (!hasViewPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
@ -294,7 +288,7 @@ namespace Marco.Pms.Services.Helpers
}
catch (Exception ex)
{
_logger.LogWarning("Error occurred while fetching work status list : {Error}", ex.Message);
_logger.LogError(ex, "Error occurred while fetching work status list");
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to fetch work status list", 500);
}
}
@ -304,12 +298,11 @@ namespace Marco.Pms.Services.Helpers
try
{
// Step 1: Get tenant and logged-in employee
Guid tenantId = _userHelper.GetTenantId();
// Step 1: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check if user has permission to manage master data
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
@ -343,7 +336,7 @@ namespace Marco.Pms.Services.Helpers
}
catch (Exception ex)
{
_logger.LogWarning("Error occurred while creating work status : {Error}", ex.Message);
_logger.LogError(ex, "Error occurred while creating work status");
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to create work status", 500);
}
}
@ -360,12 +353,11 @@ namespace Marco.Pms.Services.Helpers
return ApiResponse<object>.ErrorResponse("Invalid data provided", "The provided work status ID is invalid", 400);
}
// Step 2: Get tenant and logged-in employee
Guid tenantId = _userHelper.GetTenantId();
// Step 2: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 3: Check permissions
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id);
@ -413,12 +405,11 @@ namespace Marco.Pms.Services.Helpers
try
{
// Step 1: Get current tenant and logged-in employee
Guid tenantId = _userHelper.GetTenantId();
// Step 1: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permission to manage master data
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
@ -462,5 +453,7 @@ namespace Marco.Pms.Services.Helpers
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to delete work status", 500);
}
}
#endregion
}
}

View File

@ -1,4 +1,5 @@
using AutoMapper;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Dtos.Project;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Master;
@ -60,9 +61,18 @@ namespace Marco.Pms.Services.MappingProfiles
opt => opt.MapFrom(src => src.Comment));
#endregion
#region ======================================================= Projects =======================================================
#region ======================================================= Employee =======================================================
CreateMap<Employee, EmployeeVM>();
#endregion
#region ======================================================= Master =======================================================
CreateMap<ExpensesTypeMasterDto, ExpensesTypeMaster>()
.ForMember(
dest => dest.Id,
// Explicitly and safely convert nullable Guid to non-nullable Guid
opt => opt.MapFrom(src => src.Id != null ? src.Id : Guid.Empty)
);
#endregion
}
}
}

View File

@ -172,6 +172,7 @@ builder.Services.AddScoped<RefreshTokenService>();
builder.Services.AddScoped<PermissionServices>();
builder.Services.AddScoped<ISignalRService, SignalRService>();
builder.Services.AddScoped<IProjectServices, ProjectServices>();
builder.Services.AddScoped<IMasterService, MasterService>();
#endregion
#region Helpers

View File

@ -0,0 +1,80 @@
using AutoMapper;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Helpers;
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 UserHelper _userHelper;
private readonly PermissionServices _permission;
private readonly IMapper _mapper;
private readonly Guid tenantId;
public MasterService(
ApplicationDbContext context,
ILoggingService logger,
UserHelper userHelper,
PermissionServices permission,
IMapper mapper)
{
_context = context;
_logger = logger;
_userHelper = userHelper;
_permission = permission;
_mapper = mapper;
tenantId = userHelper.GetTenantId();
}
#region =================================================================== Expenses Type APIs ===================================================================
public async Task<ApiResponse<object>> GetExpenseTypeListAsync()
{
var typeList = await _context.ExpensesTypeMaster.Where(et => et.TenantId == tenantId).ToListAsync();
return ApiResponse<object>.SuccessResponse(typeList);
}
public async Task<ApiResponse<object>> CreateExpenseTypeAsync(ExpensesTypeMasterDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
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<object>.ErrorResponse("Access Denied.", "You do not have permission to Upload expenses for this project", 403);
}
var expensesType = _mapper.Map<ExpensesTypeMaster>(dto);
return ApiResponse<object>.SuccessResponse(expensesType);
}
#endregion
#region =================================================================== Expenses Status APIs ===================================================================
public async Task<ApiResponse<object>> GetExpenseStatusListAsync()
{
var typeList = await _context.ExpensesStatusMaster.Where(et => et.TenantId == tenantId).ToListAsync();
return ApiResponse<object>.SuccessResponse(typeList);
}
#endregion
#region =================================================================== Payment mode APIs ===================================================================
public async Task<ApiResponse<object>> GetPaymentModeListAsync()
{
var typeList = await _context.PaymentModeMatser.Where(et => et.TenantId == tenantId).ToListAsync();
return ApiResponse<object>.SuccessResponse(typeList);
}
#endregion
}
}

View File

@ -5,6 +5,7 @@ using Marco.Pms.Model.Utilities;
using MarcoBMS.Services.Service;
using Microsoft.Extensions.Options;
using MimeDetective;
using System.Text.RegularExpressions;
namespace Marco.Pms.Services.Service
{
@ -12,7 +13,7 @@ namespace Marco.Pms.Services.Service
public class S3UploadService
{
private readonly IAmazonS3 _s3Client;
private readonly string _bucketName = "your-bucket-name";
private readonly string _bucketName;
private readonly ILoggingService _logger;
private readonly IConfiguration _configuration;
@ -64,7 +65,7 @@ namespace Marco.Pms.Services.Service
}
catch (Exception ex)
{
_logger.LogError(ex, "error occured while uploading file to S3");
_logger.LogError(ex, "Error ocurred while uploading file to S3", ex.Message);
}
@ -87,7 +88,7 @@ namespace Marco.Pms.Services.Service
}
catch (Exception ex)
{
_logger.LogError(ex, "error occured while requesting presigned url from Amazon S3", ex.Message);
_logger.LogError(ex, "Error occured while requesting presigned url from Amazon S3");
return string.Empty;
}
}
@ -107,17 +108,17 @@ namespace Marco.Pms.Services.Service
}
catch (Exception ex)
{
_logger.LogError(ex, "error ocured while deleting from Amazon S3");
_logger.LogError(ex, "while deleting from Amazon S3");
return false;
}
}
public string GenerateFileName(string contentType, Guid tenantId, string? name)
public string GenerateFileName(string contentType, Guid entityId, string? name)
{
string extenstion = GetExtensionFromMimeType(contentType);
if (string.IsNullOrEmpty(name))
return $"{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}";
return $"{name}_{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}";
return $"{entityId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}";
return $"{name}_{entityId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}";
}
public string GetExtensionFromMimeType(string contentType)
@ -220,9 +221,38 @@ namespace Marco.Pms.Services.Service
catch (Exception ex)
{
// Handle other potential errors during decoding or inspection
_logger.LogError(ex, "errors during decoding or inspection");
_logger.LogError(ex, "An error occurred while decoding base64");
return string.Empty;
}
}
public bool IsBase64String(string? input)
{
if (string.IsNullOrWhiteSpace(input))
return false;
// Normalize string
input = input.Trim();
// Length must be multiple of 4
if (input.Length % 4 != 0)
return false;
// Valid Base64 characters with correct padding
var base64Regex = new Regex(@"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$");
if (!base64Regex.IsMatch(input))
return false;
try
{
// Decode and re-encode to confirm validity
var bytes = Convert.FromBase64String(input);
var reEncoded = Convert.ToBase64String(bytes);
return input == reEncoded;
}
catch
{
return false;
}
}
}
}

View File

@ -0,0 +1,11 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Services.Service.ServiceInterfaces
{
public interface IMasterService
{
Task<ApiResponse<object>> GetExpenseTypeListAsync();
Task<ApiResponse<object>> GetExpenseStatusListAsync();
Task<ApiResponse<object>> GetPaymentModeListAsync();
}
}