Solved the rebase issues

This commit is contained in:
ashutosh.nehete 2025-09-09 16:33:23 +05:30
commit 7324537a90
58 changed files with 38807 additions and 622 deletions

View File

@ -59,6 +59,7 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<Module> Modules { get; set; } public DbSet<Module> Modules { get; set; }
public DbSet<Feature> Features { get; set; } public DbSet<Feature> Features { get; set; }
public DbSet<FeaturePermission> FeaturePermissions { get; set; } public DbSet<FeaturePermission> FeaturePermissions { get; set; }
public DbSet<ProjectLevelPermissionMapping> ProjectLevelPermissionMappings { get; set; }
public DbSet<CurrencyMaster> CurrencyMaster { get; set; } public DbSet<CurrencyMaster> CurrencyMaster { get; set; }
public DbSet<ApplicationRole> ApplicationRoles { get; set; } public DbSet<ApplicationRole> ApplicationRoles { get; set; }
public DbSet<JobRole> JobRoles { get; set; } public DbSet<JobRole> JobRoles { get; set; }
@ -108,6 +109,13 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<StatusPermissionMapping> StatusPermissionMapping { get; set; } public DbSet<StatusPermissionMapping> StatusPermissionMapping { get; set; }
public DbSet<ExpensesStatusMapping> ExpensesStatusMapping { get; set; } public DbSet<ExpensesStatusMapping> ExpensesStatusMapping { get; set; }
public DbSet<EntityTypeMaster> EntityTypeMasters { get; set; }
public DbSet<DocumentTypeMaster> DocumentTypeMasters { get; set; }
public DbSet<DocumentCategoryMaster> DocumentCategoryMasters { get; set; }
public DbSet<DocumentTagMaster> DocumentTagMasters { get; set; }
public DbSet<DocumentAttachment> DocumentAttachments { get; set; }
public DbSet<AttachmentVersionMapping> AttachmentVersionMappings { get; set; }
public DbSet<AttachmentTagMapping> AttachmentTagMappings { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
@ -720,6 +728,205 @@ namespace Marco.Pms.DataAccess.Data
} }
); );
modelBuilder.Entity<EntityTypeMaster>().HasData(
new EntityTypeMaster
{
Id = Guid.Parse("c8fe7115-aa27-43bc-99f4-7b05fabe436e"),
Name = "Project Entity",
Description = "Emtities related to project."
},
new EntityTypeMaster
{
Id = Guid.Parse("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"),
Name = "Employee Entity",
Description = "Employee related entitie",
}
);
modelBuilder.Entity<DocumentCategoryMaster>().HasData(
new DocumentCategoryMaster
{
Id = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
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 = DateTime.UtcNow,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentCategoryMaster
{
Id = Guid.Parse("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
Name = "Employee Documents",
Description = "Employment details along with legal IDs like passports or drivers licenses to verify identity and work authorization.",
EntityTypeId = Guid.Parse("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"),
CreatedAt = DateTime.UtcNow,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
}
);
modelBuilder.Entity<DocumentTypeMaster>().HasData(
new DocumentTypeMaster
{
Id = Guid.Parse("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
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 = Guid.Parse("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("6344393b-9bb1-45f8-b620-9f6e279d012c"),
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 = Guid.Parse("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("2d1d7441-46a8-425e-9395-94d0956f8e91"),
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 = Guid.Parse("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("16c40b80-c207-4a0c-a4d3-381414afe35a"),
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 = Guid.Parse("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("f76d8215-d399-4f0e-b414-12e427f50be3"),
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 = Guid.Parse("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
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 = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
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 = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("07ca7182-9ac0-4407-b988-59901170cb86"),
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 = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("846e89a9-5735-45ec-a21d-c97f85a94ada"),
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 = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("7cc41c91-23cb-442b-badd-f932138d149f"),
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 = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new DocumentTypeMaster
{
Id = Guid.Parse("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
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 = Guid.Parse("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
}
);
modelBuilder.Entity<SubscriptionStatus>().HasData( modelBuilder.Entity<SubscriptionStatus>().HasData(
new SubscriptionStatus new SubscriptionStatus
{ {
@ -777,6 +984,7 @@ namespace Marco.Pms.DataAccess.Data
// Employee Module // Employee Module
new Feature { Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), Description = "Manage Employee", Name = "Employee Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true }, new Feature { Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), Description = "Manage Employee", Name = "Employee Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true },
new Feature { Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), Description = "Attendance", Name = "Attendance Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true }, new Feature { Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), Description = "Attendance", Name = "Attendance Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true },
new Feature { Id = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), Description = "Manage Document", Name = "Document Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true },
new Feature { Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), Description = "Global Masters", Name = "Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true }, new Feature { Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), Description = "Global Masters", Name = "Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true },
new Feature { Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), Description = "Managing all directory related rights", Name = "Directory Management", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true }, new Feature { Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), Description = "Managing all directory related rights", Name = "Directory Management", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true },
@ -817,6 +1025,14 @@ namespace Marco.Pms.DataAccess.Data
new FeaturePermission { Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "View Masters", Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency" }, new FeaturePermission { Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "View Masters", Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency" },
new FeaturePermission { Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "Manage Masters", Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories" }, new FeaturePermission { Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "Manage Masters", Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories" },
//Document Management Feature
new FeaturePermission { Id = new Guid("71189504-f1c8-4ca5-8db6-810497be2854"), FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), IsEnabled = true, Name = "View Document", Description = "Grants a user the authority to view all documents related to employees and projects" },
new FeaturePermission { Id = new Guid("3f6d1f67-6fa5-4b7c-b17b-018d4fe4aab8"), FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), IsEnabled = true, Name = "Upload Document", Description = "Grants a user the authority to upload the document" },
new FeaturePermission { Id = new Guid("c423fd81-6273-4b9d-bb5e-76a0fb343833"), FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), IsEnabled = true, Name = "Mofify Document", Description = "Grants a user the authority to modify document" },
new FeaturePermission { Id = new Guid("40863a13-5a66-469d-9b48-135bc5dbf486"), FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), IsEnabled = true, Name = "Delete Document", Description = "Grants a user the authority to delete the document" },
new FeaturePermission { Id = new Guid("404373d0-860f-490e-a575-1c086ffbce1d"), FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), IsEnabled = true, Name = "Download Document", Description = "Grants a user the authority to download the document" },
new FeaturePermission { Id = new Guid("13a1f30f-38d1-41bf-8e7a-b75189aab8e0"), FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), IsEnabled = true, Name = "Verify Document", Description = "Grants a user the authority to verify the document" },
// Directory Management Feature // Directory Management Feature
new FeaturePermission { Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Admin", Description = "Full control over all directories, including the ability to manage permissions for all directories in the system." }, new FeaturePermission { Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Admin", Description = "Full control over all directories, including the ability to manage permissions for all directories in the system." },
new FeaturePermission { Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Manager", Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories." }, new FeaturePermission { Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Manager", Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories." },

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,488 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_Document_Manager_Tables : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "DocumentTagMasters",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_DocumentTagMasters", x => x.Id);
table.ForeignKey(
name: "FK_DocumentTagMasters_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "EntityTypeMasters",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_EntityTypeMasters", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "DocumentCategoryMasters",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
EntityTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_DocumentCategoryMasters", x => x.Id);
table.ForeignKey(
name: "FK_DocumentCategoryMasters_EntityTypeMasters_EntityTypeId",
column: x => x.EntityTypeId,
principalTable: "EntityTypeMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentCategoryMasters_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "DocumentTypeMasters",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
RegexExpression = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
AllowedContentType = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
MaxSizeAllowedInMB = table.Column<double>(type: "double", nullable: false),
IsValidationRequired = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsMandatory = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsSystem = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
DocumentCategoryId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_DocumentTypeMasters", x => x.Id);
table.ForeignKey(
name: "FK_DocumentTypeMasters_DocumentCategoryMasters_DocumentCategory~",
column: x => x.DocumentCategoryId,
principalTable: "DocumentCategoryMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentTypeMasters_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "DocumentAttachments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DocumentId = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UploadedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UploadedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
VerifiedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
IsVerified = table.Column<bool>(type: "tinyint(1)", nullable: true),
VerifiedById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
EntityId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_DocumentAttachments", x => x.Id);
table.ForeignKey(
name: "FK_DocumentAttachments_DocumentTypeMasters_DocumentTypeId",
column: x => x.DocumentTypeId,
principalTable: "DocumentTypeMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentAttachments_Employees_UpdatedById",
column: x => x.UpdatedById,
principalTable: "Employees",
principalColumn: "Id");
table.ForeignKey(
name: "FK_DocumentAttachments_Employees_UploadedById",
column: x => x.UploadedById,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentAttachments_Employees_VerifiedById",
column: x => x.VerifiedById,
principalTable: "Employees",
principalColumn: "Id");
table.ForeignKey(
name: "FK_DocumentAttachments_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AttachmentTagMappings",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentTagId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
AttachmentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_AttachmentTagMappings", x => x.Id);
table.ForeignKey(
name: "FK_AttachmentTagMappings_DocumentAttachments_AttachmentId",
column: x => x.AttachmentId,
principalTable: "DocumentAttachments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AttachmentTagMappings_DocumentTagMasters_DocumentTagId",
column: x => x.DocumentTagId,
principalTable: "DocumentTagMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AttachmentTagMappings_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AttachmentVersionMappings",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
ParentAttachmentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Version = table.Column<int>(type: "int", nullable: false),
ChildAttachmentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_AttachmentVersionMappings", x => x.Id);
table.ForeignKey(
name: "FK_AttachmentVersionMappings_DocumentAttachments_ChildAttachmen~",
column: x => x.ChildAttachmentId,
principalTable: "DocumentAttachments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AttachmentVersionMappings_DocumentAttachments_ParentAttachme~",
column: x => x.ParentAttachmentId,
principalTable: "DocumentAttachments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AttachmentVersionMappings_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "DocumentAttachmentMappings",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
AttachmentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_DocumentAttachmentMappings", x => x.Id);
table.ForeignKey(
name: "FK_DocumentAttachmentMappings_DocumentAttachments_AttachmentId",
column: x => x.AttachmentId,
principalTable: "DocumentAttachments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentAttachmentMappings_Documents_DocumentId",
column: x => x.DocumentId,
principalTable: "Documents",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentAttachmentMappings_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "EntityTypeMasters",
columns: new[] { "Id", "Description", "Name" },
values: new object[,]
{
{ new Guid("c8fe7115-aa27-43bc-99f4-7b05fabe436e"), "Emtities related to project.", "Project Entity" },
{ new Guid("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"), "Employee related entitie", "Employee Entity" }
});
migrationBuilder.InsertData(
table: "Features",
columns: new[] { "Id", "Description", "IsActive", "ModuleId", "Name" },
values: new object[] { new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), "Manage Document", true, new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), "Document Management" });
migrationBuilder.InsertData(
table: "DocumentCategoryMasters",
columns: new[] { "Id", "CreatedAt", "Description", "EntityTypeId", "Name", "TenantId" },
values: new object[,]
{
{ new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"), new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8157), "Employment details along with legal IDs like passports or drivers licenses to verify identity and work authorization.", new Guid("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"), "Employee Documents", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8150), "Project documents are formal records that outline the plans, progress, and details necessary to execute and manage a project effectively.", new Guid("c8fe7115-aa27-43bc-99f4-7b05fabe436e"), "Project Documents", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
});
migrationBuilder.InsertData(
table: "FeaturePermissions",
columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" },
values: new object[,]
{
{ new Guid("13a1f30f-38d1-41bf-8e7a-b75189aab8e0"), "Grants a user the authority to verify the document", new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), true, "Verify Document" },
{ new Guid("3f6d1f67-6fa5-4b7c-b17b-018d4fe4aab8"), "Grants a user the authority to upload the document", new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), true, "Upload Document" },
{ new Guid("40863a13-5a66-469d-9b48-135bc5dbf486"), "Grants a user the authority to delete the document", new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), true, "Delete Document" },
{ new Guid("71189504-f1c8-4ca5-8db6-810497be2854"), "Grants a user the authority to view all documents related to employees and projects", new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), true, "View Document" },
{ new Guid("c423fd81-6273-4b9d-bb5e-76a0fb343833"), "Grants a user the authority to modify document", new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), true, "Mofify Document" }
});
migrationBuilder.InsertData(
table: "DocumentTypeMasters",
columns: new[] { "Id", "AllowedContentType", "CreatedAt", "DocumentCategoryId", "IsActive", "IsMandatory", "IsSystem", "IsValidationRequired", "MaxSizeAllowedInMB", "Name", "RegexExpression", "TenantId" },
values: new object[,]
{
{ new Guid("07ca7182-9ac0-4407-b988-59901170cb86"), "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8229), new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), true, false, true, false, 1.0, "Letter of Agreement", null, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"), "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8216), new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"), true, true, true, true, 2.0, "Passport", "^[A-PR-WY][1-9]\\d\\s?\\d{4}[1-9]$", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"), "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8222), new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), true, false, true, false, 1.0, "Bill of Quantities (BOQ)", null, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"), "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8212), new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"), true, true, true, true, 2.0, "Voter Card", "^[A-Z]{3}[0-9]{7}$", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"), "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8204), new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"), true, true, true, true, 2.0, "Aadhaar card", "^[2-9][0-9]{11}$", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"), "application/pdf,image/vnd.dwg,application/acad", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8238), new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), true, false, true, false, 20.0, "Drawings", null, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"), "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8209), new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"), true, true, true, true, 2.0, "Pan Card", "^[A-Z]{5}[0-9]{4}[A-Z]{1}$", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("7cc41c91-23cb-442b-badd-f932138d149f"), "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8235), new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), true, false, true, false, 1.0, "Standard Operating Procedure (SOP)", null, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"), "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8232), new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), true, false, true, false, 1.0, "Health and Safety Document", null, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"), "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8226), new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"), true, false, true, false, 1.0, "Work Order", null, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"), "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8219), new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"), true, true, true, true, 2.0, "Bank Passbook", "^\\d{9,18}$", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
});
migrationBuilder.CreateIndex(
name: "IX_AttachmentTagMappings_AttachmentId",
table: "AttachmentTagMappings",
column: "AttachmentId");
migrationBuilder.CreateIndex(
name: "IX_AttachmentTagMappings_DocumentTagId",
table: "AttachmentTagMappings",
column: "DocumentTagId");
migrationBuilder.CreateIndex(
name: "IX_AttachmentTagMappings_TenantId",
table: "AttachmentTagMappings",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_AttachmentVersionMappings_ChildAttachmentId",
table: "AttachmentVersionMappings",
column: "ChildAttachmentId");
migrationBuilder.CreateIndex(
name: "IX_AttachmentVersionMappings_ParentAttachmentId",
table: "AttachmentVersionMappings",
column: "ParentAttachmentId");
migrationBuilder.CreateIndex(
name: "IX_AttachmentVersionMappings_TenantId",
table: "AttachmentVersionMappings",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachmentMappings_AttachmentId",
table: "DocumentAttachmentMappings",
column: "AttachmentId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachmentMappings_DocumentId",
table: "DocumentAttachmentMappings",
column: "DocumentId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachmentMappings_TenantId",
table: "DocumentAttachmentMappings",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachments_DocumentTypeId",
table: "DocumentAttachments",
column: "DocumentTypeId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachments_TenantId",
table: "DocumentAttachments",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachments_UpdatedById",
table: "DocumentAttachments",
column: "UpdatedById");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachments_UploadedById",
table: "DocumentAttachments",
column: "UploadedById");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachments_VerifiedById",
table: "DocumentAttachments",
column: "VerifiedById");
migrationBuilder.CreateIndex(
name: "IX_DocumentCategoryMasters_EntityTypeId",
table: "DocumentCategoryMasters",
column: "EntityTypeId");
migrationBuilder.CreateIndex(
name: "IX_DocumentCategoryMasters_TenantId",
table: "DocumentCategoryMasters",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_DocumentTagMasters_TenantId",
table: "DocumentTagMasters",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_DocumentTypeMasters_DocumentCategoryId",
table: "DocumentTypeMasters",
column: "DocumentCategoryId");
migrationBuilder.CreateIndex(
name: "IX_DocumentTypeMasters_TenantId",
table: "DocumentTypeMasters",
column: "TenantId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AttachmentTagMappings");
migrationBuilder.DropTable(
name: "AttachmentVersionMappings");
migrationBuilder.DropTable(
name: "DocumentAttachmentMappings");
migrationBuilder.DropTable(
name: "DocumentTagMasters");
migrationBuilder.DropTable(
name: "DocumentAttachments");
migrationBuilder.DropTable(
name: "DocumentTypeMasters");
migrationBuilder.DropTable(
name: "DocumentCategoryMasters");
migrationBuilder.DropTable(
name: "EntityTypeMasters");
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("13a1f30f-38d1-41bf-8e7a-b75189aab8e0"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("3f6d1f67-6fa5-4b7c-b17b-018d4fe4aab8"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("40863a13-5a66-469d-9b48-135bc5dbf486"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("71189504-f1c8-4ca5-8db6-810497be2854"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("c423fd81-6273-4b9d-bb5e-76a0fb343833"));
migrationBuilder.DeleteData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"));
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,285 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Removed_DocumentAttachmentyMapping_And_Added : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DocumentAttachmentMappings");
migrationBuilder.AddColumn<Guid>(
name: "DocumentDataId",
table: "DocumentAttachments",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
collation: "ascii_general_ci");
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7895));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7887));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7995));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf,image/jpeg", new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7975) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7984));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf,image/jpeg", new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7971) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf,image/jpeg", new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7958) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(8008));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf,image/jpeg", new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7966) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(8004));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(8000));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7991));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf,image/jpeg", new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7980) });
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachments_DocumentDataId",
table: "DocumentAttachments",
column: "DocumentDataId");
migrationBuilder.AddForeignKey(
name: "FK_DocumentAttachments_Documents_DocumentDataId",
table: "DocumentAttachments",
column: "DocumentDataId",
principalTable: "Documents",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_DocumentAttachments_Documents_DocumentDataId",
table: "DocumentAttachments");
migrationBuilder.DropIndex(
name: "IX_DocumentAttachments_DocumentDataId",
table: "DocumentAttachments");
migrationBuilder.DropColumn(
name: "DocumentDataId",
table: "DocumentAttachments");
migrationBuilder.CreateTable(
name: "DocumentAttachmentMappings",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
AttachmentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_DocumentAttachmentMappings", x => x.Id);
table.ForeignKey(
name: "FK_DocumentAttachmentMappings_DocumentAttachments_AttachmentId",
column: x => x.AttachmentId,
principalTable: "DocumentAttachments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentAttachmentMappings_Documents_DocumentId",
column: x => x.DocumentId,
principalTable: "Documents",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DocumentAttachmentMappings_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8157));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8150));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8229));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8216) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8222));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8212) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8204) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8238));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8209) });
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8235));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8232));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8226));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
columns: new[] { "AllowedContentType", "CreatedAt" },
values: new object[] { "application/pdf", new DateTime(2025, 8, 28, 5, 50, 2, 39, DateTimeKind.Utc).AddTicks(8219) });
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachmentMappings_AttachmentId",
table: "DocumentAttachmentMappings",
column: "AttachmentId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachmentMappings_DocumentId",
table: "DocumentAttachmentMappings",
column: "DocumentId");
migrationBuilder.CreateIndex(
name: "IX_DocumentAttachmentMappings_TenantId",
table: "DocumentAttachmentMappings",
column: "TenantId");
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,212 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_IsCurrentVersion_Field_In_Document_Attachment : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsCurrentVersion",
table: "DocumentAttachments",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1227));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1217));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1308));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1293));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1300));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1289));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1275));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1391));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1284));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1388));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1384));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1305));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1297));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsCurrentVersion",
table: "DocumentAttachments");
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7895));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7887));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7995));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7975));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7984));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7971));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7958));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(8008));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7966));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(8004));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(8000));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7991));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 9, 22, 46, 902, DateTimeKind.Utc).AddTicks(7980));
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,237 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Modified_UpdatedAt_And_VerifiedAt_To_Nullable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "VerifiedAt",
table: "DocumentAttachments",
type: "datetime(6)",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime(6)");
migrationBuilder.AlterColumn<DateTime>(
name: "UpdatedAt",
table: "DocumentAttachments",
type: "datetime(6)",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime(6)");
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(8988));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(8981));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9059));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9042));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9051));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9038));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9028));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9072));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9034));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9068));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9063));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9055));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9046));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "VerifiedAt",
table: "DocumentAttachments",
type: "datetime(6)",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime(6)",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "UpdatedAt",
table: "DocumentAttachments",
type: "datetime(6)",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime(6)",
oldNullable: true);
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1227));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1217));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1308));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1293));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1300));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1289));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1275));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1391));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1284));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1388));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1384));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1305));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 11, 44, 468, DateTimeKind.Utc).AddTicks(1297));
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,211 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_New_Permission_To_Download_Document : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2627));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2617));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2718));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2700));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2710));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2695));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2684));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2731));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2690));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2727));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2722));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2714));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2705));
migrationBuilder.InsertData(
table: "FeaturePermissions",
columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" },
values: new object[] { new Guid("404373d0-860f-490e-a575-1c086ffbce1d"), "Grants a user the authority to download the document", new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), true, "Download Document" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("404373d0-860f-490e-a575-1c086ffbce1d"));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(8988));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(8981));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9059));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9042));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9051));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9038));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9028));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9072));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9034));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9068));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9063));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9055));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 28, 11, 18, 55, 873, DateTimeKind.Utc).AddTicks(9046));
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,264 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_Project_Level_Permssion_Mapping_Table : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ProjectLevelPermissionMappings",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
EmployeeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
ProjectId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
PermissionId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_ProjectLevelPermissionMappings", x => x.Id);
table.ForeignKey(
name: "FK_ProjectLevelPermissionMappings_Employees_EmployeeId",
column: x => x.EmployeeId,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ProjectLevelPermissionMappings_FeaturePermissions_Permission~",
column: x => x.PermissionId,
principalTable: "FeaturePermissions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ProjectLevelPermissionMappings_Projects_ProjectId",
column: x => x.ProjectId,
principalTable: "Projects",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ProjectLevelPermissionMappings_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6233));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6226));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6307));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6290));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6298));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6286));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6275));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6319));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6282));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6314));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6311));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6302));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6295));
migrationBuilder.CreateIndex(
name: "IX_ProjectLevelPermissionMappings_EmployeeId",
table: "ProjectLevelPermissionMappings",
column: "EmployeeId");
migrationBuilder.CreateIndex(
name: "IX_ProjectLevelPermissionMappings_PermissionId",
table: "ProjectLevelPermissionMappings",
column: "PermissionId");
migrationBuilder.CreateIndex(
name: "IX_ProjectLevelPermissionMappings_ProjectId",
table: "ProjectLevelPermissionMappings",
column: "ProjectId");
migrationBuilder.CreateIndex(
name: "IX_ProjectLevelPermissionMappings_TenantId",
table: "ProjectLevelPermissionMappings",
column: "TenantId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ProjectLevelPermissionMappings");
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2627));
migrationBuilder.UpdateData(
table: "DocumentCategoryMasters",
keyColumn: "Id",
keyValue: new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2617));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2718));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2700));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2710));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2695));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2684));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2731));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2690));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2727));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2722));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2714));
migrationBuilder.UpdateData(
table: "DocumentTypeMasters",
keyColumn: "Id",
keyValue: new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
column: "CreatedAt",
value: new DateTime(2025, 8, 30, 4, 55, 10, 359, DateTimeKind.Utc).AddTicks(2705));
}
}
}

