Issues_June_3W #99

Merged
ashutosh.nehete merged 20 commits from Issues_June_3W into main 2025-07-01 10:25:44 +00:00
19 changed files with 10838 additions and 63 deletions

View File

@ -511,14 +511,14 @@ namespace Marco.Pms.DataAccess.Data
modelBuilder.Entity<Feature>().HasData( modelBuilder.Entity<Feature>().HasData(
new Feature { Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), Description = "Manage Project", Name = "Manage Project", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, new Feature { Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), Description = "Manage Project", Name = "Project Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
new Feature { Id = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), Description = "Manage Infra", Name = "Manage Infra", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, //new Feature { Id = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), Description = "Manage Infra", Name = "Manage Infra", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
new Feature { Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", Name = "Task Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, new Feature { Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", Name = "Task Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), 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("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", 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("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), Description = "Global Masters", Name = "Global 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 }
//new Feature { Id = new Guid("660131a4-788c-4739-a082-cbbf7879cbf2"), Description = "Tenant Masters", Name = "Tenant Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true } //new Feature { Id = new Guid("660131a4-788c-4739-a082-cbbf7879cbf2"), Description = "Tenant Masters", Name = "Tenant Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true }
@ -528,9 +528,8 @@ namespace Marco.Pms.DataAccess.Data
new FeaturePermission { Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project", Description = "Access all information related to the project." }, new FeaturePermission { Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project", Description = "Access all information related to the project." },
new FeaturePermission { Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project", Description = "Potentially edit the project name, description, start/end dates, or status." }, new FeaturePermission { Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project", Description = "Potentially edit the project name, description, start/end dates, or status." },
new FeaturePermission { Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Team", Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects." }, new FeaturePermission { Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Team", Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects." },
new FeaturePermission { Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project Infra", Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations" },
new FeaturePermission { Id = new Guid("c7b68e33-72f0-474f-bd96-77636427ecc8"), FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), IsEnabled = true, Name = "View Project Infra", Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations" }, new FeaturePermission { Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project Infra", Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure." },
new FeaturePermission { Id = new Guid("f2aee20a-b754-4537-8166-f9507b44585b"), FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), IsEnabled = true, Name = "Manage Project Infra", Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure." },
new FeaturePermission { Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "View Task", Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions." }, new FeaturePermission { Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "View Task", Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions." },
@ -539,7 +538,8 @@ namespace Marco.Pms.DataAccess.Data
new FeaturePermission { Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Approve Task", Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria" }, new FeaturePermission { Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Approve Task", Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria" },
new FeaturePermission { Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View Employee", Description = "Grants a user read-only access to details about the individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" }, new FeaturePermission { Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View All Employees", Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" },
new FeaturePermission { Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View Team Members", Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" },
new FeaturePermission { Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Add/Edit Employee", Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data" }, new FeaturePermission { Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Add/Edit Employee", Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data" },
new FeaturePermission { Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Assign Roles", Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system." }, new FeaturePermission { Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Assign Roles", Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system." },

View File

@ -0,0 +1,101 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_UpdatedBy_In_Contacts_And_ContactNotes_Table : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "UpdatedAt",
table: "Contacts",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "UpdatedById",
table: "Contacts",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci");
migrationBuilder.AddColumn<DateTime>(
name: "UpdatedAt",
table: "ContactNotes",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "UpdatedById",
table: "ContactNotes",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci");
migrationBuilder.CreateIndex(
name: "IX_Contacts_UpdatedById",
table: "Contacts",
column: "UpdatedById");
migrationBuilder.CreateIndex(
name: "IX_ContactNotes_UpdatedById",
table: "ContactNotes",
column: "UpdatedById");
migrationBuilder.AddForeignKey(
name: "FK_ContactNotes_Employees_UpdatedById",
table: "ContactNotes",
column: "UpdatedById",
principalTable: "Employees",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Contacts_Employees_UpdatedById",
table: "Contacts",
column: "UpdatedById",
principalTable: "Employees",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ContactNotes_Employees_UpdatedById",
table: "ContactNotes");
migrationBuilder.DropForeignKey(
name: "FK_Contacts_Employees_UpdatedById",
table: "Contacts");
migrationBuilder.DropIndex(
name: "IX_Contacts_UpdatedById",
table: "Contacts");
migrationBuilder.DropIndex(
name: "IX_ContactNotes_UpdatedById",
table: "ContactNotes");
migrationBuilder.DropColumn(
name: "UpdatedAt",
table: "Contacts");
migrationBuilder.DropColumn(
name: "UpdatedById",
table: "Contacts");
migrationBuilder.DropColumn(
name: "UpdatedAt",
table: "ContactNotes");
migrationBuilder.DropColumn(
name: "UpdatedById",
table: "ContactNotes");
}
}
}

View File

@ -0,0 +1,131 @@
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_New_Feature_Permissiom_View_All_Employee : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("c7b68e33-72f0-474f-bd96-77636427ecc8"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("f2aee20a-b754-4537-8166-f9507b44585b"));
migrationBuilder.DeleteData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"));
migrationBuilder.UpdateData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"),
column: "Description",
value: "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data");
migrationBuilder.InsertData(
table: "FeaturePermissions",
columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" },
values: new object[,]
{
{ new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), true, "View All Employee" },
{ new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), true, "View Project Infra" },
{ new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), true, "Manage Project Infra" }
});
migrationBuilder.UpdateData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
column: "Name",
value: "Attendance Management");
migrationBuilder.UpdateData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"),
column: "Name",
value: "Project Management");
migrationBuilder.UpdateData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"),
column: "Name",
value: "Masters");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"));
migrationBuilder.UpdateData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"),
column: "Description",
value: "Grants a user read-only access to details about the individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data");
migrationBuilder.UpdateData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
column: "Name",
value: "Attendance");
migrationBuilder.UpdateData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"),
column: "Name",
value: "Manage Project");
migrationBuilder.UpdateData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"),
column: "Name",
value: "Global Masters");
migrationBuilder.InsertData(
table: "Features",
columns: new[] { "Id", "Description", "IsActive", "ModuleId", "Name" },
values: new object[] { new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), "Manage Infra", true, new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), "Manage Infra" });
migrationBuilder.InsertData(
table: "FeaturePermissions",
columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" },
values: new object[,]
{
{ new Guid("c7b68e33-72f0-474f-bd96-77636427ecc8"), "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), true, "View Project Infra" },
{ new Guid("f2aee20a-b754-4537-8166-f9507b44585b"), "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), true, "Manage Project Infra" }
});
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Changed_Name_Of_Feature_Permission_To_ViewTeamMembers : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"),
column: "Name",
value: "View All Employees");
migrationBuilder.UpdateData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"),
column: "Name",
value: "View Team Members");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"),
column: "Name",
value: "View All Employee");
migrationBuilder.UpdateData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"),
column: "Name",
value: "View Employee");
}
}
}

