Activity_Hierarchy #94

Open
ashutosh.nehete wants to merge 15 commits from Activity_Hierarchy into main
19 changed files with 9408 additions and 153 deletions

View File

@ -33,6 +33,8 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<RefreshToken> RefreshTokens { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<ServicesMaster> ServicesMasters { get; set; }
public DbSet<ActivityGroupMaster> ActivityGroupMasters { get; set; }
public DbSet<ActivityMaster> ActivityMasters { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<ProjectAllocation> ProjectAllocations { get; set; }
@ -363,7 +365,265 @@ namespace Marco.Pms.DataAccess.Data
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
}
);
modelBuilder.Entity<ServicesMaster>().HasData(
new ServicesMaster
{
Id = new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
Name = "Civil",
Description = "Construction Civil service involves planning, designing, and overseeing infrastructure and building projects",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ServicesMaster
{
Id = new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"),
Name = "Plumbing",
Description = "Plumbing service involves installing, maintaining, and repairing systems for water supply, drainage, and sewage in residential, commercial, and industrial buildings",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ServicesMaster
{
Id = new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
Name = "Electric",
Description = "Electric service involves the installation, maintenance, and repair of electrical systems, including wiring, lighting, and power distribution in buildings and infrastructure",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ServicesMaster
{
Id = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Name = "Fire fighting",
Description = "Fire fighting service involves installing and maintaining systems like sprinklers, hydrants, and alarms to detect, control, and extinguish fires in buildings and facilities.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ServicesMaster
{
Id = new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
Name = "HVAC",
Description = "HVAC (Heating, Ventilation, and Air Conditioning) service involves the installation, maintenance, and repair of systems that control indoor climate, air quality, and thermal comfort in buildings.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ServicesMaster
{
Id = new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
Name = "Interior infrastructure",
Description = "Interior infrastructure (Interior Infra) service involves the construction and installation of essential internal structural elements like partitions, ceilings, flooring, and utility layouts to prepare spaces for interior design and functional use.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
}
);
modelBuilder.Entity<ActivityGroupMaster>().HasData(
new ActivityGroupMaster
{
Id = new Guid("6f048b41-f909-41dd-af5f-02369ca80639"),
ServiceId = Guid.Parse("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
Name = "Site Preparation",
Description = "Site Preparation involves clearing, leveling, and preparing the land for construction by removing obstacles, performing excavation, and conducting soil tests.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("1d29b7d1-ffdc-486d-ac7b-ee2661ae9979"),
ServiceId = Guid.Parse("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
Name = "Foundation Work",
Description = "Foundation Work involves excavating, reinforcing, and casting the base structure that supports the entire building load, including footings and plinth beams.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("3a712ddb-8927-4d58-8b24-83290e6ba8d1"),
ServiceId = Guid.Parse("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
Name = "Sub-Structure Work",
Description = "Sub-Structure Work involves constructing the portion of the building below ground level, including plinth beams, basement walls, and backfilling, to support the superstructure.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("47fa23fb-0e1c-459e-9cc9-9136c61effbd"),
ServiceId = Guid.Parse("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
Name = "Super-Structure Work",
Description = "Super-Structure Work involves constructing the part of the building above ground level, including columns, beams, slabs, and walls, forming the main structural framework.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("7613959e-5718-4e46-926b-efa45722c844"),
ServiceId = Guid.Parse("fa208600-b761-480d-95ad-98cad2e61c9b"),
Name = "Water Supply System",
Description = "Water Supply System involves installing pipelines, pumps, tanks, and fittings to ensure the reliable distribution of clean water throughout a building or facility.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("ba4ada9c-ed35-4d5e-bc9f-216f32612c85"),
ServiceId = Guid.Parse("fa208600-b761-480d-95ad-98cad2e61c9b"),
Name = "Drainage & Wastewater System",
Description = "Drainage & Wastewater System involves installing pipes, traps, and chambers to safely collect and dispose of wastewater and sewage from a building to the municipal or septic system.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("44326c01-f69e-430c-a403-d5bf3dcc35d5"),
ServiceId = Guid.Parse("fa208600-b761-480d-95ad-98cad2e61c9b"),
Name = "Rainwater Harvesting",
Description = "Rainwater Harvesting involves collecting, channeling, and storing rainwater from rooftops or surfaces for reuse or groundwater recharge.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("3ef85f9f-e23e-4e6f-9cb7-40ec70a184dd"),
ServiceId = Guid.Parse("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
Name = "Conduiting & Cabling",
Description = "Conduiting & Cabling involves laying electrical conduits and pulling cables to safely route and protect electrical wiring throughout a building.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("a71182a5-0579-4624-b252-4cae2ea11948"),
ServiceId = Guid.Parse("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
Name = "Wiring Installation",
Description = "Wiring Installation involves connecting electrical wires from distribution boards to switches, sockets, and fixtures to provide power and lighting within a building.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("b5e2291f-3569-45e5-9c30-ef33ad0abbf1"),
ServiceId = Guid.Parse("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
Name = "Lighting System",
Description = "Lighting System involves installing and connecting various lighting fixtures, controls, and fittings to ensure proper illumination for indoor and outdoor areas.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("56584b0f-b2a5-4a5e-afea-590516473bcd"),
ServiceId = Guid.Parse("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Name = "Sprinkler System",
Description = "Sprinkler System involves installing a network of pipes and sprinkler heads designed to automatically discharge water to suppress or extinguish fires.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("78a12040-4ab6-493a-b199-ee636f45f77f"),
ServiceId = Guid.Parse("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Name = "Fire Hydrant System",
Description = "Fire Hydrant System involves installing external and internal hydrants, piping, and valves to provide high-pressure water access for manual firefighting during emergencies.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("fbb04bec-53a7-4f86-8536-34c4b5c691a2"),
ServiceId = Guid.Parse("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Name = "Liaisoning",
Description = "Liaisoning Fire Fighting involves coordinating with fire authorities to obtain necessary approvals and no-objection certificates (NOCs) for fire safety systems, ensuring compliance with local fire safety regulations.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("6eedb9f1-22e9-4d93-b770-593125085465"),
ServiceId = Guid.Parse("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Name = "Public Address (PA) System",
Description = "Public Address (PA) System involves installing speakers, microphones, amplifiers, and control units to broadcast announcements, alerts, and emergency messages throughout a building or facility.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("97c6f9f5-cd4d-4830-ba14-a81f6ee0d1e2"),
ServiceId = Guid.Parse("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Name = "Detection and Alarm System",
Description = "Detection and Alarm System involves installing smoke detectors, heat sensors, and fire alarm panels to automatically detect fire or smoke and alert occupants through audible and visual alarms.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("cdea8e5f-8b78-4f7e-ab65-bd6b38d81af2"),
ServiceId = Guid.Parse("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
Name = "HVAC System Design & Planning",
Description = "HVAC System Design & Planning involves calculating heating and cooling loads, selecting appropriate equipment, and designing duct and piping layouts to ensure efficient climate control and air quality.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("1805e22d-4220-45cc-8f39-35194c2499a5"),
ServiceId = Guid.Parse("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
Name = "Ducting Work",
Description = "Ducting Work involves fabricating, installing, and insulating ducts to distribute conditioned air throughout the building as part of the HVAC system.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("69819ea6-5550-4325-9097-c52d95db0822"),
ServiceId = Guid.Parse("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
Name = "Equipment Installation",
Description = "Equipment Installation involves setting up HVAC units such as AHUs, FCUs, chillers, and compressors to enable heating, cooling, and ventilation operations in the building.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("fe613446-c399-4a5c-8205-fd3652231f57"),
ServiceId = Guid.Parse("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
Name = "Ventilation System",
Description = "Ventilation System involves installing exhausts, fresh air units, and ductwork to ensure proper air circulation, removal of stale air, and maintenance of indoor air quality.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("0398ba10-f814-404a-a7a2-3bac0f61a9a5"),
ServiceId = Guid.Parse("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
Name = "Partition Work",
Description = "Partition Work involves constructing internal dividing walls using materials like gypsum, glass, or wood to create separate rooms or functional spaces within a building.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("9efaa80a-f115-4e78-866a-5e192faa1024"),
ServiceId = Guid.Parse("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
Name = "False Ceiling Work",
Description = "False Ceiling Work involves installing suspended ceilings made of materials like gypsum, metal, or POP to conceal services, improve aesthetics, and enhance acoustic and thermal performance.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("c0a9e90c-4c74-417d-b36e-6e63eca16463"),
ServiceId = Guid.Parse("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
Name = "Door & Window Installation",
Description = "Door & Window Installation involves fitting and fixing doors and windows made of wood, aluminum, uPVC, or glass to provide access, ventilation, and natural light within the building.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ActivityGroupMaster
{
Id = new Guid("a27d502b-20ea-4926-b294-3db7110f94e5"),
ServiceId = Guid.Parse("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
Name = "Data & Communication Cabling",
Description = "Data & Communication Cabling involves laying structured cables for internet, telephone, and networking systems to ensure reliable communication and connectivity throughout the building.",
IsSystem = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
}
);
}
private static void ManageApplicationStructure(ModelBuilder modelBuilder)

View File

@ -0,0 +1,209 @@
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_Service_And_ActivityGroup_Master_Table : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "ActivityMasters",
keyColumn: "UnitOfMeasurement",
keyValue: null,
column: "UnitOfMeasurement",
value: "");
migrationBuilder.AlterColumn<string>(
name: "UnitOfMeasurement",
table: "ActivityMasters",
type: "longtext",
nullable: false,
oldClrType: typeof(string),
oldType: "longtext",
oldNullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "ActivityMasters",
keyColumn: "ActivityName",
keyValue: null,
column: "ActivityName",
value: "");
migrationBuilder.AlterColumn<string>(
name: "ActivityName",
table: "ActivityMasters",
type: "longtext",
nullable: false,
oldClrType: typeof(string),
oldType: "longtext",
oldNullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddColumn<Guid>(
name: "ActitvityGroupId",
table: "ActivityMasters",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci");
migrationBuilder.AddColumn<Guid>(
name: "ServiceId",
table: "ActivityMasters",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci");
migrationBuilder.CreateTable(
name: "ActivityGroupMasters",
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"),
ServiceId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
IsSystem = table.Column<bool>(type: "tinyint(1)", nullable: false),
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_ActivityGroupMasters", x => x.Id);
table.ForeignKey(
name: "FK_ActivityGroupMasters_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "ServicesMasters",
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"),
IsSystem = table.Column<bool>(type: "tinyint(1)", nullable: false),
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_ServicesMasters", x => x.Id);
table.ForeignKey(
name: "FK_ServicesMasters_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "ActivityGroupMasters",
columns: new[] { "Id", "Description", "IsActive", "IsSystem", "Name", "ServiceId", "TenantId" },
values: new object[,]
{
{ new Guid("0398ba10-f814-404a-a7a2-3bac0f61a9a5"), "Partition Work involves constructing internal dividing walls using materials like gypsum, glass, or wood to create separate rooms or functional spaces within a building.", true, true, "Partition Work", new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("1805e22d-4220-45cc-8f39-35194c2499a5"), "Ducting Work involves fabricating, installing, and insulating ducts to distribute conditioned air throughout the building as part of the HVAC system.", true, true, "Ducting Work", new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("1d29b7d1-ffdc-486d-ac7b-ee2661ae9979"), "Foundation Work involves excavating, reinforcing, and casting the base structure that supports the entire building load, including footings and plinth beams.", true, true, "Foundation Work", new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("3a712ddb-8927-4d58-8b24-83290e6ba8d1"), "Sub-Structure Work involves constructing the portion of the building below ground level, including plinth beams, basement walls, and backfilling, to support the superstructure.", true, true, "Sub-Structure Work", new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("3ef85f9f-e23e-4e6f-9cb7-40ec70a184dd"), "Conduiting & Cabling involves laying electrical conduits and pulling cables to safely route and protect electrical wiring throughout a building.", true, true, "Conduiting & Cabling", new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("44326c01-f69e-430c-a403-d5bf3dcc35d5"), "Rainwater Harvesting involves collecting, channeling, and storing rainwater from rooftops or surfaces for reuse or groundwater recharge.", true, true, "Rainwater Harvesting", new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("47fa23fb-0e1c-459e-9cc9-9136c61effbd"), "Super-Structure Work involves constructing the part of the building above ground level, including columns, beams, slabs, and walls, forming the main structural framework.", true, true, "Super-Structure Work", new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("56584b0f-b2a5-4a5e-afea-590516473bcd"), "Sprinkler System involves installing a network of pipes and sprinkler heads designed to automatically discharge water to suppress or extinguish fires.", true, true, "Sprinkler System", new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("69819ea6-5550-4325-9097-c52d95db0822"), "Equipment Installation involves setting up HVAC units such as AHUs, FCUs, chillers, and compressors to enable heating, cooling, and ventilation operations in the building.", true, true, "Equipment Installation", new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("6eedb9f1-22e9-4d93-b770-593125085465"), "Public Address (PA) System involves installing speakers, microphones, amplifiers, and control units to broadcast announcements, alerts, and emergency messages throughout a building or facility.", true, true, "Public Address (PA) System", new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("6f048b41-f909-41dd-af5f-02369ca80639"), "Site Preparation involves clearing, leveling, and preparing the land for construction by removing obstacles, performing excavation, and conducting soil tests.", true, true, "Site Preparation", new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("7613959e-5718-4e46-926b-efa45722c844"), "Water Supply System involves installing pipelines, pumps, tanks, and fittings to ensure the reliable distribution of clean water throughout a building or facility.", true, true, "Water Supply System", new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("78a12040-4ab6-493a-b199-ee636f45f77f"), "Fire Hydrant System involves installing external and internal hydrants, piping, and valves to provide high-pressure water access for manual firefighting during emergencies.", true, true, "Fire Hydrant System", new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("97c6f9f5-cd4d-4830-ba14-a81f6ee0d1e2"), "Detection and Alarm System involves installing smoke detectors, heat sensors, and fire alarm panels to automatically detect fire or smoke and alert occupants through audible and visual alarms.", true, true, "Detection and Alarm System", new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("9efaa80a-f115-4e78-866a-5e192faa1024"), "False Ceiling Work involves installing suspended ceilings made of materials like gypsum, metal, or POP to conceal services, improve aesthetics, and enhance acoustic and thermal performance.", true, true, "False Ceiling Work", new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("a27d502b-20ea-4926-b294-3db7110f94e5"), "Data & Communication Cabling involves laying structured cables for internet, telephone, and networking systems to ensure reliable communication and connectivity throughout the building.", true, true, "Data & Communication Cabling", new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("a71182a5-0579-4624-b252-4cae2ea11948"), "Wiring Installation involves connecting electrical wires from distribution boards to switches, sockets, and fixtures to provide power and lighting within a building.", true, true, "Wiring Installation", new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("b5e2291f-3569-45e5-9c30-ef33ad0abbf1"), "Lighting System involves installing and connecting various lighting fixtures, controls, and fittings to ensure proper illumination for indoor and outdoor areas.", true, true, "Lighting System", new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("ba4ada9c-ed35-4d5e-bc9f-216f32612c85"), "Drainage & Wastewater System involves installing pipes, traps, and chambers to safely collect and dispose of wastewater and sewage from a building to the municipal or septic system.", true, true, "Drainage & Wastewater System", new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("c0a9e90c-4c74-417d-b36e-6e63eca16463"), "Door & Window Installation involves fitting and fixing doors and windows made of wood, aluminum, uPVC, or glass to provide access, ventilation, and natural light within the building.", true, true, "Door & Window Installation", new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("cdea8e5f-8b78-4f7e-ab65-bd6b38d81af2"), "HVAC System Design & Planning involves calculating heating and cooling loads, selecting appropriate equipment, and designing duct and piping layouts to ensure efficient climate control and air quality.", true, true, "HVAC System Design & Planning", new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("fbb04bec-53a7-4f86-8536-34c4b5c691a2"), "Liaisoning Fire Fighting involves coordinating with fire authorities to obtain necessary approvals and no-objection certificates (NOCs) for fire safety systems, ensuring compliance with local fire safety regulations.", true, true, "Liaisoning", new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("fe613446-c399-4a5c-8205-fd3652231f57"), "Ventilation System involves installing exhausts, fresh air units, and ductwork to ensure proper air circulation, removal of stale air, and maintenance of indoor air quality.", true, true, "Ventilation System", new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
});
migrationBuilder.InsertData(
table: "ServicesMasters",
columns: new[] { "Id", "Description", "IsActive", "IsSystem", "Name", "TenantId" },
values: new object[,]
{
{ new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"), "Construction Civil service involves planning, designing, and overseeing infrastructure and building projects", true, true, "Civil", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"), "Interior infrastructure (Interior Infra) service involves the construction and installation of essential internal structural elements like partitions, ceilings, flooring, and utility layouts to prepare spaces for interior design and functional use.", true, true, "Interior infrastructure", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"), "Fire fighting service involves installing and maintaining systems like sprinklers, hydrants, and alarms to detect, control, and extinguish fires in buildings and facilities.", true, true, "Fire fighting", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"), "HVAC (Heating, Ventilation, and Air Conditioning) service involves the installation, maintenance, and repair of systems that control indoor climate, air quality, and thermal comfort in buildings.", true, true, "HVAC", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"), "Electric service involves the installation, maintenance, and repair of electrical systems, including wiring, lighting, and power distribution in buildings and infrastructure", true, true, "Electric", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"), "Plumbing service involves installing, maintaining, and repairing systems for water supply, drainage, and sewage in residential, commercial, and industrial buildings", true, true, "Plumbing", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
});
migrationBuilder.CreateIndex(
name: "IX_ActivityGroupMasters_TenantId",
table: "ActivityGroupMasters",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_ServicesMasters_TenantId",
table: "ServicesMasters",
column: "TenantId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ActivityGroupMasters");
migrationBuilder.DropTable(
name: "ServicesMasters");
migrationBuilder.DropColumn(
name: "ActitvityGroupId",
table: "ActivityMasters");
migrationBuilder.DropColumn(
name: "ServiceId",
table: "ActivityMasters");
migrationBuilder.AlterColumn<string>(
name: "UnitOfMeasurement",
table: "ActivityMasters",
type: "longtext",
nullable: true,
oldClrType: typeof(string),
oldType: "longtext")
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AlterColumn<string>(
name: "ActivityName",
table: "ActivityMasters",
type: "longtext",
nullable: true,
oldClrType: typeof(string),
oldType: "longtext")
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
}
}
}

View File

@ -0,0 +1,79 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_Forgien_Keys_In_Activity_And_ActivityGroup_Master_Table : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_ActivityMasters_ActitvityGroupId",
table: "ActivityMasters",
column: "ActitvityGroupId");
migrationBuilder.CreateIndex(
name: "IX_ActivityMasters_ServiceId",
table: "ActivityMasters",
column: "ServiceId");
migrationBuilder.CreateIndex(
name: "IX_ActivityGroupMasters_ServiceId",
table: "ActivityGroupMasters",
column: "ServiceId");
migrationBuilder.AddForeignKey(
name: "FK_ActivityGroupMasters_ServicesMasters_ServiceId",
table: "ActivityGroupMasters",
column: "ServiceId",
principalTable: "ServicesMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ActivityMasters_ActivityGroupMasters_ActitvityGroupId",
table: "ActivityMasters",
column: "ActitvityGroupId",
principalTable: "ActivityGroupMasters",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ActivityMasters_ServicesMasters_ServiceId",
table: "ActivityMasters",
column: "ServiceId",
principalTable: "ServicesMasters",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ActivityGroupMasters_ServicesMasters_ServiceId",
table: "ActivityGroupMasters");
migrationBuilder.DropForeignKey(
name: "FK_ActivityMasters_ActivityGroupMasters_ActitvityGroupId",
table: "ActivityMasters");
migrationBuilder.DropForeignKey(
name: "FK_ActivityMasters_ServicesMasters_ServiceId",
table: "ActivityMasters");
migrationBuilder.DropIndex(
name: "IX_ActivityMasters_ActitvityGroupId",
table: "ActivityMasters");
migrationBuilder.DropIndex(
name: "IX_ActivityMasters_ServiceId",
table: "ActivityMasters");
migrationBuilder.DropIndex(
name: "IX_ActivityGroupMasters_ServiceId",
table: "ActivityGroupMasters");
}
}
}

View File

@ -1883,26 +1883,305 @@ namespace Marco.Pms.DataAccess.Migrations
b.ToTable("MailingList");
});
modelBuilder.Entity("Marco.Pms.Model.Master.ActivityGroupMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsSystem")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("ServiceId")
.HasColumnType("char(36)");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("TenantId");
b.ToTable("ActivityGroupMasters");
b.HasData(
new
{
Id = new Guid("6f048b41-f909-41dd-af5f-02369ca80639"),
Description = "Site Preparation involves clearing, leveling, and preparing the land for construction by removing obstacles, performing excavation, and conducting soil tests.",
IsActive = true,
IsSystem = true,
Name = "Site Preparation",
ServiceId = new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("1d29b7d1-ffdc-486d-ac7b-ee2661ae9979"),
Description = "Foundation Work involves excavating, reinforcing, and casting the base structure that supports the entire building load, including footings and plinth beams.",
IsActive = true,
IsSystem = true,
Name = "Foundation Work",
ServiceId = new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("3a712ddb-8927-4d58-8b24-83290e6ba8d1"),
Description = "Sub-Structure Work involves constructing the portion of the building below ground level, including plinth beams, basement walls, and backfilling, to support the superstructure.",
IsActive = true,
IsSystem = true,
Name = "Sub-Structure Work",
ServiceId = new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("47fa23fb-0e1c-459e-9cc9-9136c61effbd"),
Description = "Super-Structure Work involves constructing the part of the building above ground level, including columns, beams, slabs, and walls, forming the main structural framework.",
IsActive = true,
IsSystem = true,
Name = "Super-Structure Work",
ServiceId = new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("7613959e-5718-4e46-926b-efa45722c844"),
Description = "Water Supply System involves installing pipelines, pumps, tanks, and fittings to ensure the reliable distribution of clean water throughout a building or facility.",
IsActive = true,
IsSystem = true,
Name = "Water Supply System",
ServiceId = new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("ba4ada9c-ed35-4d5e-bc9f-216f32612c85"),
Description = "Drainage & Wastewater System involves installing pipes, traps, and chambers to safely collect and dispose of wastewater and sewage from a building to the municipal or septic system.",
IsActive = true,
IsSystem = true,
Name = "Drainage & Wastewater System",
ServiceId = new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("44326c01-f69e-430c-a403-d5bf3dcc35d5"),
Description = "Rainwater Harvesting involves collecting, channeling, and storing rainwater from rooftops or surfaces for reuse or groundwater recharge.",
IsActive = true,
IsSystem = true,
Name = "Rainwater Harvesting",
ServiceId = new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("3ef85f9f-e23e-4e6f-9cb7-40ec70a184dd"),
Description = "Conduiting & Cabling involves laying electrical conduits and pulling cables to safely route and protect electrical wiring throughout a building.",
IsActive = true,
IsSystem = true,
Name = "Conduiting & Cabling",
ServiceId = new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("a71182a5-0579-4624-b252-4cae2ea11948"),
Description = "Wiring Installation involves connecting electrical wires from distribution boards to switches, sockets, and fixtures to provide power and lighting within a building.",
IsActive = true,
IsSystem = true,
Name = "Wiring Installation",
ServiceId = new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("b5e2291f-3569-45e5-9c30-ef33ad0abbf1"),
Description = "Lighting System involves installing and connecting various lighting fixtures, controls, and fittings to ensure proper illumination for indoor and outdoor areas.",
IsActive = true,
IsSystem = true,
Name = "Lighting System",
ServiceId = new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("56584b0f-b2a5-4a5e-afea-590516473bcd"),
Description = "Sprinkler System involves installing a network of pipes and sprinkler heads designed to automatically discharge water to suppress or extinguish fires.",
IsActive = true,
IsSystem = true,
Name = "Sprinkler System",
ServiceId = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("78a12040-4ab6-493a-b199-ee636f45f77f"),
Description = "Fire Hydrant System involves installing external and internal hydrants, piping, and valves to provide high-pressure water access for manual firefighting during emergencies.",
IsActive = true,
IsSystem = true,
Name = "Fire Hydrant System",
ServiceId = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("fbb04bec-53a7-4f86-8536-34c4b5c691a2"),
Description = "Liaisoning Fire Fighting involves coordinating with fire authorities to obtain necessary approvals and no-objection certificates (NOCs) for fire safety systems, ensuring compliance with local fire safety regulations.",
IsActive = true,
IsSystem = true,
Name = "Liaisoning",
ServiceId = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("6eedb9f1-22e9-4d93-b770-593125085465"),
Description = "Public Address (PA) System involves installing speakers, microphones, amplifiers, and control units to broadcast announcements, alerts, and emergency messages throughout a building or facility.",
IsActive = true,
IsSystem = true,
Name = "Public Address (PA) System",
ServiceId = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("97c6f9f5-cd4d-4830-ba14-a81f6ee0d1e2"),
Description = "Detection and Alarm System involves installing smoke detectors, heat sensors, and fire alarm panels to automatically detect fire or smoke and alert occupants through audible and visual alarms.",
IsActive = true,
IsSystem = true,
Name = "Detection and Alarm System",
ServiceId = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("cdea8e5f-8b78-4f7e-ab65-bd6b38d81af2"),
Description = "HVAC System Design & Planning involves calculating heating and cooling loads, selecting appropriate equipment, and designing duct and piping layouts to ensure efficient climate control and air quality.",
IsActive = true,
IsSystem = true,
Name = "HVAC System Design & Planning",
ServiceId = new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("1805e22d-4220-45cc-8f39-35194c2499a5"),
Description = "Ducting Work involves fabricating, installing, and insulating ducts to distribute conditioned air throughout the building as part of the HVAC system.",
IsActive = true,
IsSystem = true,
Name = "Ducting Work",
ServiceId = new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("69819ea6-5550-4325-9097-c52d95db0822"),
Description = "Equipment Installation involves setting up HVAC units such as AHUs, FCUs, chillers, and compressors to enable heating, cooling, and ventilation operations in the building.",
IsActive = true,
IsSystem = true,
Name = "Equipment Installation",
ServiceId = new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("fe613446-c399-4a5c-8205-fd3652231f57"),
Description = "Ventilation System involves installing exhausts, fresh air units, and ductwork to ensure proper air circulation, removal of stale air, and maintenance of indoor air quality.",
IsActive = true,
IsSystem = true,
Name = "Ventilation System",
ServiceId = new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("0398ba10-f814-404a-a7a2-3bac0f61a9a5"),
Description = "Partition Work involves constructing internal dividing walls using materials like gypsum, glass, or wood to create separate rooms or functional spaces within a building.",
IsActive = true,
IsSystem = true,
Name = "Partition Work",
ServiceId = new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("9efaa80a-f115-4e78-866a-5e192faa1024"),
Description = "False Ceiling Work involves installing suspended ceilings made of materials like gypsum, metal, or POP to conceal services, improve aesthetics, and enhance acoustic and thermal performance.",
IsActive = true,
IsSystem = true,
Name = "False Ceiling Work",
ServiceId = new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("c0a9e90c-4c74-417d-b36e-6e63eca16463"),
Description = "Door & Window Installation involves fitting and fixing doors and windows made of wood, aluminum, uPVC, or glass to provide access, ventilation, and natural light within the building.",
IsActive = true,
IsSystem = true,
Name = "Door & Window Installation",
ServiceId = new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("a27d502b-20ea-4926-b294-3db7110f94e5"),
Description = "Data & Communication Cabling involves laying structured cables for internet, telephone, and networking systems to ensure reliable communication and connectivity throughout the building.",
IsActive = true,
IsSystem = true,
Name = "Data & Communication Cabling",
ServiceId = new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
});
});
modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid?>("ActitvityGroupId")
.HasColumnType("char(36)");
b.Property<string>("ActivityName")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("ServiceId")
.HasColumnType("char(36)");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.Property<string>("UnitOfMeasurement")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ActitvityGroupId");
b.HasIndex("ServiceId");
b.HasIndex("TenantId");
b.ToTable("ActivityMasters");
@ -2451,6 +2730,92 @@ namespace Marco.Pms.DataAccess.Migrations
});
});
modelBuilder.Entity("Marco.Pms.Model.Master.ServicesMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsSystem")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId");
b.ToTable("ServicesMasters");
b.HasData(
new
{
Id = new Guid("0aa3e986-d6a4-49b4-818b-564d2d7799a2"),
Description = "Construction Civil service involves planning, designing, and overseeing infrastructure and building projects",
IsActive = true,
IsSystem = true,
Name = "Civil",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("fa208600-b761-480d-95ad-98cad2e61c9b"),
Description = "Plumbing service involves installing, maintaining, and repairing systems for water supply, drainage, and sewage in residential, commercial, and industrial buildings",
IsActive = true,
IsSystem = true,
Name = "Plumbing",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("e3c1d91d-7e86-4257-9c2d-04a4352d8283"),
Description = "Electric service involves the installation, maintenance, and repair of electrical systems, including wiring, lighting, and power distribution in buildings and infrastructure",
IsActive = true,
IsSystem = true,
Name = "Electric",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("da465f54-0f58-48c8-ab1d-8e31d59b3607"),
Description = "Fire fighting service involves installing and maintaining systems like sprinklers, hydrants, and alarms to detect, control, and extinguish fires in buildings and facilities.",
IsActive = true,
IsSystem = true,
Name = "Fire fighting",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("df3805d6-8d02-45cb-9c53-5c42b527ebb6"),
Description = "HVAC (Heating, Ventilation, and Air Conditioning) service involves the installation, maintenance, and repair of systems that control indoor climate, air quality, and thermal comfort in buildings.",
IsActive = true,
IsSystem = true,
Name = "HVAC",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
},
new
{
Id = new Guid("8d196e15-4099-4c9a-9a84-86650d79d4b4"),
Description = "Interior infrastructure (Interior Infra) service involves the construction and installation of essential internal structural elements like partitions, ceilings, flooring, and utility layouts to prepare spaces for interior design and functional use.",
IsActive = true,
IsSystem = true,
Name = "Interior infrastructure",
TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26")
});
});
modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b =>
{
b.Property<Guid>("Id")
@ -4143,14 +4508,45 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("MailBody");
});
modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b =>
modelBuilder.Entity("Marco.Pms.Model.Master.ActivityGroupMaster", b =>
{
b.HasOne("Marco.Pms.Model.Master.ServicesMaster", "ServicesMaster")
.WithMany()
.HasForeignKey("ServiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ServicesMaster");
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b =>
{
b.HasOne("Marco.Pms.Model.Master.ActivityGroupMaster", "ActivityGroupMaster")
.WithMany()
.HasForeignKey("ActitvityGroupId");
b.HasOne("Marco.Pms.Model.Master.ServicesMaster", "ServicesMaster")
.WithMany()
.HasForeignKey("ServiceId");
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ActivityGroupMaster");
b.Navigation("ServicesMaster");
b.Navigation("Tenant");
});
@ -4187,6 +4583,17 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Master.ServicesMaster", b =>
{
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b =>
{
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")

View File

@ -2,6 +2,8 @@
{
public class CreateActivityMasterDto
{
public Guid ActitvityGroupId { get; set; }
public Guid ServiceId { get; set; }
public string? ActivityName { get; set; }
public string? UnitOfMeasurement { get; set; }
public List<CreateCheckListDto>? CheckList { get; set; }

View File

@ -0,0 +1,10 @@
namespace Marco.Pms.Model.Dtos.Master
{
public class ActivityGroupDto
{
public Guid? Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public Guid ServiceId { get; set; }
}
}

View File

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

View File

@ -95,8 +95,11 @@ namespace Marco.Pms.Model.Mapper
{
return new ActivityMaster
{
ActivityName = createActivity.ActivityName,
UnitOfMeasurement = createActivity.UnitOfMeasurement,
ServiceId = createActivity.ServiceId,
ActitvityGroupId = createActivity.ActitvityGroupId,
ActivityName = createActivity.ActivityName ?? string.Empty,
UnitOfMeasurement = createActivity.UnitOfMeasurement ?? string.Empty,
IsActive = true,
TenantId = tenantId
};
}
@ -135,13 +138,18 @@ namespace Marco.Pms.Model.Mapper
};
}
public static ActivityVM ToActivityVMFromActivityMaster(this ActivityMaster activity, List<CheckListVM> checkList)
public static ActivityVM ToActivityVMFromActivityMaster(this ActivityMaster activity, List<CheckListVM> checkList, string? serviceName, string? activityGroupName)
{
return new ActivityVM
{
Id = activity.Id,
ServiceId = activity.ServiceId,
ServicesName = serviceName,
ActitvityGroupId = activity.ActitvityGroupId,
ActivityGroupName = activityGroupName,
ActivityName = activity.ActivityName,
UnitOfMeasurement = activity.UnitOfMeasurement,
IsActive = activity.IsActive,
CheckLists = checkList,
};
}

View File

@ -27,5 +27,53 @@ namespace Marco.Pms.Model.Mapper
IsSystem = categoryMaster.IsSystem
};
}
// -------------------------------- Services --------------------------------
public static ServicesMaster ToServicesMasterFromServiceMasterDto(this ServiceMasterDto model, Guid tenantId)
{
return new ServicesMaster
{
Name = model.Name ?? string.Empty,
Description = model.Description ?? string.Empty,
TenantId = tenantId
};
}
public static ServiceMasterVM ToServiceMasterVMFromServiceMaster(this ServicesMaster model)
{
return new ServiceMasterVM
{
Id = model.Id,
Name = model.Name,
Description = model.Description,
IsActive = model.IsActive,
IsSystem = model.IsSystem
};
}
// -------------------------------- Activity Group --------------------------------
public static ActivityGroupMaster ToActivityGroupMasterFromActivityGroupDto(this ActivityGroupDto model, Guid tenantId)
{
return new ActivityGroupMaster
{
ServiceId = model.ServiceId,
Name = model.Name ?? string.Empty,
Description = model.Description ?? string.Empty,
TenantId = tenantId
};
}
public static ActivityGroupMasterVM ToActivityGroupMasterVMFromActivityGroupMaster(this ActivityGroupMaster model, string serviceName)
{
return new ActivityGroupMasterVM
{
Id = model.Id,
ServiceId = model.ServiceId,
ServicesName = serviceName,
Name = model.Name ?? string.Empty,
Description = model.Description ?? string.Empty,
IsActive = model.IsActive,
IsSystem = model.IsSystem
};
}
}
}

View File

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations.Schema;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Marco.Pms.Model.Master
{
public class ActivityGroupMaster : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public Guid ServiceId { get; set; }
[ValidateNever]
[ForeignKey("ServiceId")]
public ServicesMaster? ServicesMaster { get; set; }
public bool IsSystem { get; set; } = false;
public bool IsActive { get; set; } = true;
}
}

View File

@ -1,14 +1,24 @@
using Marco.Pms.Model.Utilities;
using System.ComponentModel.DataAnnotations.Schema;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Marco.Pms.Model.Master
{
public class ActivityMaster : TenantRelation
{
public Guid Id { get; set; }
public string? ActivityName { get; set; }
public Guid? ActitvityGroupId { get; set; }
public string? UnitOfMeasurement { get; set; }
[ValidateNever]
[ForeignKey("ActitvityGroupId")]
public ActivityGroupMaster? ActivityGroupMaster { get; set; }
public Guid? ServiceId { get; set; }
[ValidateNever]
[ForeignKey("ServiceId")]
public ServicesMaster? ServicesMaster { get; set; }
public string ActivityName { get; set; } = string.Empty;
public string UnitOfMeasurement { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
}
}

View File

@ -0,0 +1,13 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.Master
{
public class ServicesMaster : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public bool IsSystem { get; set; } = false;
public bool IsActive { get; set; } = true;
}
}

View File

@ -4,8 +4,12 @@
{
public Guid Id { get; set; }
public string? ActivityName { get; set; }
public string? UnitOfMeasurement { get; set; }
public Guid? ActitvityGroupId { get; set; }
public string? ActivityGroupName { get; set; }
public Guid? ServiceId { get; set; }
public string? ServicesName { get; set; }
public bool IsActive { get; set; }
public List<CheckListVM>? CheckLists { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace Marco.Pms.Model.ViewModels.Master
{
public class ActivityGroupMasterVM
{
public Guid Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public Guid ServiceId { get; set; }
public string? ServicesName { get; set; }
public bool IsSystem { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,11 @@
namespace Marco.Pms.Model.ViewModels.Master
{
public class ServiceMasterVM
{
public Guid Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public bool IsSystem { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -1,12 +1,10 @@
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Dtos.Activities;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Forum;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Helpers;
@ -40,156 +38,99 @@ namespace Marco.Pms.Services.Controllers
tenantId = userHelper.GetTenantId();
}
#region =================================================================== Services APIs ===================================================================
[HttpGet("services")]
public async Task<IActionResult> GetServices()
{
var response = await _masterHelper.GetServices();
return StatusCode(response.StatusCode, response);
}
[HttpPost("service")]
public async Task<IActionResult> CreateService([FromBody] ServiceMasterDto serviceMasterDto)
{
var response = await _masterHelper.CreateService(serviceMasterDto);
return StatusCode(response.StatusCode, response);
}
[HttpPut("service/{id}")]
public async Task<IActionResult> UpdateService(Guid id, [FromBody] ServiceMasterDto serviceMasterDto)
{
var response = await _masterHelper.UpdateService(id, serviceMasterDto);
return StatusCode(response.StatusCode, response);
}
[HttpDelete("service/{id}")]
public async Task<IActionResult> DeleteService(Guid id, [FromQuery] bool? isActive)
{
var response = await _masterHelper.DeleteService(id, isActive ?? false);
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Activity Group APIs ===================================================================
[HttpGet("activity-groups")]
public async Task<IActionResult> GetActivityGroups()
{
var response = await _masterHelper.GetActivityGroups();
return StatusCode(response.StatusCode, response);
}
[HttpPost("activity-group")]
public async Task<IActionResult> CreateActivityGroup([FromBody] ActivityGroupDto activityGroupDto)
{
var response = await _masterHelper.CreateActivityGroup(activityGroupDto);
return StatusCode(response.StatusCode, response);
}
[HttpPut("activity-group/{id}")]
public async Task<IActionResult> UpdateActivityGroup(Guid id, [FromBody] ActivityGroupDto activityGroupDto)
{
var response = await _masterHelper.UpdateActivityGroup(id, activityGroupDto);
return StatusCode(response.StatusCode, response);
}
[HttpDelete("activity-group/{id}")]
public async Task<IActionResult> DeleteActivityGroup(Guid id, [FromQuery] bool? isActive)
{
var response = await _masterHelper.DeleteActivityGroup(id, isActive ?? false);
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Activity APIs ===================================================================
[HttpGet]
[Route("activities")]
[HttpGet("activities")]
public async Task<IActionResult> GetActivitiesMaster()
{
Guid tenantId = _userHelper.GetTenantId();
var activities = await _context.ActivityMasters.Where(c => c.TenantId == tenantId && c.IsActive == true).ToListAsync();
List<ActivityVM> activitiesVM = new List<ActivityVM>();
foreach (var activity in activities)
{
var checkList = await _context.ActivityCheckLists.Where(c => c.TenantId == tenantId && c.ActivityId == activity.Id).ToListAsync();
List<CheckListVM> checkListVM = new List<CheckListVM>();
if (checkList != null)
{
foreach (ActivityCheckList check in checkList)
{
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id, false);
checkListVM.Add(checkVM);
}
}
ActivityVM activityVM = activity.ToActivityVMFromActivityMaster(checkListVM);
activitiesVM.Add(activityVM);
}
_logger.LogInfo("{count} activity records fetched successfully from tenant {tenantId}", activitiesVM.Count, tenantId);
return Ok(ApiResponse<object>.SuccessResponse(activitiesVM, System.String.Format("{0} activity records fetched successfully", activitiesVM.Count), 200));
var response = await _masterHelper.GetActivitiesMaster();
return StatusCode(response.StatusCode, response);
}
[HttpPost("activity")]
public async Task<IActionResult> CreateActivity([FromBody] CreateActivityMasterDto createActivity)
{
Guid tenantId = _userHelper.GetTenantId();
var employee = await _userHelper.GetCurrentEmployeeAsync();
if (employee.TenantId != tenantId)
{
_logger.LogWarning("User from tenant {employeeTenantId} tries to access data from tenant {tenantId}", employee.TenantId, tenantId);
return Unauthorized(ApiResponse<object>.ErrorResponse("Current tenant did not match with user's tenant", "Current tenant did not match with user's tenant", 401));
}
var activityMaster = createActivity.ToActivityMasterFromCreateActivityMasterDto(tenantId);
_context.ActivityMasters.Add(activityMaster);
await _context.SaveChangesAsync();
List<CheckListVM> checkListVM = new List<CheckListVM>();
if (createActivity.CheckList != null)
{
List<ActivityCheckList> activityCheckList = new List<ActivityCheckList>();
foreach (var check in createActivity.CheckList)
{
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId, activityMaster.Id);
activityCheckList.Add(checkList);
}
_context.ActivityCheckLists.AddRange(activityCheckList);
await _context.SaveChangesAsync();
foreach (ActivityCheckList check in activityCheckList)
{
var checkVM = check.ToCheckListVMFromActivityCheckList(activityMaster.Id, false);
checkListVM.Add(checkVM);
}
}
ActivityVM activityVM = activityMaster.ToActivityVMFromActivityMaster(checkListVM);
_logger.LogInfo("activity created successfully from tenant {tenantId}", tenantId);
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity created successfully", 200));
var response = await _masterHelper.CreateActivity(createActivity);
return StatusCode(response.StatusCode, response);
}
[HttpPost("activity/edit/{id}")]
[HttpPut("activity/{id}")]
public async Task<IActionResult> UpdateActivity(Guid id, [FromBody] CreateActivityMasterDto createActivity)
{
Guid tenantId = _userHelper.GetTenantId();
var employee = await _userHelper.GetCurrentEmployeeAsync();
ActivityMaster? activity = await _context.ActivityMasters.FirstOrDefaultAsync(x => x.Id == id && x.IsActive == true && x.TenantId == tenantId);
if (activity != null && createActivity.UnitOfMeasurement != null && createActivity.ActivityName != null)
{
var response = await _masterHelper.UpdateActivity(id, createActivity);
return StatusCode(response.StatusCode, response);
activity.ActivityName = createActivity.ActivityName;
activity.UnitOfMeasurement = createActivity.UnitOfMeasurement;
List<ActivityCheckList> activityCheckLists = await _context.ActivityCheckLists.AsNoTracking().Where(c => c.ActivityId == activity.Id).ToListAsync();
List<CheckListVM> checkListVM = new List<CheckListVM>();
if (createActivity.CheckList != null)
{
var newCheckIds = createActivity.CheckList.Select(c => c.Id);
List<ActivityCheckList> updateCheckList = new List<ActivityCheckList>();
List<ActivityCheckList> deleteCheckList = new List<ActivityCheckList>();
if (newCheckIds.Contains(null))
{
foreach (var check in createActivity.CheckList)
{
if (check.Id == null)
{
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id);
updateCheckList.Add(checkList);
}
}
}
foreach (var check in activityCheckLists)
{
if (newCheckIds.Contains(check.Id))
{
var updatedCheck = createActivity.CheckList.Find(c => c.Id == check.Id);
ActivityCheckList checkList = updatedCheck != null ? updatedCheck.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id) : new ActivityCheckList();
updateCheckList.Add(checkList);
}
else
{
deleteCheckList.Add(check);
}
}
_context.ActivityCheckLists.UpdateRange(updateCheckList);
if (deleteCheckList != null)
{
_context.ActivityCheckLists.RemoveRange(deleteCheckList);
}
await _context.SaveChangesAsync();
foreach (ActivityCheckList check in updateCheckList)
{
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id, false);
checkListVM.Add(checkVM);
}
}
else if (activityCheckLists != null)
{
_context.ActivityCheckLists.RemoveRange(activityCheckLists);
await _context.SaveChangesAsync();
}
ActivityVM activityVM = activity.ToActivityVMFromActivityMaster(checkListVM);
_logger.LogInfo("activity updated successfully from tenant {tenantId}", tenantId);
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity updated successfully", 200));
}
_logger.LogWarning("Activity {ActivityId} not found", id);
return NotFound(ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404));
}
[HttpDelete("activity/delete/{id}")]
public async Task<IActionResult> DeleteActivity(Guid Id)
[HttpDelete("activity/{id}")]
public async Task<IActionResult> DeleteActivity(Guid id, [FromQuery] bool? isActive)
{
Guid tenantId = _userHelper.GetTenantId();
var activity = await _context.ActivityMasters.FirstOrDefaultAsync(a => a.Id == Id && a.TenantId == tenantId);
if (activity != null)
{
activity.IsActive = false;
}
await _context.SaveChangesAsync();
_logger.LogInfo("Activity Deleted Successfully from tenant {tenantId}", tenantId);
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Activity Deleted Successfully", 200));
var response = await _masterHelper.DeleteActivity(id, isActive ?? false);
return StatusCode(response.StatusCode, response);
}
#endregion

View File

@ -1,11 +1,13 @@
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Directory;
using Marco.Pms.Model.Dtos.Activities;
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.Activities;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers;
@ -19,19 +21,666 @@ namespace Marco.Pms.Services.Helpers
private readonly ApplicationDbContext _context;
private readonly ILoggingService _logger;
private readonly UserHelper _userHelper;
private readonly PermissionServices _permission;
private readonly PermissionServices _permissionService;
private readonly Guid tenantId;
public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permission)
public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permissionServices)
{
_context = context;
_logger = logger;
_userHelper = userHelper;
_permission = permission;
tenantId = userHelper.GetTenantId();
_permissionService = permissionServices;
tenantId = _userHelper.GetTenantId();
}
#region =================================================================== Contact Category APIs ===================================================================
#region =================================================================== Services APIs ===================================================================
public async Task<ApiResponse<object>> GetServices()
{
_logger.LogInfo("GetServices called");
try
{
// Step 1: Get current logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Fetch services for the tenant
var services = await _context.ServicesMasters
.Where(s => s.TenantId == tenantId && s.IsActive)
.Select(s => s.ToServiceMasterVMFromServiceMaster())
.ToListAsync();
_logger.LogInfo("Fetched {Count} service records for tenantId: {TenantId}", services.Count, tenantId);
return ApiResponse<object>.SuccessResponse(services, $"{services.Count} record(s) of services fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching services");
return ApiResponse<object>.ErrorResponse("An error occurred while fetching services", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> CreateService(ServiceMasterDto serviceMasterDto)
{
_logger.LogInfo("CreateService called with Name: {ServiceName}", serviceMasterDto?.Name ?? "null");
try
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 1: Permission check
var hasManagePermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You don't have access", "You don't have permission to take this action", 403);
}
// Step 2: Validate input
if (string.IsNullOrWhiteSpace(serviceMasterDto?.Name) ||
string.IsNullOrWhiteSpace(serviceMasterDto?.Description))
{
_logger.LogWarning("Invalid input data for service creation by employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Invalid data", "Name and Description are required", 400);
}
// Step 3: Check for duplicate name
bool isExist = await _context.ServicesMasters
.AnyAsync(s => s.TenantId == tenantId && s.Name.ToLower() == serviceMasterDto.Name.ToLower());
if (isExist)
{
_logger.LogWarning("Duplicate service name '{ServiceName}' attempted by employeeId: {EmployeeId}", serviceMasterDto.Name, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse(
$"Service with name '{serviceMasterDto.Name}' already exists",
$"Service with name '{serviceMasterDto.Name}' already exists", 400);
}
// Step 4: Save new service
ServicesMaster service = serviceMasterDto.ToServicesMasterFromServiceMasterDto(tenantId);
_context.ServicesMasters.Add(service);
await _context.SaveChangesAsync();
var response = service.ToServiceMasterVMFromServiceMaster();
_logger.LogInfo("New service '{ServiceName}' created successfully by employeeId: {EmployeeId}", service.Name, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, "New service created successfully", 201);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating service");
return ApiResponse<object>.ErrorResponse("Failed to create service", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> UpdateService(Guid id, ServiceMasterDto serviceMasterDto)
{
_logger.LogInfo("UpdateService called for Id: {Id}", id);
try
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 1: Permission check
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to take this action", 403);
}
// Step 2: Input validation
if (serviceMasterDto == null || serviceMasterDto.Id != id ||
string.IsNullOrWhiteSpace(serviceMasterDto.Name) ||
string.IsNullOrWhiteSpace(serviceMasterDto.Description))
{
_logger.LogWarning("Invalid input data provided for UpdateService. Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("Invalid input", "Please provide valid service data", 400);
}
// Step 3: Retrieve service
var service = await _context.ServicesMasters
.FirstOrDefaultAsync(s => s.Id == id && s.TenantId == tenantId && s.IsActive);
if (service == null)
{
_logger.LogWarning("Service not found for Id: {Id}, Tenant: {TenantId}", id, tenantId);
return ApiResponse<object>.ErrorResponse("Service not found", "The requested service does not exist", 404);
}
// Step 4: Update and save
service.Name = serviceMasterDto.Name.Trim();
service.Description = serviceMasterDto.Description.Trim();
await _context.SaveChangesAsync();
var response = service.ToServiceMasterVMFromServiceMaster();
_logger.LogInfo("Service updated successfully. Id: {Id}, TenantId: {TenantId}", service.Id, tenantId);
return ApiResponse<object>.SuccessResponse(response, "Service updated successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while updating service Id: {Id}.", id);
return ApiResponse<object>.ErrorResponse("An error occurred while updating the service", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> DeleteService(Guid id, bool isActive)
{
_logger.LogInfo("DeleteService called with ServiceId: {ServiceId}, IsActive: {IsActive}", id, isActive);
try
{
// Step 1: Get current user and validate permission
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to delete services", 403);
}
// Step 2: Check if the service exists
var service = await _context.ServicesMasters
.FirstOrDefaultAsync(s => s.Id == id && s.TenantId == tenantId);
if (service == null)
{
_logger.LogWarning("Service not found. ServiceId: {ServiceId}", id);
return ApiResponse<object>.ErrorResponse("Service not found", "Service not found or already deleted", 404);
}
// Protect system-defined service
if (service.IsSystem)
{
_logger.LogWarning("Attempt to delete system-defined service. ServiceId: {ServiceId}", id);
return ApiResponse<object>.ErrorResponse("Cannot delete system-defined service", "This service is system-defined and cannot be deleted", 400);
}
// Step 3: Soft delete or restore
service.IsActive = isActive;
await _context.SaveChangesAsync();
var status = isActive ? "restored" : "deactivated";
_logger.LogInfo("Service {ServiceId} has been {Status} successfully by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(new { }, $"Service {status} successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occurred while deleting service {ServiceId}", id);
return ApiResponse<object>.ErrorResponse("Error deleting service", ex.Message, 500);
}
}
#endregion
#region =================================================================== Activity Group APIs ===================================================================
public async Task<ApiResponse<object>> GetActivityGroups()
{
_logger.LogInfo("GetActivityGroups called");
try
{
// Step 1: Get logged-in employee
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Fetch all activity groups for the tenant
var activityGroups = await _context.ActivityGroupMasters
.Include(ag => ag.ServicesMaster)
.Where(ag => ag.TenantId == tenantId && ag.IsActive)
.Select(ag => ag.ToActivityGroupMasterVMFromActivityGroupMaster(ag.ServicesMaster != null ? ag.ServicesMaster.Name : ""))
.ToListAsync();
_logger.LogInfo("{Count} activity group(s) fetched for tenantId: {TenantId}", activityGroups.Count, tenantId);
return ApiResponse<object>.SuccessResponse(activityGroups, $"{activityGroups.Count} record(s) of activity groups fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching activity groups");
return ApiResponse<object>.ErrorResponse("An error occurred while fetching activity groups", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> CreateActivityGroup(ActivityGroupDto activityGroupDto)
{
_logger.LogInfo("CreateActivityGroup called with Name: {Name}", activityGroupDto?.Name ?? "null");
try
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 1: Check Manage Master permission
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to take this action", 403);
}
// Step 2: Validate input
if (string.IsNullOrWhiteSpace(activityGroupDto?.Name) || string.IsNullOrWhiteSpace(activityGroupDto.Description))
{
_logger.LogWarning("Invalid input data for activity group by employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Invalid input", "Name and Description are required", 400);
}
// Step 3: Check for duplicate name within ActivityGroupMasters
bool isExist = await _context.ActivityGroupMasters
.AnyAsync(ag => ag.TenantId == tenantId && ag.Name.ToLower() == activityGroupDto.Name.ToLower());
if (isExist)
{
_logger.LogWarning("Duplicate activity group name '{Name}' attempted by employeeId: {EmployeeId}", activityGroupDto.Name, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse(
$"Activity group with name '{activityGroupDto.Name}' already exists",
$"Activity group with name '{activityGroupDto.Name}' already exists", 400);
}
// Step 4: Map and persist
var activityGroup = activityGroupDto.ToActivityGroupMasterFromActivityGroupDto(tenantId);
_context.ActivityGroupMasters.Add(activityGroup);
await _context.SaveChangesAsync();
var service = await _context.ServicesMasters.FirstOrDefaultAsync(s => s.Id == activityGroup.ServiceId);
var response = activityGroup.ToActivityGroupMasterVMFromActivityGroupMaster(service?.Name ?? "");
_logger.LogInfo("New activity group '{Name}' created successfully by employeeId: {EmployeeId}", activityGroup.Name, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, "New activity group created successfully", 201);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating activity group");
return ApiResponse<object>.ErrorResponse("Failed to create activity group", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> UpdateActivityGroup(Guid id, ActivityGroupDto activityGroupDto)
{
_logger.LogInfo("UpdateActivityGroup called for Id: {Id}", id);
try
{
// Step 1: Permission check
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to take this action", 403);
}
// Step 2: Input validation
if (activityGroupDto == null || activityGroupDto.Id != id ||
string.IsNullOrWhiteSpace(activityGroupDto.Name) ||
string.IsNullOrWhiteSpace(activityGroupDto.Description))
{
_logger.LogWarning("Invalid input for activity group update. Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("Invalid input", "Please provide valid data to update activity group", 400);
}
var service = await _context.ServicesMasters.FirstOrDefaultAsync(s => s.Id == activityGroupDto.ServiceId && s.IsActive);
if (service == null)
{
_logger.LogWarning("User tries to update activity group, but service not found");
return ApiResponse<object>.ErrorResponse("Invalid service ID", "Please provide valid service ID to update activity group", 400);
}
// Step 3: Retrieve existing activity group
var activityGroup = await _context.ActivityGroupMasters
.Include(ag => ag.ServicesMaster)
.FirstOrDefaultAsync(ag => ag.Id == id && ag.TenantId == tenantId && ag.IsActive);
if (activityGroup == null)
{
_logger.LogWarning("Activity group not found. Id: {Id}, TenantId: {TenantId}", id, tenantId);
return ApiResponse<object>.ErrorResponse("Activity group not found", "No such activity group exists", 404);
}
// Step 4: Update and save
activityGroup.Name = activityGroupDto.Name.Trim();
activityGroup.Description = activityGroupDto.Description.Trim();
await _context.SaveChangesAsync();
var response = activityGroup.ToActivityGroupMasterVMFromActivityGroupMaster(service.Name ?? "");
_logger.LogInfo("Activity group updated successfully. Id: {Id}, TenantId: {TenantId}", activityGroup.Id, tenantId);
return ApiResponse<object>.SuccessResponse(response, "Activity group updated successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while updating activity group Id: {Id}", id);
return ApiResponse<object>.ErrorResponse("An error occurred while updating the activity group", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> DeleteActivityGroup(Guid id, bool isActive)
{
_logger.LogInfo("DeleteActivityGroup called with ActivityGroupId: {ActivityGroupId}, IsActive: {IsActive}", id, isActive);
try
{
// Step 1: Permission check
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to delete activity groups", 403);
}
// Step 2: Fetch the activity group
var activityGroup = await _context.ActivityGroupMasters
.FirstOrDefaultAsync(ag => ag.Id == id && ag.TenantId == tenantId);
if (activityGroup == null)
{
_logger.LogWarning("ActivityGroup not found. Id: {ActivityGroupId}", id);
return ApiResponse<object>.ErrorResponse("Activity group not found", "Activity group not found or already deleted", 404);
}
//Protect system-defined activity group
if (activityGroup.IsSystem)
{
_logger.LogWarning("Attempt to delete system-defined activity group. Id: {ActivityGroupId}", id);
return ApiResponse<object>.ErrorResponse("Cannot delete system-defined activity group", "This activity group is system-defined and cannot be deleted", 400);
}
// Step 3: Perform soft delete or restore
activityGroup.IsActive = isActive;
await _context.SaveChangesAsync();
var status = isActive ? "restored" : "deactivated";
_logger.LogInfo("ActivityGroup {ActivityGroupId} has been {Status} by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(new { }, $"Activity group {status} successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occurred while deleting ActivityGroup {ActivityGroupId}", id);
return ApiResponse<object>.ErrorResponse("Error deleting activity group", ex.Message, 500);
}
}
#endregion
#region =================================================================== Activity APIs ===================================================================
public async Task<ApiResponse<object>> GetActivitiesMaster()
{
_logger.LogInfo("GetActivitiesMaster called");
try
{
// Step 1: Fetch all active activities for the tenant
var activities = await _context.ActivityMasters
.Include(c => c.ServicesMaster)
.Include(c => c.ActivityGroupMaster)
.Where(c => c.TenantId == tenantId && c.IsActive)
.ToListAsync();
if (activities.Count == 0)
{
_logger.LogWarning("No active activities found for tenantId: {TenantId}", tenantId);
return ApiResponse<object>.SuccessResponse(new List<ActivityVM>(), "No activity records found", 200);
}
// Step 2: Fetch all checklists for those activities in a single query to avoid N+1
var activityIds = activities.Select(a => a.Id).ToList();
var checkLists = await _context.ActivityCheckLists
.Where(c => c.TenantId == tenantId && activityIds.Contains(c.ActivityId))
.ToListAsync();
// Step 3: Group checklists by activity
var groupedChecklists = checkLists
.GroupBy(c => c.ActivityId)
.ToDictionary(g => g.Key, g => g.ToList());
// Step 4: Map to ViewModel
var activityVMs = activities.Select(activity =>
{
var checklistForActivity = groupedChecklists.ContainsKey(activity.Id)
? groupedChecklists[activity.Id]
: new List<ActivityCheckList>();
var checklistVMs = checklistForActivity
.Select(cl => cl.ToCheckListVMFromActivityCheckList(activity.Id, false))
.ToList();
return activity.ToActivityVMFromActivityMaster(checklistVMs, activity.ServicesMaster?.Name, activity.ActivityGroupMaster?.Name);
}).ToList();
_logger.LogInfo("{Count} activity records fetched successfully for tenantId: {TenantId}", activityVMs.Count, tenantId);
return ApiResponse<object>.SuccessResponse(activityVMs, $"{activityVMs.Count} activity records fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred in GetActivitiesMaster");
return ApiResponse<object>.ErrorResponse("Failed to fetch activity records", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> CreateActivity(CreateActivityMasterDto createActivity)
{
_logger.LogInfo("CreateActivity called with ActivityName: {Name}", createActivity?.ActivityName ?? "null");
try
{
// Step 1: Validate input
if (createActivity == null)
{
_logger.LogWarning("Null request body received in CreateActivity");
return ApiResponse<object>.ErrorResponse("Invalid input", "Activity data is required", 400);
}
var activityGroup = await _context.ActivityGroupMasters
.Include(ag => ag.ServicesMaster)
.FirstOrDefaultAsync(ag => ag.Id == createActivity.ActitvityGroupId && ag.ServiceId == createActivity.ServiceId);
if (activityGroup == null)
{
_logger.LogWarning("User tried to create new activity, but not found activity group");
return ApiResponse<object>.ErrorResponse("Invalid input", "Activity data is required", 400);
}
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permissions
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to perform this action", 403);
}
// Step 3: Convert DTO to entity and add activity
var activityMaster = createActivity.ToActivityMasterFromCreateActivityMasterDto(tenantId);
_context.ActivityMasters.Add(activityMaster);
await _context.SaveChangesAsync();
List<CheckListVM> checkListVMs = new();
// Step 4: Handle checklist items if present
if (createActivity.CheckList?.Any() == true)
{
var activityCheckLists = createActivity.CheckList
.Select(c => c.ToActivityCheckListFromCreateCheckListDto(tenantId, activityMaster.Id))
.ToList();
_context.ActivityCheckLists.AddRange(activityCheckLists);
await _context.SaveChangesAsync();
checkListVMs = activityCheckLists
.Select(c => c.ToCheckListVMFromActivityCheckList(activityMaster.Id, false))
.ToList();
}
// Step 5: Prepare final response
var activityVM = activityMaster.ToActivityVMFromActivityMaster(checkListVMs, activityGroup.ServicesMaster?.Name, activityGroup.Name);
_logger.LogInfo("Activity '{Name}' created successfully for tenant {TenantId}", activityMaster.ActivityName, tenantId);
return ApiResponse<object>.SuccessResponse(activityVM, "Activity created successfully", 201);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating activity");
return ApiResponse<object>.ErrorResponse("An error occurred while creating activity", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> UpdateActivity(Guid id, CreateActivityMasterDto createActivity)
{
_logger.LogInfo("UpdateActivity called for ActivityId: {ActivityId}", id);
try
{
// Step 1: Validate input
if (createActivity == null || string.IsNullOrWhiteSpace(createActivity.ActivityName) || string.IsNullOrWhiteSpace(createActivity.UnitOfMeasurement))
{
_logger.LogWarning("Invalid activity update input for ActivityId: {ActivityId}", id);
return ApiResponse<object>.ErrorResponse("Invalid input", "ActivityName and UnitOfMeasurement are required", 400);
}
// Step 2: Check permissions
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to update activities", 403);
}
// Step 3: Validate service, activity group, and activity existence
var activityGroup = await _context.ActivityGroupMasters.Include(ag => ag.ServicesMaster).FirstOrDefaultAsync(ag => ag.Id == createActivity.ActitvityGroupId && ag.IsActive);
if (activityGroup == null || activityGroup.ServiceId != createActivity.ServiceId)
{
_logger.LogWarning("User tries to update activity, but cannot able found activity group or service");
return ApiResponse<object>.ErrorResponse("Invalid activity group ID or service ID", "Please provide valid activity group ID or service ID to update activity group", 400);
}
var activity = await _context.ActivityMasters
.Include(a => a.ServicesMaster)
.Include(a => a.ActivityGroupMaster)
.FirstOrDefaultAsync(a => a.Id == id && a.IsActive && a.TenantId == tenantId);
if (activity == null)
{
_logger.LogWarning("Activity not found for ActivityId: {ActivityId}, TenantId: {TenantId}", id, tenantId);
return ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404);
}
// Step 4: Update activity core data
activity.ActivityName = createActivity.ActivityName.Trim();
activity.UnitOfMeasurement = createActivity.UnitOfMeasurement.Trim();
if (activity.ServiceId == null)
{
activity.ServiceId = createActivity.ServiceId;
}
activity.ActitvityGroupId = createActivity.ActitvityGroupId;
await _context.SaveChangesAsync();
// Step 5: Handle checklist updates
var existingChecklists = await _context.ActivityCheckLists
.AsNoTracking()
.Where(c => c.ActivityId == activity.Id)
.ToListAsync();
var updatedChecklistVMs = new List<CheckListVM>();
if (createActivity.CheckList != null && createActivity.CheckList.Any())
{
var incomingCheckIds = createActivity.CheckList.Where(c => c.Id != null).Select(c => c.Id!.Value).ToHashSet();
// Prepare lists
var newChecks = createActivity.CheckList.Where(c => c.Id == null);
var updates = createActivity.CheckList.Where(c => c.Id != null && existingChecklists.Any(ec => ec.Id == c.Id));
var deletes = existingChecklists.Where(ec => !incomingCheckIds.Contains(ec.Id)).ToList();
var toAdd = newChecks
.Select(c => c.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id))
.ToList();
var toUpdate = updates
.Select(c => c.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id))
.ToList();
_context.ActivityCheckLists.AddRange(toAdd);
_context.ActivityCheckLists.UpdateRange(toUpdate);
_context.ActivityCheckLists.RemoveRange(deletes);
await _context.SaveChangesAsync();
// Prepare view model
updatedChecklistVMs = toAdd.Concat(toUpdate)
.Select(c => c.ToCheckListVMFromActivityCheckList(activity.Id, false))
.ToList();
}
else if (existingChecklists.Any())
{
// If no checklist provided, remove all existing
_context.ActivityCheckLists.RemoveRange(existingChecklists);
await _context.SaveChangesAsync();
}
// Step 6: Prepare response
var activityVM = activity.ToActivityVMFromActivityMaster(updatedChecklistVMs, activityGroup.ServicesMaster?.Name, activityGroup.Name);
_logger.LogInfo("Activity updated successfully. ActivityId: {ActivityId}, TenantId: {TenantId}", activity.Id, tenantId);
return ApiResponse<object>.SuccessResponse(activityVM, "Activity updated successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception in UpdateActivity");
return ApiResponse<object>.ErrorResponse("Error updating activity", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> DeleteActivity(Guid id, bool isActive)
{
_logger.LogInfo("DeleteActivity called with ActivityId: {ActivityId}, IsActive: {IsActive}", id, isActive);
try
{
// Step 1: Validate permission
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to delete activities", 403);
}
// Step 2: Fetch the activity
var activity = await _context.ActivityMasters
.FirstOrDefaultAsync(a => a.Id == id && a.TenantId == tenantId);
if (activity == null)
{
_logger.LogWarning("Activity not found. ActivityId: {ActivityId}", id);
return ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found or already deleted", 404);
}
// Step 3: Perform soft delete/restore
activity.IsActive = isActive;
await _context.SaveChangesAsync();
string status = isActive ? "restored" : "deactivated";
_logger.LogInfo("Activity {ActivityId} {Status} successfully by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(new { }, $"Activity {status} successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error while deleting activity {ActivityId}", id);
return ApiResponse<object>.ErrorResponse("Error deleting activity", ex.Message, 500);
}
}
#endregion
#region =================================================================== Contact Category APIs ===================================================================
public async Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
@ -258,7 +907,7 @@ namespace Marco.Pms.Services.Helpers
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permission to view master data
bool hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id);
bool hasViewPermission = await _permissionService.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id);
if (!hasViewPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
@ -302,7 +951,7 @@ namespace Marco.Pms.Services.Helpers
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);
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
@ -357,7 +1006,7 @@ namespace Marco.Pms.Services.Helpers
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 3: Check permissions
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id);
@ -409,7 +1058,7 @@ namespace Marco.Pms.Services.Helpers
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// Step 2: Check permission to manage master data
var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManageMasterPermission)
{
_logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);