View File

@ -720,6 +720,61 @@ namespace Marco.Pms.DataAccess.Migrations
b.ToTable("EmployeeBucketMappings"); b.ToTable("EmployeeBucketMappings");
}); });
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.AttachmentTagMapping", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("AttachmentId")
.HasColumnType("char(36)");
b.Property<Guid>("DocumentTagId")
.HasColumnType("char(36)");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("AttachmentId");
b.HasIndex("DocumentTagId");
b.HasIndex("TenantId");
b.ToTable("AttachmentTagMappings");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.AttachmentVersionMapping", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("ChildAttachmentId")
.HasColumnType("char(36)");
b.Property<Guid>("ParentAttachmentId")
.HasColumnType("char(36)");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ChildAttachmentId");
b.HasIndex("ParentAttachmentId");
b.HasIndex("TenantId");
b.ToTable("AttachmentVersionMappings");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -768,6 +823,366 @@ namespace Marco.Pms.DataAccess.Migrations
b.ToTable("Documents"); b.ToTable("Documents");
}); });
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentAttachment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("DocumentDataId")
.HasColumnType("char(36)");
b.Property<string>("DocumentId")
.HasColumnType("longtext");
b.Property<Guid>("DocumentTypeId")
.HasColumnType("char(36)");
b.Property<Guid>("EntityId")
.HasColumnType("char(36)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsCurrentVersion")
.HasColumnType("tinyint(1)");
b.Property<bool?>("IsVerified")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid?>("UpdatedById")
.HasColumnType("char(36)");
b.Property<DateTime>("UploadedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("UploadedById")
.HasColumnType("char(36)");
b.Property<DateTime?>("VerifiedAt")
.HasColumnType("datetime(6)");
b.Property<Guid?>("VerifiedById")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("DocumentDataId");
b.HasIndex("DocumentTypeId");
b.HasIndex("TenantId");
b.HasIndex("UpdatedById");
b.HasIndex("UploadedById");
b.HasIndex("VerifiedById");
b.ToTable("DocumentAttachments");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentCategoryMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("EntityTypeId")
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("EntityTypeId");
b.HasIndex("TenantId");
b.ToTable("DocumentCategoryMasters");
b.HasData(
new
{
Id = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6226),
Description = "Project documents are formal records that outline the plans, progress, and details necessary to execute and manage a project effectively.",
EntityTypeId = new Guid("c8fe7115-aa27-43bc-99f4-7b05fabe436e"),
Name = "Project Documents",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6233),
Description = "Employment details along with legal IDs like passports or drivers licenses to verify identity and work authorization.",
EntityTypeId = new Guid("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"),
Name = "Employee Documents",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
});
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentTagMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId");
b.ToTable("DocumentTagMasters");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentTypeMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("AllowedContentType")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("DocumentCategoryId")
.HasColumnType("char(36)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsMandatory")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsSystem")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsValidationRequired")
.HasColumnType("tinyint(1)");
b.Property<double>("MaxSizeAllowedInMB")
.HasColumnType("double");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RegexExpression")
.HasColumnType("longtext");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("DocumentCategoryId");
b.HasIndex("TenantId");
b.ToTable("DocumentTypeMasters");
b.HasData(
new
{
Id = new Guid("336225ac-67f3-4e14-ba7a-8fad03cf2832"),
AllowedContentType = "application/pdf,image/jpeg",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6275),
DocumentCategoryId = new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
IsActive = true,
IsMandatory = true,
IsSystem = true,
IsValidationRequired = true,
MaxSizeAllowedInMB = 2.0,
Name = "Aadhaar card",
RegexExpression = "^[2-9][0-9]{11}$",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("6344393b-9bb1-45f8-b620-9f6e279d012c"),
AllowedContentType = "application/pdf,image/jpeg",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6282),
DocumentCategoryId = new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
IsActive = true,
IsMandatory = true,
IsSystem = true,
IsValidationRequired = true,
MaxSizeAllowedInMB = 2.0,
Name = "Pan Card",
RegexExpression = "^[A-Z]{5}[0-9]{4}[A-Z]{1}$",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("2d1d7441-46a8-425e-9395-94d0956f8e91"),
AllowedContentType = "application/pdf,image/jpeg",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6286),
DocumentCategoryId = new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
IsActive = true,
IsMandatory = true,
IsSystem = true,
IsValidationRequired = true,
MaxSizeAllowedInMB = 2.0,
Name = "Voter Card",
RegexExpression = "^[A-Z]{3}[0-9]{7}$",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("16c40b80-c207-4a0c-a4d3-381414afe35a"),
AllowedContentType = "application/pdf,image/jpeg",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6290),
DocumentCategoryId = new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
IsActive = true,
IsMandatory = true,
IsSystem = true,
IsValidationRequired = true,
MaxSizeAllowedInMB = 2.0,
Name = "Passport",
RegexExpression = "^[A-PR-WY][1-9]\\d\\s?\\d{4}[1-9]$",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("f76d8215-d399-4f0e-b414-12e427f50be3"),
AllowedContentType = "application/pdf,image/jpeg",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6295),
DocumentCategoryId = new Guid("2d9fb9cf-db53-476b-a452-492e88e2b51f"),
IsActive = true,
IsMandatory = true,
IsSystem = true,
IsValidationRequired = true,
MaxSizeAllowedInMB = 2.0,
Name = "Bank Passbook",
RegexExpression = "^\\d{9,18}$",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("260abd7e-c96d-4ae4-a29b-9b5bb5d24ebd"),
AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6298),
DocumentCategoryId = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
IsActive = true,
IsMandatory = false,
IsSystem = true,
IsValidationRequired = false,
MaxSizeAllowedInMB = 1.0,
Name = "Bill of Quantities (BOQ)",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("a1a190ba-c4a8-432f-b26d-1231ca1d44bc"),
AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6302),
DocumentCategoryId = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
IsActive = true,
IsMandatory = false,
IsSystem = true,
IsValidationRequired = false,
MaxSizeAllowedInMB = 1.0,
Name = "Work Order",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("07ca7182-9ac0-4407-b988-59901170cb86"),
AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6307),
DocumentCategoryId = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
IsActive = true,
IsMandatory = false,
IsSystem = true,
IsValidationRequired = false,
MaxSizeAllowedInMB = 1.0,
Name = "Letter of Agreement",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("846e89a9-5735-45ec-a21d-c97f85a94ada"),
AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6311),
DocumentCategoryId = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
IsActive = true,
IsMandatory = false,
IsSystem = true,
IsValidationRequired = false,
MaxSizeAllowedInMB = 1.0,
Name = "Health and Safety Document",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("7cc41c91-23cb-442b-badd-f932138d149f"),
AllowedContentType = "application/pdf,application/msword,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6314),
DocumentCategoryId = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
IsActive = true,
IsMandatory = false,
IsSystem = true,
IsValidationRequired = false,
MaxSizeAllowedInMB = 1.0,
Name = "Standard Operating Procedure (SOP)",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("5668de00-5d84-47f7-b9b5-7fefd1219f05"),
AllowedContentType = "application/pdf,image/vnd.dwg,application/acad",
CreatedAt = new DateTime(2025, 9, 3, 10, 46, 49, 955, DateTimeKind.Utc).AddTicks(6319),
DocumentCategoryId = new Guid("cfbff269-072b-477a-b48b-72cdc57dd1d3"),
IsActive = true,
IsMandatory = false,
IsSystem = true,
IsValidationRequired = false,
MaxSizeAllowedInMB = 20.0,
Name = "Drawings",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
});
});
modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -1139,6 +1554,54 @@ namespace Marco.Pms.DataAccess.Migrations
Name = "Manage Masters" Name = "Manage Masters"
}, },
new new
{
Id = new Guid("71189504-f1c8-4ca5-8db6-810497be2854"),
Description = "Grants a user the authority to view all documents related to employees and projects",
FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
IsEnabled = true,
Name = "View Document"
},
new
{
Id = new Guid("3f6d1f67-6fa5-4b7c-b17b-018d4fe4aab8"),
Description = "Grants a user the authority to upload the document",
FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
IsEnabled = true,
Name = "Upload Document"
},
new
{
Id = new Guid("c423fd81-6273-4b9d-bb5e-76a0fb343833"),
Description = "Grants a user the authority to modify document",
FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
IsEnabled = true,
Name = "Mofify Document"
},
new
{
Id = new Guid("40863a13-5a66-469d-9b48-135bc5dbf486"),
Description = "Grants a user the authority to delete the document",
FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
IsEnabled = true,
Name = "Delete Document"
},
new
{
Id = new Guid("404373d0-860f-490e-a575-1c086ffbce1d"),
Description = "Grants a user the authority to download the document",
FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
IsEnabled = true,
Name = "Download Document"
},
new
{
Id = new Guid("13a1f30f-38d1-41bf-8e7a-b75189aab8e0"),
Description = "Grants a user the authority to verify the document",
FeatureId = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
IsEnabled = true,
Name = "Verify Document"
},
new
{ {
Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"),
Description = "Full control over all directories, including the ability to manage permissions for all directories in the system.", Description = "Full control over all directories, including the ability to manage permissions for all directories in the system.",
@ -1220,6 +1683,37 @@ namespace Marco.Pms.DataAccess.Migrations
}); });
}); });
modelBuilder.Entity("Marco.Pms.Model.Entitlements.ProjectLevelPermissionMapping", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("EmployeeId")
.HasColumnType("char(36)");
b.Property<Guid>("PermissionId")
.HasColumnType("char(36)");
b.Property<Guid>("ProjectId")
.HasColumnType("char(36)");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("EmployeeId");
b.HasIndex("PermissionId");
b.HasIndex("ProjectId");
b.HasIndex("TenantId");
b.ToTable("ProjectLevelPermissionMappings");
});
modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b =>
{ {
b.Property<Guid>("ApplicationRoleId") b.Property<Guid>("ApplicationRoleId")
@ -1961,6 +2455,39 @@ namespace Marco.Pms.DataAccess.Migrations
}); });
}); });
modelBuilder.Entity("Marco.Pms.Model.Master.EntityTypeMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("EntityTypeMasters");
b.HasData(
new
{
Id = new Guid("c8fe7115-aa27-43bc-99f4-7b05fabe436e"),
Description = "Emtities related to project.",
Name = "Project Entity"
},
new
{
Id = new Guid("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7"),
Description = "Employee related entitie",
Name = "Employee Entity"
});
});
modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b => modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -2236,6 +2763,14 @@ namespace Marco.Pms.DataAccess.Migrations
Name = "Attendance Management" Name = "Attendance Management"
}, },
new new
{
Id = new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"),
Description = "Manage Document",
IsActive = true,
ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"),
Name = "Document Management"
},
new
{ {
Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"),
Description = "Global Masters", Description = "Global Masters",
@ -4007,6 +4542,60 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("Employee"); b.Navigation("Employee");
}); });
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.AttachmentTagMapping", b =>
{
b.HasOne("Marco.Pms.Model.DocumentManager.DocumentAttachment", "Attachment")
.WithMany()
.HasForeignKey("AttachmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.DocumentManager.DocumentTagMaster", "DocumentTag")
.WithMany()
.HasForeignKey("DocumentTagId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attachment");
b.Navigation("DocumentTag");
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.AttachmentVersionMapping", b =>
{
b.HasOne("Marco.Pms.Model.DocumentManager.DocumentAttachment", "ChildAttachment")
.WithMany()
.HasForeignKey("ChildAttachmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.DocumentManager.DocumentAttachment", "ParentAttachment")
.WithMany()
.HasForeignKey("ParentAttachmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ChildAttachment");
b.Navigation("ParentAttachment");
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b =>
{ {
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant") b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
@ -4024,6 +4613,102 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("UploadedBy"); b.Navigation("UploadedBy");
}); });
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentAttachment", b =>
{
b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document")
.WithMany()
.HasForeignKey("DocumentDataId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.DocumentManager.DocumentTypeMaster", "DocumentType")
.WithMany()
.HasForeignKey("DocumentTypeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy")
.WithMany()
.HasForeignKey("UpdatedById");
b.HasOne("Marco.Pms.Model.Employees.Employee", "UploadedBy")
.WithMany()
.HasForeignKey("UploadedById")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Employees.Employee", "VerifiedBy")
.WithMany()
.HasForeignKey("VerifiedById");
b.Navigation("Document");
b.Navigation("DocumentType");
b.Navigation("Tenant");
b.Navigation("UpdatedBy");
b.Navigation("UploadedBy");
b.Navigation("VerifiedBy");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentCategoryMaster", b =>
{
b.HasOne("Marco.Pms.Model.Master.EntityTypeMaster", "EntityTypeMaster")
.WithMany()
.HasForeignKey("EntityTypeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("EntityTypeMaster");
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentTagMaster", b =>
{
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.DocumentTypeMaster", b =>
{
b.HasOne("Marco.Pms.Model.DocumentManager.DocumentCategoryMaster", "DocumentCategory")
.WithMany()
.HasForeignKey("DocumentCategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("DocumentCategory");
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b =>
{ {
b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser") b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser")
@ -4096,6 +4781,41 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("Feature"); b.Navigation("Feature");
}); });
modelBuilder.Entity("Marco.Pms.Model.Entitlements.ProjectLevelPermissionMapping", b =>
{
b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee")
.WithMany()
.HasForeignKey("EmployeeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", "Permission")
.WithMany()
.HasForeignKey("PermissionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Projects.Project", "Project")
.WithMany()
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.TenantModels.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employee");
b.Navigation("Permission");
b.Navigation("Project");
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b =>
{ {
b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", null) b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", null)

View File

@ -0,0 +1,22 @@
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager
{
public class AttachmentTagMapping : TenantRelation
{
public Guid Id { get; set; }
public Guid DocumentTagId { get; set; }
[ValidateNever]
[ForeignKey("DocumentTagId")]
public DocumentTagMaster? DocumentTag { get; set; }
public Guid AttachmentId { get; set; }
[ValidateNever]
[ForeignKey("AttachmentId")]
public DocumentAttachment? Attachment { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager
{
public class AttachmentVersionMapping : TenantRelation
{
public Guid Id { get; set; }
public Guid ParentAttachmentId { get; set; }
[ValidateNever]
[ForeignKey("ParentAttachmentId")]
public DocumentAttachment? ParentAttachment { get; set; }
public int Version { get; set; } = 1;
public Guid ChildAttachmentId { get; set; }
[ValidateNever]
[ForeignKey("ChildAttachmentId")]
public DocumentAttachment? ChildAttachment { get; set; }
}
}

View File

@ -0,0 +1,48 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager
{
public class DocumentAttachment : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? DocumentId { get; set; }
public string Description { get; set; } = string.Empty;
public bool IsCurrentVersion { get; set; } = true;
public DateTime UploadedAt { get; set; }
public Guid UploadedById { get; set; } // References the employee who uploaded the document
[ValidateNever]
[ForeignKey("UploadedById")]
public Employee? UploadedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public Guid? UpdatedById { get; set; } // References the employee who updates the document
[ValidateNever]
[ForeignKey("UpdatedById")]
public Employee? UpdatedBy { get; set; }
public DateTime? VerifiedAt { get; set; }
public bool? IsVerified { get; set; }
public Guid? VerifiedById { get; set; } // Associates the document with a specific employee, if applicable
[ValidateNever]
[ForeignKey("VerifiedById")]
public Employee? VerifiedBy { get; set; }
public Guid EntityId { get; set; } // Associates the document with a specific project, if applicable
public Guid DocumentTypeId { get; set; }
[ValidateNever]
[ForeignKey("DocumentTypeId")]
public DocumentTypeMaster? DocumentType { get; set; }
public Guid DocumentDataId { get; set; }
[ValidateNever]
[ForeignKey("DocumentDataId")]
public Document? Document { get; set; }
public bool IsActive { get; set; } = true;
}
}

View File

@ -0,0 +1,17 @@
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager
{
public class DocumentAttachmentMapping : TenantRelation
{
public Guid Id { get; set; }
public Guid AttachmentId { get; set; }
[ValidateNever]
[ForeignKey("AttachmentId")]
public DocumentAttachment? Attachment { get; set; }
}
}

View File

@ -0,0 +1,21 @@
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager
{
public class DocumentCategoryMaster : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public Guid EntityTypeId { get; set; }
[ValidateNever]
[ForeignKey("EntityTypeId")]
public EntityTypeMaster? EntityTypeMaster { get; set; }
public DateTime CreatedAt { get; set; }
}
}

View File

@ -0,0 +1,11 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.DocumentManager
{
public class DocumentTagMaster : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,26 @@
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager
{
public class DocumentTypeMaster : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? RegexExpression { get; set; }
public string AllowedContentType { get; set; } = string.Empty;
public double MaxSizeAllowedInMB { get; set; } = 2;
public bool IsValidationRequired { get; set; } = true;
public bool IsMandatory { get; set; } = true;
public bool IsSystem { get; set; } = false;
public bool IsActive { get; set; } = true;
public Guid DocumentCategoryId { get; set; }
[ValidateNever]
[ForeignKey("DocumentCategoryId")]
public DocumentCategoryMaster? DocumentCategory { get; set; }
public DateTime CreatedAt { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace Marco.Pms.Model.Dtos.DocumentManager
{
public class CreateDocumentCategoryDto
{
public Guid? Id { get; set; }
public required string Name { get; set; }
public required string Description { get; set; }
public required Guid EntityTypeId { get; set; }
}
}

View File

@ -0,0 +1,14 @@
namespace Marco.Pms.Model.Dtos.DocumentManager
{
public class CreateDocumentTypeDto
{
public Guid? Id { get; set; }
public required string Name { get; set; } = string.Empty;
public string? RegexExpression { get; set; }
public required string AllowedContentType { get; set; }
public required double MaxSizeAllowedInMB { get; set; } = 2;
public bool IsValidationRequired { get; set; }
public bool IsMandatory { get; set; }
public required Guid DocumentCategoryId { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.Dtos.DocumentManager
{
public class DocumentAttachmentDto
{
public required string Name { get; set; }
public string? DocumentId { get; set; }
public required string Description { get; set; }
public required Guid EntityId { get; set; }
public required Guid DocumentTypeId { get; set; } // References the type of the document
public required FileUploadModel Attachment { get; set; }
public List<DocumentTagDto>? Tags { get; set; }
}
public class UpdateDocumentAttachmentDto
{
public required Guid Id { get; set; }
public required string Name { get; set; }
public string? DocumentId { get; set; }
public required string Description { get; set; }
public FileUploadModel? Attachment { get; set; }
public List<DocumentTagDto>? Tags { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace Marco.Pms.Model.Dtos.DocumentManager
{
public class DocumentTagDto
{
public required string Name { get; set; }
public required bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,11 @@
using Marco.Pms.Model.Dtos.Roles;
namespace Marco.Pms.Model.Dtos.Util
{
public class ProjctLevelPermissionDto
{
public required Guid EmployeeId { get; set; }
public required Guid ProjectId { get; set; }
public required List<FeaturesPermissionDto> Permission { get; set; }
}
}

View File

@ -39,6 +39,13 @@
public static readonly Guid ExpenseApprove = Guid.Parse("eaafdd76-8aac-45f9-a530-315589c6deca"); public static readonly Guid ExpenseApprove = Guid.Parse("eaafdd76-8aac-45f9-a530-315589c6deca");
public static readonly Guid ExpenseProcess = Guid.Parse("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"); public static readonly Guid ExpenseProcess = Guid.Parse("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11");
public static readonly Guid ExpenseManage = Guid.Parse("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"); public static readonly Guid ExpenseManage = Guid.Parse("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3");
public static readonly Guid ViewDocument = Guid.Parse("71189504-f1c8-4ca5-8db6-810497be2854");
public static readonly Guid UploadDocument = Guid.Parse("3f6d1f67-6fa5-4b7c-b17b-018d4fe4aab8");
public static readonly Guid MofifyDocument = Guid.Parse("c423fd81-6273-4b9d-bb5e-76a0fb343833");
public static readonly Guid DeleteDocument = Guid.Parse("40863a13-5a66-469d-9b48-135bc5dbf486");
public static readonly Guid DownloadDocument = Guid.Parse("404373d0-860f-490e-a575-1c086ffbce1d");
public static readonly Guid VerifyDocument = Guid.Parse("13a1f30f-38d1-41bf-8e7a-b75189aab8e0");
} }
} }

View File

@ -0,0 +1,28 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Entitlements
{
public class ProjectLevelPermissionMapping : TenantRelation
{
public Guid Id { get; set; }
public Guid EmployeeId { get; set; }
[ValidateNever]
[ForeignKey("EmployeeId")]
public Employee? Employee { get; set; }
public Guid ProjectId { get; set; }
[ValidateNever]
[ForeignKey("ProjectId")]
public Project? Project { get; set; }
public Guid PermissionId { get; set; }
[ValidateNever]
[ForeignKey("PermissionId")]
public FeaturePermission? Permission { get; set; }
}
}

View File

@ -0,0 +1,14 @@
namespace Marco.Pms.Model.Filters
{
public class DocumentFilter
{
public List<Guid>? UploadedByIds { get; set; }
public List<Guid>? DocumentCategoryIds { get; set; }
public List<Guid>? DocumentTypeIds { get; set; }
public List<Guid>? DocumentTagIds { get; set; }
public bool IsUploadedAt { get; set; } = true;
public bool? IsVerified { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
}

View File

@ -1,4 +1,4 @@
namespace Marco.Pms.Model.Utilities namespace Marco.Pms.Model.Filters
{ {
public class ImageFilter public class ImageFilter
{ {

View File

@ -1,4 +1,4 @@
namespace Marco.Pms.Model.Utilities namespace Marco.Pms.Model.Filters
{ {
public class TenantFilter public class TenantFilter
{ {

View File

@ -0,0 +1,9 @@
namespace Marco.Pms.Model.Master
{
public class EntityTypeMaster
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
}

View File

@ -3,9 +3,9 @@
public class FileUploadModel public class FileUploadModel
{ {
public Guid? DocumentId { get; set; } public Guid? DocumentId { get; set; }
public string? FileName { get; set; } // Name of the file (e.g., "image1.png") public required string FileName { get; set; } // Name of the file (e.g., "image1.png")
public string? Base64Data { get; set; } // Base64-encoded string of the file public required string Base64Data { get; set; } // Base64-encoded string of the file
public string? ContentType { get; set; } // MIME type (e.g., "image/png", "application/pdf") public required string ContentType { get; set; } // MIME type (e.g., "image/png", "application/pdf")
public long FileSize { get; set; } // File size in bytes public long FileSize { get; set; } // File size in bytes
public string? Description { get; set; } // Optional: Description or purpose of the file public string? Description { get; set; } // Optional: Description or purpose of the file
public bool IsActive { get; set; } = true; public bool IsActive { get; set; } = true;

View File

@ -0,0 +1,21 @@
using Marco.Pms.Model.ViewModels.Activities;
namespace Marco.Pms.Model.ViewModels.DocumentManager
{
public class AttachmentVersionVM
{
public Guid Id { get; set; }
public string? Name { get; set; }
public string? DocumentId { get; set; }
public int Version { get; set; }
public long FileSize { get; set; }
public string? ContentType { get; set; }
public DateTime UploadedAt { get; set; }
public BasicEmployeeVM? UploadedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public BasicEmployeeVM? UpdatedBy { get; set; }
public DateTime? VerifiedAt { get; set; }
public BasicEmployeeVM? VerifiedBy { get; set; }
public bool? IsVerified { get; set; }
}
}

View File

@ -0,0 +1,29 @@
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.ViewModels.Activities;
namespace Marco.Pms.Model.ViewModels.DocumentManager
{
public class DocumentAttachmentDetailsVM
{
public Guid Id { get; set; }
public string? Name { get; set; }
public string? DocumentId { get; set; }
public string? Description { get; set; }
public int Version { get; set; }
public bool IsCurrentVersion { get; set; }
public Guid ParentAttachmentId { get; set; }
public long FileSize { get; set; }
public string? ContentType { get; set; }
public DateTime UploadedAt { get; set; }
public BasicEmployeeVM? UploadedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public BasicEmployeeVM? UpdatedBy { get; set; }
public DateTime? VerifiedAt { get; set; }
public bool? IsVerified { get; set; }
public BasicEmployeeVM? VerifiedBy { get; set; }
public Guid EntityId { get; set; }
public DocumentTypeVM? DocumentType { get; set; }
public List<DocumentTagDto>? Tags { get; set; }
public bool IsActive { get; set; } = true;
}
}

View File

@ -0,0 +1,10 @@
namespace Marco.Pms.Model.ViewModels.DocumentManager
{
public class DocumentCategoryVM
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public Guid EntityTypeId { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using Marco.Pms.Model.ViewModels.Activities;
namespace Marco.Pms.Model.ViewModels.DocumentManager
{
public class DocumentListVM
{
public Guid Id { get; set; }
public string? Name { get; set; }
public string? DocumentId { get; set; }
public string? Description { get; set; }
public DateTime UploadedAt { get; set; }
public Guid? ParentAttachmentId { get; set; }
public bool IsCurrentVersion { get; set; }
public int Version { get; set; }
public bool IsActive { get; set; }
public bool? IsVerified { get; set; }
public BasicEmployeeVM? UploadedBy { get; set; }
public DocumentTypeVM? DocumentType { get; set; }
}
}

View File

@ -0,0 +1,16 @@
namespace Marco.Pms.Model.ViewModels.DocumentManager
{
public class DocumentTypeVM
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? RegexExpression { get; set; }
public string AllowedContentType { get; set; } = string.Empty;
public double MaxSizeAllowedInMB { get; set; }
public bool IsValidationRequired { get; set; }
public bool IsMandatory { get; set; }
public bool IsSystem { get; set; }
public bool IsActive { get; set; }
public DocumentCategoryVM? DocumentCategory { get; set; }
}
}

View File

@ -2,6 +2,7 @@
using Marco.Pms.CacheHelper; using Marco.Pms.CacheHelper;
using Marco.Pms.Model.AppMenu; using Marco.Pms.Model.AppMenu;
using Marco.Pms.Model.Dtos.AppMenu; using Marco.Pms.Model.Dtos.AppMenu;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.AppMenu; using Marco.Pms.Model.ViewModels.AppMenu;
using Marco.Pms.Model.ViewModels.DocumentManager; using Marco.Pms.Model.ViewModels.DocumentManager;
@ -558,7 +559,9 @@ namespace Marco.Pms.Services.Controllers
EmployeeManagement, new List<MasterMenuVM> EmployeeManagement, new List<MasterMenuVM>
{ {
new MasterMenuVM { Id = 1, Name = "Application Role" }, new MasterMenuVM { Id = 1, Name = "Application Role" },
new MasterMenuVM { Id = 2, Name = "Job Role" } new MasterMenuVM { Id = 2, Name = "Job Role" },
new MasterMenuVM { Id = 9, Name = "Document Category" },
new MasterMenuVM { Id = 10, Name = "Document Type" }
} }
}, },
{ {
@ -714,10 +717,19 @@ namespace Marco.Pms.Services.Controllers
menu.Items = allowedItems; menu.Items = allowedItems;
} }
if (await _permissions.HasPermission(PermissionsMaster.ViewDocument, employeeId))
{
response.Add(new MenuSectionApplicationVM
{
Id = Guid.NewGuid(),
Name = "Documents",
Available = true,
});
}
// Step 3: Log success // Step 3: Log success
_logger.LogInfo("Fetched sidebar menu successfully. Tenant: {TenantId}, EmployeeId: {EmployeeId}, SectionsReturned: {Count}", _logger.LogInfo("Fetched sidebar menu successfully. Tenant: {TenantId}, EmployeeId: {EmployeeId}, SectionsReturned: {Count}",
tenantId, employeeId, menus.Count); tenantId, employeeId, menus.Count);
return Ok(ApiResponse<object>.SuccessResponse(response, "Sidebar menu fetched successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(response, "Sidebar menu fetched successfully", 200));
} }
catch (Exception ex) catch (Exception ex)

View File

@ -518,7 +518,7 @@ namespace MarcoBMS.Services.Controllers
{ {
UserId = Guid.Parse(requestedUser.Id), UserId = Guid.Parse(requestedUser.Id),
OTP = otp, OTP = otp,
ExpriesInSec = 600, // 10 minutes ExpriesInSec = 300, // 10 minutes
TimeStamp = DateTime.UtcNow, TimeStamp = DateTime.UtcNow,
TenantId = requestedUser.TenantId TenantId = requestedUser.TenantId
}; };

File diff suppressed because it is too large Load Diff

View File

@ -143,15 +143,16 @@ namespace MarcoBMS.Services.Controllers
else if (hasViewTeamMembersPermission && !ShowInactive) else if (hasViewTeamMembersPermission && !ShowInactive)
{ {
var employeeIds = await _context.ProjectAllocations var employeeIds = await _context.ProjectAllocations
.Where(pa => projectIds.Contains(pa.ProjectId) && pa.IsActive) .Where(pa => projectIds.Contains(pa.ProjectId) && pa.IsActive && pa.TenantId == tenantId)
.Select(pa => pa.EmployeeId) .Select(pa => pa.EmployeeId)
.Distinct() .Distinct()
.ToListAsync(); .ToListAsync();
result = await _context.Employees result = await _context.Employees
.Include(fp => fp.JobRole) .Include(fp => fp.JobRole)
.Where(e => employeeIds.Contains(e.Id) && e.IsActive) .Where(e => employeeIds.Contains(e.Id) && e.IsActive && e.TenantId == tenantId)
.Select(e => e.ToEmployeeVMFromEmployee()) .Select(e => e.ToEmployeeVMFromEmployee())
.Distinct()
.ToListAsync(); .ToListAsync();
_logger.LogInfo("Employee list fetched using limited access (active only)."); _logger.LogInfo("Employee list fetched using limited access (active only).");

View File

@ -2,6 +2,7 @@
using Marco.Pms.Model.Activities; using Marco.Pms.Model.Activities;
using Marco.Pms.Model.Dtos.DocumentManager; using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Filters;
using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.Projects; using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;

View File

@ -1,5 +1,6 @@
using Marco.Pms.DataAccess.Data; using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Dtos.Activities; using Marco.Pms.Model.Dtos.Activities;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Forum; using Marco.Pms.Model.Forum;
@ -9,7 +10,6 @@ using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities; using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Forum; using Marco.Pms.Model.ViewModels.Forum;
using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Model.ViewModels.Master;
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;
@ -27,15 +27,13 @@ namespace Marco.Pms.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 MasterHelper _masterHelper;
private readonly IMasterService _masterService; private readonly IMasterService _masterService;
private readonly Guid tenantId; private readonly Guid tenantId;
public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, MasterHelper masterHelper, IMasterService masterService) public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, IMasterService masterService)
{ {
_context = context; _context = context;
_userHelper = userHelper; _userHelper = userHelper;
_logger = logger; _logger = logger;
_masterHelper = masterHelper;
_masterService = masterService; _masterService = masterService;
tenantId = userHelper.GetTenantId(); tenantId = userHelper.GetTenantId();
} }
@ -696,37 +694,32 @@ namespace Marco.Pms.Services.Controllers
[HttpGet("work-status")] [HttpGet("work-status")]
public async Task<IActionResult> GetWorkStatusMasterList() public async Task<IActionResult> GetWorkStatusMasterList()
{ {
var response = await _masterHelper.GetWorkStatusList(); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.GetWorkStatusList(loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }
[HttpPost("work-status")] [HttpPost("work-status")]
public async Task<IActionResult> CreateWorkStatusMaster([FromBody] CreateWorkStatusMasterDto createWorkStatusDto) public async Task<IActionResult> CreateWorkStatusMaster([FromBody] CreateWorkStatusMasterDto createWorkStatusDto)
{ {
if (!ModelState.IsValid) var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
{ var response = await _masterService.CreateWorkStatus(createWorkStatusDto, loggedInEmpoyee, tenantId);
var errors = ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage)
.ToList();
_logger.LogWarning("User sent Invalid Date while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
}
var response = await _masterHelper.CreateWorkStatus(createWorkStatusDto);
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }
[HttpPost("work-status/edit/{id}")] [HttpPost("work-status/edit/{id}")]
public async Task<IActionResult> UpdateWorkStatusMaster(Guid id, [FromBody] UpdateWorkStatusMasterDto updateWorkStatusDto) public async Task<IActionResult> UpdateWorkStatusMaster(Guid id, [FromBody] UpdateWorkStatusMasterDto updateWorkStatusDto)
{ {
var response = await _masterHelper.UpdateWorkStatus(id, updateWorkStatusDto); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.UpdateWorkStatus(id, updateWorkStatusDto, loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }
[HttpDelete("work-status/{id}")] [HttpDelete("work-status/{id}")]
public async Task<IActionResult> DeleteWorkStatusMaster(Guid id) public async Task<IActionResult> DeleteWorkStatusMaster(Guid id)
{ {
var response = await _masterHelper.DeleteWorkStatus(id); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.DeleteWorkStatus(id, loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }
@ -737,68 +730,44 @@ namespace Marco.Pms.Services.Controllers
[HttpGet("contact-categories")] [HttpGet("contact-categories")]
public async Task<IActionResult> GetContactCategoryMasterList() public async Task<IActionResult> GetContactCategoryMasterList()
{ {
var response = await _masterHelper.GetContactCategoriesList(); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
return Ok(response); var response = await _masterService.GetContactCategoriesList(loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response);
} }
[HttpGet("contact-category/{id}")] [HttpGet("contact-category/{id}")]
public async Task<IActionResult> GetContactCategoryMaster(Guid id) public async Task<IActionResult> GetContactCategoryMaster(Guid id)
{ {
var response = await _masterHelper.GetContactCategoryById(id); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
if (response.StatusCode == 200) var response = await _masterService.GetContactCategoryById(id, loggedInEmpoyee, tenantId);
{ return StatusCode(response.StatusCode, response);
return Ok(response);
}
else if (response.StatusCode == 404)
{
return NotFound(response);
}
else
{
return BadRequest(response);
}
} }
[HttpPost("contact-category")] [HttpPost("contact-category")]
public async Task<IActionResult> CreateContactCategoryMaster([FromBody] CreateContactCategoryDto contactCategoryDto) public async Task<IActionResult> CreateContactCategoryMaster([FromBody] CreateContactCategoryDto contactCategoryDto)
{ {
var response = await _masterHelper.CreateContactCategory(contactCategoryDto); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
if (response.StatusCode == 200) var response = await _masterService.CreateContactCategory(contactCategoryDto, loggedInEmpoyee, tenantId);
{ return StatusCode(response.StatusCode, response);
return Ok(response);
}
else if (response.StatusCode == 409)
{
return Conflict(response);
}
else
{
return BadRequest(response);
}
} }
[HttpPost("contact-category/edit/{id}")] [HttpPost("contact-category/edit/{id}")]
public async Task<IActionResult> UpdateContactCategoryMaster(Guid id, [FromBody] UpdateContactCategoryDto updateContactCategoryDto) public async Task<IActionResult> UpdateContactCategoryMaster(Guid id, [FromBody] UpdateContactCategoryDto updateContactCategoryDto)
{ {
var response = await _masterHelper.UpdateContactCategory(id, updateContactCategoryDto); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
if (response.StatusCode == 200) var response = await _masterService.UpdateContactCategory(id, updateContactCategoryDto, loggedInEmpoyee, tenantId);
{ return StatusCode(response.StatusCode, response);
return Ok(response);
}
else if (response.StatusCode == 404)
{
return NotFound(response);
}
else
{
return BadRequest(response);
}
} }
[HttpDelete("contact-category/{id}")] [HttpDelete("contact-category/{id}")]
public async Task<IActionResult> DeletecontactCategoryMaster(Guid id) public async Task<IActionResult> DeletecontactCategoryMaster(Guid id)
{ {
var response = await _masterHelper.DeleteContactCategory(id); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
return Ok(response); var response = await _masterService.DeleteContactCategory(id, loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response);
} }
#endregion #endregion
@ -808,61 +777,37 @@ namespace Marco.Pms.Services.Controllers
[HttpGet("contact-tags")] [HttpGet("contact-tags")]
public async Task<IActionResult> GetContactTagMasterList() public async Task<IActionResult> GetContactTagMasterList()
{ {
var response = await _masterHelper.GetContactTags(); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
return Ok(response); var response = await _masterService.GetContactTags(loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response);
} }
[HttpPost("contact-tag")] [HttpPost("contact-tag")]
public async Task<IActionResult> CreateContactTagMaster([FromBody] CreateContactTagDto contactTagDto) public async Task<IActionResult> CreateContactTagMaster([FromBody] CreateContactTagDto contactTagDto)
{ {
if (!ModelState.IsValid) var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
{ var response = await _masterService.CreateContactTag(contactTagDto, loggedInEmpoyee, tenantId);
var errors = ModelState.Values return StatusCode(response.StatusCode, response);
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage)
.ToList();
_logger.LogWarning("User sent Invalid Date while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
}
var response = await _masterHelper.CreateContactTag(contactTagDto);
if (response.StatusCode == 200)
{
return Ok(response);
}
else if (response.StatusCode == 409)
{
return Conflict(response);
}
else
{
return BadRequest(response);
}
} }
[HttpPost("contact-tag/edit/{id}")] [HttpPost("contact-tag/edit/{id}")]
public async Task<IActionResult> UpdateContactTagMaster(Guid id, [FromBody] UpdateContactTagDto updateContactTagDto) public async Task<IActionResult> UpdateContactTagMaster(Guid id, [FromBody] UpdateContactTagDto updateContactTagDto)
{ {
var response = await _masterHelper.UpdateContactTag(id, updateContactTagDto); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
if (response.StatusCode == 200) var response = await _masterService.UpdateContactTag(id, updateContactTagDto, loggedInEmpoyee, tenantId);
{ return StatusCode(response.StatusCode, response);
return Ok(response);
}
else if (response.StatusCode == 404)
{
return NotFound(response);
}
else
{
return BadRequest(response);
}
} }
[HttpDelete("contact-tag/{id}")] [HttpDelete("contact-tag/{id}")]
public async Task<IActionResult> DeletecontactTagMaster(Guid id) public async Task<IActionResult> DeletecontactTagMaster(Guid id)
{ {
var response = await _masterHelper.DeleteContactTag(id); var loggedInEmpoyee = await _userHelper.GetCurrentEmployeeAsync();
return Ok(response); var response = await _masterService.DeleteContactTag(id, loggedInEmpoyee, tenantId);
return StatusCode(response.StatusCode, response);
} }
#endregion #endregion
@ -949,5 +894,77 @@ namespace Marco.Pms.Services.Controllers
} }
#endregion #endregion
#region =================================================================== Document Category APIs ===================================================================
[HttpGet("document-category/list")]
public async Task<IActionResult> GetDocumentCategoryMasterList([FromQuery] Guid? entityTypeId)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.GetDocumentCategoryMasterListAsync(entityTypeId, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPost("document-category")]
public async Task<IActionResult> CreateDocumentCategoryMaster([FromBody] CreateDocumentCategoryDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.CreateDocumentCategoryMasterAsync(dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPut("document-category/edit/{id}")]
public async Task<IActionResult> UpdateDocumentCategoryMaster(Guid id, [FromBody] CreateDocumentCategoryDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.UpdateDocumentCategoryMasterAsync(id, dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpDelete("document-category/delete/{id}")]
public async Task<IActionResult> DeleteDocumentCategoryMaster(Guid id)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.DeleteDocumentCategoryMasterAsync(id, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Document Type APIs ===================================================================
[HttpGet("document-type/list")]
public async Task<IActionResult> GetDocumentTypeMasterList([FromQuery] Guid? documentCategoryId)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.GetDocumentTypeMasterListAsync(documentCategoryId, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPost("document-type")]
public async Task<IActionResult> CreateDocumentTypeMaster([FromBody] CreateDocumentTypeDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.CreateDocumentTypeMasterAsync(dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPut("document-type/edit/{id}")]
public async Task<IActionResult> UpdateDocumentTypeMaster(Guid id, [FromBody] CreateDocumentTypeDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.UpdateDocumentTypeMasterAsync(id, dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpDelete("document-type/delete/{id}")]
public async Task<IActionResult> DeleteDocumentTypeMaster(Guid id, [FromQuery] bool isActive = false)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.DeleteDocumentTypeMasterAsync(id, isActive, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
#endregion
} }
} }

View File

@ -1,4 +1,5 @@
using Marco.Pms.Model.Dtos.Project; using Marco.Pms.Model.Dtos.Project;
using Marco.Pms.Model.Dtos.Util;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Services.Service.ServiceInterfaces; using Marco.Pms.Services.Service.ServiceInterfaces;
@ -454,5 +455,35 @@ namespace MarcoBMS.Services.Controllers
#endregion #endregion
[HttpPost("assign/project-level-permission")]
public async Task<IActionResult> ManageProjectLevelPermission([FromBody] ProjctLevelPermissionDto model)
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _projectServices.ManageProjectLevelPermissionAsync(model, tenantId, loggedInEmployee);
return StatusCode(response.StatusCode, response);
}
[HttpGet("get/project-level-permission/employee/{employeeId}/project/{projectId}")]
public async Task<IActionResult> GetAssignedProjectLevelPermission(Guid employeeId, Guid projectId)
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _projectServices.GetAssignedProjectLevelPermissionAsync(employeeId, projectId, tenantId, loggedInEmployee);
return StatusCode(response.StatusCode, response);
}
[HttpGet("get/proejct-level/modules")]
public async Task<IActionResult> AssignProjectLevelModules()
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _projectServices.AssignProjectLevelModulesAsync(tenantId, loggedInEmployee);
return StatusCode(response.StatusCode, response);
}
[HttpGet("get/proejct-level/employees/{projectId}")]
public async Task<IActionResult> GetEmployeeToWhomProjectLevelAssigned(Guid projectId)
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _projectServices.GetEmployeeToWhomProjectLevelAssignedAsync(projectId, tenantId, loggedInEmployee);
return StatusCode(response.StatusCode, response);
}
} }
} };

View File

@ -154,34 +154,6 @@ namespace Marco.Pms.Services.Controllers
} }
} }
[HttpPost("mail-template1")]
public async Task<IActionResult> AddMailTemplate1([FromBody] MailTemeplateDto mailTemeplateDto)
{
Guid tenantId = _userHelper.GetTenantId();
if (string.IsNullOrWhiteSpace(mailTemeplateDto.Body) && string.IsNullOrWhiteSpace(mailTemeplateDto.Title))
{
_logger.LogWarning("User tries to set email template but send invalid data");
return BadRequest(ApiResponse<object>.ErrorResponse("Provided Invalid data", "Provided Invalid data", 400));
}
var existngTemalate = await _context.MailingList.FirstOrDefaultAsync(t => t.Title.ToLower() == mailTemeplateDto.Title.ToLower());
if (existngTemalate != null)
{
_logger.LogWarning("User tries to set email template, but title already existed in database");
return BadRequest(ApiResponse<object>.ErrorResponse("Email title is already existed", "Email title is already existed", 400));
}
MailingList mailingList = new MailingList
{
Title = mailTemeplateDto.Title,
Body = mailTemeplateDto.Body,
Subject = mailTemeplateDto.Subject,
Keywords = mailTemeplateDto.Keywords,
TenantId = tenantId
};
_context.MailingList.Add(mailingList);
await _context.SaveChangesAsync();
return Ok("Success");
}
/// <summary> /// <summary>
/// Adds a new mail template. /// Adds a new mail template.
/// </summary> /// </summary>

View File

@ -4,6 +4,7 @@ using Marco.Pms.Helpers.Utility;
using Marco.Pms.Model.Dtos.Tenant; using Marco.Pms.Model.Dtos.Tenant;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Filters;
using Marco.Pms.Model.MongoDBModels.Utility; using Marco.Pms.Model.MongoDBModels.Utility;
using Marco.Pms.Model.Projects; using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Roles; using Marco.Pms.Model.Roles;

View File

@ -4,6 +4,7 @@ using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.ViewModels.Employee; using Marco.Pms.Model.ViewModels.Employee;
using MarcoBMS.Services.Service; using MarcoBMS.Services.Service;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace MarcoBMS.Services.Helpers namespace MarcoBMS.Services.Helpers
@ -71,30 +72,35 @@ namespace MarcoBMS.Services.Helpers
} }
} }
public async Task<List<EmployeeVM>> GetEmployeeByProjectId(Guid TenentId, Guid? ProjectId, bool ShowInActive) public async Task<List<EmployeeVM>> GetEmployeeByProjectId(Guid tenantId, Guid? projectId, bool ShowInActive)
{ {
try try
{ {
List<EmployeeVM> result = new List<EmployeeVM>(); List<EmployeeVM> result = new List<EmployeeVM>();
if (ProjectId.HasValue) if (projectId.HasValue)
{ {
var employeeIds = await _context.ProjectAllocations
.Where(pa => projectId == pa.ProjectId && pa.IsActive && pa.TenantId == tenantId)
.Select(pa => pa.EmployeeId)
.Distinct()
.ToListAsync();
result = await _context.ProjectAllocations result = await _context.Employees
.Include(pa => pa.Employee) .Include(fp => fp.JobRole)
.ThenInclude(e => e!.JobRole) .Where(e => employeeIds.Contains(e.Id) && e.IsActive && e.TenantId == tenantId)
.Where(c => c.ProjectId == ProjectId.Value && c.IsActive && c.Employee != null) .Select(e => e.ToEmployeeVMFromEmployee())
.Select(pa => pa.Employee!.ToEmployeeVMFromEmployee()) .Distinct()
.ToListAsync(); .ToListAsync();
} }
else if (ShowInActive) else if (ShowInActive)
{ {
result = await _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == false).Include(fp => fp.JobRole) result = await _context.Employees.Where(c => c.TenantId == tenantId && c.IsActive == false).Include(fp => fp.JobRole)
.Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync(); .Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync();
} }
else else
{ {
result = await _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true).Include(fp => fp.JobRole) result = await _context.Employees.Where(c => c.TenantId == tenantId && c.IsActive == true).Include(fp => fp.JobRole)
.Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync(); .Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync();
} }
@ -102,7 +108,7 @@ namespace MarcoBMS.Services.Helpers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Error occured while featching list of employee by project ID {ProjectId}", ProjectId ?? Guid.Empty); _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>();
} }
} }

View File

@ -13,6 +13,7 @@ namespace Marco.Pms.Services.Helpers
private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate
private readonly ILoggingService _logger; private readonly ILoggingService _logger;
private readonly FeatureDetailsHelper _featureDetailsHelper; private readonly FeatureDetailsHelper _featureDetailsHelper;
private static readonly Guid SuperTenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26");
public GeneralHelper(IDbContextFactory<ApplicationDbContext> dbContextFactory, public GeneralHelper(IDbContextFactory<ApplicationDbContext> dbContextFactory,
ApplicationDbContext context, ApplicationDbContext context,
ILoggingService logger, ILoggingService logger,
@ -307,6 +308,10 @@ namespace Marco.Pms.Services.Helpers
try try
{ {
if (tenantId == SuperTenantId)
{
return true;
}
// Run both queries concurrently // Run both queries concurrently
var totalSeatsTask = GetMaxSeatsAsync(tenantId); var totalSeatsTask = GetMaxSeatsAsync(tenantId);
var totalSeatsTakenTask = GetActiveEmployeesCountAsync(tenantId); var totalSeatsTakenTask = GetActiveEmployeesCountAsync(tenantId);

View File

@ -1,459 +0,0 @@
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Directory;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.EntityFrameworkCore;
namespace Marco.Pms.Services.Helpers
{
public class MasterHelper
{
private readonly ApplicationDbContext _context;
private readonly ILoggingService _logger;
private readonly UserHelper _userHelper;
private readonly PermissionServices _permission;
private readonly Guid tenantId;
public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permission)
{
_context = context;
_logger = logger;
_userHelper = userHelper;
_permission = permission;
tenantId = userHelper.GetTenantId();
}
#region =================================================================== Contact Category APIs ===================================================================
public async Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactCategoryDto != null)
{
ContactCategoryMaster? existingContactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Name.ToLower() == (contactCategoryDto.Name != null ? contactCategoryDto.Name.ToLower() : ""));
if (existingContactCategory == null)
{
ContactCategoryMaster contactCategory = contactCategoryDto.ToContactCategoryMasterFromCreateContactCategoryDto(tenantId);
_context.ContactCategoryMasters.Add(contactCategory);
await _context.SaveChangesAsync();
ContactCategoryVM categoryVM = contactCategory.ToContactCategoryVMFromContactCategoryMaster();
_logger.LogInfo("Employee ID {LoggedInEmployeeId} created a contact category {ContactCategoryId}.", LoggedInEmployee.Id, contactCategory.Id);
return ApiResponse<object>.SuccessResponse(categoryVM, "Category Created Successfully", 200);
}
_logger.LogWarning("Employee ID {LoggedInEmployeeId} attempted to create an existing contact category.", LoggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Category already existed", "Category already existed", 409);
}
_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>> UpdateContactCategory(Guid id, UpdateContactCategoryDto contactCategoryDto)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactCategoryDto != null && id == contactCategoryDto.Id)
{
ContactCategoryMaster? contactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Id == id);
if (contactCategory != null)
{
contactCategory.Name = contactCategoryDto.Name ?? "";
contactCategory.Description = contactCategoryDto.Description ?? "";
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = contactCategory.Id,
UpdatedById = LoggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
ContactCategoryVM categoryVM = contactCategory.ToContactCategoryVMFromContactCategoryMaster();
_logger.LogInfo("Employee ID {LoggedInEmployeeId} created a contact category {ContactCategoryId}.", LoggedInEmployee.Id, contactCategory.Id);
return ApiResponse<object>.SuccessResponse(categoryVM, "Category Created Successfully", 200);
}
_logger.LogWarning("Employee ID {LoggedInEmployeeId} attempted to update a contact category but not found in database.", LoggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Category not found", "Category 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>> GetContactCategoriesList()
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var categoryList = await _context.ContactCategoryMasters.Where(c => c.TenantId == tenantId).ToListAsync();
List<ContactCategoryVM> contactCategories = new List<ContactCategoryVM>();
foreach (var category in categoryList)
{
ContactCategoryVM categoryVM = category.ToContactCategoryVMFromContactCategoryMaster();
contactCategories.Add(categoryVM);
}
_logger.LogInfo("{count} contact categoires are fetched by Employee with ID {LoggedInEmployeeId}", contactCategories.Count, LoggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(contactCategories, System.String.Format("{0} contact categories fetched successfully", contactCategories.Count), 200);
}
public async Task<ApiResponse<object>> GetContactCategoryById(Guid id)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var category = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (category != null)
{
ContactCategoryVM categoryVM = category.ToContactCategoryVMFromContactCategoryMaster();
_logger.LogInfo("Employee {EmployeeId} fetched contact category {ContactCategoryID}", LoggedInEmployee.Id, category.Id);
return ApiResponse<object>.SuccessResponse(categoryVM, "Category fetched successfully", 200);
}
_logger.LogWarning("Employee {EmployeeId} attempted to fetch contact category {ContactCategoryID} but not found in database", LoggedInEmployee.Id, id);
return ApiResponse<object>.ErrorResponse("Category not found", "Category not found", 404);
}
public async Task<ApiResponse<object>> DeleteContactCategory(Guid id)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
ContactCategoryMaster? contactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (contactCategory != null)
{
List<Contact>? existingContacts = await _context.Contacts.AsNoTracking().Where(c => c.ContactCategoryId == contactCategory.Id).ToListAsync();
if (existingContacts.Count > 0)
{
List<Contact>? contacts = new List<Contact>();
foreach (var contact in existingContacts)
{
contact.ContactCategoryId = null;
contacts.Add(contact);
}
_context.Contacts.UpdateRange(contacts);
}
_context.ContactCategoryMasters.Remove(contactCategory);
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = LoggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
_logger.LogInfo("Employee {EmployeeId} deleted contact category {ContactCategoryId}", LoggedInEmployee.Id, id);
}
_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
#region =================================================================== Contact Tag APIs ===================================================================
public async Task<ApiResponse<Object>> GetContactTags()
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var taglist = await _context.ContactTagMasters.Where(t => t.TenantId == tenantId).ToListAsync();
List<ContactTagVM> contactTags = new List<ContactTagVM>();
foreach (var tag in taglist)
{
ContactTagVM tagVm = tag.ToContactTagVMFromContactTagMaster();
contactTags.Add(tagVm);
}
_logger.LogInfo("{count} contact Tags are fetched by Employee with ID {LoggedInEmployeeId}", contactTags.Count, LoggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(contactTags, System.String.Format("{0} contact tags fetched successfully", contactTags.Count), 200);
}
public async Task<ApiResponse<object>> CreateContactTag(CreateContactTagDto contactTagDto)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactTagDto != null)
{
ContactTagMaster? existingContactTag = await _context.ContactTagMasters.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Name.ToLower() == (contactTagDto.Name != null ? contactTagDto.Name.ToLower() : ""));
if (existingContactTag == null)
{
ContactTagMaster contactTag = contactTagDto.ToContactTagMasterFromCreateContactTagDto(tenantId);
_context.ContactTagMasters.Add(contactTag);
await _context.SaveChangesAsync();
ContactTagVM tagVM = contactTag.ToContactTagVMFromContactTagMaster();
_logger.LogInfo("Employee ID {LoggedInEmployeeId} created a contact tag {ContactTagId}.", LoggedInEmployee.Id, contactTag.Id);
return ApiResponse<object>.SuccessResponse(tagVM, "Tag Created Successfully", 200);
}
_logger.LogWarning("Employee ID {LoggedInEmployeeId} attempted to create an existing contact tag.", LoggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Tag already existed", "Tag already existed", 409);
}
_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>> UpdateContactTag(Guid id, UpdateContactTagDto contactTagDto)
{
Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
if (contactTagDto != null && contactTagDto.Id == id)
{
ContactTagMaster? contactTag = await _context.ContactTagMasters.AsNoTracking().FirstOrDefaultAsync(t => t.TenantId == tenantId && t.Id == contactTagDto.Id);
if (contactTag != null)
{
contactTag = contactTagDto.ToContactTagMasterFromUpdateContactTagDto(tenantId);
_context.ContactTagMasters.Update(contactTag);
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = contactTag.Id,
UpdatedById = LoggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
ContactTagVM contactTagVm = contactTag.ToContactTagVMFromContactTagMaster();
_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);
}
_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);
}
_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>> DeleteContactTag(Guid id)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
ContactTagMaster? contactTag = await _context.ContactTagMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (contactTag != null)
{
List<ContactTagMapping>? tagMappings = await _context.ContactTagMappings.Where(t => t.ContactTagId == contactTag.Id).ToListAsync();
_context.ContactTagMasters.Remove(contactTag);
if (tagMappings.Any())
{
_context.ContactTagMappings.RemoveRange(tagMappings);
}
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = LoggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
_logger.LogInfo("Employee {EmployeeId} deleted contact tag {ContactTagId}", LoggedInEmployee.Id, id);
}
_logger.LogWarning("Employee {EmployeeId} tries to delete Tag {ContactTagId} but not found in database", LoggedInEmployee.Id, id);
return ApiResponse<object>.SuccessResponse(new { }, "Tag deleted successfully", 200);
}
#endregion
#region =================================================================== Work Status APIs ===================================================================
public async Task<ApiResponse<object>> GetWorkStatusList()
{
_logger.LogInfo("GetWorkStatusList called.");
try
{
// Step 1: Get logged-in employee info
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permission to view master data
bool hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id);
if (!hasViewPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "Don't have access to take action", 403);
}
// Step 3: Fetch work statuses for the tenant
var workStatusList = await _context.WorkStatusMasters
.Where(ws => ws.TenantId == tenantId)
.Select(ws => new
{
ws.Id,
ws.Name,
ws.Description,
ws.IsSystem
})
.ToListAsync();
_logger.LogInfo("{Count} work statuses fetched for tenantId: {TenantId}", workStatusList.Count, tenantId);
// Step 4: Return successful response
return ApiResponse<object>.SuccessResponse(
workStatusList,
$"{workStatusList.Count} work status records fetched successfully",
200
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while fetching work status list");
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to fetch work status list", 500);
}
}
public async Task<ApiResponse<object>> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto)
{
_logger.LogInfo("CreateWorkStatus called with Name: {Name}", createWorkStatusDto.Name ?? "");
try
{
// 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 _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "Don't have access to take action", 403);
}
// Step 3: Check if work status with the same name already exists
var existingWorkStatus = await _context.WorkStatusMasters
.FirstOrDefaultAsync(ws => ws.Name == createWorkStatusDto.Name && ws.TenantId == tenantId);
if (existingWorkStatus != null)
{
_logger.LogWarning("Work status already exists: {Name}", createWorkStatusDto.Name ?? "");
return ApiResponse<object>.ErrorResponse("Work status already exists", "Work status already exists", 400);
}
// Step 4: Create new WorkStatusMaster entry
var workStatus = new WorkStatusMaster
{
Name = createWorkStatusDto.Name?.Trim() ?? "",
Description = createWorkStatusDto.Description?.Trim() ?? "",
IsSystem = false,
TenantId = tenantId
};
_context.WorkStatusMasters.Add(workStatus);
await _context.SaveChangesAsync();
_logger.LogInfo("Work status created successfully: {Id}, Name: {Name}", workStatus.Id, workStatus.Name);
return ApiResponse<object>.SuccessResponse(workStatus, "Work status created successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating work status");
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to create work status", 500);
}
}
public async Task<ApiResponse<object>> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto updateWorkStatusDto)
{
_logger.LogInfo("UpdateWorkStatus called for WorkStatus ID: {Id}, New Name: {Name}", id, updateWorkStatusDto.Name ?? "");
try
{
// Step 1: Validate input
if (id == Guid.Empty || id != updateWorkStatusDto.Id)
{
_logger.LogWarning("Invalid ID provided for update. Route ID: {RouteId}, DTO ID: {DtoId}", id, updateWorkStatusDto.Id);
return ApiResponse<object>.ErrorResponse("Invalid data provided", "The provided work status ID is invalid", 400);
}
// Step 2: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 3: Check permissions
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);
return ApiResponse<object>.ErrorResponse("Access denied", "You do not have permission to update this work status", 403);
}
// Step 4: Retrieve the work status record
var workStatus = await _context.WorkStatusMasters
.FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId);
if (workStatus == null)
{
_logger.LogWarning("Work status not found for ID: {Id}", id);
return ApiResponse<object>.ErrorResponse("Work status not found", "No work status found with the provided ID", 404);
}
// Step 5: Check for duplicate name (optional)
var isDuplicate = await _context.WorkStatusMasters
.AnyAsync(ws => ws.Name == updateWorkStatusDto.Name && ws.Id != id && ws.TenantId == tenantId);
if (isDuplicate)
{
_logger.LogWarning("Duplicate work status name '{Name}' detected during update. ID: {Id}", updateWorkStatusDto.Name ?? "", id);
return ApiResponse<object>.ErrorResponse("Work status with the same name already exists", "Duplicate name", 400);
}
// Step 6: Update fields
workStatus.Name = updateWorkStatusDto.Name?.Trim() ?? "";
workStatus.Description = updateWorkStatusDto.Description?.Trim() ?? "";
await _context.SaveChangesAsync();
_logger.LogInfo("Work status updated successfully. ID: {Id}", id);
return ApiResponse<object>.SuccessResponse(workStatus, "Work status updated successfully", 200);
}
catch (Exception ex)
{
_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);
}
}
public async Task<ApiResponse<object>> DeleteWorkStatus(Guid id)
{
_logger.LogInfo("DeleteWorkStatus called for Id: {Id}", id);
try
{
// Step 1: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permission to manage master data
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "Access denied for deleting work status", 403);
}
// Step 3: Find the work status
var workStatus = await _context.WorkStatusMasters
.FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId);
if (workStatus == null)
{
_logger.LogWarning("Work status not found for Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("Work status not found", "Work status not found", 404);
}
// Step 4: Check for dependencies in TaskAllocations
bool hasDependency = await _context.TaskAllocations
.AnyAsync(ta => ta.TenantId == tenantId && ta.WorkStatusId == id);
if (hasDependency)
{
_logger.LogWarning("Cannot delete WorkStatus Id: {Id} due to existing task dependency", id);
return ApiResponse<object>.ErrorResponse(
"Work status has a dependency in assigned tasks and cannot be deleted",
"Deletion failed due to associated tasks",
400
);
}
// Step 5: Delete and persist
_context.WorkStatusMasters.Remove(workStatus);
await _context.SaveChangesAsync();
_logger.LogInfo("Work status deleted successfully. Id: {Id}", id);
return ApiResponse<object>.SuccessResponse(new { }, "Work status deleted successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while deleting WorkStatus Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to delete work status", 500);
}
}
#endregion
}
}

View File

@ -2,7 +2,9 @@ using AutoMapper;
using Marco.Pms.Model.Directory; using Marco.Pms.Model.Directory;
using Marco.Pms.Model.Dtos.Directory; using Marco.Pms.Model.Dtos.Directory;
using Marco.Pms.Model.AppMenu; using Marco.Pms.Model.AppMenu;
using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Dtos.AppMenu; using Marco.Pms.Model.Dtos.AppMenu;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Expenses; using Marco.Pms.Model.Dtos.Expenses;
using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Dtos.Project; using Marco.Pms.Model.Dtos.Project;
@ -100,6 +102,7 @@ namespace Marco.Pms.Services.MappingProfiles
// Your mappings // Your mappings
CreateMap<Project, ProjectVM>(); CreateMap<Project, ProjectVM>();
CreateMap<Project, ProjectInfoVM>(); CreateMap<Project, ProjectInfoVM>();
CreateMap<Project, BasicProjectVM>();
CreateMap<ProjectMongoDB, ProjectInfoVM>(); CreateMap<ProjectMongoDB, ProjectInfoVM>();
CreateMap<UpdateProjectDto, Project>(); CreateMap<UpdateProjectDto, Project>();
CreateMap<Project, ProjectListVM>(); CreateMap<Project, ProjectListVM>();
@ -310,6 +313,17 @@ namespace Marco.Pms.Services.MappingProfiles
dest => dest.DocumentId, dest => dest.DocumentId,
opt => opt.MapFrom(src => Guid.Parse(src.DocumentId))); opt => opt.MapFrom(src => Guid.Parse(src.DocumentId)));
CreateMap<DocumentAttachmentDto, DocumentAttachment>();
CreateMap<DocumentAttachment, DocumentListVM>();
CreateMap<DocumentAttachment, AttachmentVersionVM>();
CreateMap<DocumentAttachment, DocumentAttachmentDetailsVM>();
CreateMap<DocumentCategoryMaster, DocumentCategoryVM>();
CreateMap<CreateDocumentCategoryDto, DocumentCategoryMaster>();
CreateMap<DocumentTypeMaster, DocumentTypeVM>();
CreateMap<CreateDocumentTypeDto, DocumentTypeMaster>();
#endregion #endregion
#region ======================================================= AppMenu ======================================================= #region ======================================================= AppMenu =======================================================