View File

@ -434,6 +434,12 @@ namespace Marco.Pms.DataAccess.Migrations
b.Property<Guid>("TenantId") b.Property<Guid>("TenantId")
.HasColumnType("char(36)"); .HasColumnType("char(36)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid?>("UpdatedById")
.HasColumnType("char(36)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("ContactCategoryId"); b.HasIndex("ContactCategoryId");
@ -442,6 +448,8 @@ namespace Marco.Pms.DataAccess.Migrations
b.HasIndex("TenantId"); b.HasIndex("TenantId");
b.HasIndex("UpdatedById");
b.ToTable("Contacts"); b.ToTable("Contacts");
}); });
@ -545,6 +553,12 @@ namespace Marco.Pms.DataAccess.Migrations
b.Property<Guid>("TenantId") b.Property<Guid>("TenantId")
.HasColumnType("char(36)"); .HasColumnType("char(36)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid?>("UpdatedById")
.HasColumnType("char(36)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("ContactId"); b.HasIndex("ContactId");
@ -553,6 +567,8 @@ namespace Marco.Pms.DataAccess.Migrations
b.HasIndex("TenantId"); b.HasIndex("TenantId");
b.HasIndex("UpdatedById");
b.ToTable("ContactNotes"); b.ToTable("ContactNotes");
}); });
@ -971,17 +987,17 @@ namespace Marco.Pms.DataAccess.Migrations
}, },
new new
{ {
Id = new Guid("c7b68e33-72f0-474f-bd96-77636427ecc8"), Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"),
Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations",
FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"),
IsEnabled = true, IsEnabled = true,
Name = "View Project Infra" Name = "View Project Infra"
}, },
new new
{ {
Id = new Guid("f2aee20a-b754-4537-8166-f9507b44585b"), Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"),
Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.",
FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"),
IsEnabled = true, IsEnabled = true,
Name = "Manage Project Infra" Name = "Manage Project Infra"
}, },
@ -1019,11 +1035,19 @@ namespace Marco.Pms.DataAccess.Migrations
}, },
new new
{ {
Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"),
Description = "Grants a user read-only access to details about the individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data",
FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"),
IsEnabled = true, IsEnabled = true,
Name = "View Employee" Name = "View All Employees"
},
new
{
Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"),
Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data",
FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"),
IsEnabled = true,
Name = "View Team Members"
}, },
new new
{ {
@ -1498,15 +1522,7 @@ namespace Marco.Pms.DataAccess.Migrations
Description = "Manage Project", Description = "Manage Project",
IsActive = true, IsActive = true,
ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"),
Name = "Manage Project" Name = "Project Management"
},
new
{
Id = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"),
Description = "Manage Infra",
IsActive = true,
ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"),
Name = "Manage Infra"
}, },
new new
{ {
@ -1530,7 +1546,7 @@ namespace Marco.Pms.DataAccess.Migrations
Description = "Attendance", Description = "Attendance",
IsActive = true, IsActive = true,
ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"),
Name = "Attendance" Name = "Attendance Management"
}, },
new new
{ {
@ -1538,7 +1554,7 @@ namespace Marco.Pms.DataAccess.Migrations
Description = "Global Masters", Description = "Global Masters",
IsActive = true, IsActive = true,
ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"),
Name = "Global Masters" Name = "Masters"
}, },
new new
{ {
@ -2742,11 +2758,17 @@ namespace Marco.Pms.DataAccess.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy")
.WithMany()
.HasForeignKey("UpdatedById");
b.Navigation("ContactCategory"); b.Navigation("ContactCategory");
b.Navigation("CreatedBy"); b.Navigation("CreatedBy");
b.Navigation("Tenant"); b.Navigation("Tenant");
b.Navigation("UpdatedBy");
}); });
modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b =>
@ -2810,11 +2832,17 @@ namespace Marco.Pms.DataAccess.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy")
.WithMany()
.HasForeignKey("UpdatedById");
b.Navigation("Contact"); b.Navigation("Contact");
b.Navigation("Createdby"); b.Navigation("Createdby");
b.Navigation("Tenant"); b.Navigation("Tenant");
b.Navigation("UpdatedBy");
}); });
modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b =>

