diff --git a/Marco.Pms.Services/Controllers/AppMenuController.cs b/Marco.Pms.Services/Controllers/AppMenuController.cs index 46889ec..8f1c3d7 100644 --- a/Marco.Pms.Services/Controllers/AppMenuController.cs +++ b/Marco.Pms.Services/Controllers/AppMenuController.cs @@ -608,6 +608,20 @@ namespace Marco.Pms.Services.Controllers var featureIds = await generalHelper.GetFeatureIdsByTenentIdAsync(tenantId); _logger.LogInfo("Enabled features for TenantId: {TenantId} -> {FeatureIds}", tenantId, string.Join(",", featureIds)); + if (!(featureIds?.Any() ?? false)) + { + featureIds = new List + { + new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), // Expense Management feature + new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), // Employee Management feature + new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), // Attendance Management feature + new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), // Document Management feature + new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), // Masters Management feature + new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), // Directory Management feature + new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914") // Organization Management feature + }; + } + // Aggregate menus based on enabled features var response = featureIds .Where(id => featureMenus.ContainsKey(id)) diff --git a/Marco.Pms.Services/Controllers/AttendanceController.cs b/Marco.Pms.Services/Controllers/AttendanceController.cs index cdcd71c..7c1b31f 100644 --- a/Marco.Pms.Services/Controllers/AttendanceController.cs +++ b/Marco.Pms.Services/Controllers/AttendanceController.cs @@ -190,17 +190,26 @@ namespace MarcoBMS.Services.Controllers var result = new List(); //Attendance? attendance = null; - ProjectAllocation? teamMember = null; if (dateFrom == null) fromDate = DateTime.UtcNow.Date; if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1); if (hasTeamAttendancePermission) { - List lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == tenantId).ToListAsync(); + List lstAttendance = await _context.Attendes + .Include(a => a.Employee) + .ThenInclude(e => e!.Organization) + .Include(a => a.Employee) + .ThenInclude(e => e!.JobRole) + .Where(a => a.ProjectID == projectId && + a.AttendanceDate.Date >= fromDate.Date && + a.AttendanceDate.Date <= toDate.Date && + a.TenantId == tenantId && + a.Employee != null && + a.Employee.Organization != null && + a.Employee.JobRole != null + ).ToListAsync(); - - List projectteam = await _projectServices.GetTeamByProject(tenantId, projectId, organizationId, true); var jobRole = await _context.JobRoles.ToListAsync(); foreach (Attendance? attendance in lstAttendance) { @@ -209,70 +218,56 @@ namespace MarcoBMS.Services.Controllers Id = attendance.Id, CheckInTime = attendance.InTime, CheckOutTime = attendance.OutTime, - Activity = attendance.Activity + Activity = attendance.Activity, + EmployeeId = attendance.EmployeeId, + FirstName = attendance.Employee?.FirstName, + LastName = attendance.Employee?.LastName, + JobRoleName = attendance.Employee?.JobRole?.Name, + OrganizationName = attendance.Employee?.Organization?.Name + }; - teamMember = projectteam.Find(x => x.EmployeeId == attendance.EmployeeId); - if (teamMember != null) - { - result1.EmployeeAvatar = null; - result1.EmployeeId = teamMember.EmployeeId; - if (teamMember.Employee != null) - { - result1.FirstName = teamMember.Employee.FirstName; - result1.LastName = teamMember.Employee.LastName; - result1.JobRoleName = teamMember.Employee.JobRole != null ? teamMember.Employee.JobRole.Name : null; - result1.OrganizationName = teamMember.Employee.Organization?.Name; - } - else - { - result1.FirstName = null; - result1.LastName = null; - result1.JobRoleName = null; - result1.OrganizationName = null; - } - - result.Add(result1); - } - + result.Add(result1); } } else if (hasSelfAttendancePermission) { - List lstAttendances = await _context.Attendes - .Where(c => c.ProjectID == projectId && c.EmployeeId == LoggedInEmployee.Id && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == tenantId) - .ToListAsync(); - - var projectAllocationQuery = _context.ProjectAllocations - .Include(pa => pa.Employee) + var lstAttendanceQuery = _context.Attendes + .Include(a => a.Employee) .ThenInclude(e => e!.Organization) - .Where(pa => pa.ProjectId == projectId && pa.EmployeeId == LoggedInEmployee.Id && pa.TenantId == tenantId && pa.IsActive); + .Include(a => a.Employee) + .ThenInclude(e => e!.JobRole) + .Where(a => a.ProjectID == projectId && + a.EmployeeId == LoggedInEmployee.Id && + a.AttendanceDate.Date >= fromDate.Date && + a.AttendanceDate.Date <= toDate.Date && + a.TenantId == tenantId && + a.Employee != null && + a.Employee.Organization != null && + a.Employee.JobRole != null); if (organizationId.HasValue) { - projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId); + lstAttendanceQuery = lstAttendanceQuery.Where(a => a.Employee != null && a.Employee.OrganizationId == organizationId); } - var projectAllocation = await projectAllocationQuery.FirstOrDefaultAsync(); + var lstAttendances = await lstAttendanceQuery.ToListAsync(); foreach (var attendance in lstAttendances) { - if (projectAllocation != null) + EmployeeAttendanceVM result1 = new EmployeeAttendanceVM { - EmployeeAttendanceVM result1 = new EmployeeAttendanceVM - { - Id = attendance.Id, - EmployeeAvatar = null, - EmployeeId = projectAllocation.EmployeeId, - FirstName = projectAllocation.Employee?.FirstName, - LastName = projectAllocation.Employee?.LastName, - JobRoleName = projectAllocation.Employee?.JobRole?.Name, - OrganizationName = projectAllocation.Employee?.Organization?.Name, - CheckInTime = attendance.InTime, - CheckOutTime = attendance.OutTime, - Activity = attendance.Activity - }; - result.Add(result1); - } + Id = attendance.Id, + EmployeeAvatar = null, + EmployeeId = attendance.EmployeeId, + FirstName = attendance.Employee?.FirstName, + LastName = attendance.Employee?.LastName, + JobRoleName = attendance.Employee?.JobRole?.Name, + OrganizationName = attendance.Employee?.Organization?.Name, + CheckInTime = attendance.InTime, + CheckOutTime = attendance.OutTime, + Activity = attendance.Activity + }; + result.Add(result1); } } _logger.LogInfo("{count} Attendance records fetched successfully", result.Count); @@ -280,6 +275,7 @@ namespace MarcoBMS.Services.Controllers } [HttpGet("project/team")] + /// /// Retrieves employee attendance records for a specified project and date. /// The result is filtered based on the logged-in employee's permissions (Team or Self). @@ -325,13 +321,17 @@ namespace MarcoBMS.Services.Controllers if (hasTeamAttendancePermission) { + if (!organizationId.HasValue) + { + organizationId = loggedInEmployee.OrganizationId; + } _logger.LogInfo("EmployeeId: {EmployeeId} has Team Attendance permission. Fetching team attendance.", loggedInEmployee.Id); - result = await GetTeamAttendanceAsync(tenantId, projectId, organizationId, forDate, includeInactive); + result = await GetTeamAttendanceAsync(tenantId, projectId, organizationId.Value, forDate, includeInactive); } else if (await _permission.HasPermission(PermissionsMaster.SelfAttendance, loggedInEmployee.Id)) { _logger.LogInfo("EmployeeId: {EmployeeId} has Self Attendance permission. Fetching self attendance.", loggedInEmployee.Id); - result = await GetSelfAttendanceAsync(tenantId, projectId, loggedInEmployee.Id, organizationId, forDate); + result = await GetSelfAttendanceAsync(tenantId, projectId, loggedInEmployee.Id, forDate); } else { @@ -813,50 +813,39 @@ namespace MarcoBMS.Services.Controllers /// /// Fetches attendance for an entire project team using a single, optimized database query. /// - private async Task> GetTeamAttendanceAsync(Guid tenantId, Guid projectId, Guid? organizationId, DateTime forDate, bool includeInactive) + private async Task> GetTeamAttendanceAsync(Guid tenantId, Guid projectId, Guid organizationId, DateTime forDate, bool includeInactive) { // This single query joins ProjectAllocations with Employees and performs a LEFT JOIN with Attendances. // This is far more efficient than fetching collections and joining them in memory. - var query = _context.ProjectAllocations - .Include(pa => pa.Employee) - .ThenInclude(e => e!.Organization) - .Include(pa => pa.Employee) - .ThenInclude(e => e!.JobRole) - .Where(pa => pa.TenantId == tenantId && pa.ProjectId == projectId); + var query = _context.Employees + .Include(e => e!.Organization) + .Include(e => e!.JobRole) + .Where(e => e.OrganizationId == organizationId && e.Organization != null && e.JobRole != null && e.IsActive); - // Apply filters based on optional parameters - if (!includeInactive) - { - query = query.Where(pa => pa.IsActive); - } - if (organizationId.HasValue) - { - query = query.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId); - } List lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId).ToListAsync(); - var teamAttendance = await query + var employees = await query .AsNoTracking() .ToListAsync(); - var response = teamAttendance - .Select(teamMember => + var response = employees + .Select(employee => { var result1 = new EmployeeAttendanceVM() { EmployeeAvatar = null, - EmployeeId = teamMember.EmployeeId, - FirstName = teamMember.Employee?.FirstName, - LastName = teamMember.Employee?.LastName, - OrganizationName = teamMember.Employee?.Organization?.Name, - JobRoleName = teamMember.Employee?.JobRole?.Name, + EmployeeId = employee.Id, + FirstName = employee.FirstName, + LastName = employee.LastName, + OrganizationName = employee.Organization!.Name, + JobRoleName = employee.JobRole!.Name, }; //var member = emp.Where(e => e.Id == teamMember.EmployeeId); - var attendance = lstAttendance.Find(x => x.EmployeeId == teamMember.EmployeeId) ?? new Attendance(); + var attendance = lstAttendance.Find(x => x.EmployeeId == employee.Id) ?? new Attendance(); if (attendance != null) { result1.Id = attendance.Id; @@ -875,7 +864,7 @@ namespace MarcoBMS.Services.Controllers /// /// Fetches a single attendance record for the logged-in employee. /// - private async Task> GetSelfAttendanceAsync(Guid tenantId, Guid projectId, Guid employeeId, Guid? organizationId, DateTime forDate) + private async Task> GetSelfAttendanceAsync(Guid tenantId, Guid projectId, Guid employeeId, DateTime forDate) { List result = new List(); @@ -883,29 +872,22 @@ namespace MarcoBMS.Services.Controllers Attendance lstAttendance = await _context.Attendes .FirstOrDefaultAsync(c => c.ProjectID == projectId && c.EmployeeId == employeeId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId) ?? new Attendance(); - var projectAllocationQuery = _context.ProjectAllocations - .Include(pa => pa.Employee) - .ThenInclude(e => e!.Organization) - .Where(pa => pa.ProjectId == projectId && pa.EmployeeId == employeeId && pa.TenantId == tenantId && pa.IsActive); + var employee = await _context.Employees + .Include(e => e.Organization) + .Include(e => e.JobRole) + .FirstOrDefaultAsync(e => e.Id == employeeId && e.IsActive); - if (organizationId.HasValue) - { - projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId); - } - - var projectAllocation = await projectAllocationQuery.FirstOrDefaultAsync(); - - if (projectAllocation != null) + if (employee != null && employee.JobRole != null && employee.Organization != null) { EmployeeAttendanceVM result1 = new EmployeeAttendanceVM { Id = lstAttendance.Id, EmployeeAvatar = null, - EmployeeId = projectAllocation.EmployeeId, - FirstName = projectAllocation.Employee?.FirstName, - OrganizationName = projectAllocation.Employee?.Organization?.Name, - LastName = projectAllocation.Employee?.LastName, - JobRoleName = projectAllocation.Employee?.JobRole?.Name, + EmployeeId = employee.Id, + FirstName = employee.FirstName, + OrganizationName = employee.Organization.Name, + LastName = employee.LastName, + JobRoleName = employee.JobRole.Name, CheckInTime = lstAttendance.InTime, CheckOutTime = lstAttendance.OutTime, Activity = lstAttendance.Activity diff --git a/Marco.Pms.Services/Controllers/TenantController.cs b/Marco.Pms.Services/Controllers/TenantController.cs index 0c11daf..caf9c83 100644 --- a/Marco.Pms.Services/Controllers/TenantController.cs +++ b/Marco.Pms.Services/Controllers/TenantController.cs @@ -273,12 +273,7 @@ namespace Marco.Pms.Services.Controllers return StatusCode(403, ApiResponse.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403)); } - if (!hasManagePermission && (hasModifyPermission || hasViewPermission) && id != loggedInEmployee.TenantId) - { - _logger.LogWarning("Permission denied: User {EmployeeId} attempted to access tenant details of other tenant.", loggedInEmployee.Id); - return StatusCode(403, - ApiResponse.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403)); - } + // Create a single DbContext for main tenant fetch and related data requests await using var _context = await _dbContextFactory.CreateDbContextAsync(); @@ -297,6 +292,13 @@ namespace Marco.Pms.Services.Controllers } _logger.LogInfo("Tenant {TenantId} found.", tenant.Id); + if (!hasManagePermission && (hasModifyPermission || hasViewPermission) && tenant.OrganizationId != loggedInEmployee.OrganizationId) + { + _logger.LogWarning("Permission denied: User {EmployeeId} attempted to access tenant details of other tenant.", loggedInEmployee.Id); + return StatusCode(403, + ApiResponse.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403)); + } + // Fetch dependent data in parallel to improve performance var employeesTask = Task.Run(async () => { @@ -550,7 +552,7 @@ namespace Marco.Pms.Services.Controllers JobRole = adminJobRole, // Link to the newly created role CurrentAddress = model.BillingAddress, IsActive = true, - IsSystem = false, + IsSystem = true, IsPrimary = true, OrganizationId = organization.Id, HasApplicationAccess = true @@ -566,43 +568,36 @@ namespace Marco.Pms.Services.Controllers }; _context.ApplicationRoles.Add(applicationRole); - var rolePermissionMappigs = new List { - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.ModifyTenant - }, - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.ViewTenant - }, - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.ManageMasters - }, - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.ViewMasters - }, - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.ViewOrganization - }, - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.AddOrganization - }, - new RolePermissionMappings - { - ApplicationRoleId = applicationRole.Id, - FeaturePermissionId = PermissionsMaster.EditOrganization - } + var featureIds = new List + { + new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), // Expense Management feature + new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), // Employee Management feature + new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), // Attendance Management feature + new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), // Document Management feature + new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), // Masters Management feature + new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), // Directory Management feature + new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914") // Organization Management feature }; + + var permissionIds = await _context.FeaturePermissions.Where(fp => featureIds.Contains(fp.FeatureId)).Select(fp => fp.Id).ToListAsync(); + + var rolePermissionMappigs = permissionIds.Select(p => new RolePermissionMappings + { + ApplicationRoleId = applicationRole.Id, + FeaturePermissionId = p + }).ToList(); + + rolePermissionMappigs.Add(new RolePermissionMappings + { + ApplicationRoleId = applicationRole.Id, + FeaturePermissionId = PermissionsMaster.ModifyTenant + }); + rolePermissionMappigs.Add(new RolePermissionMappings + { + ApplicationRoleId = applicationRole.Id, + FeaturePermissionId = PermissionsMaster.ViewTenant + }); + _context.RolePermissionMappings.AddRange(rolePermissionMappigs); _context.EmployeeRoleMappings.Add(new EmployeeRoleMapping @@ -651,6 +646,22 @@ namespace Marco.Pms.Services.Controllers _context.OrgServiceMappings.AddRange(serviceOrgMappings); } + var _masteData = scope.ServiceProvider.GetRequiredService(); + + var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id); + var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id); + var documentCategoryMaster = _masteData.GetDocumentCategoryData(tenant.Id); + + var employeeDocumentId = documentCategoryMaster.Where(dc => dc.Name == "Employee Documents").Select(dc => dc.Id).FirstOrDefault(); + var projectDocumentId = documentCategoryMaster.Where(dc => dc.Name == "Project Documents").Select(dc => dc.Id).FirstOrDefault(); + + var documentTypeMaster = _masteData.GetDocumentTypeData(tenant.Id, employeeDocumentId, projectDocumentId); + + _context.ExpensesTypeMaster.AddRange(expensesTypeMaster); + _context.PaymentModeMatser.AddRange(paymentModeMatser); + _context.DocumentCategoryMasters.AddRange(documentCategoryMaster); + _context.DocumentTypeMasters.AddRange(documentTypeMaster); + // All entities are now added to the context. Save them all in a single database operation. await _context.SaveChangesAsync(); diff --git a/Marco.Pms.Services/Helpers/GeneralHelper.cs b/Marco.Pms.Services/Helpers/GeneralHelper.cs index c983b84..2c4b35f 100644 --- a/Marco.Pms.Services/Helpers/GeneralHelper.cs +++ b/Marco.Pms.Services/Helpers/GeneralHelper.cs @@ -253,16 +253,29 @@ namespace Marco.Pms.Services.Helpers !ts.IsCancelled && ts.EndDate.Date >= DateTime.UtcNow.Date); // FIX: Subscription should not be expired + var featureIds = new List + { + new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), // Expense Management feature + new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), // Employee Management feature + new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), // Attendance Management feature + new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), // Document Management feature + new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), // Masters Management feature + new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), // Directory Management feature + new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914"), // Organization Management feature + new Guid("2f3509b7-160d-410a-b9b6-daadd96c986d") // Tenant Management feature + }; + if (tenantSubscription == null) { _logger.LogWarning("No active subscription found for tenant: {TenantId}", tenantId); - return new List(); + return featureIds; } _logger.LogDebug("Active subscription found for tenant: {TenantId}, PlanId: {PlanId}", tenantId, tenantSubscription.Plan!.Id); - var featureIds = new List { new Guid("2f3509b7-160d-410a-b9b6-daadd96c986d"), new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be") }; + //var featureIds = new List { new Guid("2f3509b7-160d-410a-b9b6-daadd96c986d"), new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be") }; + // Step 2: Get feature details from Plan var featureDetails = await _featureDetailsHelper.GetFeatureDetails(tenantSubscription.Plan!.FeaturesId); diff --git a/Marco.Pms.Services/Service/MasterDataService.cs b/Marco.Pms.Services/Service/MasterDataService.cs index 7e4a735..e8f0997 100644 --- a/Marco.Pms.Services/Service/MasterDataService.cs +++ b/Marco.Pms.Services/Service/MasterDataService.cs @@ -1,4 +1,5 @@ -using Marco.Pms.Model.Forum; +using Marco.Pms.Model.DocumentManager; +using Marco.Pms.Model.Forum; using Marco.Pms.Model.Master; namespace Marco.Pms.Services.Service @@ -335,6 +336,194 @@ namespace Marco.Pms.Services.Service } }; } + public List GetDocumentCategoryData(Guid tenantId) + { + return new List { + new DocumentCategoryMaster + { + Id = Guid.NewGuid(), + Name = "Project Documents", + Description = "Project documents are formal records that outline the plans, progress, and details necessary to execute and manage a project effectively.", + EntityTypeId = Guid.Parse("c8fe7115-aa27-43bc-99f4-7b05fabe436e"), + CreatedAt = new DateTime(2025, 9, 15, 12, 42, 3, 202, DateTimeKind.Utc), + TenantId = tenantId + }, + new DocumentCategoryMaster + { + Id = Guid.NewGuid(), + Name = "Employee Documents", + Description = "Employment details along with legal IDs like passports or driver’s licenses to verify identity and work authorization.", + EntityTypeId = Guid.Parse("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"), + CreatedAt = new DateTime(2025, 9, 15, 12, 42, 3, 202, DateTimeKind.Utc), + TenantId = tenantId + } + }; + } + public List GetDocumentTypeData(Guid tenantId, Guid employeeDocumentId, Guid projectDocumentId) + { + return new List { + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Aadhaar card", + RegexExpression = "^[2-9][0-9]{11}$", + AllowedContentType = "application/pdf,image/jpeg", + MaxSizeAllowedInMB = 2, + IsValidationRequired = true, + IsMandatory = true, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = employeeDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Pan Card", + RegexExpression = "^[A-Z]{5}[0-9]{4}[A-Z]{1}$", + AllowedContentType = "application/pdf,image/jpeg", + MaxSizeAllowedInMB = 2, + IsValidationRequired = true, + IsMandatory = true, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = employeeDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Voter Card", + RegexExpression = "^[A-Z]{3}[0-9]{7}$", + AllowedContentType = "application/pdf,image/jpeg", + MaxSizeAllowedInMB = 2, + IsValidationRequired = true, + IsMandatory = true, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = employeeDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Passport", + RegexExpression = "^[A-PR-WY][1-9]\\d\\s?\\d{4}[1-9]$", + AllowedContentType = "application/pdf,image/jpeg", + MaxSizeAllowedInMB = 2, + IsValidationRequired = true, + IsMandatory = true, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = employeeDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Bank Passbook", + RegexExpression = "^\\d{9,18}$", + AllowedContentType = "application/pdf,image/jpeg", + MaxSizeAllowedInMB = 2, + IsValidationRequired = true, + IsMandatory = true, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = employeeDocumentId, + TenantId = tenantId + }, + + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Bill of Quantities (BOQ)", + AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", + MaxSizeAllowedInMB = 1, + IsValidationRequired = false, + IsMandatory = false, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = projectDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Work Order", + AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", + MaxSizeAllowedInMB = 1, + IsValidationRequired = false, + IsMandatory = false, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = projectDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Letter of Agreement", + AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", + MaxSizeAllowedInMB = 1, + IsValidationRequired = false, + IsMandatory = false, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = projectDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Health and Safety Document", + AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", + MaxSizeAllowedInMB = 1, + IsValidationRequired = false, + IsMandatory = false, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = projectDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Standard Operating Procedure (SOP)", + AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", + MaxSizeAllowedInMB = 1, + IsValidationRequired = false, + IsMandatory = false, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = projectDocumentId, + TenantId = tenantId + }, + new DocumentTypeMaster + { + Id = Guid.NewGuid(), + Name = "Drawings", + AllowedContentType = "application/pdf,image/vnd.dwg,application/acad", + MaxSizeAllowedInMB = 20, + IsValidationRequired = false, + IsMandatory = false, + CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc), + IsSystem = true, + IsActive = true, + DocumentCategoryId = projectDocumentId, + TenantId = tenantId + } + }; + } public List GetData(Guid tenantId) { return new List