View File

@ -185,8 +185,6 @@ builder.Services.AddScoped<IDirectoryService, DirectoryService>();
builder.Services.AddScoped<GeneralHelper>(); builder.Services.AddScoped<GeneralHelper>();
builder.Services.AddScoped<UserHelper>(); builder.Services.AddScoped<UserHelper>();
builder.Services.AddScoped<RolesHelper>(); builder.Services.AddScoped<RolesHelper>();
builder.Services.AddScoped<EmployeeHelper>();
builder.Services.AddScoped<MasterHelper>();
builder.Services.AddScoped<ReportHelper>(); builder.Services.AddScoped<ReportHelper>();
builder.Services.AddScoped<CacheUpdateHelper>(); builder.Services.AddScoped<CacheUpdateHelper>();
builder.Services.AddScoped<FeatureDetailsHelper>(); builder.Services.AddScoped<FeatureDetailsHelper>();

View File

@ -1,12 +1,17 @@
using AutoMapper; using AutoMapper;
using Marco.Pms.DataAccess.Data; using Marco.Pms.DataAccess.Data;
using Marco.Pms.Helpers.Utility; using Marco.Pms.Helpers.Utility;
using Marco.Pms.Model.Directory;
using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.Master; using Marco.Pms.Model.Master;
using Marco.Pms.Model.MongoDBModels.Utility; using Marco.Pms.Model.MongoDBModels.Utility;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.DocumentManager;
using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Helpers; using Marco.Pms.Services.Helpers;
using Marco.Pms.Services.Service.ServiceInterfaces; using Marco.Pms.Services.Service.ServiceInterfaces;
@ -44,6 +49,410 @@ namespace Marco.Pms.Services.Service
_cache = cache; _cache = cache;
} }
#region =================================================================== Contact Category APIs ===================================================================
public async Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId)
{
if (contactCategoryDto != null)
{
ContactCategoryMaster? existingContactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Name.ToLower() == (contactCategoryDto.Name != null ? contactCategoryDto.Name.ToLower() : ""));
if (existingContactCategory == null)
{
ContactCategoryMaster contactCategory = contactCategoryDto.ToContactCategoryMasterFromCreateContactCategoryDto(tenantId);
_context.ContactCategoryMasters.Add(contactCategory);
await _context.SaveChangesAsync();
ContactCategoryVM categoryVM = contactCategory.ToContactCategoryVMFromContactCategoryMaster();
_logger.LogInfo("Employee ID {LoggedInEmployeeId} created a contact category {ContactCategoryId}.", loggedInEmployee.Id, contactCategory.Id);
return ApiResponse<object>.SuccessResponse(categoryVM, "Category Created Successfully", 200);
}
_logger.LogWarning("Employee ID {LoggedInEmployeeId} attempted to create an existing contact category.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Category already existed", "Category already existed", 409);
}
_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>> UpdateContactCategory(Guid id, UpdateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId)
{
if (contactCategoryDto != null && id == contactCategoryDto.Id)
{
ContactCategoryMaster? contactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Id == id);
if (contactCategory != null)
{
contactCategory.Name = contactCategoryDto.Name ?? "";
contactCategory.Description = contactCategoryDto.Description ?? "";
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = contactCategory.Id,
UpdatedById = loggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
ContactCategoryVM categoryVM = contactCategory.ToContactCategoryVMFromContactCategoryMaster();
_logger.LogInfo("Employee ID {LoggedInEmployeeId} created a contact category {ContactCategoryId}.", loggedInEmployee.Id, contactCategory.Id);
return ApiResponse<object>.SuccessResponse(categoryVM, "Category Created Successfully", 200);
}
_logger.LogWarning("Employee ID {LoggedInEmployeeId} attempted to update a contact category but not found in database.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Category not found", "Category 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>> GetContactCategoriesList(Employee loggedInEmployee, Guid tenantId)
{
var categoryList = await _context.ContactCategoryMasters.Where(c => c.TenantId == tenantId).ToListAsync();
List<ContactCategoryVM> contactCategories = new List<ContactCategoryVM>();
foreach (var category in categoryList)
{
ContactCategoryVM categoryVM = category.ToContactCategoryVMFromContactCategoryMaster();
contactCategories.Add(categoryVM);
}
_logger.LogInfo("{count} contact categoires are fetched by Employee with ID {LoggedInEmployeeId}", contactCategories.Count, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(contactCategories, System.String.Format("{0} contact categories fetched successfully", contactCategories.Count), 200);
}
public async Task<ApiResponse<object>> GetContactCategoryById(Guid id, Employee loggedInEmployee, Guid tenantId)
{
var category = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (category != null)
{
ContactCategoryVM categoryVM = category.ToContactCategoryVMFromContactCategoryMaster();
_logger.LogInfo("Employee {EmployeeId} fetched contact category {ContactCategoryID}", loggedInEmployee.Id, category.Id);
return ApiResponse<object>.SuccessResponse(categoryVM, "Category fetched successfully", 200);
}
_logger.LogWarning("Employee {EmployeeId} attempted to fetch contact category {ContactCategoryID} but not found in database", loggedInEmployee.Id, id);
return ApiResponse<object>.ErrorResponse("Category not found", "Category not found", 404);
}
public async Task<ApiResponse<object>> DeleteContactCategory(Guid id, Employee loggedInEmployee, Guid tenantId)
{
ContactCategoryMaster? contactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (contactCategory != null)
{
List<Contact>? existingContacts = await _context.Contacts.AsNoTracking().Where(c => c.ContactCategoryId == contactCategory.Id).ToListAsync();
if (existingContacts.Count > 0)
{
List<Contact>? contacts = new List<Contact>();
foreach (var contact in existingContacts)
{
contact.ContactCategoryId = null;
contacts.Add(contact);
}
_context.Contacts.UpdateRange(contacts);
}
_context.ContactCategoryMasters.Remove(contactCategory);
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = loggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
_logger.LogInfo("Employee {EmployeeId} deleted contact category {ContactCategoryId}", loggedInEmployee.Id, id);
}
_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
#region =================================================================== Contact Tag APIs ===================================================================
public async Task<ApiResponse<Object>> GetContactTags(Employee loggedInEmployee, Guid tenantId)
{
var taglist = await _context.ContactTagMasters.Where(t => t.TenantId == tenantId).ToListAsync();
List<ContactTagVM> contactTags = new List<ContactTagVM>();
foreach (var tag in taglist)
{
ContactTagVM tagVm = tag.ToContactTagVMFromContactTagMaster();
contactTags.Add(tagVm);
}
_logger.LogInfo("{count} contact Tags are fetched by Employee with ID {LoggedInEmployeeId}", contactTags.Count, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(contactTags, System.String.Format("{0} contact tags fetched successfully", contactTags.Count), 200);
}
public async Task<ApiResponse<object>> CreateContactTag(CreateContactTagDto contactTagDto, Employee loggedInEmployee, Guid tenantId)
{
if (contactTagDto != null)
{
ContactTagMaster? existingContactTag = await _context.ContactTagMasters.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Name.ToLower() == (contactTagDto.Name != null ? contactTagDto.Name.ToLower() : ""));
if (existingContactTag == null)
{
ContactTagMaster contactTag = contactTagDto.ToContactTagMasterFromCreateContactTagDto(tenantId);
_context.ContactTagMasters.Add(contactTag);
await _context.SaveChangesAsync();
ContactTagVM tagVM = contactTag.ToContactTagVMFromContactTagMaster();
_logger.LogInfo("Employee ID {LoggedInEmployeeId} created a contact tag {ContactTagId}.", loggedInEmployee.Id, contactTag.Id);
return ApiResponse<object>.SuccessResponse(tagVM, "Tag Created Successfully", 200);
}
_logger.LogWarning("Employee ID {LoggedInEmployeeId} attempted to create an existing contact tag.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Tag already existed", "Tag already existed", 409);
}
_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>> UpdateContactTag(Guid id, UpdateContactTagDto contactTagDto, Employee loggedInEmployee, Guid tenantId)
{
if (contactTagDto != null && contactTagDto.Id == id)
{
ContactTagMaster? contactTag = await _context.ContactTagMasters.AsNoTracking().FirstOrDefaultAsync(t => t.TenantId == tenantId && t.Id == contactTagDto.Id);
if (contactTag != null)
{
contactTag = contactTagDto.ToContactTagMasterFromUpdateContactTagDto(tenantId);
_context.ContactTagMasters.Update(contactTag);
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = contactTag.Id,
UpdatedById = loggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
await _context.SaveChangesAsync();
ContactTagVM contactTagVm = contactTag.ToContactTagVMFromContactTagMaster();
_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);
}
_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);
}
_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>> DeleteContactTag(Guid id, Employee loggedInEmployee, Guid tenantId)
{
ContactTagMaster? contactTag = await _context.ContactTagMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId);
if (contactTag != null)
{
List<ContactTagMapping>? tagMappings = await _context.ContactTagMappings.Where(t => t.ContactTagId == contactTag.Id).ToListAsync();
_context.ContactTagMasters.Remove(contactTag);
if (tagMappings.Any())
{
_context.ContactTagMappings.RemoveRange(tagMappings);
}
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{
RefereanceId = id,
UpdatedById = loggedInEmployee.Id,
UpdateAt = DateTime.UtcNow
});
await _context.SaveChangesAsync();
_logger.LogInfo("Employee {EmployeeId} deleted contact tag {ContactTagId}", loggedInEmployee.Id, id);
}
_logger.LogWarning("Employee {EmployeeId} tries to delete Tag {ContactTagId} but not found in database", loggedInEmployee.Id, id);
return ApiResponse<object>.SuccessResponse(new { }, "Tag deleted successfully", 200);
}
#endregion
#region =================================================================== Work Status APIs ===================================================================
public async Task<ApiResponse<object>> GetWorkStatusList(Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("GetWorkStatusList called.");
try
{
// Step 1: Check permission to view master data
bool hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id);
if (!hasViewPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "Don't have access to take action", 403);
}
// Step 2: Fetch work statuses for the tenant
var workStatusList = await _context.WorkStatusMasters
.Where(ws => ws.TenantId == tenantId)
.Select(ws => new
{
ws.Id,
ws.Name,
ws.Description,
ws.IsSystem
})
.ToListAsync();
_logger.LogInfo("{Count} work statuses fetched for tenantId: {TenantId}", workStatusList.Count, tenantId);
// Step 3: Return successful response
return ApiResponse<object>.SuccessResponse(
workStatusList,
$"{workStatusList.Count} work status records fetched successfully",
200
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while fetching work status list");
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to fetch work status list", 500);
}
}
public async Task<ApiResponse<object>> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("CreateWorkStatus called with Name: {Name}", createWorkStatusDto.Name ?? "");
try
{
// Step 1: Check if user has permission to manage master data
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "Don't have access to take action", 403);
}
// Step 2: Check if work status with the same name already exists
var existingWorkStatus = await _context.WorkStatusMasters
.FirstOrDefaultAsync(ws => ws.Name == createWorkStatusDto.Name && ws.TenantId == tenantId);
if (existingWorkStatus != null)
{
_logger.LogWarning("Work status already exists: {Name}", createWorkStatusDto.Name ?? "");
return ApiResponse<object>.ErrorResponse("Work status already exists", "Work status already exists", 400);
}
// Step 3: Create new WorkStatusMaster entry
var workStatus = new WorkStatusMaster
{
Name = createWorkStatusDto.Name?.Trim() ?? "",
Description = createWorkStatusDto.Description?.Trim() ?? "",
IsSystem = false,
TenantId = tenantId
};
_context.WorkStatusMasters.Add(workStatus);
await _context.SaveChangesAsync();
_logger.LogInfo("Work status created successfully: {Id}, Name: {Name}", workStatus.Id, workStatus.Name);
return ApiResponse<object>.SuccessResponse(workStatus, "Work status created successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating work status");
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to create work status", 500);
}
}
public async Task<ApiResponse<object>> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto updateWorkStatusDto, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("UpdateWorkStatus called for WorkStatus ID: {Id}, New Name: {Name}", id, updateWorkStatusDto.Name ?? "");
try
{
// Step 1: Validate input
if (id == Guid.Empty || id != updateWorkStatusDto.Id)
{
_logger.LogWarning("Invalid ID provided for update. Route ID: {RouteId}, DTO ID: {DtoId}", id, updateWorkStatusDto.Id);
return ApiResponse<object>.ErrorResponse("Invalid data provided", "The provided work status ID is invalid", 400);
}
// Step 2: Check permissions
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);
return ApiResponse<object>.ErrorResponse("Access denied", "You do not have permission to update this work status", 403);
}
// Step 3: Retrieve the work status record
var workStatus = await _context.WorkStatusMasters
.FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId);
if (workStatus == null)
{
_logger.LogWarning("Work status not found for ID: {Id}", id);
return ApiResponse<object>.ErrorResponse("Work status not found", "No work status found with the provided ID", 404);
}
// Step 4: Check for duplicate name (optional)
var isDuplicate = await _context.WorkStatusMasters
.AnyAsync(ws => ws.Name == updateWorkStatusDto.Name && ws.Id != id && ws.TenantId == tenantId);
if (isDuplicate)
{
_logger.LogWarning("Duplicate work status name '{Name}' detected during update. ID: {Id}", updateWorkStatusDto.Name ?? "", id);
return ApiResponse<object>.ErrorResponse("Work status with the same name already exists", "Duplicate name", 400);
}
// Step 5: Update fields
workStatus.Name = updateWorkStatusDto.Name?.Trim() ?? "";
workStatus.Description = updateWorkStatusDto.Description?.Trim() ?? "";
await _context.SaveChangesAsync();
_logger.LogInfo("Work status updated successfully. ID: {Id}", id);
return ApiResponse<object>.SuccessResponse(workStatus, "Work status updated successfully", 200);
}
catch (Exception ex)
{
_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);
}
}
public async Task<ApiResponse<object>> DeleteWorkStatus(Guid id, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("DeleteWorkStatus called for Id: {Id}", id);
try
{
// Step 2: Check permission to manage master data
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "Access denied for deleting work status", 403);
}
// Step 3: Find the work status
var workStatus = await _context.WorkStatusMasters
.FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId);
if (workStatus == null)
{
_logger.LogWarning("Work status not found for Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("Work status not found", "Work status not found", 404);
}
// Step 4: Check for dependencies in TaskAllocations
bool hasDependency = await _context.TaskAllocations
.AnyAsync(ta => ta.TenantId == tenantId && ta.WorkStatusId == id);
if (hasDependency)
{
_logger.LogWarning("Cannot delete WorkStatus Id: {Id} due to existing task dependency", id);
return ApiResponse<object>.ErrorResponse(
"Work status has a dependency in assigned tasks and cannot be deleted",
"Deletion failed due to associated tasks",
400
);
}
// Step 5: Delete and persist
_context.WorkStatusMasters.Remove(workStatus);
await _context.SaveChangesAsync();
_logger.LogInfo("Work status deleted successfully. Id: {Id}", id);
return ApiResponse<object>.SuccessResponse(new { }, "Work status deleted successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while deleting WorkStatus Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("An error occurred", "Unable to delete work status", 500);
}
}
#endregion
#region =================================================================== Expenses Type APIs =================================================================== #region =================================================================== Expenses Type APIs ===================================================================
public async Task<ApiResponse<object>> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive) public async Task<ApiResponse<object>> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive)
@ -440,7 +849,7 @@ namespace Marco.Pms.Services.Service
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission) if (!hasManagePermission)
{ {
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPENSE STATUS MASTER.", loggedInEmployee.Id); _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing PAYMENT MODE MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
} }
@ -489,6 +898,520 @@ namespace Marco.Pms.Services.Service
#endregion #endregion
#region =================================================================== Document Category APIs ===================================================================
/// <summary>
/// Fetches the list of Document Categories for a given tenant and optional entity type.
/// Ensures tenant validation, mapping, and proper logging.
/// </summary>
/// <param name="entityTypeId">Optional entity type filter (e.g., EmployeeEntity, ProjectEntity).</param>
/// <param name="loggedInEmployee">Currently logged-in employee.</param>
/// <param name="tenantId">Tenant Id context.</param>
/// <returns>ApiResponse containing the document categories or error details.</returns>
public async Task<ApiResponse<object>> GetDocumentCategoryMasterListAsync(Guid? entityTypeId, Employee loggedInEmployee, Guid tenantId)
{
try
{
// ✅ Tenant validation
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Access denied. Employee {EmployeeId} (TenantId: {EmployeeTenantId}) attempted to fetch document categories for TenantId: {RequestedTenantId}",
loggedInEmployee.Id, loggedInEmployee.TenantId, tenantId);
return ApiResponse<object>.ErrorResponse("Access Denied", "You do not have access to this information", 403);
}
// ✅ Build query
IQueryable<DocumentCategoryMaster> documentCategoryQuery = _context.DocumentCategoryMasters
.AsNoTracking() // optimization: read-only
.Where(dc => dc.TenantId == tenantId);
// ✅ Apply optional filter
if (entityTypeId.HasValue)
{
documentCategoryQuery = documentCategoryQuery.Where(dc => dc.EntityTypeId == entityTypeId.Value);
}
// ✅ Fetch and map
var documentCategories = await documentCategoryQuery.ToListAsync();
var response = _mapper.Map<List<DocumentCategoryVM>>(documentCategories);
_logger.LogInfo("{Count} document categories fetched successfully for TenantId: {TenantId} by Employee {EmployeeId}",
response.Count, tenantId, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, $"{response.Count} document categories have been fetched successfully.", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while fetching document categories for TenantId: {TenantId} by Employee {EmployeeId}",
tenantId, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Server Error", "Server Error occured", 500);
}
}
public async Task<ApiResponse<object>> CreateDocumentCategoryMasterAsync(CreateDocumentCategoryDto model, Employee loggedInEmployee, Guid tenantId)
{
try
{
// Validation if employee is taking action in same tenant
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Employee {EmployeeId} attempted to add new Document Category in different tenant", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied", "User do not have access for this information", 403);
}
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing Document Category Master.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var oldExists = await _context.DocumentCategoryMasters
.AnyAsync(dc => dc.Name == model.Name && dc.EntityTypeId == model.EntityTypeId && dc.TenantId == tenantId);
if (oldExists)
{
_logger.LogWarning("Document Category of {Name} is already exists in database for {TenantId}", model.Name, tenantId);
return ApiResponse<object>.ErrorResponse("Document Category already exists.", "Document Category already exists in database", 409);
}
// Mapping the DTO to Document Category Master Model
var documentCategory = _mapper.Map<DocumentCategoryMaster>(model);
documentCategory.CreatedAt = DateTime.UtcNow;
documentCategory.TenantId = tenantId;
_context.DocumentCategoryMasters.Add(documentCategory);
await _context.SaveChangesAsync();
_logger.LogInfo("New Document Category {DocumentCategoryId} was added by employee {EmployeeId}", documentCategory.Id, loggedInEmployee.Id);
// Mapping the Document Category Master Model to View Model
var response = _mapper.Map<DocumentCategoryVM>(documentCategory);
return ApiResponse<object>.SuccessResponse(response, "Document Category craeted Successfully", 201);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while adding new Document Category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while adding new Document Category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> UpdateDocumentCategoryMasterAsync(Guid id, CreateDocumentCategoryDto model, Employee loggedInEmployee, Guid tenantId)
{
try
{
// Validation if employee is taking action in same tenant
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Employee {EmployeeId} attempted to update Document Category in different tenant", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied", "User do not have access for this information", 403);
}
// Checking permssion for managing masters
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing DOCUMENT CATEGORY MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
// Validating the prvided data
if (model.Id != id)
{
_logger.LogWarning("Employee {EmployeeId} provide different Ids in payload and path variable", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Invalid Data", "User has send invalid payload", 400);
}
var categoryTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.DocumentCategoryMasters.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId);
});
var oldCategoryExistsTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.DocumentCategoryMasters.AnyAsync(dc => dc.Name == model.Name && dc.Id != model.Id.Value && dc.EntityTypeId == model.EntityTypeId && dc.TenantId == tenantId);
});
await Task.WhenAll(categoryTask, oldCategoryExistsTask);
var documentCategory = categoryTask.Result;
var oldCategoryExists = oldCategoryExistsTask.Result;
// Checking if Document Category exists
if (documentCategory == null)
{
_logger.LogWarning("Employee {EmployeeId} tries to update Document Category, but not found in database", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Document Category not found", "Document Category not found", 404);
}
if (oldCategoryExists)
{
_logger.LogWarning("Document Category of {Name} is already exists in database for {TenantId} while updating document category", model.Name, tenantId);
return ApiResponse<object>.ErrorResponse("Document Category already exists.", "Document Category already exists in database", 409);
}
// Mapping DocumentCategoryMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(documentCategory);
// Mapping DocumentCategoryDto to DocumentCategoryMaster
_mapper.Map(model, documentCategory);
_context.DocumentCategoryMasters.Update(documentCategory);
await _context.SaveChangesAsync();
_logger.LogInfo("Document Category {DocumentCategoryId} was updated by employee {EmployeeId}", documentCategory.Id, loggedInEmployee.Id);
// Saving the old entity in mongoDB
var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = documentCategory.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = existingEntityBson,
UpdatedAt = DateTime.UtcNow
}, "DocumentCategoryModificationLog");
// Mapping DocumentCategoryMaster to DocumentCategoryVM
var response = _mapper.Map<DocumentCategoryVM>(documentCategory);
return ApiResponse<object>.SuccessResponse(response, "Document Category updated Successfully", 200);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while updating Document Category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while updating Document Category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> DeleteDocumentCategoryMasterAsync(Guid id, Employee loggedInEmployee, Guid tenantId)
{
try
{
// Validation if employee is taking action in same tenant
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Employee {EmployeeId} attempted to delete Document Category in different tenant", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied", "User do not have access for this information", 403);
}
// Checking permssion for managing masters
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing DOCUMENT CATEGORY MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var documentCategory = await _context.DocumentCategoryMasters.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId);
// Checking if Document Category exists
if (documentCategory == null)
{
_logger.LogWarning("Employee {EmployeeId} tries to delete Document Category, but not found in database", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Document Category not found", "Document Category not found", 404);
}
// Mapping DocumentCategoryMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(documentCategory);
_context.DocumentCategoryMasters.Remove(documentCategory);
await _context.SaveChangesAsync();
_logger.LogInfo("Document Category {DocumentCategoryId} was deleted by employee {EmployeeId}", documentCategory.Id, loggedInEmployee.Id);
// Saving the old entity in mongoDB
var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = documentCategory.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = existingEntityBson,
UpdatedAt = DateTime.UtcNow
}, "DocumentCategoryModificationLog");
// Mapping DocumentCategoryMatser to DocumentCategoryVM
var response = _mapper.Map<DocumentCategoryVM>(documentCategory);
return ApiResponse<object>.SuccessResponse(response, "Document Category deleted Successfully", 200);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while deleteing Document Category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while deleteing Document Category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
#endregion
#region =================================================================== Document Type APIs ===================================================================
public async Task<ApiResponse<object>> GetDocumentTypeMasterListAsync(Guid? documentCategoryId, Employee loggedInEmployee, Guid tenantId)
{
try
{
// ✅ Tenant validation
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Access denied. Employee {EmployeeId} (TenantId: {EmployeeTenantId}) attempted to fetch document types for TenantId: {RequestedTenantId}",
loggedInEmployee.Id, loggedInEmployee.TenantId, tenantId);
return ApiResponse<object>.ErrorResponse("Access Denied", "You do not have access to this information", 403);
}
// ✅ Build query
IQueryable<DocumentTypeMaster> documentTypeQuery = _context.DocumentTypeMasters
.AsNoTracking() // optimization: read-only
.Where(dc => dc.TenantId == tenantId);
// ✅ Apply optional filter
if (documentCategoryId.HasValue)
{
documentTypeQuery = documentTypeQuery.Where(dc => dc.DocumentCategoryId == documentCategoryId.Value);
}
// ✅ Fetch and map
var documentType = await documentTypeQuery.Include(dt => dt.DocumentCategory).ToListAsync();
var response = _mapper.Map<List<DocumentTypeVM>>(documentType);
_logger.LogInfo("{Count} document type fetched successfully for TenantId: {TenantId} by Employee {EmployeeId}",
response.Count, tenantId, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, $"{response.Count} document type have been fetched successfully.", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while fetching document type for TenantId: {TenantId} by Employee {EmployeeId}",
tenantId, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Server Error", "Server Error occured", 500);
}
}
public async Task<ApiResponse<object>> CreateDocumentTypeMasterAsync(CreateDocumentTypeDto model, Employee loggedInEmployee, Guid tenantId)
{
try
{
// Validation if employee is taking action in same tenant
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Employee {EmployeeId} attempted to add new Document Type in different tenant", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied", "User do not have access for this information", 403);
}
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing DOCUMENT TYPE MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var oldExists = await _context.DocumentTypeMasters
.AnyAsync(dt => dt.Name == model.Name && dt.DocumentCategoryId == model.DocumentCategoryId && dt.TenantId == tenantId);
if (oldExists)
{
_logger.LogWarning("Document Type of {Name} is already exists in database for {TenantId} while creating new document type", model.Name, tenantId);
return ApiResponse<object>.ErrorResponse("Document Type already exists.", "Document Type already exists in database", 409);
}
// Mapping the DTO to Document Type Master Model
var documentType = _mapper.Map<DocumentTypeMaster>(model);
if (string.IsNullOrWhiteSpace(model.RegexExpression))
{
documentType.IsValidationRequired = false;
}
documentType.IsSystem = false;
documentType.IsActive = true;
documentType.CreatedAt = DateTime.UtcNow;
documentType.TenantId = tenantId;
_context.DocumentTypeMasters.Add(documentType);
await _context.SaveChangesAsync();
_logger.LogInfo("New Document Type {DocumentTypeId} was added by employee {EmployeeId}", documentType.Id, loggedInEmployee.Id);
// Mapping the Document Type Master Model to View Model
var response = _mapper.Map<DocumentTypeVM>(documentType);
return ApiResponse<object>.SuccessResponse(response, "Document Type craeted Successfully", 201);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while adding new Document Type by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while adding new Document Type by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> UpdateDocumentTypeMasterAsync(Guid id, CreateDocumentTypeDto model, Employee loggedInEmployee, Guid tenantId)
{
try
{
// Validation if employee is taking action in same tenant
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Employee {EmployeeId} attempted to update Document Type in different tenant", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied", "User do not have access for this information", 403);
}
// Checking permssion for managing masters
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing DOCUMENT TYPE MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
// Validating the prvided data
if (model.Id != id)
{
_logger.LogWarning("Employee {EmployeeId} provide different Ids in payload and path variable", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Invalid Data", "User has send invalid payload", 400);
}
var documentTypeTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.DocumentTypeMasters.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId);
});
var oldTypeExistsTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.DocumentTypeMasters
.AnyAsync(dt => dt.Name == model.Name && dt.Id != model.Id.Value && dt.DocumentCategoryId == model.DocumentCategoryId && dt.TenantId == tenantId);
});
await Task.WhenAll(documentTypeTask, oldTypeExistsTask);
var documentType = documentTypeTask.Result;
var oldTypeExists = oldTypeExistsTask.Result;
// Checking if Document Type exists
if (documentType == null)
{
_logger.LogWarning("Employee {EmployeeId} tries to update Document Type, but not found in database", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Document Type not found", "Document Type not found", 404);
}
if (oldTypeExists)
{
_logger.LogWarning("Document Type of {Name} is already exists in database for {TenantId} while updating document Type", model.Name, tenantId);
return ApiResponse<object>.ErrorResponse("Document Type already exists.", "Document Type already exists in database", 409);
}
// Mapping DocumentTypeMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(documentType);
// Mapping DocumentTypeDto to DocumentTypeMaster
_mapper.Map(model, documentType);
_context.DocumentTypeMasters.Update(documentType);
await _context.SaveChangesAsync();
_logger.LogInfo("Document Type {DocumentTypeId} was updated by employee {EmployeeId}", documentType.Id, loggedInEmployee.Id);
// Saving the old entity in mongoDB
var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = documentType.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = existingEntityBson,
UpdatedAt = DateTime.UtcNow
}, "DocumentTypeModificationLog");
// Mapping DocumentTypeMaster to DocumentTypeVM
var response = _mapper.Map<DocumentTypeVM>(documentType);
return ApiResponse<object>.SuccessResponse(response, "Document Type updated Successfully", 200);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while updating Document Type by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while updating Document Type by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> DeleteDocumentTypeMasterAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId)
{
string action = isActive ? "restore" : "delete";
try
{
// Validation if employee is taking action in same tenant
if (tenantId != loggedInEmployee.TenantId)
{
_logger.LogWarning("Employee {EmployeeId} attempted to {Action} Document Type in different tenant", loggedInEmployee.Id, action);
return ApiResponse<object>.ErrorResponse("Access Denied", "User do not have access for this information", 403);
}
// Checking permssion for managing masters
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing DOCUMENT TYPE MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var documentType = await _context.DocumentTypeMasters.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId);
// Checking if Document Type exists
if (documentType == null)
{
_logger.LogWarning("Employee {EmployeeId} tries to {Action} Document Type, but not found in database", loggedInEmployee.Id, action);
return ApiResponse<object>.ErrorResponse("Document Type not found", "Document Type not found", 404);
}
if (documentType.IsSystem)
{
_logger.LogWarning("Employee {EmployeeId} tries to {Action} Document Type, but could not take action on system defined entity", loggedInEmployee.Id, action);
return ApiResponse<object>.ErrorResponse($"Document is system defined cannot be {action}d", $"Document is system defined cannot be {action}d", 400);
}
// Mapping DocumentTypeMatser to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(documentType);
documentType.IsActive = isActive;
await _context.SaveChangesAsync();
_logger.LogInfo("Document Type {DocumentTypeId} was {Action}d by employee {EmployeeId}", documentType.Id, action, loggedInEmployee.Id);
// Saving the old entity in mongoDB
var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = documentType.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = existingEntityBson,
UpdatedAt = DateTime.UtcNow
}, "DocumentTypeModificationLog");
// Mapping DocumentTypeMatser to DocumentTypeVM
var response = _mapper.Map<DocumentTypeVM>(documentType);
return ApiResponse<object>.SuccessResponse(response, $"Document Type {action}d Successfully", 200);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while {Action}ing Document Type by employee {EmployeeId}", action, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while {Action}ing Document Type by employee {EmployeeId}", action, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
#endregion
#region =================================================================== Helper Function =================================================================== #region =================================================================== Helper Function ===================================================================
private static object ExceptionMapper(Exception ex) private static object ExceptionMapper(Exception ex)
{ {

View File

@ -19,16 +19,100 @@ namespace Marco.Pms.Services.Service
_cache = cache; _cache = cache;
} }
public async Task<bool> HasPermission(Guid featurePermissionId, Guid employeeId) //public async Task<bool> HasPermission(Guid featurePermissionId, Guid employeeId, Guid? projectId = null)
//{
// var featurePermissionIds = await _cache.GetPermissions(employeeId);
// if (featurePermissionIds == null)
// {
// List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId);
// featurePermissionIds = featurePermission.Select(fp => fp.Id).ToList();
// }
// if (projectId != null)
// {
// var projectLevelPerissionIds = await _context.ProjectLevelPermissionMappings
// .Where(pl => pl.ProjectId == projectId.Value && pl.EmployeeId == employeeId).Select(pl => pl.PermissionId).ToListAsync();
// var projectLevelModuleIds = new HashSet<Guid>
// {
// Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def"),
// Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"),
// Guid.Parse("81ab8a87-8ccd-4015-a917-0627cee6a100"),
// Guid.Parse("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
// Guid.Parse("a8cf4331-8f04-4961-8360-a3f7c3cc7462")
// };
// var allProjectLevelPermissionIds = await _context.FeaturePermissions
// .Where(fp => projectLevelModuleIds.Contains(fp.FeatureId) && !projectLevelPerissionIds.Contains(fp.Id)).Select(fp => fp.Id).ToListAsync();
// featurePermissionIds.RemoveRange(allProjectLevelPermissionIds);
// featurePermissionIds.AddRange(projectLevelPerissionIds);
// featurePermissionIds = featurePermissionIds.Distinct().ToList();
// }
// var hasPermission = featurePermissionIds.Contains(featurePermissionId);
// return hasPermission;
//}
/// <summary>
/// Checks whether an employee has a specific feature permission, optionally within a project context.
/// </summary>
/// <param name="featurePermissionId">The target feature permission ID to check.</param>
/// <param name="employeeId">The ID of the employee.</param>
/// <param name="projectId">Optional project ID for project-scoped permissions.</param>
/// <returns>True if the user has the permission, otherwise false.</returns>
public async Task<bool> HasPermission(Guid featurePermissionId, Guid employeeId, Guid? projectId = null)
{ {
// 1. Try fetching permissions from cache (fast-path lookup).
var featurePermissionIds = await _cache.GetPermissions(employeeId); var featurePermissionIds = await _cache.GetPermissions(employeeId);
// If not found in cache, fallback to database (slower).
if (featurePermissionIds == null) if (featurePermissionIds == null)
{ {
List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId); var featurePermissions = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId);
featurePermissionIds = featurePermission.Select(fp => fp.Id).ToList(); featurePermissionIds = featurePermissions.Select(fp => fp.Id).ToList();
} }
var hasPermission = featurePermissionIds.Contains(featurePermissionId);
return hasPermission; // 2. Handle project-level permission overrides if a project is specified.
if (projectId.HasValue)
{
// Fetch permissions explicitly assigned to this employee in the project.
var projectLevelPermissionIds = await _context.ProjectLevelPermissionMappings
.Where(pl => pl.ProjectId == projectId.Value && pl.EmployeeId == employeeId)
.Select(pl => pl.PermissionId)
.ToListAsync();
if (projectLevelPermissionIds?.Any() ?? false)
{
// Define modules where project-level overrides apply.
var projectLevelModuleIds = new HashSet<Guid>
{
Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def"),
Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"),
Guid.Parse("81ab8a87-8ccd-4015-a917-0627cee6a100"),
Guid.Parse("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
Guid.Parse("a8cf4331-8f04-4961-8360-a3f7c3cc7462")
};
// Get all feature permissions under those modules where the user didn't have explicit project-level grants.
var allOverriddenPermissions = await _context.FeaturePermissions
.Where(fp => projectLevelModuleIds.Contains(fp.FeatureId) &&
!projectLevelPermissionIds.Contains(fp.Id))
.Select(fp => fp.Id)
.ToListAsync();
// Apply overrides:
// - Remove global permissions overridden by project-level rules.
// - Add explicit project-level permissions.
featurePermissionIds = featurePermissionIds
.Except(allOverriddenPermissions) // Remove overridden
.Concat(projectLevelPermissionIds) // Add project-level
.Distinct() // Ensure no duplicates
.ToList();
}
}
// 3. Final check: does the employee have the requested permission?
return featurePermissionIds.Contains(featurePermissionId);
} }
public async Task<bool> HasPermissionAny(List<Guid> featurePermissionIds, Guid employeeId) public async Task<bool> HasPermissionAny(List<Guid> featurePermissionIds, Guid employeeId)
{ {

View File

@ -3,13 +3,16 @@ 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;
using Marco.Pms.Model.Dtos.Util;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.MongoDBModels.Project; using Marco.Pms.Model.MongoDBModels.Project;
using Marco.Pms.Model.Projects; using Marco.Pms.Model.Projects;
using Marco.Pms.Model.TenantModels; using Marco.Pms.Model.TenantModels;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Employee; using Marco.Pms.Model.ViewModels.Employee;
using Marco.Pms.Model.ViewModels.Master;
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;
@ -46,6 +49,7 @@ namespace Marco.Pms.Services.Service
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_generalHelper = generalHelper ?? throw new ArgumentNullException(nameof(generalHelper)); _generalHelper = generalHelper ?? throw new ArgumentNullException(nameof(generalHelper));
} }
#region =================================================================== Project Get APIs =================================================================== #region =================================================================== Project Get APIs ===================================================================
public async Task<ApiResponse<object>> GetAllProjectsBasicAsync(Guid tenantId, Employee loggedInEmployee) public async Task<ApiResponse<object>> GetAllProjectsBasicAsync(Guid tenantId, Employee loggedInEmployee)
@ -194,7 +198,7 @@ namespace Marco.Pms.Services.Service
_logger.LogInfo("Details requested by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}", loggedInEmployee.Id, id); _logger.LogInfo("Details requested by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}", loggedInEmployee.Id, id);
// Step 1: Check global view project permission // Step 1: Check global view project permission
var hasViewProjectPermission = await _permission.HasPermission(PermissionsMaster.ViewProject, loggedInEmployee.Id); var hasViewProjectPermission = await _permission.HasPermission(PermissionsMaster.ViewProject, loggedInEmployee.Id, id);
if (!hasViewProjectPermission) if (!hasViewProjectPermission)
{ {
_logger.LogWarning("ViewProjects permission denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id); _logger.LogWarning("ViewProjects permission denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
@ -490,7 +494,7 @@ namespace Marco.Pms.Services.Service
// This is a placeholder for your actual permission logic. // This is a placeholder for your actual permission logic.
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value); var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value);
var hasAllEmployeePermission = await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id); var hasAllEmployeePermission = await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id);
var hasviewTeamPermission = await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id); var hasviewTeamPermission = await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id, projectId);
if (!(hasProjectPermission && (hasAllEmployeePermission || hasviewTeamPermission))) if (!(hasProjectPermission && (hasAllEmployeePermission || hasviewTeamPermission)))
{ {
@ -975,7 +979,7 @@ namespace Marco.Pms.Services.Service
{ {
// --- Step 1: Run independent permission checks in PARALLEL --- // --- Step 1: Run independent permission checks in PARALLEL ---
var projectPermissionTask = _permission.HasProjectPermission(loggedInEmployee, projectId); var projectPermissionTask = _permission.HasProjectPermission(loggedInEmployee, projectId);
var viewInfraPermissionTask = _permission.HasPermission(PermissionsMaster.ViewProjectInfra, loggedInEmployee.Id); var viewInfraPermissionTask = _permission.HasPermission(PermissionsMaster.ViewProjectInfra, loggedInEmployee.Id, projectId);
await Task.WhenAll(projectPermissionTask, viewInfraPermissionTask); await Task.WhenAll(projectPermissionTask, viewInfraPermissionTask);
@ -1053,7 +1057,7 @@ namespace Marco.Pms.Services.Service
} }
var hasProjectAccess = await _permission.HasProjectPermission(loggedInEmployee, projectInfo.ProjectId); var hasProjectAccess = await _permission.HasProjectPermission(loggedInEmployee, projectInfo.ProjectId);
var hasGenericViewInfraPermission = await _permission.HasPermission(PermissionsMaster.ViewProjectInfra, loggedInEmployee.Id); var hasGenericViewInfraPermission = await _permission.HasPermission(PermissionsMaster.ViewProjectInfra, loggedInEmployee.Id, projectInfo.ProjectId);
if (!hasProjectAccess || !hasGenericViewInfraPermission) if (!hasProjectAccess || !hasGenericViewInfraPermission)
{ {
@ -1165,7 +1169,6 @@ namespace Marco.Pms.Services.Service
} }
} }
#endregion #endregion
#region =================================================================== Project Infrastructre Manage APIs =================================================================== #region =================================================================== Project Infrastructre Manage APIs ===================================================================
@ -1290,7 +1293,7 @@ namespace Marco.Pms.Services.Service
// --- (Placeholder) Security Check --- // --- (Placeholder) Security Check ---
// You MUST verify the user has permission to modify ALL WorkAreas in the batch. // You MUST verify the user has permission to modify ALL WorkAreas in the batch.
var projectIdsInBatch = workAreasFromDb.Values.Select(wa => wa.Floor!.Building!.ProjectId).Distinct(); var projectIdsInBatch = workAreasFromDb.Values.Select(wa => wa.Floor!.Building!.ProjectId).Distinct();
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageProjectInfra, loggedInEmployee.Id); var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageProjectInfra, loggedInEmployee.Id, projectIdsInBatch.FirstOrDefault());
if (!hasPermission) if (!hasPermission)
{ {
_logger.LogWarning("Access DENIED for user {UserId} trying to create/update tasks.", loggedInEmployee.Id); _logger.LogWarning("Access DENIED for user {UserId} trying to create/update tasks.", loggedInEmployee.Id);
@ -1462,6 +1465,309 @@ namespace Marco.Pms.Services.Service
Response = ApiResponse<object>.SuccessResponse(new { id = task.Id }, "Task deleted successfully.", 200) Response = ApiResponse<object>.SuccessResponse(new { id = task.Id }, "Task deleted successfully.", 200)
}; };
} }
#endregion
#region =================================================================== Project-Level Permission APIs ===================================================================
/// <summary>
/// Manages project-level permissions for an employee, optimizing DB calls and operations.
/// </summary>
/// <param name="model">Project-level permission DTO.</param>
/// <param name="tenantId">Tenant Guid.</param>
/// <param name="loggedInEmployee">Currently logged in employee.</param>
/// <returns>API response indicating the result.</returns>
public async Task<ApiResponse<object>> ManageProjectLevelPermissionAsync(ProjctLevelPermissionDto model, Guid tenantId, Employee loggedInEmployee)
{
// Log: Method entry and received parameters
_logger.LogInfo("ManageProjectLevelPermissionAsync started for EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, TenantId: {TenantId}",
model.EmployeeId, model.ProjectId, tenantId);
var hasTeamPermission = await _permission.HasPermission(PermissionsMaster.ManageTeam, loggedInEmployee.Id, model.ProjectId);
if (!hasTeamPermission)
{
_logger.LogWarning("Access Denied. User {UserId} tried to Manage the project-level permission for Employee {EmployeeId} and Project {ProjectId}"
, loggedInEmployee.Id, model.EmployeeId, model.ProjectId);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage the project-level permission", 403);
}
// Fetch all required entities in parallel where possible
var featurePermissionIds = model.Permission.Select(p => p.Id).ToList();
// Log: Starting DB queries
_logger.LogDebug("Fetching employee, project, feature permissions, and existing mappings.");
var employeeTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.ProjectAllocations.Include(pa => pa.Employee)
.AsNoTracking()
.Where(pa => pa.EmployeeId == model.EmployeeId && pa.ProjectId == model.ProjectId && pa.TenantId == tenantId && pa.IsActive)
.Select(pa => pa.Employee).FirstOrDefaultAsync();
});
var projectTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId);
});
var featurePermissionsTask = Task.Run(async () =>
{
var featurePermissionIds = model.Permission.Select(p => p.Id).ToList();
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.FeaturePermissions.AsNoTracking().Where(p => featurePermissionIds.Contains(p.Id)).ToListAsync();
});
var oldProjectLevelMappingTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.ProjectLevelPermissionMappings
.AsNoTracking()
.Where(p => p.EmployeeId == model.EmployeeId && p.ProjectId == model.ProjectId && p.TenantId == tenantId).ToListAsync();
});
await Task.WhenAll(employeeTask, projectTask, featurePermissionsTask, oldProjectLevelMappingTask);
var employee = employeeTask.Result;
var project = projectTask.Result;
var featurePermissions = featurePermissionsTask.Result;
var oldProjectLevelMapping = oldProjectLevelMappingTask.Result;
// Validate all loaded entities
if (employee == null)
{
_logger.LogWarning("Employee not found: {EmployeeId}", model.EmployeeId);
return ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found in database", 404);
}
if (project == null)
{
_logger.LogWarning("Project not found: {ProjectId}", model.ProjectId);
return ApiResponse<object>.ErrorResponse("Project not found", "Project not found in database", 404);
}
if (!(featurePermissions?.Any() ?? false))
{
_logger.LogWarning("No feature permissions found for provided ids");
return ApiResponse<object>.ErrorResponse("No permission found", "No permission found in database", 404);
}
_logger.LogDebug("All entities loaded successfully for permission processing.");
// Permission diff logic: Add new, Remove old
var oldProjectLevelPermissionIds = oldProjectLevelMapping.Select(p => p.PermissionId).ToList();
var newProjectLevelPermissions = model.Permission
.Where(p => p.IsEnabled && !oldProjectLevelPermissionIds.Contains(p.Id))
.Select(p => new ProjectLevelPermissionMapping
{
EmployeeId = model.EmployeeId,
ProjectId = model.ProjectId,
PermissionId = p.Id,
TenantId = tenantId
}).ToList();
var deleteProjectLevelPermissions = oldProjectLevelMapping
.Where(pl => model.Permission.Any(p => !p.IsEnabled && p.Id == pl.PermissionId))
.ToList();
// Apply permission changes
if (newProjectLevelPermissions.Any())
{
_context.ProjectLevelPermissionMappings.AddRange(newProjectLevelPermissions);
_logger.LogInfo("Added {Count} new project-level permissions.", newProjectLevelPermissions.Count);
}
if (deleteProjectLevelPermissions.Any())
{
_context.ProjectLevelPermissionMappings.RemoveRange(deleteProjectLevelPermissions);
_logger.LogInfo("Removed {Count} old project-level permissions.", deleteProjectLevelPermissions.Count);
}
await _context.SaveChangesAsync();
_logger.LogInfo("Project-level permission changes persisted for EmployeeId: {EmployeeId}, ProjectId: {ProjectId}", model.EmployeeId, model.ProjectId);
// Final permissions for response
var permissions = await _context.ProjectLevelPermissionMappings
.Include(p => p.Permission)
.AsNoTracking()
.Where(p => p.EmployeeId == model.EmployeeId && p.ProjectId == model.ProjectId && p.TenantId == tenantId)
.Select(p => _mapper.Map<FeaturePermissionVM>(p.Permission))
.ToListAsync();
_logger.LogInfo("ManageProjectLevelPermissionAsync completed successfully.");
var response = new
{
EmployeeId = _mapper.Map<BasicEmployeeVM>(employee),
ProjectId = _mapper.Map<BasicProjectVM>(project),
Permissions = permissions
};
return ApiResponse<object>.SuccessResponse(response, "Project-Level permission assigned successfully", 200);
}
/// <summary>
/// Retrieves the project-level permissions assigned to a specific employee for a given project and tenant.
/// </summary>
/// <param name="employeeId">Unique identifier of the employee.</param>
/// <param name="projectId">Unique identifier of the project.</param>
/// <param name="tenantId">Unique identifier of the tenant.</param>
/// <param name="loggedInEmployee">The authenticated employee making this request.</param>
/// <returns>ApiResponse containing the permission mappings or error details.</returns>
public async Task<ApiResponse<object>> GetAssignedProjectLevelPermissionAsync(Guid employeeId, Guid projectId, Guid tenantId, Employee loggedInEmployee)
{
// Log the attempt to fetch project-level permissions
_logger.LogInfo(
"Fetching project-level permissions for EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, TenantId: {TenantId} by {LoggedInEmployeeId}",
employeeId, projectId, tenantId, loggedInEmployee.Id);
// Query the database for relevant project-level permission mappings
var permissionMappings = await _context.ProjectLevelPermissionMappings
.Include(p => p.Employee)
.ThenInclude(e => e!.JobRole)
.Include(p => p.Project)
.Include(p => p.Permission)
.ThenInclude(fp => fp!.Feature)
.AsNoTracking()
.Where(p => p.EmployeeId == employeeId
&& p.ProjectId == projectId
&& p.TenantId == tenantId)
.ToListAsync();
if (permissionMappings == null || !permissionMappings.Any())
{
_logger.LogWarning("No project-level permissions found for EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, TenantId: {TenantId}",
employeeId, projectId, tenantId);
return ApiResponse<object>.ErrorResponse("Project-Level Permissions not found", "Project-Level Permissions not found in database", 404);
}
// Map the employee, project, and permissions.
var employee = _mapper.Map<BasicEmployeeVM>(permissionMappings.First().Employee);
var project = _mapper.Map<BasicProjectVM>(permissionMappings.First().Project);
var permissions = permissionMappings
.Select(p => _mapper.Map<FeaturePermissionVM>(p.Permission))
.ToList();
if (employee == null)
{
_logger.LogWarning("Employee record missing for EmployeeId: {EmployeeId}", employeeId);
return ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found in database", 404);
}
if (project == null)
{
_logger.LogWarning("Project record missing for ProjectId: {ProjectId}", projectId);
return ApiResponse<object>.ErrorResponse("Project not found", "Project not found in database", 404);
}
// Prepare the result object.
var result = new
{
Employee = employee,
Project = project,
Permissions = permissions
};
_logger.LogInfo("Project-level permissions fetched successfully for EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, TenantId: {TenantId}",
employeeId, projectId, tenantId);
return ApiResponse<object>.SuccessResponse(result, "Project-Level Permissions fetched successfully", 200);
}
/// <summary>
/// Assigns features at the project module level for the given tenant and employee.
/// </summary>
/// <param name="tenantId">Tenant ID associated with assignment.</param>
/// <param name="loggedInEmployee">Logged-in employee context.</param>
/// <returns>API response containing feature details associated with specified modules.</returns>
public async Task<ApiResponse<object>> AssignProjectLevelModulesAsync(Guid tenantId, Employee loggedInEmployee)
{
// Log entry at the start of the method.
_logger.LogInfo("AssignProjectLevelModulesAsync called for TenantId: {TenantId}, EmployeeId: {EmployeeId}", tenantId, loggedInEmployee.Id);
// Define target module IDs. These could alternatively be stored in a config file or DB.
var projectLevelModuleIds = new HashSet<Guid>
{
Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def"),
Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"),
Guid.Parse("81ab8a87-8ccd-4015-a917-0627cee6a100"),
Guid.Parse("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
Guid.Parse("a8cf4331-8f04-4961-8360-a3f7c3cc7462")
};
try
{
// Query features associated with specified modules. Also include module and permissions.
_logger.LogDebug("Querying Features with module filters: {ModuleIds}", string.Join(", ", projectLevelModuleIds));
var features = await _context.Features
.AsNoTracking() // Improves read-only query performance
.Include(f => f.FeaturePermissions)
.Include(f => f.Module)
.Where(f => projectLevelModuleIds.Contains(f.Id) && f.Module != null)
.Select(f => new FeatureVM
{
Id = f.Id,
Name = f.Name,
Description = f.Description,
FeaturePermissions = _mapper.Map<List<FeaturePermissionVM>>(f.FeaturePermissions),
ModuleId = f.ModuleId,
ModuleName = f.Module!.Name,
IsActive = f.IsActive,
ModuleKey = f.Module!.Key
})
.ToListAsync();
_logger.LogInfo("Features successfully retrieved for TenantId: {TenantId}. FeatureCount: {FeatureCount}", tenantId, features.Count);
// Return successful response.
return ApiResponse<object>.SuccessResponse(features, "Feature Permission for project-level is fetched successfully", 200);
}
catch (Exception ex)
{
// Log the error for further diagnostics.
_logger.LogError(ex, "Error in AssignProjectLevelModulesAsync for TenantId: {TenantId}, EmployeeId: {EmployeeId}", tenantId, loggedInEmployee.Id);
// Return an appropriate error response to consumer.
return ApiResponse<object>.ErrorResponse("Failed to assign project-level modules.", ex.Message);
}
}
public async Task<ApiResponse<object>> GetEmployeeToWhomProjectLevelAssignedAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee)
{
// Log method entry and parameters for traceability
_logger.LogInfo("Fetching employees with project-level permissions. ProjectId: {ProjectId}, TenantId: {TenantId}, RequestedBy: {EmployeeId}",
projectId, tenantId, loggedInEmployee.Id);
try
{
// Optimized query: Selecting only employees with necessary joins
// Instead of fetching entire mapping objects, directly project required employees
var assignedEmployees = await _context.ProjectLevelPermissionMappings
.Include(pl => pl.Employee)
.ThenInclude(e => e!.JobRole)
.AsNoTracking()
.Where(pl => pl.ProjectId == projectId && pl.TenantId == tenantId)
.Select(pl => pl.Employee) // only employees
.Distinct() // ensure unique employees
.ToListAsync();
_logger.LogInfo("Retrieved {Count} employees with project-level permissions for ProjectId: {ProjectId}, TenantId: {TenantId}",
assignedEmployees.Count, projectId, tenantId);
// Use AutoMapper to transform DB entities into VMs
var response = _mapper.Map<List<BasicEmployeeVM>>(assignedEmployees);
// Return a consistent API response with success message
return ApiResponse<object>.SuccessResponse(response, "The list of employees with project-level permissions has been successfully retrieved.", 200);
}
catch (Exception ex)
{
// Log exception details for debugging
_logger.LogError(ex, "Error occurred while fetching employees for ProjectId: {ProjectId}, TenantId: {TenantId}, RequestedBy: {EmployeeId}",
projectId, tenantId, loggedInEmployee.Id);
// Return standard error response
return ApiResponse<object>.ErrorResponse("An error occurred while retrieving employees with project-level permissions.", 500);
}
}
#endregion #endregion
#region =================================================================== Helper Functions =================================================================== #region =================================================================== Helper Functions ===================================================================