View File

@ -20,6 +20,11 @@ namespace Marco.Pms.Model.Directory
[ValidateNever] [ValidateNever]
[ForeignKey("CreatedById")] [ForeignKey("CreatedById")]
public Employee? CreatedBy { get; set; } public Employee? CreatedBy { get; set; }
public Guid? UpdatedById { get; set; }
[ValidateNever]
[ForeignKey("UpdatedById")]
public Employee? UpdatedBy { get; set; }
[DisplayName("ContactCategoryId")] [DisplayName("ContactCategoryId")]
public Guid? ContactCategoryId { get; set; } public Guid? ContactCategoryId { get; set; }
@ -27,5 +32,6 @@ namespace Marco.Pms.Model.Directory
[ForeignKey(nameof(ContactCategoryId))] [ForeignKey(nameof(ContactCategoryId))]
public ContactCategoryMaster? ContactCategory { get; set; } public ContactCategoryMaster? ContactCategory { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
} }
} }

View File

@ -14,7 +14,13 @@ namespace Marco.Pms.Model.Directory
[ValidateNever] [ValidateNever]
[ForeignKey("CreatedById")] [ForeignKey("CreatedById")]
public Employee? Createdby { get; set; } public Employee? Createdby { get; set; }
public Guid? UpdatedById { get; set; }
[ValidateNever]
[ForeignKey("UpdatedById")]
public Employee? UpdatedBy { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; }
public Guid ContactId { get; set; } public Guid ContactId { get; set; }
[ValidateNever] [ValidateNever]

View File

@ -232,9 +232,13 @@ namespace Marco.Pms.Model.Mapper
{ {
Id = note.Id, Id = note.Id,
Note = note.Note, Note = note.Note,
ContactName = note.Contact?.Name,
OrganizationName = note.Contact?.Organization,
ContactId = note.ContactId, ContactId = note.ContactId,
CreatedAt = note.CreatedAt, CreatedAt = note.CreatedAt,
UpdatedAt = note.UpdatedAt,
CreatedBy = note.Createdby != null ? note.Createdby.ToBasicEmployeeVMFromEmployee() : null, CreatedBy = note.Createdby != null ? note.Createdby.ToBasicEmployeeVMFromEmployee() : null,
UpdatedBy = note.UpdatedBy != null ? note.UpdatedBy.ToBasicEmployeeVMFromEmployee() : null,
IsActive = note.IsActive IsActive = note.IsActive
}; };
} }

View File

@ -6,6 +6,8 @@ namespace Marco.Pms.Model.ViewModels.Directory
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public string Note { get; set; } = string.Empty; public string Note { get; set; } = string.Empty;
public string? ContactName { get; set; }
public string? OrganizationName { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; } public BasicEmployeeVM? CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; } public DateTime? UpdatedAt { get; set; }

View File

@ -158,6 +158,13 @@ namespace Marco.Pms.Services.Controllers
// -------------------------------- Contact Notes -------------------------------- // -------------------------------- Contact Notes --------------------------------
[HttpGet("notes")]
public async Task<IActionResult> GetListOFAllNotes([FromQuery] Guid? projectId, [FromQuery] int? pageSize, [FromQuery] int pageNumber)
{
var response = await _directoryHelper.GetListOFAllNotes(projectId, pageSize ?? 25, pageNumber);
return StatusCode(response.StatusCode, response);
}
[HttpPost("note")] [HttpPost("note")]
public async Task<IActionResult> CreateContactNote([FromBody] CreateContactNoteDto noteDto) public async Task<IActionResult> CreateContactNote([FromBody] CreateContactNoteDto noteDto)
{ {

View File

@ -10,6 +10,7 @@ using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Employee; using Marco.Pms.Model.ViewModels.Employee;
using Marco.Pms.Services.Hubs; using Marco.Pms.Services.Hubs;
using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service; using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -35,10 +36,16 @@ namespace MarcoBMS.Services.Controllers
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
private readonly ILoggingService _logger; private readonly ILoggingService _logger;
private readonly IHubContext<MarcoHub> _signalR; private readonly IHubContext<MarcoHub> _signalR;
private readonly PermissionServices _permission;
private readonly ProjectsHelper _projectsHelper;
private readonly Guid ViewAllEmployees;
private readonly Guid ViewTeamMembers;
private readonly Guid tenantId;
public EmployeeController(UserManager<ApplicationUser> userManager, IEmailSender emailSender, public EmployeeController(UserManager<ApplicationUser> userManager, IEmailSender emailSender,
ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger, ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger,
IHubContext<MarcoHub> signalR) IHubContext<MarcoHub> signalR, PermissionServices permission, ProjectsHelper projectsHelper)
{ {
_context = context; _context = context;
_userManager = userManager; _userManager = userManager;
@ -48,6 +55,11 @@ namespace MarcoBMS.Services.Controllers
_configuration = configuration; _configuration = configuration;
_logger = logger; _logger = logger;
_signalR = signalR; _signalR = signalR;
_permission = permission;
ViewAllEmployees = Guid.Parse("60611762-7f8a-4fb5-b53f-b1139918796b");
ViewTeamMembers = Guid.Parse("b82d2b7e-0d52-45f3-997b-c008ea460e7f");
_projectsHelper = projectsHelper;
tenantId = _userHelper.GetTenantId();
} }
[HttpGet] [HttpGet]
@ -93,18 +105,65 @@ namespace MarcoBMS.Services.Controllers
[Route("list/{projectid?}")] [Route("list/{projectid?}")]
public async Task<IActionResult> GetEmployeesByProject(Guid? projectid, [FromQuery] bool ShowInactive) public async Task<IActionResult> GetEmployeesByProject(Guid? projectid, [FromQuery] bool ShowInactive)
{ {
// Step 1: Validate incoming request model state
if (!ModelState.IsValid) if (!ModelState.IsValid)
{ {
var errors = ModelState.Values var errors = ModelState.Values
.SelectMany(v => v.Errors) .SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage) .Select(e => e.ErrorMessage)
.ToList(); .ToList();
_logger.LogWarning("Invalid model state in GetEmployeesByProject. Errors: {@Errors}", errors);
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
} }
var result = await _employeeHelper.GetEmployeeByProjectId(GetTenantId(), projectid, ShowInactive);
// Step 2: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
_logger.LogInfo("GetEmployeesByProject called by EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, ShowInactive: {ShowInactive}",
loggedInEmployee.Id, projectid ?? Guid.Empty, ShowInactive);
// Step 3: Fetch project access and permissions
List<Project> projects = await _projectsHelper.GetMyProjects(tenantId, loggedInEmployee);
var projectIds = projects.Select(p => p.Id).ToList();
var hasViewAllEmployeesPermission = await _permission.HasPermission(ViewAllEmployees, loggedInEmployee.Id);
var hasViewTeamMembersPermission = await _permission.HasPermission(ViewTeamMembers, loggedInEmployee.Id);
List<EmployeeVM> result = new();
// Step 4: Determine access level and fetch employees accordingly
if (hasViewAllEmployeesPermission || projectid != null)
{
result = await _employeeHelper.GetEmployeeByProjectId(tenantId, projectid, ShowInactive);
_logger.LogInfo("Employee list fetched using full access or specific project.");
}
else if (hasViewTeamMembersPermission && !ShowInactive)
{
var employeeIds = await _context.ProjectAllocations
.Where(pa => projectIds.Contains(pa.ProjectId) && pa.IsActive)
.Select(pa => pa.EmployeeId)
.Distinct()
.ToListAsync();
result = await _context.Employees
.Include(fp => fp.JobRole)
.Where(e => employeeIds.Contains(e.Id) && e.IsActive)
.Select(e => e.ToEmployeeVMFromEmployee())
.ToListAsync();
_logger.LogInfo("Employee list fetched using limited access (active only).");
}
else
{
_logger.LogWarning("Access denied for EmployeeId: {EmployeeId} - insufficient permissions.", loggedInEmployee.Id);
return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
}
// Step 5: Log and return results
_logger.LogInfo("Employees fetched successfully by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}. Count: {Count}",
loggedInEmployee.Id, projectid ?? Guid.Empty, result.Count);
return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200)); return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
} }
[HttpGet] [HttpGet]