View File

@ -1,4 +1,5 @@
using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
@ -6,6 +7,27 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
{ {
public interface IMasterService public interface IMasterService
{ {
#region =================================================================== Contact Category APIs ===================================================================
Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateContactCategory(Guid id, UpdateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetContactCategoriesList(Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetContactCategoryById(Guid id, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteContactCategory(Guid id, Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Contact Tag APIs ===================================================================
Task<ApiResponse<Object>> GetContactTags(Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateContactTag(CreateContactTagDto contactTagDto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateContactTag(Guid id, UpdateContactTagDto contactTagDto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteContactTag(Guid id, Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Work Status APIs ===================================================================
Task<ApiResponse<object>> GetWorkStatusList(Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto updateWorkStatusDto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteWorkStatus(Guid id, Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Expenses Type APIs =================================================================== #region =================================================================== Expenses Type APIs ===================================================================
Task<ApiResponse<object>> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive); Task<ApiResponse<object>> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive);
Task<ApiResponse<object>> CreateExpenseTypeAsync(ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> CreateExpenseTypeAsync(ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId);
@ -26,5 +48,20 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<ApiResponse<object>> DeletePaymentModeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> DeletePaymentModeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
#endregion #endregion
#region =================================================================== Document Category APIs ===================================================================
Task<ApiResponse<object>> GetDocumentCategoryMasterListAsync(Guid? entityTypeId, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateDocumentCategoryMasterAsync(CreateDocumentCategoryDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateDocumentCategoryMasterAsync(Guid id, CreateDocumentCategoryDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteDocumentCategoryMasterAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Document Type APIs ===================================================================
Task<ApiResponse<object>> GetDocumentTypeMasterListAsync(Guid? documentCategoryId, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateDocumentTypeMasterAsync(CreateDocumentTypeDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateDocumentTypeMasterAsync(Guid id, CreateDocumentTypeDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteDocumentTypeMasterAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
#endregion
} }
} }

View File

@ -1,4 +1,5 @@
using Marco.Pms.Model.Dtos.Project; using Marco.Pms.Model.Dtos.Project;
using Marco.Pms.Model.Dtos.Util;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Projects; using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
@ -34,5 +35,11 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<List<ProjectAllocation>> GetTeamByProject(Guid TenantId, Guid ProjectId, bool IncludeInactive); Task<List<ProjectAllocation>> GetTeamByProject(Guid TenantId, Guid ProjectId, bool IncludeInactive);
Task<List<Guid>> GetMyProjectIdsAsync(Guid tenantId, Employee LoggedInEmployee); Task<List<Guid>> GetMyProjectIdsAsync(Guid tenantId, Employee LoggedInEmployee);
Task<ApiResponse<object>> ManageProjectLevelPermissionAsync(ProjctLevelPermissionDto model, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> GetAssignedProjectLevelPermissionAsync(Guid employeeId, Guid projectId, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> AssignProjectLevelModulesAsync(Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> GetEmployeeToWhomProjectLevelAssignedAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
} }
} }