View File

@ -33,7 +33,7 @@ namespace MarcoBMS.Services.Controllers
features.Add(item); features.Add(item);
} }
} }
return features; return features.OrderBy(f => f.Name).ToList();
} }
[HttpGet] [HttpGet]
@ -50,7 +50,7 @@ namespace MarcoBMS.Services.Controllers
ModuleId = c.ModuleId, ModuleId = c.ModuleId,
ModuleName = c.Module != null ? c.Module.Name : string.Empty, ModuleName = c.Module != null ? c.Module.Name : string.Empty,
IsActive = c.IsActive IsActive = c.IsActive
}); }).OrderBy(f => f.Name).ToList();
return Ok(ApiResponse<object>.SuccessResponse(rolesVM, "Success.", 200)); return Ok(ApiResponse<object>.SuccessResponse(rolesVM, "Success.", 200));
} }
} }

View File

@ -156,6 +156,7 @@ namespace MarcoBMS.Services.Controllers
RoleName = x.Role.Role, RoleName = x.Role.Role,
FeaturePermission = x.FeaturePermission FeaturePermission = x.FeaturePermission
}) })
.OrderByDescending(r => r.RoleName)
.ToListAsync(); .ToListAsync();
List<ApplicationRolesVM> applicationRoles = new List<ApplicationRolesVM>(); List<ApplicationRolesVM> applicationRoles = new List<ApplicationRolesVM>();

View File

@ -7,6 +7,7 @@ using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Directory; using Marco.Pms.Model.ViewModels.Directory;
using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Projects; using Marco.Pms.Model.ViewModels.Projects;
using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service; using MarcoBMS.Services.Service;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -18,15 +19,17 @@ namespace Marco.Pms.Services.Helpers
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;
private readonly ILoggingService _logger; private readonly ILoggingService _logger;
private readonly UserHelper _userHelper; private readonly UserHelper _userHelper;
private readonly PermissionServices _permissionServices;
private readonly Guid directoryAdmin; private readonly Guid directoryAdmin;
private readonly Guid directoryManager; private readonly Guid directoryManager;
private readonly Guid directoryUser; private readonly Guid directoryUser;
public DirectoryHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper) public DirectoryHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permissionServices)
{ {
_context = context; _context = context;
_logger = logger; _logger = logger;
_userHelper = userHelper; _userHelper = userHelper;
_permissionServices = permissionServices;
directoryAdmin = Guid.Parse("4286a13b-bb40-4879-8c6d-18e9e393beda"); directoryAdmin = Guid.Parse("4286a13b-bb40-4879-8c6d-18e9e393beda");
directoryManager = Guid.Parse("62668630-13ce-4f52-a0f0-db38af2230c5"); directoryManager = Guid.Parse("62668630-13ce-4f52-a0f0-db38af2230c5");
directoryUser = Guid.Parse("0f919170-92d4-4337-abd3-49b66fc871bb"); directoryUser = Guid.Parse("0f919170-92d4-4337-abd3-49b66fc871bb");
@ -504,6 +507,8 @@ namespace Marco.Pms.Services.Helpers
var newContact = updateContact.ToContactFromUpdateContactDto(tenantId, contact); var newContact = updateContact.ToContactFromUpdateContactDto(tenantId, contact);
newContact.UpdatedById = LoggedInEmployee.Id;
newContact.UpdatedAt = DateTime.UtcNow;
_context.Contacts.Update(newContact); _context.Contacts.Update(newContact);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -893,6 +898,138 @@ namespace Marco.Pms.Services.Helpers
// -------------------------------- Contact Notes -------------------------------- // -------------------------------- Contact Notes --------------------------------
/// <summary>
/// Retrieves a paginated list of contact notes based on user permissions.
/// </summary>
/// <param name="pageSize">The number of items per page.</param>
/// <param name="pageNumber">The current page number.</param>
/// <returns>An ApiResponse containing the paginated notes or an error message.</returns>
public async Task<ApiResponse<object>> GetListOFAllNotes(Guid? projectId, int pageSize, int pageNumber)
{
_logger.LogInfo("Attempting to fetch list of all notes. PageSize: {PageSize}, PageNumber: {PageNumber}", pageSize, pageNumber);
Guid tenantId = _userHelper.GetTenantId();
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
List<Guid>? projectContactIds = null;
if (loggedInEmployee == null)
{
_logger.LogWarning("GetListOFAllNotes: LoggedInEmployee is null. Cannot proceed.");
return ApiResponse<object>.ErrorResponse("Unauthorized", "Employee not found.", 401);
}
// --- Permission Checks ---
var hasAdminPermission = await _permissionServices.HasPermission(directoryAdmin, loggedInEmployee.Id);
var hasManagerPermission = await _permissionServices.HasPermission(directoryManager, loggedInEmployee.Id);
var hasUserPermission = await _permissionServices.HasPermission(directoryUser, loggedInEmployee.Id);
IQueryable<ContactNote> notesQuery = _context.ContactNotes
.Include(cn => cn.UpdatedBy)
.Include(cn => cn.Createdby) // Assuming 'CreatedBy' (PascalCase)
.Include(cn => cn.Contact)
.Where(cn => cn.TenantId == tenantId)
.AsQueryable(); // Start building the query
if (!hasAdminPermission && !(hasManagerPermission || hasUserPermission))
{
_logger.LogWarning("GetListOFAllNotes: User {EmployeeId} does not have required permissions to access notes for TenantId: {TenantId}", loggedInEmployee.Id, tenantId);
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
}
if (projectId != null)
{
projectContactIds = await _context.ContactProjectMappings
.Where(pc => pc.ProjectId == projectId)
.Select(pc => pc.ContactId)
.ToListAsync();
}
if (!hasAdminPermission) // If not an admin, apply additional filtering
{
_logger.LogInfo("GetListOFAllNotes: User {EmployeeId} is not an admin. Applying manager/user specific filters.", loggedInEmployee.Id);
var assignedBucketIds = await _context.EmployeeBucketMappings
.Where(eb => eb.EmployeeId == loggedInEmployee.Id)
.Select(eb => eb.BucketId)
.ToListAsync();
if (!assignedBucketIds.Any())
{
_logger.LogInfo("GetListOFAllNotes: User {EmployeeId} has no assigned buckets. Returning empty list.", loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(new { CurrentPage = pageNumber, TotalPages = 0, Data = new List<ContactNoteVM>() }, "No notes found based on assigned buckets.", 200);
}
List<Guid>? contactIds = null;
if (projectContactIds == null)
{
contactIds = await _context.ContactBucketMappings
.Where(cb => assignedBucketIds.Contains(cb.BucketId))
.Select(cb => cb.ContactId)
.ToListAsync();
}
else
{
contactIds = await _context.ContactBucketMappings
.Where(cb => assignedBucketIds.Contains(cb.BucketId) && projectContactIds.Contains(cb.ContactId))
.Select(cb => cb.ContactId)
.ToListAsync();
}
if (!contactIds.Any())
{
_logger.LogInfo("GetListOFAllNotes: No contacts found for assigned buckets for user {EmployeeId}. Returning empty list.", loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(new { CurrentPage = pageNumber, TotalPages = 0, Data = new List<ContactNoteVM>() }, "No notes found for associated contacts.", 200);
}
notesQuery = notesQuery.Where(cn => contactIds.Contains(cn.ContactId));
}
else
{
if (projectContactIds != null)
{
notesQuery = notesQuery.Where(cn => projectContactIds.Contains(cn.ContactId));
}
}
// --- Pagination Logic ---
// Ensure pageSize and pageNumber are valid
pageSize = pageSize < 1 ? 25 : pageSize; // Default to 25 if less than 1
pageNumber = pageNumber < 1 ? 1 : pageNumber; // Default to 1 if less than 1
// Get total count BEFORE applying Skip/Take for accurate pagination metadata
int totalRecords = await notesQuery.CountAsync();
int totalPages = (int)Math.Ceiling((double)totalRecords / pageSize);
int skip = (pageNumber - 1) * pageSize;
// --- Apply Ordering and Pagination in the database ---
List<ContactNote> notes = await notesQuery
.OrderByDescending(cn => (cn.UpdatedAt != null ? cn.UpdatedAt : cn.CreatedAt)) // Order by updated date or created date
.Skip(skip)
.Take(pageSize)
.ToListAsync();
_logger.LogInfo("GetListOFAllNotes: Fetched {Count} notes for page {PageNumber} of {TotalPages} total pages. Total records: {TotalRecords}.",
notes.Count, pageNumber, totalPages, totalRecords);
// --- Map to ViewModel (in-memory) ---
// This mapping is done in memory because ToBasicEmployeeVMFromEmployee() is likely a C# method
// that cannot be translated to SQL by Entity Framework.
List<ContactNoteVM> noteVMS = notes
.Select(cn => cn.ToContactNoteVMFromContactNote())
.ToList();
var response = new
{
CurrentPage = pageNumber,
PageSize = pageSize, // Include pageSize in response for client clarity
TotalPages = totalPages,
TotalRecords = totalRecords, // Add total records for client
Data = noteVMS
};
_logger.LogInfo("GetListOFAllNotes: Successfully retrieved notes and mapped to ViewModel for TenantId: {TenantId}.", tenantId);
return ApiResponse<object>.SuccessResponse(response, $"{noteVMS.Count} notes fetched successfully.", 200);
}
public async Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active) public async Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active)
{ {
Guid tenantId = _userHelper.GetTenantId(); Guid tenantId = _userHelper.GetTenantId();
@ -903,32 +1040,25 @@ namespace Marco.Pms.Services.Helpers
List<ContactNote> notes = new List<ContactNote>(); List<ContactNote> notes = new List<ContactNote>();
if (active) if (active)
{ {
notes = await _context.ContactNotes.Include(n => n.Createdby).Where(n => n.ContactId == contact.Id && n.IsActive && n.TenantId == tenantId).ToListAsync(); notes = await _context.ContactNotes
.Include(n => n.Createdby)
.Include(n => n.UpdatedBy)
.Where(n => n.ContactId == contact.Id && n.IsActive && n.TenantId == tenantId)
.ToListAsync();
} }
else else
{ {
notes = await _context.ContactNotes.Include(n => n.Createdby).Where(n => n.ContactId == contact.Id && n.TenantId == tenantId).ToListAsync(); notes = await _context.ContactNotes
.Include(n => n.Createdby)
.Include(n => n.UpdatedBy)
.Where(n => n.ContactId == contact.Id && n.TenantId == tenantId)
.ToListAsync();
} }
var noteIds = notes.Select(n => n.Id).ToList(); var noteIds = notes.Select(n => n.Id).ToList();
List<DirectoryUpdateLog>? updateLogs = await _context.DirectoryUpdateLogs.Include(l => l.Employee).Where(l => noteIds.Contains(l.RefereanceId)).ToListAsync(); List<DirectoryUpdateLog>? updateLogs = await _context.DirectoryUpdateLogs.Include(l => l.Employee).Where(l => noteIds.Contains(l.RefereanceId)).ToListAsync();
List<ContactNoteVM>? noteVMs = new List<ContactNoteVM>(); //List<ContactNoteVM>? noteVMs = new List<ContactNoteVM>();
foreach (var note in notes) List<ContactNoteVM>? noteVMs = notes.Select(n => n.ToContactNoteVMFromContactNote()).ToList();
{
ContactNoteVM noteVM = note.ToContactNoteVMFromContactNote();
DirectoryUpdateLog? updateLog = updateLogs.Where(l => l.RefereanceId == note.Id).OrderByDescending(l => l.UpdateAt).FirstOrDefault();
if (updateLog != null)
{
noteVM.UpdatedAt = updateLog.UpdateAt;
noteVM.UpdatedBy = updateLog.Employee != null ? updateLog.Employee.ToBasicEmployeeVMFromEmployee() : null;
}
else
{
noteVM.UpdatedAt = note.CreatedAt;
noteVM.UpdatedBy = note.Createdby != null ? note.Createdby.ToBasicEmployeeVMFromEmployee() : null;
}
noteVMs.Add(noteVM);
}
_logger.LogInfo("{count} contact-notes record from contact {ContactId} fetched by Employee {EmployeeId}", noteVMs.Count, id, LoggedInEmployee.Id); _logger.LogInfo("{count} contact-notes record from contact {ContactId} fetched by Employee {EmployeeId}", noteVMs.Count, id, LoggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(noteVMs, $"{noteVMs.Count} contact-notes record fetched successfully", 200); return ApiResponse<object>.SuccessResponse(noteVMs, $"{noteVMs.Count} contact-notes record fetched successfully", 200);
} }
@ -966,10 +1096,12 @@ namespace Marco.Pms.Services.Helpers
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.IsActive && c.TenantId == tenantId); Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.IsActive && c.TenantId == tenantId);
if (contact != null) if (contact != null)
{ {
ContactNote? contactNote = await _context.ContactNotes.FirstOrDefaultAsync(n => n.Id == noteDto.Id && n.ContactId == contact.Id && n.IsActive); ContactNote? contactNote = await _context.ContactNotes.Include(cn => cn.Createdby).Include(cn => cn.Contact).FirstOrDefaultAsync(n => n.Id == noteDto.Id && n.ContactId == contact.Id && n.IsActive);
if (contactNote != null) if (contactNote != null)
{ {
contactNote.Note = noteDto.Note; contactNote.Note = noteDto.Note;
contactNote.UpdatedById = LoggedInEmployee.Id;
contactNote.UpdatedAt = DateTime.UtcNow;
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog _context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{ {
@ -1004,6 +1136,9 @@ namespace Marco.Pms.Services.Helpers
if (note != null) if (note != null)
{ {
note.IsActive = active; note.IsActive = active;
note.UpdatedById = LoggedInEmployee.Id;
note.UpdatedAt = DateTime.UtcNow;
_context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog _context.DirectoryUpdateLogs.Add(new DirectoryUpdateLog
{ {
RefereanceId = id, RefereanceId = id,
@ -1335,6 +1470,9 @@ namespace Marco.Pms.Services.Helpers
_logger.LogWarning("Employee {EmployeeId} tries to delete bucket {BucketId} but not found in database", LoggedInEmployee.Id, id); _logger.LogWarning("Employee {EmployeeId} tries to delete bucket {BucketId} but not found in database", LoggedInEmployee.Id, id);
return ApiResponse<object>.SuccessResponse(new { }, "Bucket deleted successfully", 200); return ApiResponse<object>.SuccessResponse(new { }, "Bucket deleted successfully", 200);
} }
// -------------------------------- Helper --------------------------------
private bool Compare(string sentence, string search) private bool Compare(string sentence, string search)
{ {
sentence = sentence.Trim().ToLower(); sentence = sentence.Trim().ToLower();

View File

@ -218,11 +218,11 @@ namespace Marco.Pms.Services.Helpers
_logger.LogInfo("Work category master {ConatctTagId} updated successfully by employee {EmployeeId}", contactTagVm.Id, LoggedInEmployee.Id); _logger.LogInfo("Contact tag master {ConatctTagId} updated successfully by employee {EmployeeId}", contactTagVm.Id, LoggedInEmployee.Id);
ApiResponse<object>.SuccessResponse(contactTagVm, "Contact Tag master updated successfully", 200); return ApiResponse<object>.SuccessResponse(contactTagVm, "Contact Tag master updated successfully", 200);
} }
_logger.LogError("Contact Tag master {ContactTagId} not found in database", id); _logger.LogError("Contact Tag master {ContactTagId} not found in database", id);
ApiResponse<object>.ErrorResponse("Contact Tag master not found", "Contact tag master not found", 404); 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); _logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", LoggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("User Send empty Payload", "User Send empty Payload", 400); return ApiResponse<object>.ErrorResponse("User Send empty Payload", "User Send empty Payload", 400);

View File

@ -98,23 +98,23 @@ namespace Marco.Pms.Services.Service
IsSystem = true, IsSystem = true,
JoiningDate = Convert.ToDateTime("2000-04-20 10:11:17.588000"), JoiningDate = Convert.ToDateTime("2000-04-20 10:11:17.588000"),
}; };
if ((!await dbContext.Employees.Where(e => e.FirstName == "Admin").AnyAsync()) && (jobRole != null ? jobRole.Id : Guid.Empty) != Guid.Empty) if ((!await dbContext.Employees.Where(e => e.Email == "admin@marcoaiot.com").AnyAsync()) && jobRole?.Id != Guid.Empty)
{ {
await dbContext.Employees.AddAsync(employee); await dbContext.Employees.AddAsync(employee);
} }
else else
{ {
employee = await dbContext.Employees.Where(e => e.FirstName == "Admin").FirstOrDefaultAsync(); employee = await dbContext.Employees.Where(e => e.Email == "admin@marcoaiot.com").FirstOrDefaultAsync();
} }
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
if (!await dbContext.EmployeeRoleMappings.AnyAsync()) if (!await dbContext.EmployeeRoleMappings.AnyAsync())
{ {
await dbContext.EmployeeRoleMappings.AddAsync(new EmployeeRoleMapping await dbContext.EmployeeRoleMappings.AddAsync(new EmployeeRoleMapping
{ {
EmployeeId = employee != null ? employee.Id : Guid.Empty, EmployeeId = employee?.Id ?? Guid.Empty,
IsEnabled = true, IsEnabled = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"), TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"),
RoleId = role != null ? role.Id : Guid.Empty RoleId = role?.Id ?? Guid.Empty
}); });
} }
if (!await dbContext.RolePermissionMappings.AnyAsync()) if (!await dbContext.RolePermissionMappings.AnyAsync())