diff --git a/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs b/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs index 7601e60..d9a5653 100644 --- a/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs +++ b/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs @@ -1,11 +1,11 @@ -using System.Globalization; -using Marco.Pms.Model.Activities; +using Marco.Pms.Model.Activities; using Marco.Pms.Model.AttendanceModule; using Marco.Pms.Model.Authentication; using Marco.Pms.Model.Directory; using Marco.Pms.Model.DocumentManager; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; +using Marco.Pms.Model.Expenses; using Marco.Pms.Model.Forum; using Marco.Pms.Model.Mail; using Marco.Pms.Model.Master; @@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using System.Globalization; namespace Marco.Pms.DataAccess.Data { @@ -52,6 +53,7 @@ namespace Marco.Pms.DataAccess.Data public DbSet Modules { get; set; } public DbSet Features { get; set; } public DbSet FeaturePermissions { get; set; } + public DbSet CurrencyMaster { get; set; } public DbSet ApplicationRoles { get; set; } public DbSet JobRoles { get; set; } public DbSet RolePermissionMappings { get; set; } @@ -89,6 +91,17 @@ namespace Marco.Pms.DataAccess.Data public DbSet OTPDetails { get; set; } public DbSet MPINDetails { get; set; } + public DbSet Expenses { get; set; } + public DbSet ExpenseLogs { get; set; } + public DbSet ExpensesTypeMaster { get; set; } + public DbSet PaymentModeMatser { get; set; } + public DbSet ExpensesStatusMaster { get; set; } + public DbSet BillAttachments { get; set; } + public DbSet ExpensesReimburse { get; set; } + public DbSet ExpensesReimburseMapping { get; set; } + public DbSet StatusPermissionMapping { get; set; } + public DbSet ExpensesStatusMapping { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -97,49 +110,6 @@ namespace Marco.Pms.DataAccess.Data ManageApplicationStructure(modelBuilder); - //modelBuilder.Entity().HasData( - // new ApplicationRole - // { - // Id = new Guid("2c8d0808-c421-11ef-9b93-0242ac110002"), - // Role = "Super User", - // Description = "Super User", - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, - // new ApplicationRole - // { - // Id = new Guid("62e0918d-c421-11ef-9b93-0242ac110002"), - // Role = "Welder", - // Description = "", - - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, - // new ApplicationRole - // { - // Id = new Guid("68823f1f-c421-11ef-9b93-0242ac110002"), - // Role = "Helper", - // Description = "", - - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, - // new ApplicationRole - // { - // Id = new Guid("6d3a7c72-c421-11ef-9b93-0242ac110002"), - // Role = "Site Engineer", - // Description = "", - - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // } - // , - // new ApplicationRole - // { - // Id = new Guid("6d3aad72-c421-11ef-9b93-0242ac110002"), - // Role = "Project Manager", - // Description = "", - - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // } - // ); - modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); @@ -196,79 +166,11 @@ namespace Marco.Pms.DataAccess.Data ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") } - //, new Project - //{ - // Id = new Guid("3ef56a12-f5e5-4193-87d6-9e110ed10b86"), - // Name = "Project 2", - // ProjectAddress = "Project 2 Address", - // ContactPerson = "Project 2 Contact Person", - // StartDate = DateTime.ParseExact("2025-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture), - // EndDate = DateTime.ParseExact("2026-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture), - // ProjectStatusId = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - //}, new Project - //{ - // Id = new Guid("54d013e3-0a2b-48be-85c7-5ef03492a18c"), - // Name = "Project 3", - // ProjectAddress = "Project 3 Address", - // ContactPerson = "Project 3 Contact Person", - // StartDate = DateTime.ParseExact("2025-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture), - // EndDate = DateTime.ParseExact("2026-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture), - // ProjectStatusId = new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - //} ); var tenantId = _httpContextAccessor.HttpContext?.Items["TenantId"]?.ToString(); - //modelBuilder.Entity() - // .HasData( - // new ActivityMaster - // { - // Id = new Guid("4117b7de-ef6c-461f-a2c2-64eaac5f9a11"), - // ActivityName = "Core Cutting", - // UnitOfMeasurement = UnitOfMeasurement.Number.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, new ActivityMaster - // { - // Id = new Guid("1714f64d-7591-4419-bee5-118d21bb2855"), - // ActivityName = "Fabrication", - // UnitOfMeasurement = UnitOfMeasurement.Meter.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, new ActivityMaster - // { - // Id = new Guid("b3f51a93-dde6-45f9-8b22-f1bf017a640b"), - // ActivityName = "Welding", - // UnitOfMeasurement = UnitOfMeasurement.Meter.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, new ActivityMaster - // { - // Id = new Guid("53eedf44-4076-445f-be93-fedef17117e7"), - // ActivityName = "MS Support Fabrication", - // UnitOfMeasurement = UnitOfMeasurement.Number.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, new ActivityMaster - // { - // Id = new Guid("715b9ddb-d9e2-4afa-8987-d9918905cea4"), - // ActivityName = "MS Support Hanging", - // UnitOfMeasurement = UnitOfMeasurement.Number.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, new ActivityMaster - // { - // Id = new Guid("a3d191a7-a5aa-4dd8-a525-12c99263bbd6"), - // ActivityName = "Hydrant Volve", - // UnitOfMeasurement = UnitOfMeasurement.Number.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // }, new ActivityMaster - // { - // Id = new Guid("c138a7de-713a-4bd4-8292-b0b265be77a3"), - // ActivityName = "Sprinkler Installation", - // UnitOfMeasurement = UnitOfMeasurement.Number.ToString(), - // TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - // } - // ); - modelBuilder.Entity().HasData( new Industry { Id = Guid.Parse("15436ee3-a650-469e-bfc2-59993f7514bb"), Name = "Information Technology (IT) Services" }, new Industry { Id = Guid.Parse("0a63e657-2c5f-49b5-854b-42c978293154"), Name = "Manufacturing & Production" }, @@ -314,7 +216,7 @@ namespace Marco.Pms.DataAccess.Data Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), Name = "In Review", Description = "These issues are currently under review", - ColorCode = "#6c757d", + ColorCode = "#8592a3", IsDefault = true, TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") }, @@ -487,6 +389,298 @@ namespace Marco.Pms.DataAccess.Data + modelBuilder.Entity().HasData( + new ExpensesStatusMaster + { + Id = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8"), + Name = "Draft", + DisplayName = "Draft", + Description = "Expense has been created but not yet submitted.", + Color = "#8592a3", + IsSystem = true, + IsActive = true + }, + new ExpensesStatusMaster + { + Id = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + Name = "Review Pending", + DisplayName = "Submit", + Description = "Reviewer is currently reviewing the expense.", + Color = "#696cff", + IsSystem = true, + IsActive = true + }, + new ExpensesStatusMaster + { + Id = Guid.Parse("965eda62-7907-4963-b4a1-657fb0b2724b"), + Name = "Rejected by Reviewer", + DisplayName = "Reject", + Description = "Expense was declined, often with a reason(review rejected).", + Color = "#ff3e1d", + IsSystem = true, + IsActive = true + }, + new ExpensesStatusMaster + { + Id = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + Name = "Approval Pending", + DisplayName = "Mark as Reviewed", + Description = "Review is completed, waiting for action of approver.", + Color = "#03c3ec", + IsSystem = true, + IsActive = true + }, + new ExpensesStatusMaster + { + Id = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729"), + Name = "Rejected by Approver", + DisplayName = "Reject", + Description = "Expense was declined, often with a reason(approval rejected).", + Color = "#ff3e1d", + IsSystem = true, + IsActive = true + }, + new ExpensesStatusMaster + { + Id = Guid.Parse("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + Name = "Payment Pending", + DisplayName = "Mark as Approved", + Description = "Approved expense is awaiting final payment.", + Color = "#ffab00", + IsSystem = true, + IsActive = true + }, + new ExpensesStatusMaster + { + Id = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95"), + Name = "Processed", + DisplayName = "Mark as Processed", + Description = "Expense has been settled.", + Color = "#71dd37", + IsSystem = true, + IsActive = true + } + ); + + modelBuilder.Entity().HasData( + // Process to processed + new ExpensesStatusMapping + { + Id = Guid.Parse("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + StatusId = Guid.Parse("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + NextStatusId = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95") + }, + // Rejected by Approver to Review + new ExpensesStatusMapping + { + Id = Guid.Parse("4ddddc10-0ffd-4884-accf-d4fa0bd97f54"), + StatusId = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729"), + NextStatusId = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + // Approve to Rejected by Approver + new ExpensesStatusMapping + { + Id = Guid.Parse("36c00548-241c-43ec-bc95-cacebedb925c"), + StatusId = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + NextStatusId = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + // Approve to Process + new ExpensesStatusMapping + { + Id = Guid.Parse("1fca1700-1266-477d-bba4-9ac3753aa33c"), + StatusId = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + NextStatusId = Guid.Parse("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + // Rejected by Reviewer to Review + new ExpensesStatusMapping + { + Id = Guid.Parse("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + StatusId = Guid.Parse("965eda62-7907-4963-b4a1-657fb0b2724b"), + NextStatusId = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + // Review to Rejected by Reviewer + new ExpensesStatusMapping + { + Id = Guid.Parse("6b867bec-66e6-42a7-9611-f4595af9b9ce"), + StatusId = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + NextStatusId = Guid.Parse("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + // Review to Aprrove + new ExpensesStatusMapping + { + Id = Guid.Parse("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + StatusId = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + NextStatusId = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + // Draft to Review + new ExpensesStatusMapping + { + Id = Guid.Parse("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + StatusId = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8"), + NextStatusId = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + } + ); + + modelBuilder.Entity().HasData( + // Draft Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b"), + PermissionId = Guid.Parse("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8") + }, + // Review Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d"), + PermissionId = Guid.Parse("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + // Rejected by Reviewer Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + PermissionId = Guid.Parse("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = Guid.Parse("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + // Approval Pending Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa"), + PermissionId = Guid.Parse("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + // Rejected by Approver Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + PermissionId = Guid.Parse("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + // Payment Pending Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + PermissionId = Guid.Parse("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = Guid.Parse("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + // Processed Permission Mapping + new StatusPermissionMapping + { + Id = Guid.Parse("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + PermissionId = Guid.Parse("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + StatusId = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95") + }); + + modelBuilder.Entity().HasData( + new ExpensesTypeMaster + { + Id = Guid.Parse("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), + Name = "Procurement", + Description = "Materials, equipment and supplies purchased for site operations.", + NoOfPersonsRequired = false, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("2de53163-0dbd-404b-8e60-1b02e6b4886a"), + Name = "Transport", + Description = "Vehicle fuel, logistics services and delivery of goods or personnel.", + NoOfPersonsRequired = false, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), + Name = "Travelling", + Description = "Delivery of personnel.", + NoOfPersonsRequired = true, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("52484820-1b54-4865-8f0f-baa2b1d339b9"), + Name = "Mobilization", + Description = "Site setup costs including equipment deployment and temporary infrastructure.", + NoOfPersonsRequired = false, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), + Name = "Employee Welfare", + Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", + NoOfPersonsRequired = true, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("77013784-9324-4d8b-bd36-d6f928e68942"), + Name = "Maintenance & Utilities", + Description = "Machinery servicing, electricity, water, and temporary office needs.", + NoOfPersonsRequired = false, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("1e2d697a-76b4-4be8-bc66-87144561a1a0"), + Name = "Vendor/Supplier Payments", + Description = "Scheduled payments for external services or goods.", + NoOfPersonsRequired = false, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new ExpensesTypeMaster + { + Id = Guid.Parse("4842fa61-64eb-4241-aebd-8282065af9f9"), + Name = "Compliance & Safety", + Description = "Government fees, insurance, inspections and safety-related expenditures.", + NoOfPersonsRequired = false, + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + } + ); + + modelBuilder.Entity().HasData( + new PaymentModeMatser + { + Id = Guid.Parse("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), + Name = "Cash", + Description = "Physical currency; still used for small or informal transactions.", + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new PaymentModeMatser + { + Id = Guid.Parse("48d9b462-5d87-4dec-8dec-2bc943943172"), + Name = "Cheque", + Description = "Paper-based payment order; less common now due to processing delays and fraud risks.", + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new PaymentModeMatser + { + Id = Guid.Parse("ed667353-8eea-4fd1-8750-719405932480"), + Name = "NetBanking", + Description = "Online banking portals used to transfer funds directly between accounts", + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new PaymentModeMatser + { + Id = Guid.Parse("2e919e94-694c-41d9-9489-0a2b4208a027"), + Name = "UPI", + Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", + IsActive = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + } + ); modelBuilder.Entity().HasData(new Module { @@ -508,55 +702,124 @@ namespace Marco.Pms.DataAccess.Data Key = "504ec132-e6a9-422f-8f85-050602cfce05" }); - - modelBuilder.Entity().HasData( + // Project Module new Feature { Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), Description = "Manage Project", Name = "Project Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, - //new Feature { Id = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), Description = "Manage Infra", Name = "Manage Infra", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, + new Feature { Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", Name = "Expense Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, new Feature { Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", Name = "Task Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true }, + // Employee Module new Feature { Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), Description = "Manage Employee", Name = "Employee Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true }, new Feature { Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), Description = "Attendance", Name = "Attendance Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true }, - new Feature { Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), Description = "Global Masters", Name = "Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true }, + // Master Module + new Feature { Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), Description = "Global Masters", Name = "Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true }, new Feature { Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), Description = "Managing all directory related rights", Name = "Directory Management", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true } - - //new Feature { Id = new Guid("660131a4-788c-4739-a082-cbbf7879cbf2"), Description = "Tenant Masters", Name = "Tenant Masters", ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), IsActive = true } ); modelBuilder.Entity().HasData( + // Project Management Feature new FeaturePermission { Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project", Description = "Access all information related to the project." }, - new FeaturePermission { Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project", Description = "Potentially edit the project name, description, start/end dates, or status." }, - new FeaturePermission { Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Team", Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects." }, - new FeaturePermission { Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project Infra", Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations" }, - new FeaturePermission { Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project Infra", Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure." }, + new FeaturePermission { Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project", Description = "Potentially edit the project name, description, start/end dates, or status." }, + new FeaturePermission { Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Team", Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects." }, + new FeaturePermission { Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project Infra", Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations" }, + new FeaturePermission { Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project Infra", Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure." }, + // Task Management Feature + new FeaturePermission { Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "View Task", Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions." }, + new FeaturePermission { Id = new Guid("08752f33-3b29-4816-b76b-ea8a968ed3c5"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Add/Edit Task", Description = "This allows them to create new tasks, modify existing task attributes (description, status, assignee, due date, etc.)," }, + new FeaturePermission { Id = new Guid("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Assign/Report Progress", Description = "Grants a user the ability to designate team members responsible for specific tasks and to update the completion status or provide progress updates for those tasks" }, + new FeaturePermission { Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Approve Task", Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria" }, - new FeaturePermission { Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "View Task", Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions." }, - new FeaturePermission { Id = new Guid("08752f33-3b29-4816-b76b-ea8a968ed3c5"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Add/Edit Task", Description = "This allows them to create new tasks, modify existing task attributes (description, status, assignee, due date, etc.)," }, - new FeaturePermission { Id = new Guid("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Assign/Report Progress", Description = "Grants a user the ability to designate team members responsible for specific tasks and to update the completion status or provide progress updates for those tasks" }, - new FeaturePermission { Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), IsEnabled = true, Name = "Approve Task", Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria" }, + // Employee Management Feature + new FeaturePermission { Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View All Employees", Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" }, + new FeaturePermission { Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View Team Members", Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" }, + new FeaturePermission { Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Add/Edit Employee", Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data" }, + new FeaturePermission { Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Assign Roles", Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system." }, + // Attendance Management Feature + new FeaturePermission { Id = new Guid("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e"), FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), IsEnabled = true, Name = "Team Attendance ", Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager." }, + new FeaturePermission { Id = new Guid("57802c4a-00aa-4a1f-a048-fd2f70dd44b6"), FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), IsEnabled = true, Name = "Regularize Attendance", Description = "Grants a user the authority to approve requests from employees to adjust or correct their recorded attendance. This typically involves reviewing the reason for the regularization, verifying any supporting documentation, and then officially accepting the changes to the employee's attendance records" }, + new FeaturePermission { Id = new Guid("ccb0589f-712b-43de-92ed-5b6088e7dc4e"), FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), IsEnabled = true, Name = "Self Attendance", Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager." }, - new FeaturePermission { Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View All Employees", Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" }, - new FeaturePermission { Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "View Team Members", Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data" }, - new FeaturePermission { Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Add/Edit Employee", Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data" }, - new FeaturePermission { Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), IsEnabled = true, Name = "Assign Roles", Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system." }, + // Masters Feature + new FeaturePermission { Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "View Masters", Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency" }, + new FeaturePermission { Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "Manage Masters", Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories" }, + // Directory Management Feature + new FeaturePermission { Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Admin", Description = "Full control over all directories, including the ability to manage permissions for all directories in the system." }, + new FeaturePermission { Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Manager", Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories." }, + new FeaturePermission { Id = new Guid("0f919170-92d4-4337-abd3-49b66fc871bb"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory User", Description = "Full control over directories they created. Can view contacts in directories they either created or were assigned to. Can manage permissions only for directories they created." }, - new FeaturePermission { Id = new Guid("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e"), FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), IsEnabled = true, Name = "Team Attendance ", Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager." }, - new FeaturePermission { Id = new Guid("57802c4a-00aa-4a1f-a048-fd2f70dd44b6"), FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), IsEnabled = true, Name = "Regularize Attendance", Description = "Grants a user the authority to approve requests from employees to adjust or correct their recorded attendance. This typically involves reviewing the reason for the regularization, verifying any supporting documentation, and then officially accepting the changes to the employee's attendance records" }, - new FeaturePermission { Id = new Guid("ccb0589f-712b-43de-92ed-5b6088e7dc4e"), FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), IsEnabled = true, Name = "Self Attendance", Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager." }, - - new FeaturePermission { Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "View Masters", Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency" }, - new FeaturePermission { Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), IsEnabled = true, Name = "Manage Masters", Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories" }, - - new FeaturePermission { Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Admin", Description = "Full control over all directories, including the ability to manage permissions for all directories in the system." }, - new FeaturePermission { Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory Manager", Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories." }, - new FeaturePermission { Id = new Guid("0f919170-92d4-4337-abd3-49b66fc871bb"), FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory User", Description = "Full control over directories they created. Can view contacts in directories they either created or were assigned to. Can manage permissions only for directories they created." } - //new FeaturePermission { Id = new Guid("6b1a6d97-a951-4de5-9b19-709bac7c4f18"), FeatureId = new Guid("660131a4-788c-4739-a082-cbbf7879cbf2"), IsEnabled = true, Name = "Manage Masters", Description = "" } + // Expense Management Feature + new FeaturePermission { Id = new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "View Self", Description = "Allows a user to view only the expense records that they have personally submitted" }, + new FeaturePermission { Id = new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "View All", Description = "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them" }, + new FeaturePermission { Id = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Upload", Description = "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices." }, + new FeaturePermission { Id = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Review", Description = "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected." }, + new FeaturePermission { Id = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Approve", Description = "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system." }, + new FeaturePermission { Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Process", Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled." }, + new FeaturePermission { Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Manage", Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules." } ); + + modelBuilder.Entity().HasData( + new CurrencyMaster + { + Id = Guid.Parse("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"), + CurrencyCode = "INR", + CurrencyName = "Indian Rupee", + Symbol = "₹", + IsActive = true + }, + new CurrencyMaster + { + Id = Guid.Parse("2f672568-a67b-4961-acb2-a8c7834e1762"), + CurrencyCode = "USD", + CurrencyName = "US Dollar", + Symbol = "$", + IsActive = true + }, + new CurrencyMaster + { + Id = Guid.Parse("4d1155bb-1448-4d97-a732-96c92eb99c45"), + CurrencyCode = "EUR", + CurrencyName = "Euro", + Symbol = "€", + IsActive = true + }, + new CurrencyMaster + { + Id = Guid.Parse("3e456237-ef06-4ea1-a261-188c9b0c6df6"), + CurrencyCode = "GBP", + CurrencyName = "Pound Sterling", + Symbol = "£", + IsActive = true + }, + new CurrencyMaster + { + Id = Guid.Parse("297e237a-56d3-48f6-b39d-ec3991dea8bf"), + CurrencyCode = "JPY", + CurrencyName = "Japanese Yen", + Symbol = "¥", + IsActive = true + }, + new CurrencyMaster + { + Id = Guid.Parse("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"), + CurrencyCode = "RUB", + CurrencyName = "Russian Ruble", + Symbol = "₽", + IsActive = true + }, + new CurrencyMaster + { + Id = Guid.Parse("b960166a-f7e9-49e3-bb4b-28511f126c08"), + CurrencyCode = "CNY", + CurrencyName = "Chinese Yuan (Renminbi)", + Symbol = "¥", + IsActive = true + } + ); } } } diff --git a/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.Designer.cs index fcb6e0b..331a01e 100644 --- a/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.Designer.cs @@ -1274,7 +1274,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.cs b/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.cs index eb6b5d3..63c4e45 100644 --- a/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.cs +++ b/Marco.Pms.DataAccess/Migrations/20250501162003_Initmigration.cs @@ -1295,7 +1295,7 @@ namespace Marco.Pms.DataAccess.Migrations columns: new[] { "Id", "ColorCode", "Description", "IsDefault", "Name", "TenantId" }, values: new object[,] { - { new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), "#6c757d", "These issues are currently under review", true, "In Review", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), "#8592a3", "These issues are currently under review", true, "In Review", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, { new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"), "#FFCC99", "This is a newly created issue.", true, "New", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, { new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"), "#E6FF99", "Assigned to employee or team of employees", true, "Assigned", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, { new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"), "#99E6FF", "These issues are currently in progress", true, "In Progress", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, diff --git a/Marco.Pms.DataAccess/Migrations/20250505121140_Changed_DataType_ApproverdBY.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250505121140_Changed_DataType_ApproverdBY.Designer.cs index 4ce716b..4f4da8c 100644 --- a/Marco.Pms.DataAccess/Migrations/20250505121140_Changed_DataType_ApproverdBY.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250505121140_Changed_DataType_ApproverdBY.Designer.cs @@ -1216,7 +1216,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250508055854_Added_IsSystem_Flag.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250508055854_Added_IsSystem_Flag.Designer.cs index a43da65..ca6478a 100644 --- a/Marco.Pms.DataAccess/Migrations/20250508055854_Added_IsSystem_Flag.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250508055854_Added_IsSystem_Flag.Designer.cs @@ -1222,7 +1222,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250510074238_Added_WorkCategory_Master_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250510074238_Added_WorkCategory_Master_Table.Designer.cs index 5a16b4c..69834c6 100644 --- a/Marco.Pms.DataAccess/Migrations/20250510074238_Added_WorkCategory_Master_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250510074238_Added_WorkCategory_Master_Table.Designer.cs @@ -1299,7 +1299,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250511170748_Added_Foreign_key_For_WorkCategery_To_WorkItem.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250511170748_Added_Foreign_key_For_WorkCategery_To_WorkItem.Designer.cs index 748eb32..0348ebc 100644 --- a/Marco.Pms.DataAccess/Migrations/20250511170748_Added_Foreign_key_For_WorkCategery_To_WorkItem.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250511170748_Added_Foreign_key_For_WorkCategery_To_WorkItem.Designer.cs @@ -1299,7 +1299,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250513125713_Changed_Freture_Permissions.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250513125713_Changed_Freture_Permissions.Designer.cs index baf9d7f..8db96d1 100644 --- a/Marco.Pms.DataAccess/Migrations/20250513125713_Changed_Freture_Permissions.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250513125713_Changed_Freture_Permissions.Designer.cs @@ -1267,7 +1267,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250514103249_Added_Directory_Related_Tables.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250514103249_Added_Directory_Related_Tables.Designer.cs index aad7361..b873cd3 100644 --- a/Marco.Pms.DataAccess/Migrations/20250514103249_Added_Directory_Related_Tables.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250514103249_Added_Directory_Related_Tables.Designer.cs @@ -1602,7 +1602,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250517063809_Added_ContactProjectMapping_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250517063809_Added_ContactProjectMapping_Table.Designer.cs index 492cf00..0040f43 100644 --- a/Marco.Pms.DataAccess/Migrations/20250517063809_Added_ContactProjectMapping_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250517063809_Added_ContactProjectMapping_Table.Designer.cs @@ -1626,7 +1626,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250519053019_Fixed_Typo_Of_ColumnName.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250519053019_Fixed_Typo_Of_ColumnName.Designer.cs index 39fe4c3..96a4717 100644 --- a/Marco.Pms.DataAccess/Migrations/20250519053019_Fixed_Typo_Of_ColumnName.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250519053019_Fixed_Typo_Of_ColumnName.Designer.cs @@ -1593,7 +1593,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250524074333_Added_Feature_Directory_Management.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250524074333_Added_Feature_Directory_Management.Designer.cs index 6e2f931..39f365c 100644 --- a/Marco.Pms.DataAccess/Migrations/20250524074333_Added_Feature_Directory_Management.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250524074333_Added_Feature_Directory_Management.Designer.cs @@ -1633,7 +1633,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250530055939_Added_Mail_Related_Tables.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250530055939_Added_Mail_Related_Tables.Designer.cs index 09c4047..64dfc97 100644 --- a/Marco.Pms.DataAccess/Migrations/20250530055939_Added_Mail_Related_Tables.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250530055939_Added_Mail_Related_Tables.Designer.cs @@ -1358,7 +1358,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250604094759_Added_Self_Attendance_Feature_Permission.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250604094759_Added_Self_Attendance_Feature_Permission.Designer.cs index c80bbc1..fb39591 100644 --- a/Marco.Pms.DataAccess/Migrations/20250604094759_Added_Self_Attendance_Feature_Permission.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250604094759_Added_Self_Attendance_Feature_Permission.Designer.cs @@ -1366,7 +1366,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250605102139_Added_OTP_And_MPIN_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250605102139_Added_OTP_And_MPIN_Table.Designer.cs index 242339f..1269342 100644 --- a/Marco.Pms.DataAccess/Migrations/20250605102139_Added_OTP_And_MPIN_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250605102139_Added_OTP_And_MPIN_Table.Designer.cs @@ -1425,7 +1425,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250606095355_Added_Subject_In_MailingList_And_Removed_From_MailDetails.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250606095355_Added_Subject_In_MailingList_And_Removed_From_MailDetails.Designer.cs index bdf0ba4..53e758a 100644 --- a/Marco.Pms.DataAccess/Migrations/20250606095355_Added_Subject_In_MailingList_And_Removed_From_MailDetails.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250606095355_Added_Subject_In_MailingList_And_Removed_From_MailDetails.Designer.cs @@ -1425,7 +1425,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250607061133_Added_IsUsed_FLag_In_OTPDetails_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250607061133_Added_IsUsed_FLag_In_OTPDetails_Table.Designer.cs index fe82feb..7b5acc1 100644 --- a/Marco.Pms.DataAccess/Migrations/20250607061133_Added_IsUsed_FLag_In_OTPDetails_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250607061133_Added_IsUsed_FLag_In_OTPDetails_Table.Designer.cs @@ -1428,7 +1428,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250610051758_Added_Short_Name_Column_In_Projects_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250610051758_Added_Short_Name_Column_In_Projects_Table.Designer.cs index c50d6d8..63cdcab 100644 --- a/Marco.Pms.DataAccess/Migrations/20250610051758_Added_Short_Name_Column_In_Projects_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250610051758_Added_Short_Name_Column_In_Projects_Table.Designer.cs @@ -1428,7 +1428,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250612094243_Added_TaskAttachments_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250612094243_Added_TaskAttachments_Table.Designer.cs index 1407de2..f601434 100644 --- a/Marco.Pms.DataAccess/Migrations/20250612094243_Added_TaskAttachments_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250612094243_Added_TaskAttachments_Table.Designer.cs @@ -1811,7 +1811,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.Designer.cs index a00f9f1..cee5400 100644 --- a/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.Designer.cs @@ -1835,7 +1835,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs index 4d39cf1..2ce46f8 100644 --- a/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs @@ -1835,7 +1835,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250619060620_Added_New_Status_Master_In_Progress.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250619060620_Added_New_Status_Master_In_Progress.Designer.cs index 08ee943..0ea341d 100644 --- a/Marco.Pms.DataAccess/Migrations/20250619060620_Added_New_Status_Master_In_Progress.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250619060620_Added_New_Status_Master_In_Progress.Designer.cs @@ -1817,7 +1817,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250630071352_Added_UpdatedBy_In_Contacts_And_ContactNotes_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250630071352_Added_UpdatedBy_In_Contacts_And_ContactNotes_Table.Designer.cs index 7bc5be3..0a4cef2 100644 --- a/Marco.Pms.DataAccess/Migrations/20250630071352_Added_UpdatedBy_In_Contacts_And_ContactNotes_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250630071352_Added_UpdatedBy_In_Contacts_And_ContactNotes_Table.Designer.cs @@ -1857,7 +1857,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250630073319_Added_New_Feature_Permissiom_View_All_Employee.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250630073319_Added_New_Feature_Permissiom_View_All_Employee.Designer.cs index cfa4dea..43bbdbe 100644 --- a/Marco.Pms.DataAccess/Migrations/20250630073319_Added_New_Feature_Permissiom_View_All_Employee.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250630073319_Added_New_Feature_Permissiom_View_All_Employee.Designer.cs @@ -1857,7 +1857,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250630111659_Changed_Name_Of_Feature_Permission_To_ViewTeamMembers.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250630111659_Changed_Name_Of_Feature_Permission_To_ViewTeamMembers.Designer.cs index 4ddc1f7..a882d1f 100644 --- a/Marco.Pms.DataAccess/Migrations/20250630111659_Changed_Name_Of_Feature_Permission_To_ViewTeamMembers.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250630111659_Changed_Name_Of_Feature_Permission_To_ViewTeamMembers.Designer.cs @@ -1857,7 +1857,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250702042830_Added_UploadedBy_ForeginKey_In_Decuments_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250702042830_Added_UploadedBy_ForeginKey_In_Decuments_Table.Designer.cs index c0c77b8..f18d9be 100644 --- a/Marco.Pms.DataAccess/Migrations/20250702042830_Added_UploadedBy_ForeginKey_In_Decuments_Table.Designer.cs +++ b/Marco.Pms.DataAccess/Migrations/20250702042830_Added_UploadedBy_ForeginKey_In_Decuments_Table.Designer.cs @@ -1862,7 +1862,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", diff --git a/Marco.Pms.DataAccess/Migrations/20250721124928_Added_Expense_Related_Tables.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250721124928_Added_Expense_Related_Tables.Designer.cs new file mode 100644 index 0000000..495a2a8 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250721124928_Added_Expense_Related_Tables.Designer.cs @@ -0,0 +1,4345 @@ +// +using System; +using Marco.Pms.DataAccess.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Marco.Pms.DataAccess.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250721124928_Added_Expense_Related_Tables")] + partial class Added_Expense_Related_Tables + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + //MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime(6)"); + + b.Property("AssignedBy") + .HasColumnType("char(36)"); + + b.Property("AssignmentDate") + .HasColumnType("datetime(6)"); + + b.Property("CompletedTask") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedTask") + .HasColumnType("double"); + + b.Property("ReportedById") + .HasColumnType("char(36)"); + + b.Property("ReportedDate") + .HasColumnType("datetime(6)"); + + b.Property("ReportedTask") + .HasColumnType("double"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkItemId") + .HasColumnType("char(36)"); + + b.Property("WorkStatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("AssignedBy"); + + b.HasIndex("ReportedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkItemId"); + + b.HasIndex("WorkStatusId"); + + b.ToTable("TaskAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TaskAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CommentDate") + .HasColumnType("datetime(6)"); + + b.Property("CommentedBy") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentedBy"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskMembers"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("AttendanceDate") + .HasColumnType("datetime(6)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("InTime") + .HasColumnType("datetime(6)"); + + b.Property("IsApproved") + .HasColumnType("tinyint(1)"); + + b.Property("OutTime") + .HasColumnType("datetime(6)"); + + b.Property("ProjectID") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.ToTable("Attendes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ActivityTime") + .HasColumnType("datetime(6)"); + + b.Property("AttendanceId") + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("Latitude") + .HasColumnType("longtext"); + + b.Property("Longitude") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("AttendanceId"); + + b.HasIndex("DocumentId"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("AttendanceLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MPIN") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MPINToken") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("MPINDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpriesInSec") + .HasColumnType("int"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("OTP") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("OTPDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsRevoked") + .HasColumnType("tinyint(1)"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("RevokedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByID") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByID"); + + b.HasIndex("TenantId"); + + b.ToTable("Buckets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ContactCategoryId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Organization") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactCategoryId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactCategoryMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsEmails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ContactNotes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsPhones"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactProjectMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ContactTagId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ContactTagId"); + + b.ToTable("ContactTagMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactTagMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("RefereanceId") + .HasColumnType("char(36)"); + + b.Property("UpdateAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UpdatedById"); + + b.ToTable("DirectoryUpdateLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("EmployeeBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Base64Data") + .HasColumnType("longtext"); + + b.Property("BatchId") + .HasColumnType("char(36)"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("S3Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("ThumbS3Key") + .HasColumnType("longtext"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.Property("UploadedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("UploadedById"); + + b.ToTable("Documents"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AadharNumber") + .HasColumnType("longtext"); + + b.Property("ApplicationUserId") + .HasColumnType("varchar(255)"); + + b.Property("BirthDate") + .HasColumnType("datetime(6)"); + + b.Property("CurrentAddress") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("EmergencyContactPerson") + .HasColumnType("longtext"); + + b.Property("EmergencyPhoneNumber") + .HasColumnType("longtext"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("JoiningDate") + .HasColumnType("datetime(6)"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("MiddleName") + .HasColumnType("longtext"); + + b.Property("PanNumber") + .HasColumnType("longtext"); + + b.Property("PermanentAddress") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.HasIndex("JobRoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("Employees"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("RoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("EmployeeRoleMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkShifts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ActivityCheckList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsChecked") + .HasColumnType("tinyint(1)"); + + b.Property("IsMandatory") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("ActivityCheckLists"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.CheckListMappings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckListId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("CheckListMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("FeatureId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("FeaturePermissions"); + + b.HasData( + new + { + Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), + Description = "Access all information related to the project.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project" + }, + new + { + Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), + Description = "Potentially edit the project name, description, start/end dates, or status.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project" + }, + new + { + Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), + Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Team" + }, + new + { + Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), + Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project Infra" + }, + new + { + Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), + Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project Infra" + }, + new + { + Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), + Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions.", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "View Task" + }, + new + { + Id = new Guid("08752f33-3b29-4816-b76b-ea8a968ed3c5"), + Description = "This allows them to create new tasks, modify existing task attributes (description, status, assignee, due date, etc.),", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Add/Edit Task" + }, + new + { + Id = new Guid("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"), + Description = "Grants a user the ability to designate team members responsible for specific tasks and to update the completion status or provide progress updates for those tasks", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Assign/Report Progress" + }, + new + { + Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), + Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Approve Task" + }, + new + { + Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), + Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View All Employees" + }, + new + { + Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), + Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View Team Members" + }, + new + { + Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), + Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Add/Edit Employee" + }, + new + { + Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), + Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system.", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Assign Roles" + }, + new + { + Id = new Guid("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Team Attendance " + }, + new + { + Id = new Guid("57802c4a-00aa-4a1f-a048-fd2f70dd44b6"), + Description = "Grants a user the authority to approve requests from employees to adjust or correct their recorded attendance. This typically involves reviewing the reason for the regularization, verifying any supporting documentation, and then officially accepting the changes to the employee's attendance records", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Regularize Attendance" + }, + new + { + Id = new Guid("ccb0589f-712b-43de-92ed-5b6088e7dc4e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Self Attendance" + }, + new + { + Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), + Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "View Masters" + }, + new + { + Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), + Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "Manage Masters" + }, + new + { + Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), + Description = "Full control over all directories, including the ability to manage permissions for all directories in the system.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Admin" + }, + new + { + Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), + Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Manager" + }, + new + { + Id = new Guid("0f919170-92d4-4337-abd3-49b66fc871bb"), + Description = "Full control over directories they created. Can view contacts in directories they either created or were assigned to. Can manage permissions only for directories they created.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory User" + }, + new + { + Id = new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), + Description = "Allows a user to view only the expense records that they have personally submitted", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View Self" + }, + new + { + Id = new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), + Description = "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View All" + }, + new + { + Id = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + Description = "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Upload" + }, + new + { + Id = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + Description = "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Review" + }, + new + { + Id = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + Description = "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Approve" + }, + new + { + Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Process" + }, + new + { + Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), + Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Manage" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.Property("ApplicationRoleId") + .HasColumnType("char(36)"); + + b.Property("FeaturePermissionId") + .HasColumnType("char(36)"); + + b.HasKey("ApplicationRoleId", "FeaturePermissionId"); + + b.HasIndex("FeaturePermissionId"); + + b.ToTable("RolePermissionMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactName") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DomainName") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OnBoardingDate") + .HasColumnType("datetime(6)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("IndustryId"); + + b.ToTable("Tenants"); + + b.HasData( + new + { + Id = new Guid("b3466e83-7e11-464c-b93a-daf047838b26"), + ContactName = "Admin", + ContactNumber = "123456789", + Description = "", + DomainName = "www.marcobms.org", + IndustryId = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + IsActive = true, + Name = "MarcoBMS", + OnBoardingDate = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + OragnizationSize = "100-200" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("TenantId"); + + b.ToTable("BillAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Action") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("ExpenseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpenseId"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ExpenseLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpensesTypeId") + .HasColumnType("char(36)"); + + b.Property("GSTNumber") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .HasColumnType("longtext"); + + b.Property("NoOfPersons") + .HasColumnType("int"); + + b.Property("PaidById") + .HasColumnType("char(36)"); + + b.Property("PaymentModeId") + .HasColumnType("char(36)"); + + b.Property("PreApproved") + .HasColumnType("tinyint(1)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("SupplerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TransactionDate") + .HasColumnType("datetime(6)"); + + b.Property("TransactionId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ExpensesTypeId"); + + b.HasIndex("PaidById"); + + b.HasIndex("PaymentModeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Expenses"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ReimburseById") + .HasColumnType("char(36)"); + + b.Property("ReimburseDate") + .HasColumnType("datetime(6)"); + + b.Property("ReimburseNote") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReimburseTransactionId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ReimburseById"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburse"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("ExpensesReimburseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("ExpensesReimburseId"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburseMapping"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("NextStatusId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("NextStatusId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesStatusMapping"); + + b.HasData( + new + { + Id = new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + NextStatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), + NextStatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), + NextStatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("75bbda6a-6a53-47d1-ad71-5f5f9446a11e"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("fddaaf20-4ccc-4f4e-a724-dd310272b356"), + NextStatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + NextStatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("PermissionId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PermissionId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("StatusPermissionMapping"); + + b.HasData( + new + { + Id = new Guid("ed893799-1a5f-4311-a077-de93c86ca8fd"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4652d73f-fc71-4fe1-9f2f-1e48b342d741"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + PermissionId = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + StatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CommentId") + .HasColumnType("char(36)"); + + b.Property("FileId") + .HasColumnType("char(36)"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AuthorId") + .HasColumnType("char(36)"); + + b.Property("MessageText") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ParentMessageId") + .HasColumnType("char(36)"); + + b.Property("SentAt") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("TicketComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LinkedActivityId") + .HasColumnType("char(36)"); + + b.Property("LinkedProjectId") + .HasColumnType("char(36)"); + + b.Property("PriorityId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TypeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PriorityId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.HasIndex("TypeId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("TagId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TagId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketTags"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTypeMasters"); + + b.HasData( + new + { + Id = new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"), + Description = "An identified problem that affects the performance, reliability, or standards of a product or service", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"), + Description = "A support service that assists users with technical issues, requests, or inquiries.", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MailListId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("Recipient") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("MailListId"); + + b.ToTable("MailDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmailId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("MailLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailingList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Keywords") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("MailingList"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityName") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UnitOfMeasurement") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ActivityMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesStatusMaster"); + + b.HasData( + new + { + Id = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + Color = "#8592a3", + Description = "Expense has been created but not yet submitted.", + DisplayName = "Draft", + IsActive = true, + IsSystem = true, + Name = "Draft", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + Color = "#696cff", + Description = "Reviewer is currently reviewing the expense.", + DisplayName = "Submit", + IsActive = true, + IsSystem = true, + Name = "Review Pending", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + Color = "#03c3ec", + Description = "Review is completed, waiting for action of approver.", + DisplayName = "Mark as Reviewed", + IsActive = true, + IsSystem = true, + Name = "Approval Pending", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(either review rejected or approval rejected.", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + Color = "#ffab00", + Description = "Approved expense is awaiting final payment.", + DisplayName = "Mark as Approved", + IsActive = true, + IsSystem = true, + Name = "Payment Pending", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + Color = "#71dd37", + Description = "Expense has been settled.", + DisplayName = "Mark as Paid", + IsActive = true, + IsSystem = true, + Name = "Paid", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NoOfPersonsRequired") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesTypeMaster"); + + b.HasData( + new + { + Id = new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), + Description = "Materials, equipment and supplies purchased for site operations.", + IsActive = true, + Name = "Procurement", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), + Description = "Vehicle fuel, logistics services and delivery of goods or personnel.", + IsActive = true, + Name = "Transport", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), + Description = "Delivery of personnel.", + IsActive = true, + Name = "Travelling", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), + Description = "Site setup costs including equipment deployment and temporary infrastructure.", + IsActive = true, + Name = "Mobilization", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), + Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", + IsActive = true, + Name = "Employee Welfare", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), + Description = "Machinery servicing, electricity, water, and temporary office needs.", + IsActive = true, + Name = "Maintenance & Utilities", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), + Description = "Scheduled payments for external services or goods.", + IsActive = true, + Name = "Vendor/Supplier Payments", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), + Description = "Government fees, insurance, inspections and safety-related expenditures.", + IsActive = true, + Name = "Compliance & Safety", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ModuleId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ModuleId"); + + b.ToTable("Features"); + + b.HasData( + new + { + Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + Description = "Manage Project", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Project Management" + }, + new + { + Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Expense Management" + }, + new + { + Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + Description = "Manage Tasks", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Task Management" + }, + new + { + Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + Description = "Manage Employee", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Employee Management" + }, + new + { + Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + Description = "Attendance", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Attendance Management" + }, + new + { + Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + Description = "Global Masters", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Masters" + }, + new + { + Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + Description = "Managing all directory related rights", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Directory Management" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Industry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Industries"); + + b.HasData( + new + { + Id = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + Name = "Information Technology (IT) Services" + }, + new + { + Id = new Guid("0a63e657-2c5f-49b5-854b-42c978293154"), + Name = "Manufacturing & Production" + }, + new + { + Id = new Guid("bdc61e3b-69ea-4394-bab6-079ec135b5bd"), + Name = "Energy & Resources" + }, + new + { + Id = new Guid("5ca200ac-00d7-415e-a410-b948e27ac9d2"), + Name = "Finance & Professional Services" + }, + new + { + Id = new Guid("d5621700-cd87-441f-8cdb-6051ddfc83b4"), + Name = "Hospitals and Healthcare Services" + }, + new + { + Id = new Guid("23608891-657e-40f0-bbd4-2b0a2ec1a76f"), + Name = "Social Services" + }, + new + { + Id = new Guid("a493f4e3-16b1-4411-be3c-6bf2987a3168"), + Name = "Retail & Consumer Services" + }, + new + { + Id = new Guid("e9d8ce92-9371-4ed9-9831-83c07f78edec"), + Name = "Transportation & Logistics" + }, + new + { + Id = new Guid("8a0d6134-2dbe-4e0a-b250-ff34cb7b9df0"), + Name = "Education & Training" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Module", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Modules"); + + b.HasData( + new + { + Id = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Description = "Project Module", + Key = "b04da7e9-0406-409c-ac7f-b97256e6ea02", + Name = "Project" + }, + new + { + Id = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Description = "Employee Module", + Key = "0971c7fb-6ce1-458a-ae3f-8d3205893637", + Name = "Employee" + }, + new + { + Id = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Description = "Masters Module", + Key = "504ec132-e6a9-422f-8f85-050602cfce05", + Name = "Masters" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("PaymentModeMatser"); + + b.HasData( + new + { + Id = new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), + Description = "Physical currency; still used for small or informal transactions.", + IsActive = true, + Name = "Cash", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"), + Description = "Paper-based payment order; less common now due to processing delays and fraud risks.", + IsActive = true, + Name = "Cheque", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ed667353-8eea-4fd1-8750-719405932480"), + Description = "Online banking portals used to transfer funds directly between accounts", + IsActive = true, + Name = "NetBanking", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"), + Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", + IsActive = true, + Name = "UPI", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("StatusMasters"); + + b.HasData( + new + { + Id = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + Status = "Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("cdad86aa-8a56-4ff4-b633-9c629057dfef"), + Status = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("603e994b-a27f-4e5d-a251-f3d69b0498ba"), + Status = "On Hold", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), + Status = "In Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"), + Status = "Completed", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketPriorityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketPriorityMasters"); + + b.HasData( + new + { + Id = new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"), + ColorCode = "008000", + IsDefault = true, + Level = 1, + Name = "Low", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"), + ColorCode = "FFFF00", + IsDefault = true, + Level = 2, + Name = "Medium", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 3, + Name = "High", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 4, + Name = "Critical", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"), + ColorCode = "#FF0000", + IsDefault = true, + Level = 5, + Name = "Urgent", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketStatusMasters"); + + b.HasData( + new + { + Id = new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"), + ColorCode = "#FFCC99", + Description = "This is a newly created issue.", + IsDefault = true, + Name = "New", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"), + ColorCode = "#E6FF99", + Description = "Assigned to employee or team of employees", + IsDefault = true, + Name = "Assigned", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"), + ColorCode = "#99E6FF", + Description = "These issues are currently in progress", + IsDefault = true, + Name = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), + ColorCode = "#8592a3", + Description = "These issues are currently under review", + IsDefault = true, + Name = "In Review", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"), + ColorCode = "#B399FF", + Description = "The following issues are resolved and closed", + IsDefault = true, + Name = "Done", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTagMasters"); + + b.HasData( + new + { + Id = new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"), + ColorCode = "#e59866", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"), + ColorCode = "#85c1e9", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkCategoryMasters"); + + b.HasData( + new + { + Id = new Guid("86bb2cc8-f6b5-4fdd-bbee-c389c713a44b"), + Description = "Created new task in a professional or creative context", + IsSystem = true, + Name = "Fresh Work", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("9ebfa19c-53b9-481b-b863-c25d2f843201"), + Description = "Revising, modifying, or correcting a task to improve its quality or fix issues", + IsSystem = true, + Name = "Rework", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("11a79929-1d07-42dc-9e98-82d0d2f4a240"), + Description = "Any defect, deviation, or non-conformance in a task that fails to meet established standards or customer expectations.", + IsSystem = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkStatusMasters"); + + b.HasData( + new + { + Id = new Guid("030bb085-e230-4370-aec7-9a74d652864e"), + Description = "Confirm the tasks are actually finished as reported", + IsSystem = true, + Name = "Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2a1a5b96-cf93-4111-b4b1-76c19d6333b4"), + Description = "Not all tasks are actually finished as reported", + IsSystem = true, + Name = "Partially Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("00a062e6-62e6-42c5-b6b1-024328651b72"), + Description = "Tasks are not finished as reported or have any issues in al the tasks", + IsSystem = true, + Name = "NCR", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BuildingId") + .HasColumnType("char(36)"); + + b.Property("FloorName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BuildingId"); + + b.HasIndex("TenantId"); + + b.ToTable("Floor"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectAddress") + .HasColumnType("longtext"); + + b.Property("ProjectStatusId") + .HasColumnType("char(36)"); + + b.Property("ShortName") + .HasColumnType("longtext"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectStatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + Id = new Guid("85bf587b-7ca9-4685-b77c-d817f5847e85"), + ContactPerson = "Project 1 Contact Person", + EndDate = new DateTime(2026, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + Name = "Project 1", + ProjectAddress = "Project 1 Address", + ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + StartDate = new DateTime(2025, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReAllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ProjectAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AreaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FloorId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FloorId"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkAreas"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("CompletedWork") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedWork") + .HasColumnType("double"); + + b.Property("TaskDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkAreaId") + .HasColumnType("char(36)"); + + b.Property("WorkCategoryId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkAreaId"); + + b.HasIndex("WorkCategoryId"); + + b.ToTable("WorkItems"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Role") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ApplicationRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("JobRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Utilities.Inquiries", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("About") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.Property("OrganizatioinName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Inquiries"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("varchar(21)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + + b.HasDiscriminator().HasValue("IdentityUser"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ApplicationUser", b => + { + b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsRootUser") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasDiscriminator().HasValue("ApplicationUser"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("AssignedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReportedBy") + .WithMany() + .HasForeignKey("ReportedById"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkItem", "WorkItem") + .WithMany() + .HasForeignKey("WorkItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkStatusMaster", "WorkStatus") + .WithMany() + .HasForeignKey("WorkStatusId"); + + b.Navigation("ApprovedBy"); + + b.Navigation("Employee"); + + b.Navigation("ReportedBy"); + + b.Navigation("Tenant"); + + b.Navigation("WorkItem"); + + b.Navigation("WorkStatus"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("CommentedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Approver") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.HasOne("Marco.Pms.Model.AttendanceModule.Attendance", "Attendance") + .WithMany() + .HasForeignKey("AttendanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedByEmployee") + .WithMany() + .HasForeignKey("UpdatedBy"); + + b.Navigation("Attendance"); + + b.Navigation("Document"); + + b.Navigation("Employee"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedByEmployee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedByID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.HasOne("Marco.Pms.Model.Directory.ContactCategoryMaster", "ContactCategory") + .WithMany() + .HasForeignKey("ContactCategoryId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("ContactCategory"); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Createdby") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("Contact"); + + b.Navigation("Createdby"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.ContactTagMaster", "ContactTag") + .WithMany() + .HasForeignKey("ContactTagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("ContactTag"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UploadedBy") + .WithMany() + .HasForeignKey("UploadedById"); + + b.Navigation("Tenant"); + + b.Navigation("UploadedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserId"); + + b.HasOne("Marco.Pms.Model.Roles.JobRole", "JobRole") + .WithMany() + .HasForeignKey("JobRoleId"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApplicationUser"); + + b.Navigation("JobRole"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Role"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.HasOne("Marco.Pms.Model.Master.Feature", "Feature") + .WithMany("FeaturePermissions") + .HasForeignKey("FeatureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Feature"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", null) + .WithMany() + .HasForeignKey("ApplicationRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", null) + .WithMany() + .HasForeignKey("FeaturePermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.HasOne("Marco.Pms.Model.Master.Industry", "Industry") + .WithMany() + .HasForeignKey("IndustryId"); + + b.Navigation("Industry"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Expenses"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expense") + .WithMany() + .HasForeignKey("ExpenseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expense"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesTypeMaster", "ExpensesType") + .WithMany() + .HasForeignKey("ExpensesTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "PaidBy") + .WithMany() + .HasForeignKey("PaidById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.PaymentModeMatser", "PaymentMode") + .WithMany() + .HasForeignKey("PaymentModeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("ExpensesType"); + + b.Navigation("PaidBy"); + + b.Navigation("PaymentMode"); + + b.Navigation("Project"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReimburseBy") + .WithMany() + .HasForeignKey("ReimburseById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReimburseBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.ExpensesReimburse", "ExpensesReimburse") + .WithMany() + .HasForeignKey("ExpensesReimburseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expenses"); + + b.Navigation("ExpensesReimburse"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "NextStatus") + .WithMany() + .HasForeignKey("NextStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NextStatus"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment") + .WithMany("Attachments") + .HasForeignKey("CommentId"); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + + b.Navigation("TicketComment"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketPriorityMaster", "Priority") + .WithMany() + .HasForeignKey("PriorityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.TicketStatusMaster", "TicketStatusMaster") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketTypeMaster", "TicketTypeMaster") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Priority"); + + b.Navigation("Tenant"); + + b.Navigation("TicketStatusMaster"); + + b.Navigation("TicketTypeMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketTagMaster", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.HasOne("Marco.Pms.Model.Mail.MailingList", "MailBody") + .WithMany() + .HasForeignKey("MailListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MailBody"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", 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.ExpensesStatusMaster", 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.ExpensesTypeMaster", 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.Feature", b => + { + b.HasOne("Marco.Pms.Model.Master.Module", "Module") + .WithMany() + .HasForeignKey("ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", 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") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", 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.WorkStatusMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.HasOne("Marco.Pms.Model.Projects.Building", "Building") + .WithMany() + .HasForeignKey("BuildingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Building"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.HasOne("Marco.Pms.Model.Master.StatusMaster", "ProjectStatus") + .WithMany() + .HasForeignKey("ProjectStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectStatus"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.HasOne("Marco.Pms.Model.Projects.Floor", "Floor") + .WithMany() + .HasForeignKey("FloorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Floor"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.HasOne("Marco.Pms.Model.Master.ActivityMaster", "ActivityMaster") + .WithMany() + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkArea", "WorkArea") + .WithMany() + .HasForeignKey("WorkAreaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkCategoryMaster", "WorkCategoryMaster") + .WithMany() + .HasForeignKey("WorkCategoryId"); + + b.Navigation("ActivityMaster"); + + b.Navigation("Tenant"); + + b.Navigation("WorkArea"); + + b.Navigation("WorkCategoryMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", null) + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Navigation("FeaturePermissions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250721124928_Added_Expense_Related_Tables.cs b/Marco.Pms.DataAccess/Migrations/20250721124928_Added_Expense_Related_Tables.cs new file mode 100644 index 0000000..11136ab --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250721124928_Added_Expense_Related_Tables.cs @@ -0,0 +1,664 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Marco.Pms.DataAccess.Migrations +{ + /// + public partial class Added_Expense_Related_Tables : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ExpensesReimburse", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ReimburseTransactionId = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ReimburseDate = table.Column(type: "datetime(6)", nullable: false), + ReimburseById = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ReimburseNote = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ExpensesReimburse", x => x.Id); + table.ForeignKey( + name: "FK_ExpensesReimburse_Employees_ReimburseById", + column: x => x.ReimburseById, + principalTable: "Employees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpensesReimburse_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ExpensesStatusMaster", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Color = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsSystem = table.Column(type: "tinyint(1)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ExpensesStatusMaster", x => x.Id); + table.ForeignKey( + name: "FK_ExpensesStatusMaster_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ExpensesTypeMaster", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NoOfPersonsRequired = table.Column(type: "tinyint(1)", nullable: false), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ExpensesTypeMaster", x => x.Id); + table.ForeignKey( + name: "FK_ExpensesTypeMaster_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "PaymentModeMatser", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_PaymentModeMatser", x => x.Id); + table.ForeignKey( + name: "FK_PaymentModeMatser_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ExpensesStatusMapping", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + StatusId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + NextStatusId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ExpensesStatusMapping", x => x.Id); + table.ForeignKey( + name: "FK_ExpensesStatusMapping_ExpensesStatusMaster_NextStatusId", + column: x => x.NextStatusId, + principalTable: "ExpensesStatusMaster", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpensesStatusMapping_ExpensesStatusMaster_StatusId", + column: x => x.StatusId, + principalTable: "ExpensesStatusMaster", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpensesStatusMapping_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "StatusPermissionMapping", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + StatusId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + PermissionId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_StatusPermissionMapping", x => x.Id); + table.ForeignKey( + name: "FK_StatusPermissionMapping_ExpensesStatusMaster_StatusId", + column: x => x.StatusId, + principalTable: "ExpensesStatusMaster", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_StatusPermissionMapping_FeaturePermissions_PermissionId", + column: x => x.PermissionId, + principalTable: "FeaturePermissions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_StatusPermissionMapping_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Expenses", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ProjectId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ExpensesTypeId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + PaymentModeId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + PaidById = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedById = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TransactionDate = table.Column(type: "datetime(6)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + TransactionId = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Location = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + GSTNumber = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SupplerName = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Amount = table.Column(type: "double", nullable: false), + NoOfPersons = table.Column(type: "int", nullable: true), + StatusId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + PreApproved = table.Column(type: "tinyint(1)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_Expenses", x => x.Id); + table.ForeignKey( + name: "FK_Expenses_Employees_CreatedById", + column: x => x.CreatedById, + principalTable: "Employees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Expenses_Employees_PaidById", + column: x => x.PaidById, + principalTable: "Employees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Expenses_ExpensesStatusMaster_StatusId", + column: x => x.StatusId, + principalTable: "ExpensesStatusMaster", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Expenses_ExpensesTypeMaster_ExpensesTypeId", + column: x => x.ExpensesTypeId, + principalTable: "ExpensesTypeMaster", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Expenses_PaymentModeMatser_PaymentModeId", + column: x => x.PaymentModeId, + principalTable: "PaymentModeMatser", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Expenses_Projects_ProjectId", + column: x => x.ProjectId, + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Expenses_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "BillAttachments", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ExpensesId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + DocumentId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_BillAttachments", x => x.Id); + table.ForeignKey( + name: "FK_BillAttachments_Documents_DocumentId", + column: x => x.DocumentId, + principalTable: "Documents", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_BillAttachments_Expenses_ExpensesId", + column: x => x.ExpensesId, + principalTable: "Expenses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_BillAttachments_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ExpenseLogs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ExpenseId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + UpdatedById = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Action = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Comment = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ExpenseLogs", x => x.Id); + table.ForeignKey( + name: "FK_ExpenseLogs_Employees_UpdatedById", + column: x => x.UpdatedById, + principalTable: "Employees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpenseLogs_Expenses_ExpenseId", + column: x => x.ExpenseId, + principalTable: "Expenses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpenseLogs_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ExpensesReimburseMapping", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ExpensesId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ExpensesReimburseId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ExpensesReimburseMapping", x => x.Id); + table.ForeignKey( + name: "FK_ExpensesReimburseMapping_ExpensesReimburse_ExpensesReimburse~", + column: x => x.ExpensesReimburseId, + principalTable: "ExpensesReimburse", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpensesReimburseMapping_Expenses_ExpensesId", + column: x => x.ExpensesId, + principalTable: "Expenses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ExpensesReimburseMapping_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "ExpensesStatusMaster", + columns: new[] { "Id", "Color", "Description", "DisplayName", "IsActive", "IsSystem", "Name", "TenantId" }, + values: new object[,] + { + { new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), "#8592a3", "Expense has been created but not yet submitted.", "Draft", true, true, "Draft", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), "#03c3ec", "Review is completed, waiting for action of approver.", "Mark as Reviewed", true, true, "Approval Pending", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), "#71dd37", "Expense has been settled.", "Mark as Paid", true, true, "Paid", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), "#696cff", "Reviewer is currently reviewing the expense.", "Submit", true, true, "Review Pending", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), "#ff3e1d", "Expense was declined, often with a reason(either review rejected or approval rejected.", "Reject", true, true, "Rejected", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), "#ffab00", "Approved expense is awaiting final payment.", "Mark as Approved", true, true, "Payment Pending", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.InsertData( + table: "ExpensesTypeMaster", + columns: new[] { "Id", "Description", "IsActive", "Name", "NoOfPersonsRequired", "TenantId" }, + values: new object[,] + { + { new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), "Scheduled payments for external services or goods.", true, "Vendor/Supplier Payments", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), "Vehicle fuel, logistics services and delivery of goods or personnel.", true, "Transport", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), "Government fees, insurance, inspections and safety-related expenditures.", true, "Compliance & Safety", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), "Site setup costs including equipment deployment and temporary infrastructure.", true, "Mobilization", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), "Materials, equipment and supplies purchased for site operations.", true, "Procurement", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), "Machinery servicing, electricity, water, and temporary office needs.", true, "Maintenance & Utilities", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), "Delivery of personnel.", true, "Travelling", true, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", true, "Employee Welfare", true, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.InsertData( + table: "Features", + columns: new[] { "Id", "Description", "IsActive", "ModuleId", "Name" }, + values: new object[] { new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", true, new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), "Expense Management" }); + + migrationBuilder.InsertData( + table: "PaymentModeMatser", + columns: new[] { "Id", "Description", "IsActive", "Name", "TenantId" }, + values: new object[,] + { + { new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), "Physical currency; still used for small or informal transactions.", true, "Cash", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"), "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", true, "UPI", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"), "Paper-based payment order; less common now due to processing delays and fraud risks.", true, "Cheque", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("ed667353-8eea-4fd1-8750-719405932480"), "Online banking portals used to transfer funds directly between accounts", true, "NetBanking", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.InsertData( + table: "ExpensesStatusMapping", + columns: new[] { "Id", "NextStatusId", "StatusId", "TenantId" }, + values: new object[,] + { + { new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("75bbda6a-6a53-47d1-ad71-5f5f9446a11e"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("fddaaf20-4ccc-4f4e-a724-dd310272b356"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.InsertData( + table: "FeaturePermissions", + columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" }, + values: new object[,] + { + { new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "View All" }, + { new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices.", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "Upload" }, + { new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected.", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "Review" }, + { new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), "Allows a user to view only the expense records that they have personally submitted", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "View Self" }, + { new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules.", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "Manage" }, + { new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled.", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "Process" }, + { new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system.", new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), true, "Approve" } + }); + + migrationBuilder.InsertData( + table: "StatusPermissionMapping", + columns: new[] { "Id", "PermissionId", "StatusId", "TenantId" }, + values: new object[,] + { + { new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("4652d73f-fc71-4fe1-9f2f-1e48b342d741"), new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("ed893799-1a5f-4311-a077-de93c86ca8fd"), new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.CreateIndex( + name: "IX_BillAttachments_DocumentId", + table: "BillAttachments", + column: "DocumentId"); + + migrationBuilder.CreateIndex( + name: "IX_BillAttachments_ExpensesId", + table: "BillAttachments", + column: "ExpensesId"); + + migrationBuilder.CreateIndex( + name: "IX_BillAttachments_TenantId", + table: "BillAttachments", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpenseLogs_ExpenseId", + table: "ExpenseLogs", + column: "ExpenseId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpenseLogs_TenantId", + table: "ExpenseLogs", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpenseLogs_UpdatedById", + table: "ExpenseLogs", + column: "UpdatedById"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_CreatedById", + table: "Expenses", + column: "CreatedById"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_ExpensesTypeId", + table: "Expenses", + column: "ExpensesTypeId"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_PaidById", + table: "Expenses", + column: "PaidById"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_PaymentModeId", + table: "Expenses", + column: "PaymentModeId"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_ProjectId", + table: "Expenses", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_StatusId", + table: "Expenses", + column: "StatusId"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_TenantId", + table: "Expenses", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesReimburse_ReimburseById", + table: "ExpensesReimburse", + column: "ReimburseById"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesReimburse_TenantId", + table: "ExpensesReimburse", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesReimburseMapping_ExpensesId", + table: "ExpensesReimburseMapping", + column: "ExpensesId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesReimburseMapping_ExpensesReimburseId", + table: "ExpensesReimburseMapping", + column: "ExpensesReimburseId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesReimburseMapping_TenantId", + table: "ExpensesReimburseMapping", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesStatusMapping_NextStatusId", + table: "ExpensesStatusMapping", + column: "NextStatusId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesStatusMapping_StatusId", + table: "ExpensesStatusMapping", + column: "StatusId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesStatusMapping_TenantId", + table: "ExpensesStatusMapping", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesStatusMaster_TenantId", + table: "ExpensesStatusMaster", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesTypeMaster_TenantId", + table: "ExpensesTypeMaster", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_PaymentModeMatser_TenantId", + table: "PaymentModeMatser", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_StatusPermissionMapping_PermissionId", + table: "StatusPermissionMapping", + column: "PermissionId"); + + migrationBuilder.CreateIndex( + name: "IX_StatusPermissionMapping_StatusId", + table: "StatusPermissionMapping", + column: "StatusId"); + + migrationBuilder.CreateIndex( + name: "IX_StatusPermissionMapping_TenantId", + table: "StatusPermissionMapping", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "BillAttachments"); + + migrationBuilder.DropTable( + name: "ExpenseLogs"); + + migrationBuilder.DropTable( + name: "ExpensesReimburseMapping"); + + migrationBuilder.DropTable( + name: "ExpensesStatusMapping"); + + migrationBuilder.DropTable( + name: "StatusPermissionMapping"); + + migrationBuilder.DropTable( + name: "ExpensesReimburse"); + + migrationBuilder.DropTable( + name: "Expenses"); + + migrationBuilder.DropTable( + name: "ExpensesStatusMaster"); + + migrationBuilder.DropTable( + name: "ExpensesTypeMaster"); + + migrationBuilder.DropTable( + name: "PaymentModeMatser"); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f")); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7")); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b")); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116")); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3")); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11")); + + migrationBuilder.DeleteData( + table: "FeaturePermissions", + keyColumn: "Id", + keyValue: new Guid("eaafdd76-8aac-45f9-a530-315589c6deca")); + + migrationBuilder.DeleteData( + table: "Features", + keyColumn: "Id", + keyValue: new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7")); + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250730063711_Change_ExpenseStatus_To_Be_System_Scope.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250730063711_Change_ExpenseStatus_To_Be_System_Scope.Designer.cs new file mode 100644 index 0000000..7f8875d --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250730063711_Change_ExpenseStatus_To_Be_System_Scope.Designer.cs @@ -0,0 +1,4346 @@ +// +using System; +using Marco.Pms.DataAccess.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Marco.Pms.DataAccess.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250730063711_Change_ExpenseStatus_To_Be_System_Scope")] + partial class Change_ExpenseStatus_To_Be_System_Scope + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + //MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime(6)"); + + b.Property("AssignedBy") + .HasColumnType("char(36)"); + + b.Property("AssignmentDate") + .HasColumnType("datetime(6)"); + + b.Property("CompletedTask") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedTask") + .HasColumnType("double"); + + b.Property("ReportedById") + .HasColumnType("char(36)"); + + b.Property("ReportedDate") + .HasColumnType("datetime(6)"); + + b.Property("ReportedTask") + .HasColumnType("double"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkItemId") + .HasColumnType("char(36)"); + + b.Property("WorkStatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("AssignedBy"); + + b.HasIndex("ReportedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkItemId"); + + b.HasIndex("WorkStatusId"); + + b.ToTable("TaskAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TaskAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CommentDate") + .HasColumnType("datetime(6)"); + + b.Property("CommentedBy") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentedBy"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskMembers"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("AttendanceDate") + .HasColumnType("datetime(6)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("InTime") + .HasColumnType("datetime(6)"); + + b.Property("IsApproved") + .HasColumnType("tinyint(1)"); + + b.Property("OutTime") + .HasColumnType("datetime(6)"); + + b.Property("ProjectID") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.ToTable("Attendes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ActivityTime") + .HasColumnType("datetime(6)"); + + b.Property("AttendanceId") + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("Latitude") + .HasColumnType("longtext"); + + b.Property("Longitude") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("AttendanceId"); + + b.HasIndex("DocumentId"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("AttendanceLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MPIN") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MPINToken") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("MPINDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpriesInSec") + .HasColumnType("int"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("OTP") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("OTPDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsRevoked") + .HasColumnType("tinyint(1)"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("RevokedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByID") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByID"); + + b.HasIndex("TenantId"); + + b.ToTable("Buckets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ContactCategoryId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Organization") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactCategoryId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactCategoryMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsEmails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ContactNotes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsPhones"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactProjectMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ContactTagId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ContactTagId"); + + b.ToTable("ContactTagMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactTagMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("RefereanceId") + .HasColumnType("char(36)"); + + b.Property("UpdateAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UpdatedById"); + + b.ToTable("DirectoryUpdateLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("EmployeeBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Base64Data") + .HasColumnType("longtext"); + + b.Property("BatchId") + .HasColumnType("char(36)"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("S3Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("ThumbS3Key") + .HasColumnType("longtext"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.Property("UploadedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("UploadedById"); + + b.ToTable("Documents"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AadharNumber") + .HasColumnType("longtext"); + + b.Property("ApplicationUserId") + .HasColumnType("varchar(255)"); + + b.Property("BirthDate") + .HasColumnType("datetime(6)"); + + b.Property("CurrentAddress") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("EmergencyContactPerson") + .HasColumnType("longtext"); + + b.Property("EmergencyPhoneNumber") + .HasColumnType("longtext"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("JoiningDate") + .HasColumnType("datetime(6)"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("MiddleName") + .HasColumnType("longtext"); + + b.Property("PanNumber") + .HasColumnType("longtext"); + + b.Property("PermanentAddress") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.HasIndex("JobRoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("Employees"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("RoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("EmployeeRoleMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkShifts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ActivityCheckList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsChecked") + .HasColumnType("tinyint(1)"); + + b.Property("IsMandatory") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("ActivityCheckLists"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.CheckListMappings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckListId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("CheckListMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("FeatureId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("FeaturePermissions"); + + b.HasData( + new + { + Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), + Description = "Access all information related to the project.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project" + }, + new + { + Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), + Description = "Potentially edit the project name, description, start/end dates, or status.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project" + }, + new + { + Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), + Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Team" + }, + new + { + Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), + Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project Infra" + }, + new + { + Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), + Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project Infra" + }, + new + { + Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), + Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions.", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "View Task" + }, + new + { + Id = new Guid("08752f33-3b29-4816-b76b-ea8a968ed3c5"), + Description = "This allows them to create new tasks, modify existing task attributes (description, status, assignee, due date, etc.),", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Add/Edit Task" + }, + new + { + Id = new Guid("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"), + Description = "Grants a user the ability to designate team members responsible for specific tasks and to update the completion status or provide progress updates for those tasks", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Assign/Report Progress" + }, + new + { + Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), + Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Approve Task" + }, + new + { + Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), + Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View All Employees" + }, + new + { + Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), + Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View Team Members" + }, + new + { + Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), + Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Add/Edit Employee" + }, + new + { + Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), + Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system.", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Assign Roles" + }, + new + { + Id = new Guid("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Team Attendance " + }, + new + { + Id = new Guid("57802c4a-00aa-4a1f-a048-fd2f70dd44b6"), + Description = "Grants a user the authority to approve requests from employees to adjust or correct their recorded attendance. This typically involves reviewing the reason for the regularization, verifying any supporting documentation, and then officially accepting the changes to the employee's attendance records", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Regularize Attendance" + }, + new + { + Id = new Guid("ccb0589f-712b-43de-92ed-5b6088e7dc4e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Self Attendance" + }, + new + { + Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), + Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "View Masters" + }, + new + { + Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), + Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "Manage Masters" + }, + new + { + Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), + Description = "Full control over all directories, including the ability to manage permissions for all directories in the system.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Admin" + }, + new + { + Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), + Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Manager" + }, + new + { + Id = new Guid("0f919170-92d4-4337-abd3-49b66fc871bb"), + Description = "Full control over directories they created. Can view contacts in directories they either created or were assigned to. Can manage permissions only for directories they created.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory User" + }, + new + { + Id = new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), + Description = "Allows a user to view only the expense records that they have personally submitted", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View Self" + }, + new + { + Id = new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), + Description = "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View All" + }, + new + { + Id = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + Description = "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Upload" + }, + new + { + Id = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + Description = "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Review" + }, + new + { + Id = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + Description = "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Approve" + }, + new + { + Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Process" + }, + new + { + Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), + Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Manage" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.Property("ApplicationRoleId") + .HasColumnType("char(36)"); + + b.Property("FeaturePermissionId") + .HasColumnType("char(36)"); + + b.HasKey("ApplicationRoleId", "FeaturePermissionId"); + + b.HasIndex("FeaturePermissionId"); + + b.ToTable("RolePermissionMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactName") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DomainName") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OnBoardingDate") + .HasColumnType("datetime(6)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("IndustryId"); + + b.ToTable("Tenants"); + + b.HasData( + new + { + Id = new Guid("b3466e83-7e11-464c-b93a-daf047838b26"), + ContactName = "Admin", + ContactNumber = "123456789", + Description = "", + DomainName = "www.marcobms.org", + IndustryId = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + IsActive = true, + Name = "MarcoBMS", + OnBoardingDate = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + OragnizationSize = "100-200" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("TenantId"); + + b.ToTable("BillAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Action") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("ExpenseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpenseId"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ExpenseLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpensesTypeId") + .HasColumnType("char(36)"); + + b.Property("GSTNumber") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .HasColumnType("longtext"); + + b.Property("NoOfPersons") + .HasColumnType("int"); + + b.Property("PaidById") + .HasColumnType("char(36)"); + + b.Property("PaymentModeId") + .HasColumnType("char(36)"); + + b.Property("PreApproved") + .HasColumnType("tinyint(1)"); + + b.Property("ProcessedById") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReviewedById") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("SupplerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TransactionDate") + .HasColumnType("datetime(6)"); + + b.Property("TransactionId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ExpensesTypeId"); + + b.HasIndex("PaidById"); + + b.HasIndex("PaymentModeId"); + + b.HasIndex("ProcessedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("ReviewedById"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Expenses"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ReimburseById") + .HasColumnType("char(36)"); + + b.Property("ReimburseDate") + .HasColumnType("datetime(6)"); + + b.Property("ReimburseNote") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReimburseTransactionId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ReimburseById"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburse"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("ExpensesReimburseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("ExpensesReimburseId"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburseMapping"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("NextStatusId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("NextStatusId"); + + b.HasIndex("StatusId"); + + b.ToTable("ExpensesStatusMapping"); + + b.HasData( + new + { + Id = new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + NextStatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("4ddddc10-0ffd-4884-accf-d4fa0bd97f54"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), + NextStatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), + NextStatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("6b867bec-66e6-42a7-9611-f4595af9b9ce"), + NextStatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + NextStatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("PermissionId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PermissionId"); + + b.HasIndex("StatusId"); + + b.ToTable("StatusPermissionMapping"); + + b.HasData( + new + { + Id = new Guid("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }, + new + { + Id = new Guid("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + PermissionId = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + StatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CommentId") + .HasColumnType("char(36)"); + + b.Property("FileId") + .HasColumnType("char(36)"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AuthorId") + .HasColumnType("char(36)"); + + b.Property("MessageText") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ParentMessageId") + .HasColumnType("char(36)"); + + b.Property("SentAt") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("TicketComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LinkedActivityId") + .HasColumnType("char(36)"); + + b.Property("LinkedProjectId") + .HasColumnType("char(36)"); + + b.Property("PriorityId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TypeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PriorityId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.HasIndex("TypeId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("TagId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TagId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketTags"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTypeMasters"); + + b.HasData( + new + { + Id = new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"), + Description = "An identified problem that affects the performance, reliability, or standards of a product or service", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"), + Description = "A support service that assists users with technical issues, requests, or inquiries.", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MailListId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("Recipient") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("MailListId"); + + b.ToTable("MailDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmailId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("MailLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailingList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Keywords") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("MailingList"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityName") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UnitOfMeasurement") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ActivityMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ExpensesStatusMaster"); + + b.HasData( + new + { + Id = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + Color = "#8592a3", + Description = "Expense has been created but not yet submitted.", + DisplayName = "Draft", + IsActive = true, + IsSystem = true, + Name = "Draft" + }, + new + { + Id = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + Color = "#696cff", + Description = "Reviewer is currently reviewing the expense.", + DisplayName = "Submit", + IsActive = true, + IsSystem = true, + Name = "Review Pending" + }, + new + { + Id = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(review rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Reviewer" + }, + new + { + Id = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + Color = "#03c3ec", + Description = "Review is completed, waiting for action of approver.", + DisplayName = "Mark as Reviewed", + IsActive = true, + IsSystem = true, + Name = "Approval Pending" + }, + new + { + Id = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(approval rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Approver" + }, + new + { + Id = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + Color = "#ffab00", + Description = "Approved expense is awaiting final payment.", + DisplayName = "Mark as Approved", + IsActive = true, + IsSystem = true, + Name = "Payment Pending" + }, + new + { + Id = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + Color = "#71dd37", + Description = "Expense has been settled.", + DisplayName = "Mark as Processed", + IsActive = true, + IsSystem = true, + Name = "Processed" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NoOfPersonsRequired") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesTypeMaster"); + + b.HasData( + new + { + Id = new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), + Description = "Materials, equipment and supplies purchased for site operations.", + IsActive = true, + Name = "Procurement", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), + Description = "Vehicle fuel, logistics services and delivery of goods or personnel.", + IsActive = true, + Name = "Transport", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), + Description = "Delivery of personnel.", + IsActive = true, + Name = "Travelling", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), + Description = "Site setup costs including equipment deployment and temporary infrastructure.", + IsActive = true, + Name = "Mobilization", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), + Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", + IsActive = true, + Name = "Employee Welfare", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), + Description = "Machinery servicing, electricity, water, and temporary office needs.", + IsActive = true, + Name = "Maintenance & Utilities", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), + Description = "Scheduled payments for external services or goods.", + IsActive = true, + Name = "Vendor/Supplier Payments", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), + Description = "Government fees, insurance, inspections and safety-related expenditures.", + IsActive = true, + Name = "Compliance & Safety", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ModuleId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ModuleId"); + + b.ToTable("Features"); + + b.HasData( + new + { + Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + Description = "Manage Project", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Project Management" + }, + new + { + Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Expense Management" + }, + new + { + Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + Description = "Manage Tasks", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Task Management" + }, + new + { + Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + Description = "Manage Employee", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Employee Management" + }, + new + { + Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + Description = "Attendance", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Attendance Management" + }, + new + { + Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + Description = "Global Masters", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Masters" + }, + new + { + Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + Description = "Managing all directory related rights", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Directory Management" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Industry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Industries"); + + b.HasData( + new + { + Id = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + Name = "Information Technology (IT) Services" + }, + new + { + Id = new Guid("0a63e657-2c5f-49b5-854b-42c978293154"), + Name = "Manufacturing & Production" + }, + new + { + Id = new Guid("bdc61e3b-69ea-4394-bab6-079ec135b5bd"), + Name = "Energy & Resources" + }, + new + { + Id = new Guid("5ca200ac-00d7-415e-a410-b948e27ac9d2"), + Name = "Finance & Professional Services" + }, + new + { + Id = new Guid("d5621700-cd87-441f-8cdb-6051ddfc83b4"), + Name = "Hospitals and Healthcare Services" + }, + new + { + Id = new Guid("23608891-657e-40f0-bbd4-2b0a2ec1a76f"), + Name = "Social Services" + }, + new + { + Id = new Guid("a493f4e3-16b1-4411-be3c-6bf2987a3168"), + Name = "Retail & Consumer Services" + }, + new + { + Id = new Guid("e9d8ce92-9371-4ed9-9831-83c07f78edec"), + Name = "Transportation & Logistics" + }, + new + { + Id = new Guid("8a0d6134-2dbe-4e0a-b250-ff34cb7b9df0"), + Name = "Education & Training" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Module", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Modules"); + + b.HasData( + new + { + Id = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Description = "Project Module", + Key = "b04da7e9-0406-409c-ac7f-b97256e6ea02", + Name = "Project" + }, + new + { + Id = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Description = "Employee Module", + Key = "0971c7fb-6ce1-458a-ae3f-8d3205893637", + Name = "Employee" + }, + new + { + Id = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Description = "Masters Module", + Key = "504ec132-e6a9-422f-8f85-050602cfce05", + Name = "Masters" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("PaymentModeMatser"); + + b.HasData( + new + { + Id = new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), + Description = "Physical currency; still used for small or informal transactions.", + IsActive = true, + Name = "Cash", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"), + Description = "Paper-based payment order; less common now due to processing delays and fraud risks.", + IsActive = true, + Name = "Cheque", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ed667353-8eea-4fd1-8750-719405932480"), + Description = "Online banking portals used to transfer funds directly between accounts", + IsActive = true, + Name = "NetBanking", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"), + Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", + IsActive = true, + Name = "UPI", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("StatusMasters"); + + b.HasData( + new + { + Id = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + Status = "Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("cdad86aa-8a56-4ff4-b633-9c629057dfef"), + Status = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("603e994b-a27f-4e5d-a251-f3d69b0498ba"), + Status = "On Hold", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), + Status = "In Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"), + Status = "Completed", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketPriorityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketPriorityMasters"); + + b.HasData( + new + { + Id = new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"), + ColorCode = "008000", + IsDefault = true, + Level = 1, + Name = "Low", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"), + ColorCode = "FFFF00", + IsDefault = true, + Level = 2, + Name = "Medium", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 3, + Name = "High", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 4, + Name = "Critical", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"), + ColorCode = "#FF0000", + IsDefault = true, + Level = 5, + Name = "Urgent", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketStatusMasters"); + + b.HasData( + new + { + Id = new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"), + ColorCode = "#FFCC99", + Description = "This is a newly created issue.", + IsDefault = true, + Name = "New", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"), + ColorCode = "#E6FF99", + Description = "Assigned to employee or team of employees", + IsDefault = true, + Name = "Assigned", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"), + ColorCode = "#99E6FF", + Description = "These issues are currently in progress", + IsDefault = true, + Name = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), + ColorCode = "#8592a3", + Description = "These issues are currently under review", + IsDefault = true, + Name = "In Review", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"), + ColorCode = "#B399FF", + Description = "The following issues are resolved and closed", + IsDefault = true, + Name = "Done", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTagMasters"); + + b.HasData( + new + { + Id = new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"), + ColorCode = "#e59866", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"), + ColorCode = "#85c1e9", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkCategoryMasters"); + + b.HasData( + new + { + Id = new Guid("86bb2cc8-f6b5-4fdd-bbee-c389c713a44b"), + Description = "Created new task in a professional or creative context", + IsSystem = true, + Name = "Fresh Work", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("9ebfa19c-53b9-481b-b863-c25d2f843201"), + Description = "Revising, modifying, or correcting a task to improve its quality or fix issues", + IsSystem = true, + Name = "Rework", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("11a79929-1d07-42dc-9e98-82d0d2f4a240"), + Description = "Any defect, deviation, or non-conformance in a task that fails to meet established standards or customer expectations.", + IsSystem = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkStatusMasters"); + + b.HasData( + new + { + Id = new Guid("030bb085-e230-4370-aec7-9a74d652864e"), + Description = "Confirm the tasks are actually finished as reported", + IsSystem = true, + Name = "Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2a1a5b96-cf93-4111-b4b1-76c19d6333b4"), + Description = "Not all tasks are actually finished as reported", + IsSystem = true, + Name = "Partially Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("00a062e6-62e6-42c5-b6b1-024328651b72"), + Description = "Tasks are not finished as reported or have any issues in al the tasks", + IsSystem = true, + Name = "NCR", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BuildingId") + .HasColumnType("char(36)"); + + b.Property("FloorName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BuildingId"); + + b.HasIndex("TenantId"); + + b.ToTable("Floor"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectAddress") + .HasColumnType("longtext"); + + b.Property("ProjectStatusId") + .HasColumnType("char(36)"); + + b.Property("ShortName") + .HasColumnType("longtext"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectStatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + Id = new Guid("85bf587b-7ca9-4685-b77c-d817f5847e85"), + ContactPerson = "Project 1 Contact Person", + EndDate = new DateTime(2026, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + Name = "Project 1", + ProjectAddress = "Project 1 Address", + ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + StartDate = new DateTime(2025, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReAllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ProjectAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AreaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FloorId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FloorId"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkAreas"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("CompletedWork") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedWork") + .HasColumnType("double"); + + b.Property("TaskDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkAreaId") + .HasColumnType("char(36)"); + + b.Property("WorkCategoryId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkAreaId"); + + b.HasIndex("WorkCategoryId"); + + b.ToTable("WorkItems"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Role") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ApplicationRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("JobRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Utilities.Inquiries", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("About") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.Property("OrganizatioinName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Inquiries"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("varchar(21)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + + b.HasDiscriminator().HasValue("IdentityUser"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ApplicationUser", b => + { + b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsRootUser") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasDiscriminator().HasValue("ApplicationUser"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("AssignedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReportedBy") + .WithMany() + .HasForeignKey("ReportedById"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkItem", "WorkItem") + .WithMany() + .HasForeignKey("WorkItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkStatusMaster", "WorkStatus") + .WithMany() + .HasForeignKey("WorkStatusId"); + + b.Navigation("ApprovedBy"); + + b.Navigation("Employee"); + + b.Navigation("ReportedBy"); + + b.Navigation("Tenant"); + + b.Navigation("WorkItem"); + + b.Navigation("WorkStatus"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("CommentedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Approver") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.HasOne("Marco.Pms.Model.AttendanceModule.Attendance", "Attendance") + .WithMany() + .HasForeignKey("AttendanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedByEmployee") + .WithMany() + .HasForeignKey("UpdatedBy"); + + b.Navigation("Attendance"); + + b.Navigation("Document"); + + b.Navigation("Employee"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedByEmployee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedByID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.HasOne("Marco.Pms.Model.Directory.ContactCategoryMaster", "ContactCategory") + .WithMany() + .HasForeignKey("ContactCategoryId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("ContactCategory"); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Createdby") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("Contact"); + + b.Navigation("Createdby"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.ContactTagMaster", "ContactTag") + .WithMany() + .HasForeignKey("ContactTagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("ContactTag"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UploadedBy") + .WithMany() + .HasForeignKey("UploadedById"); + + b.Navigation("Tenant"); + + b.Navigation("UploadedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserId"); + + b.HasOne("Marco.Pms.Model.Roles.JobRole", "JobRole") + .WithMany() + .HasForeignKey("JobRoleId"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApplicationUser"); + + b.Navigation("JobRole"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Role"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.HasOne("Marco.Pms.Model.Master.Feature", "Feature") + .WithMany("FeaturePermissions") + .HasForeignKey("FeatureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Feature"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", null) + .WithMany() + .HasForeignKey("ApplicationRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", null) + .WithMany() + .HasForeignKey("FeaturePermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.HasOne("Marco.Pms.Model.Master.Industry", "Industry") + .WithMany() + .HasForeignKey("IndustryId"); + + b.Navigation("Industry"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Expenses"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expense") + .WithMany() + .HasForeignKey("ExpenseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expense"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesTypeMaster", "ExpensesType") + .WithMany() + .HasForeignKey("ExpensesTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "PaidBy") + .WithMany() + .HasForeignKey("PaidById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.PaymentModeMatser", "PaymentMode") + .WithMany() + .HasForeignKey("PaymentModeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ProcessedBy") + .WithMany() + .HasForeignKey("ProcessedById"); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReviewedBy") + .WithMany() + .HasForeignKey("ReviewedById"); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApprovedBy"); + + b.Navigation("CreatedBy"); + + b.Navigation("ExpensesType"); + + b.Navigation("PaidBy"); + + b.Navigation("PaymentMode"); + + b.Navigation("ProcessedBy"); + + b.Navigation("Project"); + + b.Navigation("ReviewedBy"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReimburseBy") + .WithMany() + .HasForeignKey("ReimburseById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReimburseBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.ExpensesReimburse", "ExpensesReimburse") + .WithMany() + .HasForeignKey("ExpensesReimburseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expenses"); + + b.Navigation("ExpensesReimburse"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "NextStatus") + .WithMany() + .HasForeignKey("NextStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NextStatus"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment") + .WithMany("Attachments") + .HasForeignKey("CommentId"); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + + b.Navigation("TicketComment"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketPriorityMaster", "Priority") + .WithMany() + .HasForeignKey("PriorityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.TicketStatusMaster", "TicketStatusMaster") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketTypeMaster", "TicketTypeMaster") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Priority"); + + b.Navigation("Tenant"); + + b.Navigation("TicketStatusMaster"); + + b.Navigation("TicketTypeMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketTagMaster", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.HasOne("Marco.Pms.Model.Mail.MailingList", "MailBody") + .WithMany() + .HasForeignKey("MailListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MailBody"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", 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.ExpensesTypeMaster", 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.Feature", b => + { + b.HasOne("Marco.Pms.Model.Master.Module", "Module") + .WithMany() + .HasForeignKey("ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", 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") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", 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.WorkStatusMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.HasOne("Marco.Pms.Model.Projects.Building", "Building") + .WithMany() + .HasForeignKey("BuildingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Building"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.HasOne("Marco.Pms.Model.Master.StatusMaster", "ProjectStatus") + .WithMany() + .HasForeignKey("ProjectStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectStatus"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.HasOne("Marco.Pms.Model.Projects.Floor", "Floor") + .WithMany() + .HasForeignKey("FloorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Floor"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.HasOne("Marco.Pms.Model.Master.ActivityMaster", "ActivityMaster") + .WithMany() + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkArea", "WorkArea") + .WithMany() + .HasForeignKey("WorkAreaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkCategoryMaster", "WorkCategoryMaster") + .WithMany() + .HasForeignKey("WorkCategoryId"); + + b.Navigation("ActivityMaster"); + + b.Navigation("Tenant"); + + b.Navigation("WorkArea"); + + b.Navigation("WorkCategoryMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", null) + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Navigation("FeaturePermissions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250730063711_Change_ExpenseStatus_To_Be_System_Scope.cs b/Marco.Pms.DataAccess/Migrations/20250730063711_Change_ExpenseStatus_To_Be_System_Scope.cs new file mode 100644 index 0000000..e8a09c7 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250730063711_Change_ExpenseStatus_To_Be_System_Scope.cs @@ -0,0 +1,437 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Marco.Pms.DataAccess.Migrations +{ + /// + public partial class Change_ExpenseStatus_To_Be_System_Scope : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ExpensesStatusMapping_Tenants_TenantId", + table: "ExpensesStatusMapping"); + + migrationBuilder.DropForeignKey( + name: "FK_ExpensesStatusMaster_Tenants_TenantId", + table: "ExpensesStatusMaster"); + + migrationBuilder.DropForeignKey( + name: "FK_StatusPermissionMapping_Tenants_TenantId", + table: "StatusPermissionMapping"); + + migrationBuilder.DropIndex( + name: "IX_StatusPermissionMapping_TenantId", + table: "StatusPermissionMapping"); + + migrationBuilder.DropIndex( + name: "IX_ExpensesStatusMaster_TenantId", + table: "ExpensesStatusMaster"); + + migrationBuilder.DropIndex( + name: "IX_ExpensesStatusMapping_TenantId", + table: "ExpensesStatusMapping"); + + migrationBuilder.DeleteData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("75bbda6a-6a53-47d1-ad71-5f5f9446a11e")); + + migrationBuilder.DeleteData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("fddaaf20-4ccc-4f4e-a724-dd310272b356")); + + migrationBuilder.DeleteData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("4652d73f-fc71-4fe1-9f2f-1e48b342d741")); + + migrationBuilder.DeleteData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("ed893799-1a5f-4311-a077-de93c86ca8fd")); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "StatusPermissionMapping"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "ExpensesStatusMaster"); + + migrationBuilder.DropColumn( + name: "TenantId", + table: "ExpensesStatusMapping"); + + migrationBuilder.AddColumn( + name: "ApprovedById", + table: "Expenses", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "ProcessedById", + table: "Expenses", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "ReviewedById", + table: "Expenses", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.InsertData( + table: "ExpensesStatusMapping", + columns: new[] { "Id", "NextStatusId", "StatusId" }, + values: new object[] { new Guid("4ddddc10-0ffd-4884-accf-d4fa0bd97f54"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") }); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + columns: new[] { "DisplayName", "Name" }, + values: new object[] { "Mark as Processed", "Processed" }); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + columns: new[] { "Description", "Name" }, + values: new object[] { "Expense was declined, often with a reason(approval rejected).", "Rejected by Approver" }); + + migrationBuilder.InsertData( + table: "ExpensesStatusMaster", + columns: new[] { "Id", "Color", "Description", "DisplayName", "IsActive", "IsSystem", "Name" }, + values: new object[] { new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), "#ff3e1d", "Expense was declined, often with a reason(review rejected).", "Reject", true, true, "Rejected by Reviewer" }); + + migrationBuilder.InsertData( + table: "StatusPermissionMapping", + columns: new[] { "Id", "PermissionId", "StatusId" }, + values: new object[,] + { + { new Guid("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa"), new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") }, + { new Guid("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b"), new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") }, + { new Guid("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d"), new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") } + }); + + migrationBuilder.InsertData( + table: "ExpensesStatusMapping", + columns: new[] { "Id", "NextStatusId", "StatusId" }, + values: new object[,] + { + { new Guid("6b867bec-66e6-42a7-9611-f4595af9b9ce"), new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") }, + { new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") } + }); + + migrationBuilder.InsertData( + table: "StatusPermissionMapping", + columns: new[] { "Id", "PermissionId", "StatusId" }, + values: new object[] { new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") }); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_ApprovedById", + table: "Expenses", + column: "ApprovedById"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_ProcessedById", + table: "Expenses", + column: "ProcessedById"); + + migrationBuilder.CreateIndex( + name: "IX_Expenses_ReviewedById", + table: "Expenses", + column: "ReviewedById"); + + migrationBuilder.AddForeignKey( + name: "FK_Expenses_Employees_ApprovedById", + table: "Expenses", + column: "ApprovedById", + principalTable: "Employees", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Expenses_Employees_ProcessedById", + table: "Expenses", + column: "ProcessedById", + principalTable: "Employees", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Expenses_Employees_ReviewedById", + table: "Expenses", + column: "ReviewedById", + principalTable: "Employees", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Expenses_Employees_ApprovedById", + table: "Expenses"); + + migrationBuilder.DropForeignKey( + name: "FK_Expenses_Employees_ProcessedById", + table: "Expenses"); + + migrationBuilder.DropForeignKey( + name: "FK_Expenses_Employees_ReviewedById", + table: "Expenses"); + + migrationBuilder.DropIndex( + name: "IX_Expenses_ApprovedById", + table: "Expenses"); + + migrationBuilder.DropIndex( + name: "IX_Expenses_ProcessedById", + table: "Expenses"); + + migrationBuilder.DropIndex( + name: "IX_Expenses_ReviewedById", + table: "Expenses"); + + migrationBuilder.DeleteData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("4ddddc10-0ffd-4884-accf-d4fa0bd97f54")); + + migrationBuilder.DeleteData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("6b867bec-66e6-42a7-9611-f4595af9b9ce")); + + migrationBuilder.DeleteData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e")); + + migrationBuilder.DeleteData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa")); + + migrationBuilder.DeleteData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b")); + + migrationBuilder.DeleteData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d")); + + migrationBuilder.DeleteData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e")); + + migrationBuilder.DeleteData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("965eda62-7907-4963-b4a1-657fb0b2724b")); + + migrationBuilder.DropColumn( + name: "ApprovedById", + table: "Expenses"); + + migrationBuilder.DropColumn( + name: "ProcessedById", + table: "Expenses"); + + migrationBuilder.DropColumn( + name: "ReviewedById", + table: "Expenses"); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "StatusPermissionMapping", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "ExpensesStatusMaster", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "TenantId", + table: "ExpensesStatusMapping", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMapping", + keyColumn: "Id", + keyValue: new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.InsertData( + table: "ExpensesStatusMapping", + columns: new[] { "Id", "NextStatusId", "StatusId", "TenantId" }, + values: new object[,] + { + { new Guid("75bbda6a-6a53-47d1-ad71-5f5f9446a11e"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("fddaaf20-4ccc-4f4e-a724-dd310272b356"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + columns: new[] { "DisplayName", "Name", "TenantId" }, + values: new object[] { "Mark as Paid", "Paid", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + columns: new[] { "Description", "Name", "TenantId" }, + values: new object[] { "Expense was declined, often with a reason(either review rejected or approval rejected.", "Rejected", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }); + + migrationBuilder.UpdateData( + table: "ExpensesStatusMaster", + keyColumn: "Id", + keyValue: new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.UpdateData( + table: "StatusPermissionMapping", + keyColumn: "Id", + keyValue: new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + column: "TenantId", + value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26")); + + migrationBuilder.InsertData( + table: "StatusPermissionMapping", + columns: new[] { "Id", "PermissionId", "StatusId", "TenantId" }, + values: new object[,] + { + { new Guid("4652d73f-fc71-4fe1-9f2f-1e48b342d741"), new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("ed893799-1a5f-4311-a077-de93c86ca8fd"), new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.CreateIndex( + name: "IX_StatusPermissionMapping_TenantId", + table: "StatusPermissionMapping", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesStatusMaster_TenantId", + table: "ExpensesStatusMaster", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ExpensesStatusMapping_TenantId", + table: "ExpensesStatusMapping", + column: "TenantId"); + + migrationBuilder.AddForeignKey( + name: "FK_ExpensesStatusMapping_Tenants_TenantId", + table: "ExpensesStatusMapping", + column: "TenantId", + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_ExpensesStatusMaster_Tenants_TenantId", + table: "ExpensesStatusMaster", + column: "TenantId", + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_StatusPermissionMapping_Tenants_TenantId", + table: "StatusPermissionMapping", + column: "TenantId", + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250730070549_Added_CurrencyMaster_Table.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250730070549_Added_CurrencyMaster_Table.Designer.cs new file mode 100644 index 0000000..fd265dd --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250730070549_Added_CurrencyMaster_Table.Designer.cs @@ -0,0 +1,4430 @@ +// +using System; +using Marco.Pms.DataAccess.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Marco.Pms.DataAccess.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250730070549_Added_CurrencyMaster_Table")] + partial class Added_CurrencyMaster_Table + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + //MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime(6)"); + + b.Property("AssignedBy") + .HasColumnType("char(36)"); + + b.Property("AssignmentDate") + .HasColumnType("datetime(6)"); + + b.Property("CompletedTask") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedTask") + .HasColumnType("double"); + + b.Property("ReportedById") + .HasColumnType("char(36)"); + + b.Property("ReportedDate") + .HasColumnType("datetime(6)"); + + b.Property("ReportedTask") + .HasColumnType("double"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkItemId") + .HasColumnType("char(36)"); + + b.Property("WorkStatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("AssignedBy"); + + b.HasIndex("ReportedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkItemId"); + + b.HasIndex("WorkStatusId"); + + b.ToTable("TaskAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TaskAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CommentDate") + .HasColumnType("datetime(6)"); + + b.Property("CommentedBy") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentedBy"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskMembers"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("AttendanceDate") + .HasColumnType("datetime(6)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("InTime") + .HasColumnType("datetime(6)"); + + b.Property("IsApproved") + .HasColumnType("tinyint(1)"); + + b.Property("OutTime") + .HasColumnType("datetime(6)"); + + b.Property("ProjectID") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.ToTable("Attendes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ActivityTime") + .HasColumnType("datetime(6)"); + + b.Property("AttendanceId") + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("Latitude") + .HasColumnType("longtext"); + + b.Property("Longitude") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("AttendanceId"); + + b.HasIndex("DocumentId"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("AttendanceLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MPIN") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MPINToken") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("MPINDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpriesInSec") + .HasColumnType("int"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("OTP") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("OTPDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsRevoked") + .HasColumnType("tinyint(1)"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("RevokedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByID") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByID"); + + b.HasIndex("TenantId"); + + b.ToTable("Buckets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ContactCategoryId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Organization") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactCategoryId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactCategoryMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsEmails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ContactNotes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsPhones"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactProjectMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ContactTagId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ContactTagId"); + + b.ToTable("ContactTagMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactTagMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("RefereanceId") + .HasColumnType("char(36)"); + + b.Property("UpdateAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UpdatedById"); + + b.ToTable("DirectoryUpdateLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("EmployeeBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Base64Data") + .HasColumnType("longtext"); + + b.Property("BatchId") + .HasColumnType("char(36)"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("S3Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("ThumbS3Key") + .HasColumnType("longtext"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.Property("UploadedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("UploadedById"); + + b.ToTable("Documents"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AadharNumber") + .HasColumnType("longtext"); + + b.Property("ApplicationUserId") + .HasColumnType("varchar(255)"); + + b.Property("BirthDate") + .HasColumnType("datetime(6)"); + + b.Property("CurrentAddress") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("EmergencyContactPerson") + .HasColumnType("longtext"); + + b.Property("EmergencyPhoneNumber") + .HasColumnType("longtext"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("JoiningDate") + .HasColumnType("datetime(6)"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("MiddleName") + .HasColumnType("longtext"); + + b.Property("PanNumber") + .HasColumnType("longtext"); + + b.Property("PermanentAddress") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.HasIndex("JobRoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("Employees"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("RoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("EmployeeRoleMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkShifts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ActivityCheckList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsChecked") + .HasColumnType("tinyint(1)"); + + b.Property("IsMandatory") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("ActivityCheckLists"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.CheckListMappings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckListId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("CheckListMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("FeatureId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("FeaturePermissions"); + + b.HasData( + new + { + Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), + Description = "Access all information related to the project.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project" + }, + new + { + Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), + Description = "Potentially edit the project name, description, start/end dates, or status.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project" + }, + new + { + Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), + Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Team" + }, + new + { + Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), + Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project Infra" + }, + new + { + Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), + Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project Infra" + }, + new + { + Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), + Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions.", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "View Task" + }, + new + { + Id = new Guid("08752f33-3b29-4816-b76b-ea8a968ed3c5"), + Description = "This allows them to create new tasks, modify existing task attributes (description, status, assignee, due date, etc.),", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Add/Edit Task" + }, + new + { + Id = new Guid("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"), + Description = "Grants a user the ability to designate team members responsible for specific tasks and to update the completion status or provide progress updates for those tasks", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Assign/Report Progress" + }, + new + { + Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), + Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Approve Task" + }, + new + { + Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), + Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View All Employees" + }, + new + { + Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), + Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View Team Members" + }, + new + { + Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), + Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Add/Edit Employee" + }, + new + { + Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), + Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system.", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Assign Roles" + }, + new + { + Id = new Guid("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Team Attendance " + }, + new + { + Id = new Guid("57802c4a-00aa-4a1f-a048-fd2f70dd44b6"), + Description = "Grants a user the authority to approve requests from employees to adjust or correct their recorded attendance. This typically involves reviewing the reason for the regularization, verifying any supporting documentation, and then officially accepting the changes to the employee's attendance records", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Regularize Attendance" + }, + new + { + Id = new Guid("ccb0589f-712b-43de-92ed-5b6088e7dc4e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Self Attendance" + }, + new + { + Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), + Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "View Masters" + }, + new + { + Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), + Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "Manage Masters" + }, + new + { + Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), + Description = "Full control over all directories, including the ability to manage permissions for all directories in the system.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Admin" + }, + new + { + Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), + Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Manager" + }, + new + { + Id = new Guid("0f919170-92d4-4337-abd3-49b66fc871bb"), + Description = "Full control over directories they created. Can view contacts in directories they either created or were assigned to. Can manage permissions only for directories they created.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory User" + }, + new + { + Id = new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), + Description = "Allows a user to view only the expense records that they have personally submitted", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View Self" + }, + new + { + Id = new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), + Description = "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View All" + }, + new + { + Id = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + Description = "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Upload" + }, + new + { + Id = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + Description = "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Review" + }, + new + { + Id = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + Description = "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Approve" + }, + new + { + Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Process" + }, + new + { + Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), + Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Manage" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.Property("ApplicationRoleId") + .HasColumnType("char(36)"); + + b.Property("FeaturePermissionId") + .HasColumnType("char(36)"); + + b.HasKey("ApplicationRoleId", "FeaturePermissionId"); + + b.HasIndex("FeaturePermissionId"); + + b.ToTable("RolePermissionMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactName") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DomainName") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OnBoardingDate") + .HasColumnType("datetime(6)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("IndustryId"); + + b.ToTable("Tenants"); + + b.HasData( + new + { + Id = new Guid("b3466e83-7e11-464c-b93a-daf047838b26"), + ContactName = "Admin", + ContactNumber = "123456789", + Description = "", + DomainName = "www.marcobms.org", + IndustryId = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + IsActive = true, + Name = "MarcoBMS", + OnBoardingDate = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + OragnizationSize = "100-200" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("TenantId"); + + b.ToTable("BillAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Action") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("ExpenseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpenseId"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ExpenseLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpensesTypeId") + .HasColumnType("char(36)"); + + b.Property("GSTNumber") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .HasColumnType("longtext"); + + b.Property("NoOfPersons") + .HasColumnType("int"); + + b.Property("PaidById") + .HasColumnType("char(36)"); + + b.Property("PaymentModeId") + .HasColumnType("char(36)"); + + b.Property("PreApproved") + .HasColumnType("tinyint(1)"); + + b.Property("ProcessedById") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReviewedById") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("SupplerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TransactionDate") + .HasColumnType("datetime(6)"); + + b.Property("TransactionId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ExpensesTypeId"); + + b.HasIndex("PaidById"); + + b.HasIndex("PaymentModeId"); + + b.HasIndex("ProcessedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("ReviewedById"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Expenses"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ReimburseById") + .HasColumnType("char(36)"); + + b.Property("ReimburseDate") + .HasColumnType("datetime(6)"); + + b.Property("ReimburseNote") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReimburseTransactionId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ReimburseById"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburse"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("ExpensesReimburseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("ExpensesReimburseId"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburseMapping"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("NextStatusId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("NextStatusId"); + + b.HasIndex("StatusId"); + + b.ToTable("ExpensesStatusMapping"); + + b.HasData( + new + { + Id = new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + NextStatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("4ddddc10-0ffd-4884-accf-d4fa0bd97f54"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), + NextStatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), + NextStatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("6b867bec-66e6-42a7-9611-f4595af9b9ce"), + NextStatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + NextStatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("PermissionId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PermissionId"); + + b.HasIndex("StatusId"); + + b.ToTable("StatusPermissionMapping"); + + b.HasData( + new + { + Id = new Guid("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }, + new + { + Id = new Guid("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + PermissionId = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + StatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CommentId") + .HasColumnType("char(36)"); + + b.Property("FileId") + .HasColumnType("char(36)"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AuthorId") + .HasColumnType("char(36)"); + + b.Property("MessageText") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ParentMessageId") + .HasColumnType("char(36)"); + + b.Property("SentAt") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("TicketComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LinkedActivityId") + .HasColumnType("char(36)"); + + b.Property("LinkedProjectId") + .HasColumnType("char(36)"); + + b.Property("PriorityId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TypeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PriorityId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.HasIndex("TypeId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("TagId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TagId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketTags"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTypeMasters"); + + b.HasData( + new + { + Id = new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"), + Description = "An identified problem that affects the performance, reliability, or standards of a product or service", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"), + Description = "A support service that assists users with technical issues, requests, or inquiries.", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MailListId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("Recipient") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("MailListId"); + + b.ToTable("MailDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmailId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("MailLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailingList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Keywords") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("MailingList"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityName") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UnitOfMeasurement") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ActivityMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.CurrencyMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CurrencyCode") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CurrencyName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("CurrencyMaster"); + + b.HasData( + new + { + Id = new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"), + CurrencyCode = "INR", + CurrencyName = "Indian Rupee", + IsActive = true, + Symbol = "₹" + }, + new + { + Id = new Guid("2f672568-a67b-4961-acb2-a8c7834e1762"), + CurrencyCode = "USD", + CurrencyName = "US Dollar", + IsActive = true, + Symbol = "$" + }, + new + { + Id = new Guid("4d1155bb-1448-4d97-a732-96c92eb99c45"), + CurrencyCode = "EUR", + CurrencyName = "Euro", + IsActive = true, + Symbol = "€" + }, + new + { + Id = new Guid("3e456237-ef06-4ea1-a261-188c9b0c6df6"), + CurrencyCode = "GBP", + CurrencyName = "Pound Sterling", + IsActive = true, + Symbol = "£" + }, + new + { + Id = new Guid("297e237a-56d3-48f6-b39d-ec3991dea8bf"), + CurrencyCode = "JPY", + CurrencyName = "Japanese Yen", + IsActive = true, + Symbol = "¥" + }, + new + { + Id = new Guid("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"), + CurrencyCode = "RUB", + CurrencyName = "Russian Ruble", + IsActive = true, + Symbol = "₽" + }, + new + { + Id = new Guid("b960166a-f7e9-49e3-bb4b-28511f126c08"), + CurrencyCode = "CNY", + CurrencyName = "Chinese Yuan (Renminbi)", + IsActive = true, + Symbol = "¥" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ExpensesStatusMaster"); + + b.HasData( + new + { + Id = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + Color = "#8592a3", + Description = "Expense has been created but not yet submitted.", + DisplayName = "Draft", + IsActive = true, + IsSystem = true, + Name = "Draft" + }, + new + { + Id = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + Color = "#696cff", + Description = "Reviewer is currently reviewing the expense.", + DisplayName = "Submit", + IsActive = true, + IsSystem = true, + Name = "Review Pending" + }, + new + { + Id = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(review rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Reviewer" + }, + new + { + Id = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + Color = "#03c3ec", + Description = "Review is completed, waiting for action of approver.", + DisplayName = "Mark as Reviewed", + IsActive = true, + IsSystem = true, + Name = "Approval Pending" + }, + new + { + Id = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(approval rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Approver" + }, + new + { + Id = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + Color = "#ffab00", + Description = "Approved expense is awaiting final payment.", + DisplayName = "Mark as Approved", + IsActive = true, + IsSystem = true, + Name = "Payment Pending" + }, + new + { + Id = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + Color = "#71dd37", + Description = "Expense has been settled.", + DisplayName = "Mark as Processed", + IsActive = true, + IsSystem = true, + Name = "Processed" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NoOfPersonsRequired") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesTypeMaster"); + + b.HasData( + new + { + Id = new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), + Description = "Materials, equipment and supplies purchased for site operations.", + IsActive = true, + Name = "Procurement", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), + Description = "Vehicle fuel, logistics services and delivery of goods or personnel.", + IsActive = true, + Name = "Transport", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), + Description = "Delivery of personnel.", + IsActive = true, + Name = "Travelling", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), + Description = "Site setup costs including equipment deployment and temporary infrastructure.", + IsActive = true, + Name = "Mobilization", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), + Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", + IsActive = true, + Name = "Employee Welfare", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), + Description = "Machinery servicing, electricity, water, and temporary office needs.", + IsActive = true, + Name = "Maintenance & Utilities", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), + Description = "Scheduled payments for external services or goods.", + IsActive = true, + Name = "Vendor/Supplier Payments", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), + Description = "Government fees, insurance, inspections and safety-related expenditures.", + IsActive = true, + Name = "Compliance & Safety", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ModuleId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ModuleId"); + + b.ToTable("Features"); + + b.HasData( + new + { + Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + Description = "Manage Project", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Project Management" + }, + new + { + Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Expense Management" + }, + new + { + Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + Description = "Manage Tasks", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Task Management" + }, + new + { + Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + Description = "Manage Employee", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Employee Management" + }, + new + { + Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + Description = "Attendance", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Attendance Management" + }, + new + { + Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + Description = "Global Masters", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Masters" + }, + new + { + Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + Description = "Managing all directory related rights", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Directory Management" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Industry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Industries"); + + b.HasData( + new + { + Id = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + Name = "Information Technology (IT) Services" + }, + new + { + Id = new Guid("0a63e657-2c5f-49b5-854b-42c978293154"), + Name = "Manufacturing & Production" + }, + new + { + Id = new Guid("bdc61e3b-69ea-4394-bab6-079ec135b5bd"), + Name = "Energy & Resources" + }, + new + { + Id = new Guid("5ca200ac-00d7-415e-a410-b948e27ac9d2"), + Name = "Finance & Professional Services" + }, + new + { + Id = new Guid("d5621700-cd87-441f-8cdb-6051ddfc83b4"), + Name = "Hospitals and Healthcare Services" + }, + new + { + Id = new Guid("23608891-657e-40f0-bbd4-2b0a2ec1a76f"), + Name = "Social Services" + }, + new + { + Id = new Guid("a493f4e3-16b1-4411-be3c-6bf2987a3168"), + Name = "Retail & Consumer Services" + }, + new + { + Id = new Guid("e9d8ce92-9371-4ed9-9831-83c07f78edec"), + Name = "Transportation & Logistics" + }, + new + { + Id = new Guid("8a0d6134-2dbe-4e0a-b250-ff34cb7b9df0"), + Name = "Education & Training" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Module", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Modules"); + + b.HasData( + new + { + Id = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Description = "Project Module", + Key = "b04da7e9-0406-409c-ac7f-b97256e6ea02", + Name = "Project" + }, + new + { + Id = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Description = "Employee Module", + Key = "0971c7fb-6ce1-458a-ae3f-8d3205893637", + Name = "Employee" + }, + new + { + Id = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Description = "Masters Module", + Key = "504ec132-e6a9-422f-8f85-050602cfce05", + Name = "Masters" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("PaymentModeMatser"); + + b.HasData( + new + { + Id = new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), + Description = "Physical currency; still used for small or informal transactions.", + IsActive = true, + Name = "Cash", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"), + Description = "Paper-based payment order; less common now due to processing delays and fraud risks.", + IsActive = true, + Name = "Cheque", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ed667353-8eea-4fd1-8750-719405932480"), + Description = "Online banking portals used to transfer funds directly between accounts", + IsActive = true, + Name = "NetBanking", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"), + Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", + IsActive = true, + Name = "UPI", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("StatusMasters"); + + b.HasData( + new + { + Id = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + Status = "Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("cdad86aa-8a56-4ff4-b633-9c629057dfef"), + Status = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("603e994b-a27f-4e5d-a251-f3d69b0498ba"), + Status = "On Hold", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), + Status = "In Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"), + Status = "Completed", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketPriorityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketPriorityMasters"); + + b.HasData( + new + { + Id = new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"), + ColorCode = "008000", + IsDefault = true, + Level = 1, + Name = "Low", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"), + ColorCode = "FFFF00", + IsDefault = true, + Level = 2, + Name = "Medium", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 3, + Name = "High", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 4, + Name = "Critical", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"), + ColorCode = "#FF0000", + IsDefault = true, + Level = 5, + Name = "Urgent", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketStatusMasters"); + + b.HasData( + new + { + Id = new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"), + ColorCode = "#FFCC99", + Description = "This is a newly created issue.", + IsDefault = true, + Name = "New", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"), + ColorCode = "#E6FF99", + Description = "Assigned to employee or team of employees", + IsDefault = true, + Name = "Assigned", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"), + ColorCode = "#99E6FF", + Description = "These issues are currently in progress", + IsDefault = true, + Name = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), + ColorCode = "#8592a3", + Description = "These issues are currently under review", + IsDefault = true, + Name = "In Review", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"), + ColorCode = "#B399FF", + Description = "The following issues are resolved and closed", + IsDefault = true, + Name = "Done", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTagMasters"); + + b.HasData( + new + { + Id = new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"), + ColorCode = "#e59866", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"), + ColorCode = "#85c1e9", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkCategoryMasters"); + + b.HasData( + new + { + Id = new Guid("86bb2cc8-f6b5-4fdd-bbee-c389c713a44b"), + Description = "Created new task in a professional or creative context", + IsSystem = true, + Name = "Fresh Work", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("9ebfa19c-53b9-481b-b863-c25d2f843201"), + Description = "Revising, modifying, or correcting a task to improve its quality or fix issues", + IsSystem = true, + Name = "Rework", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("11a79929-1d07-42dc-9e98-82d0d2f4a240"), + Description = "Any defect, deviation, or non-conformance in a task that fails to meet established standards or customer expectations.", + IsSystem = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkStatusMasters"); + + b.HasData( + new + { + Id = new Guid("030bb085-e230-4370-aec7-9a74d652864e"), + Description = "Confirm the tasks are actually finished as reported", + IsSystem = true, + Name = "Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2a1a5b96-cf93-4111-b4b1-76c19d6333b4"), + Description = "Not all tasks are actually finished as reported", + IsSystem = true, + Name = "Partially Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("00a062e6-62e6-42c5-b6b1-024328651b72"), + Description = "Tasks are not finished as reported or have any issues in al the tasks", + IsSystem = true, + Name = "NCR", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BuildingId") + .HasColumnType("char(36)"); + + b.Property("FloorName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BuildingId"); + + b.HasIndex("TenantId"); + + b.ToTable("Floor"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectAddress") + .HasColumnType("longtext"); + + b.Property("ProjectStatusId") + .HasColumnType("char(36)"); + + b.Property("ShortName") + .HasColumnType("longtext"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectStatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + Id = new Guid("85bf587b-7ca9-4685-b77c-d817f5847e85"), + ContactPerson = "Project 1 Contact Person", + EndDate = new DateTime(2026, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + Name = "Project 1", + ProjectAddress = "Project 1 Address", + ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + StartDate = new DateTime(2025, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReAllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ProjectAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AreaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FloorId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FloorId"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkAreas"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("CompletedWork") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedWork") + .HasColumnType("double"); + + b.Property("TaskDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkAreaId") + .HasColumnType("char(36)"); + + b.Property("WorkCategoryId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkAreaId"); + + b.HasIndex("WorkCategoryId"); + + b.ToTable("WorkItems"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Role") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ApplicationRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("JobRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Utilities.Inquiries", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("About") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.Property("OrganizatioinName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Inquiries"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("varchar(21)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + + b.HasDiscriminator().HasValue("IdentityUser"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ApplicationUser", b => + { + b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsRootUser") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasDiscriminator().HasValue("ApplicationUser"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("AssignedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReportedBy") + .WithMany() + .HasForeignKey("ReportedById"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkItem", "WorkItem") + .WithMany() + .HasForeignKey("WorkItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkStatusMaster", "WorkStatus") + .WithMany() + .HasForeignKey("WorkStatusId"); + + b.Navigation("ApprovedBy"); + + b.Navigation("Employee"); + + b.Navigation("ReportedBy"); + + b.Navigation("Tenant"); + + b.Navigation("WorkItem"); + + b.Navigation("WorkStatus"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("CommentedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Approver") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.HasOne("Marco.Pms.Model.AttendanceModule.Attendance", "Attendance") + .WithMany() + .HasForeignKey("AttendanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedByEmployee") + .WithMany() + .HasForeignKey("UpdatedBy"); + + b.Navigation("Attendance"); + + b.Navigation("Document"); + + b.Navigation("Employee"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedByEmployee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedByID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.HasOne("Marco.Pms.Model.Directory.ContactCategoryMaster", "ContactCategory") + .WithMany() + .HasForeignKey("ContactCategoryId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("ContactCategory"); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Createdby") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("Contact"); + + b.Navigation("Createdby"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.ContactTagMaster", "ContactTag") + .WithMany() + .HasForeignKey("ContactTagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("ContactTag"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UploadedBy") + .WithMany() + .HasForeignKey("UploadedById"); + + b.Navigation("Tenant"); + + b.Navigation("UploadedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserId"); + + b.HasOne("Marco.Pms.Model.Roles.JobRole", "JobRole") + .WithMany() + .HasForeignKey("JobRoleId"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApplicationUser"); + + b.Navigation("JobRole"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Role"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.HasOne("Marco.Pms.Model.Master.Feature", "Feature") + .WithMany("FeaturePermissions") + .HasForeignKey("FeatureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Feature"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", null) + .WithMany() + .HasForeignKey("ApplicationRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", null) + .WithMany() + .HasForeignKey("FeaturePermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.HasOne("Marco.Pms.Model.Master.Industry", "Industry") + .WithMany() + .HasForeignKey("IndustryId"); + + b.Navigation("Industry"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Expenses"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expense") + .WithMany() + .HasForeignKey("ExpenseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expense"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesTypeMaster", "ExpensesType") + .WithMany() + .HasForeignKey("ExpensesTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "PaidBy") + .WithMany() + .HasForeignKey("PaidById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.PaymentModeMatser", "PaymentMode") + .WithMany() + .HasForeignKey("PaymentModeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ProcessedBy") + .WithMany() + .HasForeignKey("ProcessedById"); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReviewedBy") + .WithMany() + .HasForeignKey("ReviewedById"); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApprovedBy"); + + b.Navigation("CreatedBy"); + + b.Navigation("ExpensesType"); + + b.Navigation("PaidBy"); + + b.Navigation("PaymentMode"); + + b.Navigation("ProcessedBy"); + + b.Navigation("Project"); + + b.Navigation("ReviewedBy"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReimburseBy") + .WithMany() + .HasForeignKey("ReimburseById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReimburseBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.ExpensesReimburse", "ExpensesReimburse") + .WithMany() + .HasForeignKey("ExpensesReimburseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expenses"); + + b.Navigation("ExpensesReimburse"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "NextStatus") + .WithMany() + .HasForeignKey("NextStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NextStatus"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment") + .WithMany("Attachments") + .HasForeignKey("CommentId"); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + + b.Navigation("TicketComment"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketPriorityMaster", "Priority") + .WithMany() + .HasForeignKey("PriorityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.TicketStatusMaster", "TicketStatusMaster") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketTypeMaster", "TicketTypeMaster") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Priority"); + + b.Navigation("Tenant"); + + b.Navigation("TicketStatusMaster"); + + b.Navigation("TicketTypeMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketTagMaster", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.HasOne("Marco.Pms.Model.Mail.MailingList", "MailBody") + .WithMany() + .HasForeignKey("MailListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MailBody"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", 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.ExpensesTypeMaster", 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.Feature", b => + { + b.HasOne("Marco.Pms.Model.Master.Module", "Module") + .WithMany() + .HasForeignKey("ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", 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") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", 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.WorkStatusMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.HasOne("Marco.Pms.Model.Projects.Building", "Building") + .WithMany() + .HasForeignKey("BuildingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Building"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.HasOne("Marco.Pms.Model.Master.StatusMaster", "ProjectStatus") + .WithMany() + .HasForeignKey("ProjectStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectStatus"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.HasOne("Marco.Pms.Model.Projects.Floor", "Floor") + .WithMany() + .HasForeignKey("FloorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Floor"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.HasOne("Marco.Pms.Model.Master.ActivityMaster", "ActivityMaster") + .WithMany() + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkArea", "WorkArea") + .WithMany() + .HasForeignKey("WorkAreaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkCategoryMaster", "WorkCategoryMaster") + .WithMany() + .HasForeignKey("WorkCategoryId"); + + b.Navigation("ActivityMaster"); + + b.Navigation("Tenant"); + + b.Navigation("WorkArea"); + + b.Navigation("WorkCategoryMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", null) + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Navigation("FeaturePermissions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250730070549_Added_CurrencyMaster_Table.cs b/Marco.Pms.DataAccess/Migrations/20250730070549_Added_CurrencyMaster_Table.cs new file mode 100644 index 0000000..d525786 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250730070549_Added_CurrencyMaster_Table.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Marco.Pms.DataAccess.Migrations +{ + /// + public partial class Added_CurrencyMaster_Table : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CurrencyMaster", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CurrencyCode = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CurrencyName = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Symbol = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CurrencyMaster", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "CurrencyMaster", + columns: new[] { "Id", "CurrencyCode", "CurrencyName", "IsActive", "Symbol" }, + values: new object[,] + { + { new Guid("297e237a-56d3-48f6-b39d-ec3991dea8bf"), "JPY", "Japanese Yen", true, "¥" }, + { new Guid("2f672568-a67b-4961-acb2-a8c7834e1762"), "USD", "US Dollar", true, "$" }, + { new Guid("3e456237-ef06-4ea1-a261-188c9b0c6df6"), "GBP", "Pound Sterling", true, "£" }, + { new Guid("4d1155bb-1448-4d97-a732-96c92eb99c45"), "EUR", "Euro", true, "€" }, + { new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"), "INR", "Indian Rupee", true, "₹" }, + { new Guid("b960166a-f7e9-49e3-bb4b-28511f126c08"), "CNY", "Chinese Yuan (Renminbi)", true, "¥" }, + { new Guid("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"), "RUB", "Russian Ruble", true, "₽" } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CurrencyMaster"); + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250804053705_Added_Updated_At_In_UpdateLogs.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250804053705_Added_Updated_At_In_UpdateLogs.Designer.cs new file mode 100644 index 0000000..5b67b33 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250804053705_Added_Updated_At_In_UpdateLogs.Designer.cs @@ -0,0 +1,4437 @@ +// +using System; +using Marco.Pms.DataAccess.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Marco.Pms.DataAccess.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250804053705_Added_Updated_At_In_UpdateLogs")] + partial class Added_Updated_At_In_UpdateLogs + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + //MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime(6)"); + + b.Property("AssignedBy") + .HasColumnType("char(36)"); + + b.Property("AssignmentDate") + .HasColumnType("datetime(6)"); + + b.Property("CompletedTask") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedTask") + .HasColumnType("double"); + + b.Property("ReportedById") + .HasColumnType("char(36)"); + + b.Property("ReportedDate") + .HasColumnType("datetime(6)"); + + b.Property("ReportedTask") + .HasColumnType("double"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkItemId") + .HasColumnType("char(36)"); + + b.Property("WorkStatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("AssignedBy"); + + b.HasIndex("ReportedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkItemId"); + + b.HasIndex("WorkStatusId"); + + b.ToTable("TaskAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TaskAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CommentDate") + .HasColumnType("datetime(6)"); + + b.Property("CommentedBy") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentedBy"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("TaskAllocationId"); + + b.HasIndex("TenantId"); + + b.ToTable("TaskMembers"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("AttendanceDate") + .HasColumnType("datetime(6)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("InTime") + .HasColumnType("datetime(6)"); + + b.Property("IsApproved") + .HasColumnType("tinyint(1)"); + + b.Property("OutTime") + .HasColumnType("datetime(6)"); + + b.Property("ProjectID") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.ToTable("Attendes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Activity") + .HasColumnType("int"); + + b.Property("ActivityTime") + .HasColumnType("datetime(6)"); + + b.Property("AttendanceId") + .HasColumnType("char(36)"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("EmployeeID") + .HasColumnType("char(36)"); + + b.Property("Latitude") + .HasColumnType("longtext"); + + b.Property("Longitude") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("AttendanceId"); + + b.HasIndex("DocumentId"); + + b.HasIndex("EmployeeID"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("AttendanceLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MPIN") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MPINToken") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("MPINDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpriesInSec") + .HasColumnType("int"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("OTP") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("OTPDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsRevoked") + .HasColumnType("tinyint(1)"); + + b.Property("IsUsed") + .HasColumnType("tinyint(1)"); + + b.Property("RevokedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByID") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByID"); + + b.HasIndex("TenantId"); + + b.ToTable("Buckets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ContactCategoryId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Designation") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Organization") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactCategoryId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactCategoryMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsEmails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ContactNotes"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("IsPrimary") + .HasColumnType("tinyint(1)"); + + b.Property("Label") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("ContactsPhones"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactProjectMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactId") + .HasColumnType("char(36)"); + + b.Property("ContactTagId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("ContactTagId"); + + b.ToTable("ContactTagMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ContactTagMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("RefereanceId") + .HasColumnType("char(36)"); + + b.Property("UpdateAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UpdatedById"); + + b.ToTable("DirectoryUpdateLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BucketId") + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BucketId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("EmployeeBucketMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Base64Data") + .HasColumnType("longtext"); + + b.Property("BatchId") + .HasColumnType("char(36)"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("S3Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("ThumbS3Key") + .HasColumnType("longtext"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.Property("UploadedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("UploadedById"); + + b.ToTable("Documents"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AadharNumber") + .HasColumnType("longtext"); + + b.Property("ApplicationUserId") + .HasColumnType("varchar(255)"); + + b.Property("BirthDate") + .HasColumnType("datetime(6)"); + + b.Property("CurrentAddress") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("EmergencyContactPerson") + .HasColumnType("longtext"); + + b.Property("EmergencyPhoneNumber") + .HasColumnType("longtext"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("JoiningDate") + .HasColumnType("datetime(6)"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("MiddleName") + .HasColumnType("longtext"); + + b.Property("PanNumber") + .HasColumnType("longtext"); + + b.Property("PermanentAddress") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("Photo") + .HasColumnType("longblob"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.HasIndex("JobRoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("Employees"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("RoleId"); + + b.HasIndex("TenantId"); + + b.ToTable("EmployeeRoleMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EndTime") + .HasColumnType("time(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("StartTime") + .HasColumnType("time(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkShifts"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ActivityCheckList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsChecked") + .HasColumnType("tinyint(1)"); + + b.Property("IsMandatory") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("ActivityCheckLists"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.CheckListMappings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckListId") + .HasColumnType("char(36)"); + + b.Property("TaskAllocationId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("CheckListMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("FeatureId") + .HasColumnType("char(36)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("FeaturePermissions"); + + b.HasData( + new + { + Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), + Description = "Access all information related to the project.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project" + }, + new + { + Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), + Description = "Potentially edit the project name, description, start/end dates, or status.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project" + }, + new + { + Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), + Description = "The \"Manage Team\" feature allows authorized users to organize project personnel by adding, removing, and assigning employee to projects.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Team" + }, + new + { + Id = new Guid("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4"), + Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "View Project Infra" + }, + new + { + Id = new Guid("cf2825ad-453b-46aa-91d9-27c124d63373"), + Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", + FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + IsEnabled = true, + Name = "Manage Project Infra" + }, + new + { + Id = new Guid("9fcc5f87-25e3-4846-90ac-67a71ab92e3c"), + Description = "Grants a user comprehensive read-only access to all details associated with tasks within a project. This includes task descriptions, statuses, assignees, due dates, dependencies, progress, history, and any related attachments or discussions.", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "View Task" + }, + new + { + Id = new Guid("08752f33-3b29-4816-b76b-ea8a968ed3c5"), + Description = "This allows them to create new tasks, modify existing task attributes (description, status, assignee, due date, etc.),", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Add/Edit Task" + }, + new + { + Id = new Guid("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"), + Description = "Grants a user the ability to designate team members responsible for specific tasks and to update the completion status or provide progress updates for those tasks", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Assign/Report Progress" + }, + new + { + Id = new Guid("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"), + Description = "Grants a user the authority to officially confirm the completion or acceptance of a task, often signifying that it meets the required standards or criteria", + FeatureId = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + IsEnabled = true, + Name = "Approve Task" + }, + new + { + Id = new Guid("60611762-7f8a-4fb5-b53f-b1139918796b"), + Description = "Grants a user read-only access to details about the all individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View All Employees" + }, + new + { + Id = new Guid("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), + Description = "Grants a user read-only access to details about the individuals within the system which are is assigned to same projects as user. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View Team Members" + }, + new + { + Id = new Guid("a97d366a-c2bb-448d-be93-402bd2324566"), + Description = "Grants a user the authority to create new employee profiles and modify existing employee details within the system. This typically includes adding or updating information such as names, contact details, roles, departments, skills, and potentially other personal or professional data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Add/Edit Employee" + }, + new + { + Id = new Guid("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3"), + Description = "Grants a user the authority to manage employee application roles, enabling them to assign or revoke access privileges within the system.", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "Assign Roles" + }, + new + { + Id = new Guid("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Team Attendance " + }, + new + { + Id = new Guid("57802c4a-00aa-4a1f-a048-fd2f70dd44b6"), + Description = "Grants a user the authority to approve requests from employees to adjust or correct their recorded attendance. This typically involves reviewing the reason for the regularization, verifying any supporting documentation, and then officially accepting the changes to the employee's attendance records", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Regularize Attendance" + }, + new + { + Id = new Guid("ccb0589f-712b-43de-92ed-5b6088e7dc4e"), + Description = "Team Attendance refers to tracking and managing the attendance of all team members collectively, often monitored by a team lead or manager.", + FeatureId = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + IsEnabled = true, + Name = "Self Attendance" + }, + new + { + Id = new Guid("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"), + Description = "Grants a user read-only access to foundational or reference data within the system. \"Masters\" typically refer to predefined lists, categories, or templates that are used throughout the application to standardize information and maintain consistency", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "View Masters" + }, + new + { + Id = new Guid("588a8824-f924-4955-82d8-fc51956cf323"), + Description = "Grants a user the authority to create, modify, and delete foundational or reference data within the system. These \"masters\" are typically the core lists, categories, and configurations that other data and functionalities rely upon, such as departments, job titles, product categories", + FeatureId = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + IsEnabled = true, + Name = "Manage Masters" + }, + new + { + Id = new Guid("4286a13b-bb40-4879-8c6d-18e9e393beda"), + Description = "Full control over all directories, including the ability to manage permissions for all directories in the system.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Admin" + }, + new + { + Id = new Guid("62668630-13ce-4f52-a0f0-db38af2230c5"), + Description = "Full control over directories they created or have been assigned. Can also manage permissions for those directories.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory Manager" + }, + new + { + Id = new Guid("0f919170-92d4-4337-abd3-49b66fc871bb"), + Description = "Full control over directories they created. Can view contacts in directories they either created or were assigned to. Can manage permissions only for directories they created.", + FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + IsEnabled = true, + Name = "Directory User" + }, + new + { + Id = new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), + Description = "Allows a user to view only the expense records that they have personally submitted", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View Self" + }, + new + { + Id = new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), + Description = "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View All" + }, + new + { + Id = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + Description = "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Upload" + }, + new + { + Id = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + Description = "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Review" + }, + new + { + Id = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + Description = "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Approve" + }, + new + { + Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Process" + }, + new + { + Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), + Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Manage" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.Property("ApplicationRoleId") + .HasColumnType("char(36)"); + + b.Property("FeaturePermissionId") + .HasColumnType("char(36)"); + + b.HasKey("ApplicationRoleId", "FeaturePermissionId"); + + b.HasIndex("FeaturePermissionId"); + + b.ToTable("RolePermissionMappings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactName") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DomainName") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OnBoardingDate") + .HasColumnType("datetime(6)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("IndustryId"); + + b.ToTable("Tenants"); + + b.HasData( + new + { + Id = new Guid("b3466e83-7e11-464c-b93a-daf047838b26"), + ContactName = "Admin", + ContactNumber = "123456789", + Description = "", + DomainName = "www.marcobms.org", + IndustryId = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + IsActive = true, + Name = "MarcoBMS", + OnBoardingDate = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + OragnizationSize = "100-200" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("TenantId"); + + b.ToTable("BillAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Action") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("ExpenseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdateAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpenseId"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ExpenseLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpensesTypeId") + .HasColumnType("char(36)"); + + b.Property("GSTNumber") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .HasColumnType("longtext"); + + b.Property("NoOfPersons") + .HasColumnType("int"); + + b.Property("PaidById") + .HasColumnType("char(36)"); + + b.Property("PaymentModeId") + .HasColumnType("char(36)"); + + b.Property("PreApproved") + .HasColumnType("tinyint(1)"); + + b.Property("ProcessedById") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReviewedById") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("SupplerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TransactionDate") + .HasColumnType("datetime(6)"); + + b.Property("TransactionId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ExpensesTypeId"); + + b.HasIndex("PaidById"); + + b.HasIndex("PaymentModeId"); + + b.HasIndex("ProcessedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("ReviewedById"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Expenses"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ReimburseById") + .HasColumnType("char(36)"); + + b.Property("ReimburseDate") + .HasColumnType("datetime(6)"); + + b.Property("ReimburseNote") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReimburseTransactionId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ReimburseById"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburse"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("ExpensesReimburseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("ExpensesReimburseId"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburseMapping"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("NextStatusId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("NextStatusId"); + + b.HasIndex("StatusId"); + + b.ToTable("ExpensesStatusMapping"); + + b.HasData( + new + { + Id = new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + NextStatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("4ddddc10-0ffd-4884-accf-d4fa0bd97f54"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), + NextStatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), + NextStatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("6b867bec-66e6-42a7-9611-f4595af9b9ce"), + NextStatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + NextStatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("PermissionId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PermissionId"); + + b.HasIndex("StatusId"); + + b.ToTable("StatusPermissionMapping"); + + b.HasData( + new + { + Id = new Guid("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }, + new + { + Id = new Guid("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + PermissionId = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + StatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CommentId") + .HasColumnType("char(36)"); + + b.Property("FileId") + .HasColumnType("char(36)"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CommentId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AuthorId") + .HasColumnType("char(36)"); + + b.Property("MessageText") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ParentMessageId") + .HasColumnType("char(36)"); + + b.Property("SentAt") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("TicketComments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LinkedActivityId") + .HasColumnType("char(36)"); + + b.Property("LinkedProjectId") + .HasColumnType("char(36)"); + + b.Property("PriorityId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TypeId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PriorityId"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.HasIndex("TypeId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("TagId") + .HasColumnType("char(36)"); + + b.Property("TicketId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TagId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketTags"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTypeMasters"); + + b.HasData( + new + { + Id = new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"), + Description = "An identified problem that affects the performance, reliability, or standards of a product or service", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"), + Description = "A support service that assists users with technical issues, requests, or inquiries.", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("MailListId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("Recipient") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("MailListId"); + + b.ToTable("MailDetails"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmailId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TimeStamp") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("MailLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailingList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Keywords") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("MailingList"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityName") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UnitOfMeasurement") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ActivityMasters"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.CurrencyMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CurrencyCode") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CurrencyName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("CurrencyMaster"); + + b.HasData( + new + { + Id = new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"), + CurrencyCode = "INR", + CurrencyName = "Indian Rupee", + IsActive = true, + Symbol = "₹" + }, + new + { + Id = new Guid("2f672568-a67b-4961-acb2-a8c7834e1762"), + CurrencyCode = "USD", + CurrencyName = "US Dollar", + IsActive = true, + Symbol = "$" + }, + new + { + Id = new Guid("4d1155bb-1448-4d97-a732-96c92eb99c45"), + CurrencyCode = "EUR", + CurrencyName = "Euro", + IsActive = true, + Symbol = "€" + }, + new + { + Id = new Guid("3e456237-ef06-4ea1-a261-188c9b0c6df6"), + CurrencyCode = "GBP", + CurrencyName = "Pound Sterling", + IsActive = true, + Symbol = "£" + }, + new + { + Id = new Guid("297e237a-56d3-48f6-b39d-ec3991dea8bf"), + CurrencyCode = "JPY", + CurrencyName = "Japanese Yen", + IsActive = true, + Symbol = "¥" + }, + new + { + Id = new Guid("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"), + CurrencyCode = "RUB", + CurrencyName = "Russian Ruble", + IsActive = true, + Symbol = "₽" + }, + new + { + Id = new Guid("b960166a-f7e9-49e3-bb4b-28511f126c08"), + CurrencyCode = "CNY", + CurrencyName = "Chinese Yuan (Renminbi)", + IsActive = true, + Symbol = "¥" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ExpensesStatusMaster"); + + b.HasData( + new + { + Id = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + Color = "#8592a3", + Description = "Expense has been created but not yet submitted.", + DisplayName = "Draft", + IsActive = true, + IsSystem = true, + Name = "Draft" + }, + new + { + Id = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + Color = "#696cff", + Description = "Reviewer is currently reviewing the expense.", + DisplayName = "Submit", + IsActive = true, + IsSystem = true, + Name = "Review Pending" + }, + new + { + Id = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(review rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Reviewer" + }, + new + { + Id = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + Color = "#03c3ec", + Description = "Review is completed, waiting for action of approver.", + DisplayName = "Mark as Reviewed", + IsActive = true, + IsSystem = true, + Name = "Approval Pending" + }, + new + { + Id = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(approval rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Approver" + }, + new + { + Id = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + Color = "#ffab00", + Description = "Approved expense is awaiting final payment.", + DisplayName = "Mark as Approved", + IsActive = true, + IsSystem = true, + Name = "Payment Pending" + }, + new + { + Id = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + Color = "#71dd37", + Description = "Expense has been settled.", + DisplayName = "Mark as Processed", + IsActive = true, + IsSystem = true, + Name = "Processed" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NoOfPersonsRequired") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesTypeMaster"); + + b.HasData( + new + { + Id = new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), + Description = "Materials, equipment and supplies purchased for site operations.", + IsActive = true, + Name = "Procurement", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), + Description = "Vehicle fuel, logistics services and delivery of goods or personnel.", + IsActive = true, + Name = "Transport", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), + Description = "Delivery of personnel.", + IsActive = true, + Name = "Travelling", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), + Description = "Site setup costs including equipment deployment and temporary infrastructure.", + IsActive = true, + Name = "Mobilization", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), + Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", + IsActive = true, + Name = "Employee Welfare", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), + Description = "Machinery servicing, electricity, water, and temporary office needs.", + IsActive = true, + Name = "Maintenance & Utilities", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), + Description = "Scheduled payments for external services or goods.", + IsActive = true, + Name = "Vendor/Supplier Payments", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), + Description = "Government fees, insurance, inspections and safety-related expenditures.", + IsActive = true, + Name = "Compliance & Safety", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ModuleId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ModuleId"); + + b.ToTable("Features"); + + b.HasData( + new + { + Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), + Description = "Manage Project", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Project Management" + }, + new + { + Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Expense Management" + }, + new + { + Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), + Description = "Manage Tasks", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Task Management" + }, + new + { + Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + Description = "Manage Employee", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Employee Management" + }, + new + { + Id = new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), + Description = "Attendance", + IsActive = true, + ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Name = "Attendance Management" + }, + new + { + Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + Description = "Global Masters", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Masters" + }, + new + { + Id = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), + Description = "Managing all directory related rights", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Directory Management" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Industry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Industries"); + + b.HasData( + new + { + Id = new Guid("15436ee3-a650-469e-bfc2-59993f7514bb"), + Name = "Information Technology (IT) Services" + }, + new + { + Id = new Guid("0a63e657-2c5f-49b5-854b-42c978293154"), + Name = "Manufacturing & Production" + }, + new + { + Id = new Guid("bdc61e3b-69ea-4394-bab6-079ec135b5bd"), + Name = "Energy & Resources" + }, + new + { + Id = new Guid("5ca200ac-00d7-415e-a410-b948e27ac9d2"), + Name = "Finance & Professional Services" + }, + new + { + Id = new Guid("d5621700-cd87-441f-8cdb-6051ddfc83b4"), + Name = "Hospitals and Healthcare Services" + }, + new + { + Id = new Guid("23608891-657e-40f0-bbd4-2b0a2ec1a76f"), + Name = "Social Services" + }, + new + { + Id = new Guid("a493f4e3-16b1-4411-be3c-6bf2987a3168"), + Name = "Retail & Consumer Services" + }, + new + { + Id = new Guid("e9d8ce92-9371-4ed9-9831-83c07f78edec"), + Name = "Transportation & Logistics" + }, + new + { + Id = new Guid("8a0d6134-2dbe-4e0a-b250-ff34cb7b9df0"), + Name = "Education & Training" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Module", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Modules"); + + b.HasData( + new + { + Id = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Description = "Project Module", + Key = "b04da7e9-0406-409c-ac7f-b97256e6ea02", + Name = "Project" + }, + new + { + Id = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), + Description = "Employee Module", + Key = "0971c7fb-6ce1-458a-ae3f-8d3205893637", + Name = "Employee" + }, + new + { + Id = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Description = "Masters Module", + Key = "504ec132-e6a9-422f-8f85-050602cfce05", + Name = "Masters" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("PaymentModeMatser"); + + b.HasData( + new + { + Id = new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), + Description = "Physical currency; still used for small or informal transactions.", + IsActive = true, + Name = "Cash", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"), + Description = "Paper-based payment order; less common now due to processing delays and fraud risks.", + IsActive = true, + Name = "Cheque", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ed667353-8eea-4fd1-8750-719405932480"), + Description = "Online banking portals used to transfer funds directly between accounts", + IsActive = true, + Name = "NetBanking", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"), + Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", + IsActive = true, + Name = "UPI", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("StatusMasters"); + + b.HasData( + new + { + Id = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + Status = "Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("cdad86aa-8a56-4ff4-b633-9c629057dfef"), + Status = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("603e994b-a27f-4e5d-a251-f3d69b0498ba"), + Status = "On Hold", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), + Status = "In Active", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"), + Status = "Completed", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketPriorityMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketPriorityMasters"); + + b.HasData( + new + { + Id = new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"), + ColorCode = "008000", + IsDefault = true, + Level = 1, + Name = "Low", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"), + ColorCode = "FFFF00", + IsDefault = true, + Level = 2, + Name = "Medium", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 3, + Name = "High", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"), + ColorCode = "#FFA500", + IsDefault = true, + Level = 4, + Name = "Critical", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"), + ColorCode = "#FF0000", + IsDefault = true, + Level = 5, + Name = "Urgent", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketStatusMasters"); + + b.HasData( + new + { + Id = new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"), + ColorCode = "#FFCC99", + Description = "This is a newly created issue.", + IsDefault = true, + Name = "New", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"), + ColorCode = "#E6FF99", + Description = "Assigned to employee or team of employees", + IsDefault = true, + Name = "Assigned", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"), + ColorCode = "#99E6FF", + Description = "These issues are currently in progress", + IsDefault = true, + Name = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), + ColorCode = "#8592a3", + Description = "These issues are currently under review", + IsDefault = true, + Name = "In Review", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"), + ColorCode = "#B399FF", + Description = "The following issues are resolved and closed", + IsDefault = true, + Name = "Done", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.TicketTagMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ColorCode") + .HasColumnType("longtext"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("TicketTagMasters"); + + b.HasData( + new + { + Id = new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"), + ColorCode = "#e59866", + IsDefault = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"), + ColorCode = "#85c1e9", + IsDefault = true, + Name = "Help Desk", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkCategoryMasters"); + + b.HasData( + new + { + Id = new Guid("86bb2cc8-f6b5-4fdd-bbee-c389c713a44b"), + Description = "Created new task in a professional or creative context", + IsSystem = true, + Name = "Fresh Work", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("9ebfa19c-53b9-481b-b863-c25d2f843201"), + Description = "Revising, modifying, or correcting a task to improve its quality or fix issues", + IsSystem = true, + Name = "Rework", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("11a79929-1d07-42dc-9e98-82d0d2f4a240"), + Description = "Any defect, deviation, or non-conformance in a task that fails to meet established standards or customer expectations.", + IsSystem = true, + Name = "Quality Issue", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkStatusMasters"); + + b.HasData( + new + { + Id = new Guid("030bb085-e230-4370-aec7-9a74d652864e"), + Description = "Confirm the tasks are actually finished as reported", + IsSystem = true, + Name = "Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2a1a5b96-cf93-4111-b4b1-76c19d6333b4"), + Description = "Not all tasks are actually finished as reported", + IsSystem = true, + Name = "Partially Approve", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("00a062e6-62e6-42c5-b6b1-024328651b72"), + Description = "Tasks are not finished as reported or have any issues in al the tasks", + IsSystem = true, + Name = "NCR", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BuildingId") + .HasColumnType("char(36)"); + + b.Property("FloorName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("BuildingId"); + + b.HasIndex("TenantId"); + + b.ToTable("Floor"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjectAddress") + .HasColumnType("longtext"); + + b.Property("ProjectStatusId") + .HasColumnType("char(36)"); + + b.Property("ShortName") + .HasColumnType("longtext"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectStatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + Id = new Guid("85bf587b-7ca9-4685-b77c-d817f5847e85"), + ContactPerson = "Project 1 Contact Person", + EndDate = new DateTime(2026, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + Name = "Project 1", + ProjectAddress = "Project 1 Address", + ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"), + StartDate = new DateTime(2025, 4, 20, 10, 11, 17, 588, DateTimeKind.Unspecified), + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("EmployeeId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("JobRoleId") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReAllocationDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TenantId"); + + b.ToTable("ProjectAllocations"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AreaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FloorId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FloorId"); + + b.HasIndex("TenantId"); + + b.ToTable("WorkAreas"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ActivityId") + .HasColumnType("char(36)"); + + b.Property("CompletedWork") + .HasColumnType("double"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + + b.Property("PlannedWork") + .HasColumnType("double"); + + b.Property("TaskDate") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("WorkAreaId") + .HasColumnType("char(36)"); + + b.Property("WorkCategoryId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId"); + + b.HasIndex("TenantId"); + + b.HasIndex("WorkAreaId"); + + b.HasIndex("WorkCategoryId"); + + b.ToTable("WorkItems"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Role") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ApplicationRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("JobRoles"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Utilities.Inquiries", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("About") + .HasColumnType("longtext"); + + b.Property("ContactNumber") + .HasColumnType("longtext"); + + b.Property("ContactPerson") + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("IndustryId") + .HasColumnType("char(36)"); + + b.Property("OragnizationSize") + .HasColumnType("longtext"); + + b.Property("OrganizatioinName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Inquiries"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("varchar(21)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + + b.HasDiscriminator().HasValue("IdentityUser"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.ApplicationUser", b => + { + b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsRootUser") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasDiscriminator().HasValue("ApplicationUser"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("AssignedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReportedBy") + .WithMany() + .HasForeignKey("ReportedById"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkItem", "WorkItem") + .WithMany() + .HasForeignKey("WorkItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkStatusMaster", "WorkStatus") + .WithMany() + .HasForeignKey("WorkStatusId"); + + b.Navigation("ApprovedBy"); + + b.Navigation("Employee"); + + b.Navigation("ReportedBy"); + + b.Navigation("Tenant"); + + b.Navigation("WorkItem"); + + b.Navigation("WorkStatus"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("CommentedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Activities.TaskMembers", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Activities.TaskAllocation", "TaskAllocation") + .WithMany() + .HasForeignKey("TaskAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("TaskAllocation"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.Attendance", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Approver") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.AttendanceModule.AttendanceLog", b => + { + b.HasOne("Marco.Pms.Model.AttendanceModule.Attendance", "Attendance") + .WithMany() + .HasForeignKey("AttendanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedByEmployee") + .WithMany() + .HasForeignKey("UpdatedBy"); + + b.Navigation("Attendance"); + + b.Navigation("Document"); + + b.Navigation("Employee"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedByEmployee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.MPINDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.OTPDetails", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Authentication.RefreshToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Bucket", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedByID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.Contact", b => + { + b.HasOne("Marco.Pms.Model.Directory.ContactCategoryMaster", "ContactCategory") + .WithMany() + .HasForeignKey("ContactCategoryId"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("ContactCategory"); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactCategoryMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactEmail", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactNote", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Createdby") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("Contact"); + + b.Navigation("Createdby"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactPhone", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactProjectMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Directory.ContactTagMaster", "ContactTag") + .WithMany() + .HasForeignKey("ContactTagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("ContactTag"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.ContactTagMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.DirectoryUpdateLog", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Directory.EmployeeBucketMapping", b => + { + b.HasOne("Marco.Pms.Model.Directory.Bucket", "Bucket") + .WithMany() + .HasForeignKey("BucketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bucket"); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UploadedBy") + .WithMany() + .HasForeignKey("UploadedById"); + + b.Navigation("Tenant"); + + b.Navigation("UploadedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserId"); + + b.HasOne("Marco.Pms.Model.Roles.JobRole", "JobRole") + .WithMany() + .HasForeignKey("JobRoleId"); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApplicationUser"); + + b.Navigation("JobRole"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.EmployeeRoleMapping", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Role"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Employees.WorkShift", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.FeaturePermission", b => + { + b.HasOne("Marco.Pms.Model.Master.Feature", "Feature") + .WithMany("FeaturePermissions") + .HasForeignKey("FeatureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Feature"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.RolePermissionMappings", b => + { + b.HasOne("Marco.Pms.Model.Roles.ApplicationRole", null) + .WithMany() + .HasForeignKey("ApplicationRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", null) + .WithMany() + .HasForeignKey("FeaturePermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Entitlements.Tenant", b => + { + b.HasOne("Marco.Pms.Model.Master.Industry", "Industry") + .WithMany() + .HasForeignKey("IndustryId"); + + b.Navigation("Industry"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Expenses"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expense") + .WithMany() + .HasForeignKey("ExpenseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expense"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesTypeMaster", "ExpensesType") + .WithMany() + .HasForeignKey("ExpensesTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "PaidBy") + .WithMany() + .HasForeignKey("PaidById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.PaymentModeMatser", "PaymentMode") + .WithMany() + .HasForeignKey("PaymentModeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ProcessedBy") + .WithMany() + .HasForeignKey("ProcessedById"); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReviewedBy") + .WithMany() + .HasForeignKey("ReviewedById"); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApprovedBy"); + + b.Navigation("CreatedBy"); + + b.Navigation("ExpensesType"); + + b.Navigation("PaidBy"); + + b.Navigation("PaymentMode"); + + b.Navigation("ProcessedBy"); + + b.Navigation("Project"); + + b.Navigation("ReviewedBy"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReimburseBy") + .WithMany() + .HasForeignKey("ReimburseById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReimburseBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.ExpensesReimburse", "ExpensesReimburse") + .WithMany() + .HasForeignKey("ExpensesReimburseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expenses"); + + b.Navigation("ExpensesReimburse"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "NextStatus") + .WithMany() + .HasForeignKey("NextStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NextStatus"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => + { + b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment") + .WithMany("Attachments") + .HasForeignKey("CommentId"); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + + b.Navigation("TicketComment"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketPriorityMaster", "Priority") + .WithMany() + .HasForeignKey("PriorityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.TicketStatusMaster", "TicketStatusMaster") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketTypeMaster", "TicketTypeMaster") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Priority"); + + b.Navigation("Tenant"); + + b.Navigation("TicketStatusMaster"); + + b.Navigation("TicketTypeMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b => + { + b.HasOne("Marco.Pms.Model.Master.TicketTagMaster", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket") + .WithMany() + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Mail.MailDetails", b => + { + b.HasOne("Marco.Pms.Model.Mail.MailingList", "MailBody") + .WithMany() + .HasForeignKey("MailListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MailBody"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ActivityMaster", 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.ExpensesTypeMaster", 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.Feature", b => + { + b.HasOne("Marco.Pms.Model.Master.Module", "Module") + .WithMany() + .HasForeignKey("ModuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Module"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", 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") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.WorkCategoryMaster", 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.WorkStatusMaster", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Floor", b => + { + b.HasOne("Marco.Pms.Model.Projects.Building", "Building") + .WithMany() + .HasForeignKey("BuildingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Building"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.Project", b => + { + b.HasOne("Marco.Pms.Model.Master.StatusMaster", "ProjectStatus") + .WithMany() + .HasForeignKey("ProjectStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectStatus"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.ProjectAllocation", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Project"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkArea", b => + { + b.HasOne("Marco.Pms.Model.Projects.Floor", "Floor") + .WithMany() + .HasForeignKey("FloorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Floor"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Projects.WorkItem", b => + { + b.HasOne("Marco.Pms.Model.Master.ActivityMaster", "ActivityMaster") + .WithMany() + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Projects.WorkArea", "WorkArea") + .WithMany() + .HasForeignKey("WorkAreaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.WorkCategoryMaster", "WorkCategoryMaster") + .WithMany() + .HasForeignKey("WorkCategoryId"); + + b.Navigation("ActivityMaster"); + + b.Navigation("Tenant"); + + b.Navigation("WorkArea"); + + b.Navigation("WorkCategoryMaster"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.ApplicationRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", null) + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Roles.JobRole", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => + { + b.Navigation("FeaturePermissions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/20250804053705_Added_Updated_At_In_UpdateLogs.cs b/Marco.Pms.DataAccess/Migrations/20250804053705_Added_Updated_At_In_UpdateLogs.cs new file mode 100644 index 0000000..0a60584 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250804053705_Added_Updated_At_In_UpdateLogs.cs @@ -0,0 +1,29 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Marco.Pms.DataAccess.Migrations +{ + /// + public partial class Added_Updated_At_In_UpdateLogs : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UpdateAt", + table: "ExpenseLogs", + type: "datetime(6)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UpdateAt", + table: "ExpenseLogs"); + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs index 15273ce..98a3e93 100644 --- a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs @@ -1137,6 +1137,62 @@ namespace Marco.Pms.DataAccess.Migrations FeatureId = new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), IsEnabled = true, Name = "Directory User" + }, + new + { + Id = new Guid("385be49f-8fde-440e-bdbc-3dffeb8dd116"), + Description = "Allows a user to view only the expense records that they have personally submitted", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View Self" + }, + new + { + Id = new Guid("01e06444-9ca7-4df4-b900-8c3fa051b92f"), + Description = "Allows a user to view all expense records across the organization or project, regardless of who submitted or paid them", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "View All" + }, + new + { + Id = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + Description = "Allows a user to create and submit new expense records, including attaching relevant documents like receipts or invoices.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Upload" + }, + new + { + Id = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + Description = "Allows a user to examine submitted expenses for accuracy, completeness, and policy compliance before they are approved or rejected.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Review" + }, + new + { + Id = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + Description = "Allows a user to authorize or reject submitted expenses, making them officially accepted or declined within the system.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Approve" + }, + new + { + Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Process" + }, + new + { + Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), + Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules.", + FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + IsEnabled = true, + Name = "Manage" }); }); @@ -1210,6 +1266,358 @@ namespace Marco.Pms.DataAccess.Migrations }); }); + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("TenantId"); + + b.ToTable("BillAttachments"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Action") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("ExpenseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("UpdateAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpenseId"); + + b.HasIndex("TenantId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ExpenseLogs"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpensesTypeId") + .HasColumnType("char(36)"); + + b.Property("GSTNumber") + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .HasColumnType("longtext"); + + b.Property("NoOfPersons") + .HasColumnType("int"); + + b.Property("PaidById") + .HasColumnType("char(36)"); + + b.Property("PaymentModeId") + .HasColumnType("char(36)"); + + b.Property("PreApproved") + .HasColumnType("tinyint(1)"); + + b.Property("ProcessedById") + .HasColumnType("char(36)"); + + b.Property("ProjectId") + .HasColumnType("char(36)"); + + b.Property("ReviewedById") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.Property("SupplerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("TransactionDate") + .HasColumnType("datetime(6)"); + + b.Property("TransactionId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ApprovedById"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ExpensesTypeId"); + + b.HasIndex("PaidById"); + + b.HasIndex("PaymentModeId"); + + b.HasIndex("ProcessedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("ReviewedById"); + + b.HasIndex("StatusId"); + + b.HasIndex("TenantId"); + + b.ToTable("Expenses"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ReimburseById") + .HasColumnType("char(36)"); + + b.Property("ReimburseDate") + .HasColumnType("datetime(6)"); + + b.Property("ReimburseNote") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReimburseTransactionId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ReimburseById"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburse"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ExpensesId") + .HasColumnType("char(36)"); + + b.Property("ExpensesReimburseId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ExpensesId"); + + b.HasIndex("ExpensesReimburseId"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesReimburseMapping"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("NextStatusId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("NextStatusId"); + + b.HasIndex("StatusId"); + + b.ToTable("ExpensesStatusMapping"); + + b.HasData( + new + { + Id = new Guid("5cf7f1df-9d1f-4289-add0-1775ad614f25"), + NextStatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("4ddddc10-0ffd-4884-accf-d4fa0bd97f54"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("36c00548-241c-43ec-bc95-cacebedb925c"), + NextStatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("1fca1700-1266-477d-bba4-9ac3753aa33c"), + NextStatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("6b867bec-66e6-42a7-9611-f4595af9b9ce"), + NextStatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("ef1fcfbc-60e0-4f17-9308-c583a05d48fd"), + NextStatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("af1e4492-98ee-4451-8ab7-fd8323f29c32"), + NextStatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("PermissionId") + .HasColumnType("char(36)"); + + b.Property("StatusId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("PermissionId"); + + b.HasIndex("StatusId"); + + b.ToTable("StatusPermissionMapping"); + + b.HasData( + new + { + Id = new Guid("722b0c3c-5a78-456d-b9bb-b6ba1b21d59b"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8") + }, + new + { + Id = new Guid("7deb0945-e1c9-411f-8b3c-c9bdbe3c3c2d"), + PermissionId = new Guid("0f57885d-bcb2-4711-ac95-d841ace6d5a7"), + StatusId = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7") + }, + new + { + Id = new Guid("9e2ec648-1ca2-4747-9329-e911b18edb3e"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b") + }, + new + { + Id = new Guid("0b7926fc-a34b-4a5b-8c7d-1003480cf0fa"), + PermissionId = new Guid("1f4bda08-1873-449a-bb66-3e8222bd871b"), + StatusId = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8") + }, + new + { + Id = new Guid("cd15f9b9-be45-4deb-9c71-2f23f872dbcd"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729") + }, + new + { + Id = new Guid("f6f26b2f-2fa6-40b7-8601-cbd4bcdda0cc"), + PermissionId = new Guid("eaafdd76-8aac-45f9-a530-315589c6deca"), + StatusId = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27") + }, + new + { + Id = new Guid("214354e5-daad-4569-ad69-eb5bf4e87fbc"), + PermissionId = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), + StatusId = new Guid("61578360-3a49-4c34-8604-7b35a3787b95") + }); + }); + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => { b.Property("Id") @@ -1500,6 +1908,299 @@ namespace Marco.Pms.DataAccess.Migrations b.ToTable("ActivityMasters"); }); + modelBuilder.Entity("Marco.Pms.Model.Master.CurrencyMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CurrencyCode") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CurrencyName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("CurrencyMaster"); + + b.HasData( + new + { + Id = new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"), + CurrencyCode = "INR", + CurrencyName = "Indian Rupee", + IsActive = true, + Symbol = "₹" + }, + new + { + Id = new Guid("2f672568-a67b-4961-acb2-a8c7834e1762"), + CurrencyCode = "USD", + CurrencyName = "US Dollar", + IsActive = true, + Symbol = "$" + }, + new + { + Id = new Guid("4d1155bb-1448-4d97-a732-96c92eb99c45"), + CurrencyCode = "EUR", + CurrencyName = "Euro", + IsActive = true, + Symbol = "€" + }, + new + { + Id = new Guid("3e456237-ef06-4ea1-a261-188c9b0c6df6"), + CurrencyCode = "GBP", + CurrencyName = "Pound Sterling", + IsActive = true, + Symbol = "£" + }, + new + { + Id = new Guid("297e237a-56d3-48f6-b39d-ec3991dea8bf"), + CurrencyCode = "JPY", + CurrencyName = "Japanese Yen", + IsActive = true, + Symbol = "¥" + }, + new + { + Id = new Guid("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"), + CurrencyCode = "RUB", + CurrencyName = "Russian Ruble", + IsActive = true, + Symbol = "₽" + }, + new + { + Id = new Guid("b960166a-f7e9-49e3-bb4b-28511f126c08"), + CurrencyCode = "CNY", + CurrencyName = "Chinese Yuan (Renminbi)", + IsActive = true, + Symbol = "¥" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesStatusMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ExpensesStatusMaster"); + + b.HasData( + new + { + Id = new Guid("297e0d8f-f668-41b5-bfea-e03b354251c8"), + Color = "#8592a3", + Description = "Expense has been created but not yet submitted.", + DisplayName = "Draft", + IsActive = true, + IsSystem = true, + Name = "Draft" + }, + new + { + Id = new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"), + Color = "#696cff", + Description = "Reviewer is currently reviewing the expense.", + DisplayName = "Submit", + IsActive = true, + IsSystem = true, + Name = "Review Pending" + }, + new + { + Id = new Guid("965eda62-7907-4963-b4a1-657fb0b2724b"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(review rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Reviewer" + }, + new + { + Id = new Guid("4068007f-c92f-4f37-a907-bc15fe57d4d8"), + Color = "#03c3ec", + Description = "Review is completed, waiting for action of approver.", + DisplayName = "Mark as Reviewed", + IsActive = true, + IsSystem = true, + Name = "Approval Pending" + }, + new + { + Id = new Guid("d1ee5eec-24b6-4364-8673-a8f859c60729"), + Color = "#ff3e1d", + Description = "Expense was declined, often with a reason(approval rejected).", + DisplayName = "Reject", + IsActive = true, + IsSystem = true, + Name = "Rejected by Approver" + }, + new + { + Id = new Guid("f18c5cfd-7815-4341-8da2-2c2d65778e27"), + Color = "#ffab00", + Description = "Approved expense is awaiting final payment.", + DisplayName = "Mark as Approved", + IsActive = true, + IsSystem = true, + Name = "Payment Pending" + }, + new + { + Id = new Guid("61578360-3a49-4c34-8604-7b35a3787b95"), + Color = "#71dd37", + Description = "Expense has been settled.", + DisplayName = "Mark as Processed", + IsActive = true, + IsSystem = true, + Name = "Processed" + }); + }); + + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesTypeMaster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NoOfPersonsRequired") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ExpensesTypeMaster"); + + b.HasData( + new + { + Id = new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), + Description = "Materials, equipment and supplies purchased for site operations.", + IsActive = true, + Name = "Procurement", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), + Description = "Vehicle fuel, logistics services and delivery of goods or personnel.", + IsActive = true, + Name = "Transport", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), + Description = "Delivery of personnel.", + IsActive = true, + Name = "Travelling", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), + Description = "Site setup costs including equipment deployment and temporary infrastructure.", + IsActive = true, + Name = "Mobilization", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), + Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", + IsActive = true, + Name = "Employee Welfare", + NoOfPersonsRequired = true, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), + Description = "Machinery servicing, electricity, water, and temporary office needs.", + IsActive = true, + Name = "Maintenance & Utilities", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), + Description = "Scheduled payments for external services or goods.", + IsActive = true, + Name = "Vendor/Supplier Payments", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), + Description = "Government fees, insurance, inspections and safety-related expenditures.", + IsActive = true, + Name = "Compliance & Safety", + NoOfPersonsRequired = false, + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b => { b.Property("Id") @@ -1534,6 +2235,14 @@ namespace Marco.Pms.DataAccess.Migrations Name = "Project Management" }, new + { + Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), + Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Expense Management" + }, + new { Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", @@ -1681,6 +2390,67 @@ namespace Marco.Pms.DataAccess.Migrations }); }); + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("PaymentModeMatser"); + + b.HasData( + new + { + Id = new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"), + Description = "Physical currency; still used for small or informal transactions.", + IsActive = true, + Name = "Cash", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"), + Description = "Paper-based payment order; less common now due to processing delays and fraud risks.", + IsActive = true, + Name = "Cheque", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ed667353-8eea-4fd1-8750-719405932480"), + Description = "Online banking portals used to transfer funds directly between accounts", + IsActive = true, + Name = "NetBanking", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"), + Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.", + IsActive = true, + Name = "UPI", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }); + }); + modelBuilder.Entity("Marco.Pms.Model.Master.StatusMaster", b => { b.Property("Id") @@ -1863,7 +2633,7 @@ namespace Marco.Pms.DataAccess.Migrations new { Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), - ColorCode = "#6c757d", + ColorCode = "#8592a3", Description = "These issues are currently under review", IsDefault = true, Name = "In Review", @@ -3065,6 +3835,221 @@ namespace Marco.Pms.DataAccess.Migrations b.Navigation("Industry"); }); + modelBuilder.Entity("Marco.Pms.Model.Expenses.BillAttachments", b => + { + b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Expenses"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpenseLog", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expense") + .WithMany() + .HasForeignKey("ExpenseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expense"); + + b.Navigation("Tenant"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.Expenses", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ApprovedBy") + .WithMany() + .HasForeignKey("ApprovedById"); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesTypeMaster", "ExpensesType") + .WithMany() + .HasForeignKey("ExpensesTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "PaidBy") + .WithMany() + .HasForeignKey("PaidById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.PaymentModeMatser", "PaymentMode") + .WithMany() + .HasForeignKey("PaymentModeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ProcessedBy") + .WithMany() + .HasForeignKey("ProcessedById"); + + b.HasOne("Marco.Pms.Model.Projects.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReviewedBy") + .WithMany() + .HasForeignKey("ReviewedById"); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApprovedBy"); + + b.Navigation("CreatedBy"); + + b.Navigation("ExpensesType"); + + b.Navigation("PaidBy"); + + b.Navigation("PaymentMode"); + + b.Navigation("ProcessedBy"); + + b.Navigation("Project"); + + b.Navigation("ReviewedBy"); + + b.Navigation("Status"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburse", b => + { + b.HasOne("Marco.Pms.Model.Employees.Employee", "ReimburseBy") + .WithMany() + .HasForeignKey("ReimburseById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReimburseBy"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesReimburseMapping", b => + { + b.HasOne("Marco.Pms.Model.Expenses.Expenses", "Expenses") + .WithMany() + .HasForeignKey("ExpensesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Expenses.ExpensesReimburse", "ExpensesReimburse") + .WithMany() + .HasForeignKey("ExpensesReimburseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Expenses"); + + b.Navigation("ExpensesReimburse"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.ExpensesStatusMapping", b => + { + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "NextStatus") + .WithMany() + .HasForeignKey("NextStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NextStatus"); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Marco.Pms.Model.Expenses.StatusPermissionMapping", b => + { + b.HasOne("Marco.Pms.Model.Entitlements.FeaturePermission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Marco.Pms.Model.Master.ExpensesStatusMaster", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Status"); + }); + modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b => { b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment") @@ -3169,6 +4154,17 @@ namespace Marco.Pms.DataAccess.Migrations b.Navigation("Tenant"); }); + modelBuilder.Entity("Marco.Pms.Model.Master.ExpensesTypeMaster", 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.Feature", b => { b.HasOne("Marco.Pms.Model.Master.Module", "Module") @@ -3180,6 +4176,17 @@ namespace Marco.Pms.DataAccess.Migrations b.Navigation("Module"); }); + modelBuilder.Entity("Marco.Pms.Model.Master.PaymentModeMatser", 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") diff --git a/Marco.Pms.CacheHelper/EmployeeCache.cs b/Marco.Pms.Helpers/CacheHelper/EmployeeCache.cs similarity index 94% rename from Marco.Pms.CacheHelper/EmployeeCache.cs rename to Marco.Pms.Helpers/CacheHelper/EmployeeCache.cs index 7c7f4b4..3e08484 100644 --- a/Marco.Pms.CacheHelper/EmployeeCache.cs +++ b/Marco.Pms.Helpers/CacheHelper/EmployeeCache.cs @@ -1,9 +1,9 @@ -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Employees; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MongoDB.Driver; -namespace Marco.Pms.CacheHelper +namespace Marco.Pms.Helpers.CacheHelper { public class EmployeeCache { @@ -27,6 +27,7 @@ namespace Marco.Pms.CacheHelper var update = Builders.Update .AddToSetEach(e => e.ApplicationRoleIds, newRoleIds) + .Set(r => r.ExpireAt, DateTime.UtcNow.Date.AddDays(1)) .AddToSetEach(e => e.PermissionIds, newPermissionIds); var options = new UpdateOptions { IsUpsert = true }; @@ -46,6 +47,7 @@ namespace Marco.Pms.CacheHelper var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update + .Set(r => r.ExpireAt, DateTime.UtcNow.Date.AddDays(1)) .AddToSetEach(e => e.ProjectIds, newprojectIds); var result = await _collection.UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); @@ -187,17 +189,12 @@ namespace Marco.Pms.CacheHelper // A private method to handle the one-time setup of the collection's indexes. private async Task InitializeCollectionAsync() { - // 1. Define the TTL (Time-To-Live) index on the 'ExpireAt' field. var indexKeys = Builders.IndexKeys.Ascending(x => x.ExpireAt); var indexOptions = new CreateIndexOptions { - // This tells MongoDB to automatically delete documents when their 'ExpireAt' time is reached. - ExpireAfter = TimeSpan.FromSeconds(0) + ExpireAfter = TimeSpan.Zero // required for fixed expiration time }; var indexModel = new CreateIndexModel(indexKeys, indexOptions); - - // 2. Create the index. This is an idempotent operation if the index already exists. - // Use CreateOneAsync since we are only creating a single index. await _collection.Indexes.CreateOneAsync(indexModel); } } diff --git a/Marco.Pms.Helpers/CacheHelper/ExpenseCache.cs b/Marco.Pms.Helpers/CacheHelper/ExpenseCache.cs new file mode 100644 index 0000000..9c030ed --- /dev/null +++ b/Marco.Pms.Helpers/CacheHelper/ExpenseCache.cs @@ -0,0 +1,178 @@ +using Marco.Pms.Model.MongoDBModels.Expenses; +using Marco.Pms.Model.Utilities; +using Microsoft.Extensions.Configuration; +using MongoDB.Bson; +using MongoDB.Driver; + +namespace Marco.Pms.Helpers.CacheHelper +{ + public class ExpenseCache + { + private readonly IMongoCollection _collection; + public ExpenseCache(IConfiguration configuration) + { + + var connectionString = configuration["MongoDB:ConnectionString"]; + var mongoUrl = new MongoUrl(connectionString); + var client = new MongoClient(mongoUrl); // Your MongoDB connection string + var mongoDB = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name + _collection = mongoDB.GetCollection("Expenses"); + } + public async Task AddExpenseToCacheAsync(ExpenseDetailsMongoDB expense) + { + await _collection.InsertOneAsync(expense); + + await InitializeCollectionAsync(); + } + public async Task AddExpensesListToCacheAsync(List expenses) + { + // 1. Add a guard clause to avoid an unnecessary database call for an empty list. + if (expenses == null || !expenses.Any()) + { + return; + } + + // 2. Perform the insert operation. This is the only responsibility of this method. + await _collection.InsertManyAsync(expenses); + await InitializeCollectionAsync(); + } + public async Task<(int totalPages, long totalCount, List expenseList)> GetExpenseListFromCacheAsync(Guid tenantId, Guid loggedInEmployeeId, bool viewAll, + bool viewSelf, int pageNumber, int pageSize, ExpensesFilter? expenseFilter, string? searchString) + { + var filterBuilder = Builders.Filter; + var filter = filterBuilder.Empty; + + // Permission-based filter + if (!viewAll && viewSelf) + { + filter &= filterBuilder.Eq(e => e.CreatedBy.Id, loggedInEmployeeId.ToString()); + } + else + { + filter &= filterBuilder.Or( + filterBuilder.Eq(e => e.CreatedBy.Id, loggedInEmployeeId.ToString()), + filterBuilder.Ne(e => e.Status.Id, "297e0d8f-f668-41b5-bfea-e03b354251c8") + ); + } + + // Apply filters + + if (expenseFilter != null) + { + if (expenseFilter.StartDate.HasValue && expenseFilter.EndDate.HasValue && expenseFilter.IsTransactionDate == false) + { + filter &= filterBuilder.Gte(e => e.CreatedAt, expenseFilter.StartDate.Value.Date) + & filterBuilder.Lte(e => e.CreatedAt, expenseFilter.EndDate.Value.Date.AddDays(1).AddTicks(-1)); + } + + if (expenseFilter.StartDate.HasValue && expenseFilter.EndDate.HasValue && expenseFilter.IsTransactionDate) + { + filter &= filterBuilder.Gte(e => e.TransactionDate, expenseFilter.StartDate.Value.Date) + & filterBuilder.Lte(e => e.TransactionDate, expenseFilter.EndDate.Value.Date.AddDays(1).AddTicks(-1)); + } + + if (expenseFilter.ProjectIds?.Any() == true) + { + filter &= filterBuilder.In(e => e.Project.Id, expenseFilter.ProjectIds.Select(p => p.ToString()).ToList()); + } + + if (expenseFilter.StatusIds?.Any() == true) + { + filter &= filterBuilder.In(e => e.Status.Id, expenseFilter.StatusIds.Select(p => p.ToString()).ToList()); + } + + if (expenseFilter.PaidById?.Any() == true) + { + filter &= filterBuilder.In(e => e.PaidBy.Id, expenseFilter.PaidById.Select(p => p.ToString()).ToList()); + } + + if (expenseFilter.CreatedByIds?.Any() == true && viewAll) + { + filter &= filterBuilder.In(e => e.CreatedBy.Id, expenseFilter.CreatedByIds.Select(p => p.ToString()).ToList()); + } + } + + if (!string.IsNullOrWhiteSpace(searchString)) + { + var searchPattern = new BsonRegularExpression(searchString, "i"); + + // The base text searches remain the same + var searchClauses = new List> + { + filterBuilder.Regex(e => e.Description, searchPattern), + filterBuilder.Regex(e => e.TransactionId, searchPattern) + }; + + // Build the complex filter for PaidBy.FullName + var paidByFilter = new BsonDocument("$expr", + new BsonDocument("$regexMatch", new BsonDocument + { + { "input", new BsonDocument("$concat", new BsonArray { "$PaidBy.FirstName", " ", "$PaidBy.LastName" }) }, + { "regex", searchString }, // BsonRegularExpression can't be used here, pass the string + { "options", "i" } // Case-insensitivity option + }) + ); + searchClauses.Add(paidByFilter); + + // Build the complex filter for CreatedBy.FullName + var createdByFilter = new BsonDocument("$expr", + new BsonDocument("$regexMatch", new BsonDocument + { + { "input", new BsonDocument("$concat", new BsonArray { "$CreatedBy.FirstName", " ", "$CreatedBy.LastName" }) }, + { "regex", searchString }, + { "options", "i" } + }) + ); + searchClauses.Add(createdByFilter); + + // Combine all clauses with an OR + filter &= filterBuilder.Or(searchClauses); + } + + // Total count + var totalCount = await _collection.CountDocumentsAsync(filter); + var totalPages = (int)Math.Ceiling((double)totalCount / pageSize); + + // Fetch paginated data + var expenses = await _collection + .Find(filter) + .Skip((pageNumber - 1) * pageSize) + .Limit(pageSize) + .SortByDescending(e => e.CreatedAt) + .ToListAsync(); + + return (totalPages, totalCount, expenses); + } + + public async Task GetExpenseDetailsByIdAsync(Guid id, Guid tenantId) + { + var filter = Builders.Filter.And( + Builders.Filter.Eq(e => e.Id, id.ToString()), + Builders.Filter.Eq(e => e.TenantId, tenantId.ToString()) + ); + var expense = await _collection.Find(filter).FirstOrDefaultAsync(); + + return expense; + } + + public async Task DeleteExpenseFromCacheAsync(Guid id, Guid tenantId) + { + var filter = Builders.Filter.And( + Builders.Filter.Eq(e => e.Id, id.ToString()), + Builders.Filter.Eq(e => e.TenantId, tenantId.ToString()) + ); + var result = await _collection.DeleteOneAsync(filter); + return result.DeletedCount > 0; + } + private async Task InitializeCollectionAsync() + { + var indexKeys = Builders.IndexKeys.Ascending(x => x.ExpireAt); + var indexOptions = new CreateIndexOptions + { + ExpireAfter = TimeSpan.Zero // required for fixed expiration time + }; + var indexModel = new CreateIndexModel(indexKeys, indexOptions); + await _collection.Indexes.CreateOneAsync(indexModel); + } + } +} diff --git a/Marco.Pms.CacheHelper/ProjectCache.cs b/Marco.Pms.Helpers/CacheHelper/ProjectCache.cs similarity index 96% rename from Marco.Pms.CacheHelper/ProjectCache.cs rename to Marco.Pms.Helpers/CacheHelper/ProjectCache.cs index 10eb623..bee37af 100644 --- a/Marco.Pms.CacheHelper/ProjectCache.cs +++ b/Marco.Pms.Helpers/CacheHelper/ProjectCache.cs @@ -1,13 +1,14 @@ using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Master; -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Masters; +using Marco.Pms.Model.MongoDBModels.Project; using Marco.Pms.Model.Projects; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MongoDB.Bson; using MongoDB.Driver; -namespace Marco.Pms.CacheHelper +namespace Marco.Pms.Helpers { public class ProjectCache { @@ -29,13 +30,7 @@ namespace Marco.Pms.CacheHelper { await _projectCollection.InsertOneAsync(projectDetails); - var indexKeys = Builders.IndexKeys.Ascending(x => x.ExpireAt); - var indexOptions = new CreateIndexOptions - { - ExpireAfter = TimeSpan.Zero // required for fixed expiration time - }; - var indexModel = new CreateIndexModel(indexKeys, indexOptions); - await _projectCollection.Indexes.CreateOneAsync(indexModel); + await InitializeCollectionAsync(); } public async Task AddProjectDetailsListToCache(List projectDetailsList) @@ -52,17 +47,12 @@ namespace Marco.Pms.CacheHelper } private async Task InitializeCollectionAsync() { - // 1. Define the TTL (Time-To-Live) index on the 'ExpireAt' field. var indexKeys = Builders.IndexKeys.Ascending(x => x.ExpireAt); var indexOptions = new CreateIndexOptions { - // This tells MongoDB to automatically delete documents when their 'ExpireAt' time is reached. - ExpireAfter = TimeSpan.FromSeconds(0) + ExpireAfter = TimeSpan.Zero // required for fixed expiration time }; var indexModel = new CreateIndexModel(indexKeys, indexOptions); - - // 2. Create the index. This is an idempotent operation if the index already exists. - // Use CreateOneAsync since we are only creating a single index. await _projectCollection.Indexes.CreateOneAsync(indexModel); } public async Task UpdateProjectDetailsOnlyToCache(Project project, StatusMaster projectStatus) diff --git a/Marco.Pms.CacheHelper/ReportCache.cs b/Marco.Pms.Helpers/CacheHelper/ReportCache.cs similarity index 95% rename from Marco.Pms.CacheHelper/ReportCache.cs rename to Marco.Pms.Helpers/CacheHelper/ReportCache.cs index 66611a8..009bdf2 100644 --- a/Marco.Pms.CacheHelper/ReportCache.cs +++ b/Marco.Pms.Helpers/CacheHelper/ReportCache.cs @@ -1,8 +1,8 @@ -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Utility; using Microsoft.Extensions.Configuration; using MongoDB.Driver; -namespace Marco.Pms.CacheHelper +namespace Marco.Pms.Helpers.CacheHelper { public class ReportCache { diff --git a/Marco.Pms.CacheHelper/Marco.Pms.CacheHelper.csproj b/Marco.Pms.Helpers/Marco.Pms.Helpers.csproj similarity index 100% rename from Marco.Pms.CacheHelper/Marco.Pms.CacheHelper.csproj rename to Marco.Pms.Helpers/Marco.Pms.Helpers.csproj diff --git a/Marco.Pms.Helpers/Utility/UtilityMongoDBHelper.cs b/Marco.Pms.Helpers/Utility/UtilityMongoDBHelper.cs new file mode 100644 index 0000000..7159850 --- /dev/null +++ b/Marco.Pms.Helpers/Utility/UtilityMongoDBHelper.cs @@ -0,0 +1,128 @@ +using Marco.Pms.Model.MongoDBModels.Utility; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using MongoDB.Bson; +using MongoDB.Driver; +using System.Collections; + +namespace Marco.Pms.Helpers.Utility +{ + public class UtilityMongoDBHelper + { + private readonly IMongoDatabase _mongoDatabase; + private readonly IConfiguration _configuration; + private readonly ILogger _logger; + public UtilityMongoDBHelper(IConfiguration configuration, ILogger logger) + { + _configuration = configuration; + _logger = logger; + var connectionString = configuration["MongoDB:ModificationConnectionString"]; + var mongoUrl = new MongoUrl(connectionString); + var client = new MongoClient(mongoUrl); // Your MongoDB connection string + _mongoDatabase = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name + } + + #region =================================================================== Update Log Helper Functions =================================================================== + public async Task PushToUpdateLogsAsync(UpdateLogsObject oldObject, string collectionName) + { + var collection = _mongoDatabase.GetCollection(collectionName); + await collection.InsertOneAsync(oldObject); + } + + public async Task> GetFromUpdateLogsByEntityIdAsync(Guid entityId, string collectionName) + { + var collection = _mongoDatabase.GetCollection(collectionName); + var filter = Builders.Filter.Eq(p => p.EntityId, entityId.ToString()); + + List result = await collection + .Find(filter) + .ToListAsync(); + + return result; + } + + public async Task> GetFromUpdateLogsByUpdetedByIdAsync(Guid updatedById, string collectionName) + { + var collection = _mongoDatabase.GetCollection(collectionName); + var filter = Builders.Filter.Eq(p => p.UpdatedById, updatedById.ToString()); + + List result = await collection + .Find(filter) + .ToListAsync(); + + return result; + } + + public BsonDocument EntityToBsonDocument(object entity) + { + var bson = new BsonDocument(); + + var props = entity.GetType().GetProperties(); + foreach (var prop in props) + { + var value = prop.GetValue(entity); + if (value == null) + { + bson[prop.Name] = BsonNull.Value; + continue; + } + + if (value is Guid guidValue) + { + bson[prop.Name] = guidValue.ToString(); // store Guid as string + } + else if (value is string || value.GetType().IsPrimitive || value is DateTime) + { + bson[prop.Name] = BsonValue.Create(value); // simple types + } + else if (value is IEnumerable list && !(value is string)) + { + var array = new BsonArray(); + foreach (var item in list) + { + array.Add(EntityToBsonDocument(item)); // recursive + } + bson[prop.Name] = array; + } + else + { + // nested object + continue; + } + } + + return bson; + } + + #endregion + + #region =================================================================== S3 deletion Helper Functions =================================================================== + + public async Task PushToS3DeletionAsync(List deletionObject) + { + var bucketName = _configuration["AWS:BucketName"]; + if (bucketName != null) + { + deletionObject = deletionObject.Select(d => new S3DeletionObject + { + BucketName = bucketName, + Key = d.Key, + Deleted = false + }).ToList(); + } + _logger.LogInformation("Delection object for bucket {BucketName} added to mongoDB", bucketName); + try + { + var collection = _mongoDatabase.GetCollection("S3Delection"); + await collection.InsertManyAsync(deletionObject); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while saving delection object for S3 to MogoDB"); + } + _logger.LogInformation("Delection Objects added to MongoDB Successfully"); + } + + #endregion + } +} diff --git a/Marco.Pms.Model/Dtos/Expenses/CreateExpensesDto.cs b/Marco.Pms.Model/Dtos/Expenses/CreateExpensesDto.cs new file mode 100644 index 0000000..53c8170 --- /dev/null +++ b/Marco.Pms.Model/Dtos/Expenses/CreateExpensesDto.cs @@ -0,0 +1,22 @@ +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Model.Dtos.Expenses +{ + public class CreateExpensesDto + { + public required Guid ProjectId { get; set; } + public required Guid ExpensesTypeId { get; set; } + public required Guid PaymentModeId { get; set; } + public required Guid PaidById { get; set; } + public DateTime TransactionDate { get; set; } = DateTime.Now; + public string? TransactionId { get; set; } + public required string Description { get; set; } + public string? Location { get; set; } + public string? GSTNumber { get; set; } + public required string SupplerName { get; set; } + public required double Amount { get; set; } + public int? NoOfPersons { get; set; } = 0; + public bool PreApproved { get; set; } = false; + public required List BillAttachments { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs b/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs new file mode 100644 index 0000000..d59c90e --- /dev/null +++ b/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs @@ -0,0 +1,12 @@ +namespace Marco.Pms.Model.Dtos.Expenses +{ + public class ExpenseRecordDto + { + public Guid ExpenseId { get; set; } + public Guid StatusId { get; set; } + public string? Comment { get; set; } + public string? ReimburseTransactionId { get; set; } + public DateTime? ReimburseDate { get; set; } + public Guid? ReimburseById { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Expenses/UpdateExpensesDto.cs b/Marco.Pms.Model/Dtos/Expenses/UpdateExpensesDto.cs new file mode 100644 index 0000000..28c4faf --- /dev/null +++ b/Marco.Pms.Model/Dtos/Expenses/UpdateExpensesDto.cs @@ -0,0 +1,23 @@ +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Model.Dtos.Expenses +{ + public class UpdateExpensesDto + { + public required Guid Id { get; set; } + public required Guid ProjectId { get; set; } + public required Guid ExpensesTypeId { get; set; } + public required Guid PaymentModeId { get; set; } + public required Guid PaidById { get; set; } + public DateTime TransactionDate { get; set; } = DateTime.Now; + public string? TransactionId { get; set; } + public required string Description { get; set; } + public string? Location { get; set; } + public string? GSTNumber { get; set; } + public required string SupplerName { get; set; } + public required double Amount { get; set; } + public int? NoOfPersons { get; set; } = 0; + public bool PreApproved { get; set; } = false; + public List? BillAttachments { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Master/ExpensesStatusMasterDto.cs b/Marco.Pms.Model/Dtos/Master/ExpensesStatusMasterDto.cs new file mode 100644 index 0000000..6bff02b --- /dev/null +++ b/Marco.Pms.Model/Dtos/Master/ExpensesStatusMasterDto.cs @@ -0,0 +1,12 @@ +namespace Marco.Pms.Model.Dtos.Master +{ + public class ExpensesStatusMasterDto + { + public Guid? Id { get; set; } + public required string Name { get; set; } = string.Empty; + public string DisplayName { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public List? PermissionIds { get; set; } + public required string? Color { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Master/ExpensesTypeMasterDto.cs b/Marco.Pms.Model/Dtos/Master/ExpensesTypeMasterDto.cs new file mode 100644 index 0000000..d8f204a --- /dev/null +++ b/Marco.Pms.Model/Dtos/Master/ExpensesTypeMasterDto.cs @@ -0,0 +1,10 @@ +namespace Marco.Pms.Model.Dtos.Master +{ + public class ExpensesTypeMasterDto + { + public Guid? Id { get; set; } + public required string Name { get; set; } + public required bool NoOfPersonsRequired { get; set; } + public string? Description { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Master/PaymentModeMatserDto.cs b/Marco.Pms.Model/Dtos/Master/PaymentModeMatserDto.cs new file mode 100644 index 0000000..fb89b64 --- /dev/null +++ b/Marco.Pms.Model/Dtos/Master/PaymentModeMatserDto.cs @@ -0,0 +1,9 @@ +namespace Marco.Pms.Model.Dtos.Master +{ + public class PaymentModeMatserDto + { + public Guid? Id { get; set; } + public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/Dtos/Projects/ProjectAllocationDot.cs b/Marco.Pms.Model/Dtos/Projects/ProjectAllocationDot.cs index 7a1fd91..0805e62 100644 --- a/Marco.Pms.Model/Dtos/Projects/ProjectAllocationDot.cs +++ b/Marco.Pms.Model/Dtos/Projects/ProjectAllocationDot.cs @@ -5,7 +5,6 @@ public Guid EmpID { get; set; } public Guid JobRoleId { get; set; } public Guid ProjectId { get; set; } - public bool Status { get; set; } } @@ -14,7 +13,6 @@ { public Guid ProjectId { get; set; } public Guid JobRoleId { get; set; } - public bool Status { get; set; } } } diff --git a/Marco.Pms.Model/Entitlements/PermissionsMaster.cs b/Marco.Pms.Model/Entitlements/PermissionsMaster.cs index d0bef58..07ac1b5 100644 --- a/Marco.Pms.Model/Entitlements/PermissionsMaster.cs +++ b/Marco.Pms.Model/Entitlements/PermissionsMaster.cs @@ -23,6 +23,13 @@ public static readonly Guid SelfAttendance = Guid.Parse("ccb0589f-712b-43de-92ed-5b6088e7dc4e"); public static readonly Guid ViewMasters = Guid.Parse("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"); public static readonly Guid ManageMasters = Guid.Parse("588a8824-f924-4955-82d8-fc51956cf323"); + public static readonly Guid ExpenseViewSelf = Guid.Parse("385be49f-8fde-440e-bdbc-3dffeb8dd116"); + public static readonly Guid ExpenseViewAll = Guid.Parse("01e06444-9ca7-4df4-b900-8c3fa051b92f"); + public static readonly Guid ExpenseUpload = Guid.Parse("0f57885d-bcb2-4711-ac95-d841ace6d5a7"); + public static readonly Guid ExpenseReview = Guid.Parse("1f4bda08-1873-449a-bb66-3e8222bd871b"); + public static readonly Guid ExpenseApprove = Guid.Parse("eaafdd76-8aac-45f9-a530-315589c6deca"); + public static readonly Guid ExpenseProcess = Guid.Parse("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"); + public static readonly Guid ExpenseManage = Guid.Parse("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"); } } diff --git a/Marco.Pms.Model/Expenses/BillAttachments.cs b/Marco.Pms.Model/Expenses/BillAttachments.cs new file mode 100644 index 0000000..5d62b09 --- /dev/null +++ b/Marco.Pms.Model/Expenses/BillAttachments.cs @@ -0,0 +1,22 @@ +using Marco.Pms.Model.DocumentManager; +using Marco.Pms.Model.Utilities; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class BillAttachments : TenantRelation + { + public Guid Id { get; set; } + public Guid ExpensesId { get; set; } + + [ValidateNever] + [ForeignKey("ExpensesId")] + public Expenses? Expenses { get; set; } + public Guid DocumentId { get; set; } + + [ValidateNever] + [ForeignKey("DocumentId")] + public Document? Document { get; set; } + } +} diff --git a/Marco.Pms.Model/Expenses/ExpenseLog.cs b/Marco.Pms.Model/Expenses/ExpenseLog.cs new file mode 100644 index 0000000..afee5fc --- /dev/null +++ b/Marco.Pms.Model/Expenses/ExpenseLog.cs @@ -0,0 +1,25 @@ +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Utilities; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class ExpenseLog : TenantRelation + { + public Guid Id { get; set; } + public Guid ExpenseId { get; set; } + + [ValidateNever] + [ForeignKey("ExpenseId")] + public Expenses? Expense { get; set; } + public Guid UpdatedById { get; set; } + + [ValidateNever] + [ForeignKey("UpdatedById")] + public Employee? UpdatedBy { get; set; } + public DateTime? UpdateAt { get; set; } + public string Action { get; set; } = string.Empty; + public string? Comment { get; set; } + } +} diff --git a/Marco.Pms.Model/Expenses/Expenses.cs b/Marco.Pms.Model/Expenses/Expenses.cs new file mode 100644 index 0000000..35e8836 --- /dev/null +++ b/Marco.Pms.Model/Expenses/Expenses.cs @@ -0,0 +1,70 @@ +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Master; +using Marco.Pms.Model.Projects; +using Marco.Pms.Model.Utilities; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class Expenses : TenantRelation + { + public Guid Id { get; set; } + public Guid ProjectId { get; set; } + + [ValidateNever] + [ForeignKey("ProjectId")] + public Project? Project { get; set; } + public Guid ExpensesTypeId { get; set; } + + [ValidateNever] + [ForeignKey("ExpensesTypeId")] + public ExpensesTypeMaster? ExpensesType { get; set; } + public Guid PaymentModeId { get; set; } + + [ValidateNever] + [ForeignKey("PaymentModeId")] + public PaymentModeMatser? PaymentMode { get; set; } + public Guid PaidById { get; set; } + + [ValidateNever] + [ForeignKey("PaidById")] + public Employee? PaidBy { get; set; } + public Guid CreatedById { get; set; } + + [ValidateNever] + [ForeignKey("CreatedById")] + public Employee? CreatedBy { get; set; } + public Guid? ReviewedById { get; set; } + + [ValidateNever] + [ForeignKey("ReviewedById")] + public Employee? ReviewedBy { get; set; } + public Guid? ApprovedById { get; set; } + + [ValidateNever] + [ForeignKey("ApprovedById")] + public Employee? ApprovedBy { get; set; } + public Guid? ProcessedById { get; set; } + + [ValidateNever] + [ForeignKey("ProcessedById")] + public Employee? ProcessedBy { get; set; } + public DateTime TransactionDate { get; set; } + public DateTime CreatedAt { get; set; } + public string? TransactionId { get; set; } + public string Description { get; set; } = string.Empty; + public string? Location { get; set; } + public string? GSTNumber { get; set; } + public string SupplerName { get; set; } = string.Empty; + public double Amount { get; set; } + public int? NoOfPersons { get; set; } + public Guid StatusId { get; set; } + + [ValidateNever] + [ForeignKey("StatusId")] + public ExpensesStatusMaster? Status { get; set; } + public bool PreApproved { get; set; } = false; + public bool IsActive { get; set; } = true; + } +} diff --git a/Marco.Pms.Model/Expenses/ExpensesReimburse.cs b/Marco.Pms.Model/Expenses/ExpensesReimburse.cs new file mode 100644 index 0000000..401ecda --- /dev/null +++ b/Marco.Pms.Model/Expenses/ExpensesReimburse.cs @@ -0,0 +1,20 @@ +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Utilities; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class ExpensesReimburse : TenantRelation + { + public Guid Id { get; set; } + public string ReimburseTransactionId { get; set; } = string.Empty; + public DateTime ReimburseDate { get; set; } + public Guid ReimburseById { get; set; } + + [ValidateNever] + [ForeignKey("ReimburseById")] + public Employee? ReimburseBy { get; set; } + public string ReimburseNote { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/Expenses/ExpensesReimburseMapping.cs b/Marco.Pms.Model/Expenses/ExpensesReimburseMapping.cs new file mode 100644 index 0000000..16237de --- /dev/null +++ b/Marco.Pms.Model/Expenses/ExpensesReimburseMapping.cs @@ -0,0 +1,21 @@ +using Marco.Pms.Model.Utilities; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class ExpensesReimburseMapping : TenantRelation + { + public Guid Id { get; set; } + public Guid ExpensesId { get; set; } + + [ValidateNever] + [ForeignKey("ExpensesId")] + public Expenses? Expenses { get; set; } + public Guid ExpensesReimburseId { get; set; } + + [ValidateNever] + [ForeignKey("ExpensesReimburseId")] + public ExpensesReimburse? ExpensesReimburse { get; set; } + } +} diff --git a/Marco.Pms.Model/Expenses/ExpensesStatusMapping.cs b/Marco.Pms.Model/Expenses/ExpensesStatusMapping.cs new file mode 100644 index 0000000..902927d --- /dev/null +++ b/Marco.Pms.Model/Expenses/ExpensesStatusMapping.cs @@ -0,0 +1,21 @@ +using Marco.Pms.Model.Master; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class ExpensesStatusMapping + { + public Guid Id { get; set; } + public Guid StatusId { get; set; } + + [ValidateNever] + [ForeignKey("StatusId")] + public ExpensesStatusMaster? Status { get; set; } + public Guid NextStatusId { get; set; } + + [ValidateNever] + [ForeignKey("NextStatusId")] + public ExpensesStatusMaster? NextStatus { get; set; } + } +} diff --git a/Marco.Pms.Model/Expenses/StatusPermissionMapping.cs b/Marco.Pms.Model/Expenses/StatusPermissionMapping.cs new file mode 100644 index 0000000..2fe9334 --- /dev/null +++ b/Marco.Pms.Model/Expenses/StatusPermissionMapping.cs @@ -0,0 +1,22 @@ +using Marco.Pms.Model.Entitlements; +using Marco.Pms.Model.Master; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Expenses +{ + public class StatusPermissionMapping + { + public Guid Id { get; set; } + public Guid StatusId { get; set; } + + [ValidateNever] + [ForeignKey("StatusId")] + public ExpensesStatusMaster? Status { get; set; } + public Guid PermissionId { get; set; } + + [ValidateNever] + [ForeignKey("PermissionId")] + public FeaturePermission? Permission { get; set; } + } +} diff --git a/Marco.Pms.Model/Marco.Pms.Model.csproj b/Marco.Pms.Model/Marco.Pms.Model.csproj index a1a21a5..332759a 100644 --- a/Marco.Pms.Model/Marco.Pms.Model.csproj +++ b/Marco.Pms.Model/Marco.Pms.Model.csproj @@ -1,20 +1,20 @@ - + - - net7.0 - enable - enable - + + net7.0 + enable + enable + - + - - - - + + + + - - - + + + diff --git a/Marco.Pms.Model/Master/CurrencyMaster.cs b/Marco.Pms.Model/Master/CurrencyMaster.cs new file mode 100644 index 0000000..62f73d3 --- /dev/null +++ b/Marco.Pms.Model/Master/CurrencyMaster.cs @@ -0,0 +1,11 @@ +namespace Marco.Pms.Model.Master +{ + public class CurrencyMaster + { + public Guid Id { get; set; } + public string CurrencyCode { get; set; } = string.Empty; + public string CurrencyName { get; set; } = string.Empty; + public string Symbol { get; set; } = string.Empty; + public bool IsActive { get; set; } = true; + } +} diff --git a/Marco.Pms.Model/Master/ExpensesStatusMaster.cs b/Marco.Pms.Model/Master/ExpensesStatusMaster.cs new file mode 100644 index 0000000..35358c3 --- /dev/null +++ b/Marco.Pms.Model/Master/ExpensesStatusMaster.cs @@ -0,0 +1,13 @@ +namespace Marco.Pms.Model.Master +{ + public class ExpensesStatusMaster + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string DisplayName { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public string Color { get; set; } = string.Empty; + public bool IsSystem { get; set; } = false; + public bool IsActive { get; set; } = true; + } +} diff --git a/Marco.Pms.Model/Master/ExpensesTypeMaster.cs b/Marco.Pms.Model/Master/ExpensesTypeMaster.cs new file mode 100644 index 0000000..7e7d682 --- /dev/null +++ b/Marco.Pms.Model/Master/ExpensesTypeMaster.cs @@ -0,0 +1,13 @@ +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Model.Master +{ + public class ExpensesTypeMaster : TenantRelation + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public bool NoOfPersonsRequired { get; set; } + public string Description { get; set; } = string.Empty; + public bool IsActive { get; set; } = true; + } +} diff --git a/Marco.Pms.Model/Master/PaymentModeMatser.cs b/Marco.Pms.Model/Master/PaymentModeMatser.cs new file mode 100644 index 0000000..e947c55 --- /dev/null +++ b/Marco.Pms.Model/Master/PaymentModeMatser.cs @@ -0,0 +1,12 @@ +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Model.Master +{ + public class PaymentModeMatser : TenantRelation + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public bool IsActive { get; set; } = true; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/DocumentMongoDB.cs b/Marco.Pms.Model/MongoDBModels/DocumentMongoDB.cs new file mode 100644 index 0000000..d65af2a --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/DocumentMongoDB.cs @@ -0,0 +1,11 @@ +namespace Marco.Pms.Model.MongoDBModels +{ + public class DocumentMongoDB + { + public string DocumentId { get; set; } = string.Empty; + public string FileName { get; set; } = string.Empty; + public string ContentType { get; set; } = string.Empty; + public string S3Key { get; set; } = string.Empty; + public string ThumbS3Key { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/Employees/BasicEmployeeMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Employees/BasicEmployeeMongoDB.cs new file mode 100644 index 0000000..bff2e62 --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Employees/BasicEmployeeMongoDB.cs @@ -0,0 +1,13 @@ +namespace Marco.Pms.Model.MongoDBModels.Employees +{ + public class BasicEmployeeMongoDB + { + public string Id { get; set; } = string.Empty; + public string? FirstName { get; set; } + public string? LastName { get; set; } + public byte[]? Photo { get; set; } + public string? JobRoleId { get; set; } + public string? JobRoleName { get; set; } + public string TenantId { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Employees/EmployeePermissionMongoDB.cs similarity index 91% rename from Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Employees/EmployeePermissionMongoDB.cs index fab2b84..07da2ef 100644 --- a/Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Employees/EmployeePermissionMongoDB.cs @@ -1,6 +1,6 @@ using MongoDB.Bson.Serialization.Attributes; -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Employees { [BsonIgnoreExtraElements] public class EmployeePermissionMongoDB diff --git a/Marco.Pms.Model/MongoDBModels/Expenses/ExpenseDetailsMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Expenses/ExpenseDetailsMongoDB.cs new file mode 100644 index 0000000..c2618b9 --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Expenses/ExpenseDetailsMongoDB.cs @@ -0,0 +1,35 @@ +using Marco.Pms.Model.MongoDBModels.Employees; +using Marco.Pms.Model.MongoDBModels.Masters; +using Marco.Pms.Model.MongoDBModels.Project; + +namespace Marco.Pms.Model.MongoDBModels.Expenses +{ + public class ExpenseDetailsMongoDB + { + public string Id { get; set; } = string.Empty; + public ProjectBasicMongoDB Project { get; set; } = new ProjectBasicMongoDB(); + public ExpensesTypeMasterMongoDB ExpensesType { get; set; } = new ExpensesTypeMasterMongoDB(); + public PaymentModeMatserMongoDB PaymentMode { get; set; } = new PaymentModeMatserMongoDB(); + public BasicEmployeeMongoDB PaidBy { get; set; } = new BasicEmployeeMongoDB(); + public BasicEmployeeMongoDB CreatedBy { get; set; } = new BasicEmployeeMongoDB(); + public BasicEmployeeMongoDB? ReviewedBy { get; set; } + public BasicEmployeeMongoDB? ApprovedBy { get; set; } + public BasicEmployeeMongoDB? ProcessedBy { get; set; } + public DateTime TransactionDate { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime ExpireAt { get; set; } = DateTime.UtcNow.Date.AddDays(1); + public string SupplerName { get; set; } = string.Empty; + public double Amount { get; set; } + public ExpensesStatusMasterMongoDB Status { get; set; } = new ExpensesStatusMasterMongoDB(); + public List NextStatus { get; set; } = new List(); + public bool PreApproved { get; set; } = false; + public string? TransactionId { get; set; } + public string Description { get; set; } = string.Empty; + public string? Location { get; set; } + public List Documents { get; set; } = new List(); + public string? GSTNumber { get; set; } + public int? NoOfPersons { get; set; } + public bool IsActive { get; set; } = true; + public string TenantId { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/Masters/ExpensesStatusMasterMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Masters/ExpensesStatusMasterMongoDB.cs new file mode 100644 index 0000000..03e512d --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Masters/ExpensesStatusMasterMongoDB.cs @@ -0,0 +1,13 @@ +namespace Marco.Pms.Model.MongoDBModels.Masters +{ + public class ExpensesStatusMasterMongoDB + { + public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string DisplayName { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + //public List PermissionIds { get; set; } = new List(); + public string? Color { get; set; } + public bool IsSystem { get; set; } = false; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/Masters/ExpensesTypeMasterMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Masters/ExpensesTypeMasterMongoDB.cs new file mode 100644 index 0000000..d4b80ad --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Masters/ExpensesTypeMasterMongoDB.cs @@ -0,0 +1,11 @@ +namespace Marco.Pms.Model.MongoDBModels.Masters +{ + public class ExpensesTypeMasterMongoDB + { + public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public bool NoOfPersonsRequired { get; set; } + public string Description { get; set; } = string.Empty; + public string TenantId { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/Masters/PaymentModeMatserMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Masters/PaymentModeMatserMongoDB.cs new file mode 100644 index 0000000..0d7a74b --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Masters/PaymentModeMatserMongoDB.cs @@ -0,0 +1,10 @@ +namespace Marco.Pms.Model.MongoDBModels.Masters +{ + public class PaymentModeMatserMongoDB + { + public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public string TenantId { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/StatusMasterMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Masters/StatusMasterMongoDB.cs similarity index 74% rename from Marco.Pms.Model/MongoDBModels/StatusMasterMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Masters/StatusMasterMongoDB.cs index 77e8eb5..96a56a6 100644 --- a/Marco.Pms.Model/MongoDBModels/StatusMasterMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Masters/StatusMasterMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Masters { public class StatusMasterMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/WorkCategoryMasterMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Masters/WorkCategoryMasterMongoDB.cs similarity index 82% rename from Marco.Pms.Model/MongoDBModels/WorkCategoryMasterMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Masters/WorkCategoryMasterMongoDB.cs index 4ea4682..4270a25 100644 --- a/Marco.Pms.Model/MongoDBModels/WorkCategoryMasterMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Masters/WorkCategoryMasterMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Masters { public class WorkCategoryMasterMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/ActivityMasterMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/ActivityMasterMongoDB.cs similarity index 80% rename from Marco.Pms.Model/MongoDBModels/ActivityMasterMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/ActivityMasterMongoDB.cs index cc77d96..ecb88c1 100644 --- a/Marco.Pms.Model/MongoDBModels/ActivityMasterMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/ActivityMasterMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Project { public class ActivityMasterMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/BuildingMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/BuildingMongoDB.cs similarity index 94% rename from Marco.Pms.Model/MongoDBModels/BuildingMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/BuildingMongoDB.cs index 786ceb5..640be18 100644 --- a/Marco.Pms.Model/MongoDBModels/BuildingMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/BuildingMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Project { public class BuildingMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/FloorMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/FloorMongoDB.cs similarity index 93% rename from Marco.Pms.Model/MongoDBModels/FloorMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/FloorMongoDB.cs index 15d3060..debb663 100644 --- a/Marco.Pms.Model/MongoDBModels/FloorMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/FloorMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Project { public class FloorMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/Project/ProjectBasicMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/ProjectBasicMongoDB.cs new file mode 100644 index 0000000..4d2bd6b --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Project/ProjectBasicMongoDB.cs @@ -0,0 +1,10 @@ +namespace Marco.Pms.Model.MongoDBModels.Project +{ + public class ProjectBasicMongoDB + { + public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string ShortName { get; set; } = string.Empty; + public string TenantId { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/ProjectMongoDB.cs similarity index 88% rename from Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/ProjectMongoDB.cs index aac0e2c..c2600bd 100644 --- a/Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/ProjectMongoDB.cs @@ -1,4 +1,6 @@ -namespace Marco.Pms.Model.MongoDBModels +using Marco.Pms.Model.MongoDBModels.Masters; + +namespace Marco.Pms.Model.MongoDBModels.Project { public class ProjectMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/WorkAreaInfoMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/WorkAreaInfoMongoDB.cs similarity index 89% rename from Marco.Pms.Model/MongoDBModels/WorkAreaInfoMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/WorkAreaInfoMongoDB.cs index da1001b..97da737 100644 --- a/Marco.Pms.Model/MongoDBModels/WorkAreaInfoMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/WorkAreaInfoMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Project { public class WorkAreaInfoMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/WorkAreaMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/WorkAreaMongoDB.cs similarity index 89% rename from Marco.Pms.Model/MongoDBModels/WorkAreaMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/WorkAreaMongoDB.cs index 412c940..d768e3b 100644 --- a/Marco.Pms.Model/MongoDBModels/WorkAreaMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/WorkAreaMongoDB.cs @@ -1,4 +1,4 @@ -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Project { public class WorkAreaMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Project/WorkItemMongoDB.cs similarity index 87% rename from Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Project/WorkItemMongoDB.cs index cf798f3..00aa168 100644 --- a/Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Project/WorkItemMongoDB.cs @@ -1,4 +1,6 @@ -namespace Marco.Pms.Model.MongoDBModels +using Marco.Pms.Model.MongoDBModels.Masters; + +namespace Marco.Pms.Model.MongoDBModels.Project { public class WorkItemMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/ProjectReportEmailMongoDB.cs b/Marco.Pms.Model/MongoDBModels/Utility/ProjectReportEmailMongoDB.cs similarity index 91% rename from Marco.Pms.Model/MongoDBModels/ProjectReportEmailMongoDB.cs rename to Marco.Pms.Model/MongoDBModels/Utility/ProjectReportEmailMongoDB.cs index 519ea4f..928b814 100644 --- a/Marco.Pms.Model/MongoDBModels/ProjectReportEmailMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/Utility/ProjectReportEmailMongoDB.cs @@ -1,7 +1,7 @@ using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; -namespace Marco.Pms.Model.MongoDBModels +namespace Marco.Pms.Model.MongoDBModels.Utility { public class ProjectReportEmailMongoDB { diff --git a/Marco.Pms.Model/MongoDBModels/Utility/S3DeletionObject.cs b/Marco.Pms.Model/MongoDBModels/Utility/S3DeletionObject.cs new file mode 100644 index 0000000..bb957de --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Utility/S3DeletionObject.cs @@ -0,0 +1,15 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + +namespace Marco.Pms.Model.MongoDBModels.Utility +{ + public class S3DeletionObject + { + [BsonId] + [BsonRepresentation(BsonType.String)] + public Guid Id { get; set; } = Guid.NewGuid(); + public string BucketName { get; set; } = string.Empty; + public string Key { get; set; } = string.Empty; + public bool Deleted { get; set; } = false; + } +} diff --git a/Marco.Pms.Model/MongoDBModels/Utility/UpdateLogsObject.cs b/Marco.Pms.Model/MongoDBModels/Utility/UpdateLogsObject.cs new file mode 100644 index 0000000..30f87d6 --- /dev/null +++ b/Marco.Pms.Model/MongoDBModels/Utility/UpdateLogsObject.cs @@ -0,0 +1,16 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + +namespace Marco.Pms.Model.MongoDBModels.Utility +{ + public class UpdateLogsObject + { + [BsonId] + [BsonRepresentation(BsonType.String)] + public Guid Id { get; set; } = Guid.NewGuid(); + public string EntityId { get; set; } = string.Empty; + public BsonDocument? OldObject { get; set; } + public string UpdatedById { get; set; } = string.Empty; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + } +} diff --git a/Marco.Pms.Model/Utilities/ExpensesFilter.cs b/Marco.Pms.Model/Utilities/ExpensesFilter.cs new file mode 100644 index 0000000..bd24ab8 --- /dev/null +++ b/Marco.Pms.Model/Utilities/ExpensesFilter.cs @@ -0,0 +1,13 @@ +namespace Marco.Pms.Model.Utilities +{ + public class ExpensesFilter + { + public List? ProjectIds { get; set; } + public List? StatusIds { get; set; } + public List? CreatedByIds { get; set; } + public List? PaidById { get; set; } + public bool IsTransactionDate { get; set; } = false; + public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } + } +} diff --git a/Marco.Pms.Model/Utilities/FileUploadModel.cs b/Marco.Pms.Model/Utilities/FileUploadModel.cs index 93ecb2c..98a6a26 100644 --- a/Marco.Pms.Model/Utilities/FileUploadModel.cs +++ b/Marco.Pms.Model/Utilities/FileUploadModel.cs @@ -2,10 +2,12 @@ { public class FileUploadModel { + public Guid? DocumentId { get; set; } public string? FileName { get; set; } // Name of the file (e.g., "image1.png") public string? Base64Data { get; set; } // Base64-encoded string of the file public string? ContentType { get; set; } // MIME type (e.g., "image/png", "application/pdf") public long FileSize { get; set; } // File size in bytes public string? Description { get; set; } // Optional: Description or purpose of the file + public bool IsActive { get; set; } = true; } } diff --git a/Marco.Pms.Model/ViewModels/DocumentManager/DocumentVM.cs b/Marco.Pms.Model/ViewModels/DocumentManager/DocumentVM.cs index 4940600..d971ea4 100644 --- a/Marco.Pms.Model/ViewModels/DocumentManager/DocumentVM.cs +++ b/Marco.Pms.Model/ViewModels/DocumentManager/DocumentVM.cs @@ -11,4 +11,12 @@ public string ContentType { get; set; } = string.Empty; public DateTime UploadedAt { get; set; } } + public class BasicDocumentVM + { + public Guid DocumentId { get; set; } + public string FileName { get; set; } = string.Empty; + public string ContentType { get; set; } = string.Empty; + public string? PreSignedUrl { get; set; } + public string? ThumbPreSignedUrl { get; set; } + } } diff --git a/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs b/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs new file mode 100644 index 0000000..174a53d --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs @@ -0,0 +1,36 @@ +using Marco.Pms.Model.ViewModels.Activities; +using Marco.Pms.Model.ViewModels.DocumentManager; +using Marco.Pms.Model.ViewModels.Master; +using Marco.Pms.Model.ViewModels.Projects; + +namespace Marco.Pms.Model.ViewModels.Expenses +{ + public class ExpenseDetailsVM + { + public Guid Id { get; set; } + public ProjectInfoVM? Project { get; set; } + public ExpensesTypeMasterVM? ExpensesType { get; set; } + public PaymentModeMatserVM? PaymentMode { get; set; } + public BasicEmployeeVM? PaidBy { get; set; } + public BasicEmployeeVM? CreatedBy { get; set; } + public BasicEmployeeVM? ReviewedBy { get; set; } + public BasicEmployeeVM? ApprovedBy { get; set; } + public BasicEmployeeVM? ProcessedBy { get; set; } + public DateTime TransactionDate { get; set; } + public DateTime CreatedAt { get; set; } + public string SupplerName { get; set; } = string.Empty; + public double Amount { get; set; } + public ExpensesStatusMasterVM? Status { get; set; } + public List? NextStatus { get; set; } + public bool PreApproved { get; set; } = false; + public string? TransactionId { get; set; } + public string Description { get; set; } = string.Empty; + public string? Location { get; set; } + public List Documents { get; set; } = new List(); + public List ExpenseLogs { get; set; } = new List(); + public string? GSTNumber { get; set; } + public int? NoOfPersons { get; set; } + public bool IsActive { get; set; } = true; + public ExpensesReimburseVM ExpensesReimburse { get; set; } = new ExpensesReimburseVM(); + } +} diff --git a/Marco.Pms.Model/ViewModels/Expenses/ExpenseList.cs b/Marco.Pms.Model/ViewModels/Expenses/ExpenseList.cs new file mode 100644 index 0000000..c29b020 --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Expenses/ExpenseList.cs @@ -0,0 +1,28 @@ +using Marco.Pms.Model.ViewModels.Activities; +using Marco.Pms.Model.ViewModels.Master; +using Marco.Pms.Model.ViewModels.Projects; + +namespace Marco.Pms.Model.ViewModels.Expanses +{ + public class ExpenseList + { + public Guid Id { get; set; } + public ProjectInfoVM? Project { get; set; } + public ExpensesTypeMasterVM? ExpensesType { get; set; } + public PaymentModeMatserVM? PaymentMode { get; set; } + public BasicEmployeeVM? PaidBy { get; set; } + public BasicEmployeeVM? CreatedBy { get; set; } + //public BasicEmployeeVM? ReviewedBy { get; set; } + //public BasicEmployeeVM? ApprovedBy { get; set; } + //public BasicEmployeeVM? ProcessedBy { get; set; } + public DateTime TransactionDate { get; set; } + public DateTime CreatedAt { get; set; } + public string SupplerName { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public string TransactionId { get; set; } = string.Empty; + public double Amount { get; set; } + public ExpensesStatusMasterVM? Status { get; set; } + public List? NextStatus { get; set; } + public bool PreApproved { get; set; } = false; + } +} diff --git a/Marco.Pms.Model/ViewModels/Expenses/ExpenseLogVM.cs b/Marco.Pms.Model/ViewModels/Expenses/ExpenseLogVM.cs new file mode 100644 index 0000000..4875eaf --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Expenses/ExpenseLogVM.cs @@ -0,0 +1,13 @@ +using Marco.Pms.Model.ViewModels.Activities; + +namespace Marco.Pms.Model.ViewModels.Expenses +{ + public class ExpenseLogVM + { + public Guid Id { get; set; } + public BasicEmployeeVM? UpdatedBy { get; set; } + public string Action { get; set; } = string.Empty; + public DateTime? UpdateAt { get; set; } + public string? Comment { get; set; } + } +} diff --git a/Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs b/Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs new file mode 100644 index 0000000..75e04ba --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs @@ -0,0 +1,13 @@ +using Marco.Pms.Model.ViewModels.Activities; + +namespace Marco.Pms.Model.ViewModels.Expenses +{ + public class ExpensesReimburseVM + { + public Guid Id { get; set; } + public string ReimburseTransactionId { get; set; } = string.Empty; + public DateTime ReimburseDate { get; set; } + public BasicEmployeeVM? ReimburseBy { get; set; } + public string ReimburseNote { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/ViewModels/Master/ExpensesStatusMasterVM.cs b/Marco.Pms.Model/ViewModels/Master/ExpensesStatusMasterVM.cs new file mode 100644 index 0000000..8f6f02a --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Master/ExpensesStatusMasterVM.cs @@ -0,0 +1,13 @@ +namespace Marco.Pms.Model.ViewModels.Master +{ + public class ExpensesStatusMasterVM + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string DisplayName { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public List? PermissionIds { get; set; } + public string? Color { get; set; } + public bool IsSystem { get; set; } = false; + } +} diff --git a/Marco.Pms.Model/ViewModels/Master/ExpensesTypeMasterVM.cs b/Marco.Pms.Model/ViewModels/Master/ExpensesTypeMasterVM.cs new file mode 100644 index 0000000..f4551d3 --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Master/ExpensesTypeMasterVM.cs @@ -0,0 +1,10 @@ +namespace Marco.Pms.Model.ViewModels.Master +{ + public class ExpensesTypeMasterVM + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public bool NoOfPersonsRequired { get; set; } + public string Description { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Model/ViewModels/Master/PaymentModeMatserVM.cs b/Marco.Pms.Model/ViewModels/Master/PaymentModeMatserVM.cs new file mode 100644 index 0000000..de7716a --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Master/PaymentModeMatserVM.cs @@ -0,0 +1,9 @@ +namespace Marco.Pms.Model.ViewModels.Master +{ + public class PaymentModeMatserVM + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Services/Controllers/AttendanceController.cs b/Marco.Pms.Services/Controllers/AttendanceController.cs index 7339966..5af6c67 100644 --- a/Marco.Pms.Services/Controllers/AttendanceController.cs +++ b/Marco.Pms.Services/Controllers/AttendanceController.cs @@ -74,7 +74,7 @@ namespace MarcoBMS.Services.Controllers foreach (var attendanceLog in lstAttendance) { string objectKey = attendanceLog.Document != null ? attendanceLog.Document.S3Key : string.Empty; - string preSignedUrl = string.IsNullOrEmpty(objectKey) ? string.Empty : _s3Service.GeneratePreSignedUrlAsync(objectKey); + string preSignedUrl = string.IsNullOrEmpty(objectKey) ? string.Empty : _s3Service.GeneratePreSignedUrl(objectKey); attendanceLogVMs.Add(attendanceLog.ToAttendanceLogVMFromAttendanceLog(preSignedUrl, preSignedUrl)); } _logger.LogInfo("{count} Attendance records fetched successfully", lstAttendance.Count); @@ -708,7 +708,7 @@ namespace MarcoBMS.Services.Controllers var objectKey = $"tenant-{tenantId}/Employee/{recordAttendanceDot.EmployeeID}/Attendance/{fileName}"; await _s3Service.UploadFileAsync(base64, fileType, objectKey); - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey); + preSignedUrl = _s3Service.GeneratePreSignedUrl(objectKey); document = new Document { diff --git a/Marco.Pms.Services/Controllers/AuthController.cs b/Marco.Pms.Services/Controllers/AuthController.cs index 429a38b..67dd74a 100644 --- a/Marco.Pms.Services/Controllers/AuthController.cs +++ b/Marco.Pms.Services/Controllers/AuthController.cs @@ -750,7 +750,7 @@ namespace MarcoBMS.Services.Controllers .FirstOrDefaultAsync(e => e.Id == generateMPINDto.EmployeeId && e.TenantId == tenantId); // Validate employee and MPIN input - if (requestEmployee == null || string.IsNullOrWhiteSpace(generateMPINDto.MPIN) || generateMPINDto.MPIN.Length != 6 || !generateMPINDto.MPIN.All(char.IsDigit)) + if (requestEmployee == null || string.IsNullOrWhiteSpace(generateMPINDto.MPIN) || generateMPINDto.MPIN.Length != 4 || !generateMPINDto.MPIN.All(char.IsDigit)) { _logger.LogWarning("Employee {EmployeeId} provided invalid information to generate MPIN", loggedInEmployee.Id); return BadRequest(ApiResponse.ErrorResponse("Provided invalid information", "Provided invalid information", 400)); diff --git a/Marco.Pms.Services/Controllers/EmployeeController.cs b/Marco.Pms.Services/Controllers/EmployeeController.cs index d5d7f3d..cdc28ed 100644 --- a/Marco.Pms.Services/Controllers/EmployeeController.cs +++ b/Marco.Pms.Services/Controllers/EmployeeController.cs @@ -1,4 +1,5 @@ -using Marco.Pms.DataAccess.Data; +using AutoMapper; +using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Dtos.Employees; using Marco.Pms.Model.Employees; @@ -6,6 +7,7 @@ using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Projects; using Marco.Pms.Model.Utilities; +using Marco.Pms.Model.ViewModels.Activities; using Marco.Pms.Model.ViewModels.Employee; using Marco.Pms.Services.Hubs; using Marco.Pms.Services.Service; @@ -38,13 +40,14 @@ namespace MarcoBMS.Services.Controllers private readonly ILoggingService _logger; private readonly IHubContext _signalR; private readonly PermissionServices _permission; + private readonly IMapper _mapper; private readonly IProjectServices _projectServices; private readonly Guid tenantId; public EmployeeController(UserManager userManager, IEmailSender emailSender, ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger, - IHubContext signalR, PermissionServices permission, IProjectServices projectServices) + IHubContext signalR, PermissionServices permission, IProjectServices projectServices, IMapper mapper) { _context = context; _userManager = userManager; @@ -56,6 +59,7 @@ namespace MarcoBMS.Services.Controllers _signalR = signalR; _permission = permission; _projectServices = projectServices; + _mapper = mapper; tenantId = _userHelper.GetTenantId(); } @@ -162,6 +166,31 @@ namespace MarcoBMS.Services.Controllers return Ok(ApiResponse.SuccessResponse(result, "Filter applied.", 200)); } + [HttpGet("basic")] + public async Task GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var employeeQuery = _context.Employees.Where(e => e.TenantId == tenantId); + if (projectId != null && projectId != Guid.Empty) + { + var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value); + if (!hasProjectPermission) + { + _logger.LogWarning("User {EmployeeId} attempts to get employee for project {ProjectId}, but not have access to the project", loggedInEmployee.Id, projectId); + return StatusCode(403, ApiResponse.ErrorResponse("Access denied", "User do not have access to view the list for this project", 403)); + } + var employeeIds = await _context.ProjectAllocations.Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.TenantId == tenantId).Select(p => p.EmployeeId).ToListAsync(); + employeeQuery = employeeQuery.Where(e => employeeIds.Contains(e.Id)); + } + if (!string.IsNullOrWhiteSpace(searchString)) + { + var searchStringLower = searchString.ToLower(); + employeeQuery = employeeQuery.Where(e => (e.FirstName + " " + e.LastName).ToLower().Contains(searchStringLower)); + } + + var response = await employeeQuery.Take(10).Select(e => _mapper.Map(e)).ToListAsync(); + return Ok(ApiResponse.SuccessResponse(response, $"{response.Count} records of employees fetched successfully", 200)); + } [HttpGet] [Route("search/{name}/{projectid?}")] public async Task SearchEmployee(string name, Guid? projectid) diff --git a/Marco.Pms.Services/Controllers/ExpenseController.cs b/Marco.Pms.Services/Controllers/ExpenseController.cs new file mode 100644 index 0000000..36b0f74 --- /dev/null +++ b/Marco.Pms.Services/Controllers/ExpenseController.cs @@ -0,0 +1,126 @@ +using Marco.Pms.Model.Dtos.Expenses; +using Marco.Pms.Model.Utilities; +using Marco.Pms.Services.Service.ServiceInterfaces; +using MarcoBMS.Services.Helpers; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + + +namespace Marco.Pms.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [Authorize] + public class ExpenseController : ControllerBase + { + private readonly UserHelper _userHelper; + private readonly IExpensesService _expensesService; + private readonly ISignalRService _signalR; + private readonly Guid tenantId; + public ExpenseController( + UserHelper userHelper, + IExpensesService expensesService, + ISignalRService signalR + ) + { + _userHelper = userHelper; + _expensesService = expensesService; + _signalR = signalR; + tenantId = userHelper.GetTenantId(); + } + + + /// + /// Retrieves a paginated list of expenses based on user permissions and optional filters. + /// + /// A URL-encoded JSON string containing filter criteria. See . + /// The number of records to return per page. + /// The page number to retrieve. + /// A paginated list of expenses. + + [HttpGet("list")] + public async Task GetExpensesList([FromQuery] string? searchString, [FromQuery] string? filter, [FromQuery] int pageSize = 20, [FromQuery] int pageNumber = 1) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.GetExpensesListAsync(loggedInEmployee, tenantId, searchString, filter, pageSize, pageNumber); + return StatusCode(response.StatusCode, response); + } + + [HttpGet("details/{id}")] + public async Task GetExpenseDetails(Guid id) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.GetExpenseDetailsAsync(id, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpGet("suppler-name")] + public async Task GetSupplerNameList() + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.GetSupplerNameListAsync(loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpGet("filter")] + public async Task GetFilterObject() + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.GetFilterObjectAsync(loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpPost("create")] + public async Task CreateExpense([FromBody] CreateExpensesDto model) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.CreateExpenseAsync(model, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Expanse", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + + [HttpPost("action")] + public async Task ChangeStatus([FromBody] ExpenseRecordDto model) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.ChangeStatusAsync(model, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Expanse", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + + [HttpPut("edit/{id}")] + public async Task UpdateExpanse(Guid id, [FromBody] UpdateExpensesDto model) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.UpdateExpanseAsync(id, model, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Expanse", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + + [HttpDelete("delete/{id}")] + public async Task DeleteExpanse(Guid id) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _expensesService.DeleteExpanseAsync(id, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Expanse", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + + } +} diff --git a/Marco.Pms.Services/Controllers/ForumController.cs b/Marco.Pms.Services/Controllers/ForumController.cs index fb6d0e7..4e3b948 100644 --- a/Marco.Pms.Services/Controllers/ForumController.cs +++ b/Marco.Pms.Services/Controllers/ForumController.cs @@ -129,7 +129,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl)); } @@ -301,7 +301,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } if (attachment.CommentId == null) { @@ -418,7 +418,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl)); } @@ -532,7 +532,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl)); } @@ -606,7 +606,7 @@ namespace Marco.Pms.Services.Controllers _context.TicketAttachments.Add(attachment); await _context.SaveChangesAsync(); - string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + string preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); TicketAttachmentVM attachmentVM = attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl); ticketAttachmentVMs.Add(attachmentVM); @@ -671,7 +671,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } if (attachment.CommentId == null) { @@ -749,7 +749,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } if (attachment.CommentId == null) { @@ -851,7 +851,7 @@ namespace Marco.Pms.Services.Controllers string preSignedUrl = string.Empty; if (document != null) { - preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); + preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); } if (attachment.CommentId == null) { diff --git a/Marco.Pms.Services/Controllers/ImageController.cs b/Marco.Pms.Services/Controllers/ImageController.cs index 9014171..cf046a8 100644 --- a/Marco.Pms.Services/Controllers/ImageController.cs +++ b/Marco.Pms.Services/Controllers/ImageController.cs @@ -220,8 +220,8 @@ namespace Marco.Pms.Services.Controllers Documents = d.Documents?.Select(x => new { Id = x.Id, - thumbnailUrl = x.ThumbS3Key != null ? _s3Service.GeneratePreSignedUrlAsync(x.ThumbS3Key) : (x.S3Key != null ? _s3Service.GeneratePreSignedUrlAsync(x.S3Key) : null), - Url = x.S3Key != null ? _s3Service.GeneratePreSignedUrlAsync(x.S3Key) : null, + thumbnailUrl = x.ThumbS3Key != null ? _s3Service.GeneratePreSignedUrl(x.ThumbS3Key) : (x.S3Key != null ? _s3Service.GeneratePreSignedUrl(x.S3Key) : null), + Url = x.S3Key != null ? _s3Service.GeneratePreSignedUrl(x.S3Key) : null, UploadedBy = x.UploadedBy?.ToBasicEmployeeVMFromEmployee() ?? uploadedBy?.ToBasicEmployeeVMFromEmployee(), UploadedAt = x.UploadedAt, }).ToList(), @@ -334,8 +334,8 @@ namespace Marco.Pms.Services.Controllers Documents = documents?.Select(x => new { Id = x.Id, - thumbnailUrl = x.ThumbS3Key != null ? _s3Service.GeneratePreSignedUrlAsync(x.ThumbS3Key) : (x.S3Key != null ? _s3Service.GeneratePreSignedUrlAsync(x.S3Key) : null), - Url = x.S3Key != null ? _s3Service.GeneratePreSignedUrlAsync(x.S3Key) : null, + thumbnailUrl = x.ThumbS3Key != null ? _s3Service.GeneratePreSignedUrl(x.ThumbS3Key) : (x.S3Key != null ? _s3Service.GeneratePreSignedUrl(x.S3Key) : null), + Url = x.S3Key != null ? _s3Service.GeneratePreSignedUrl(x.S3Key) : null, UploadedBy = x.UploadedBy?.ToBasicEmployeeVMFromEmployee() ?? uploadedBy?.ToBasicEmployeeVMFromEmployee(), UploadedAt = x.UploadedAt, }).ToList(), @@ -382,11 +382,11 @@ namespace Marco.Pms.Services.Controllers // Step 4: Generate pre-signed URLs for thumbnail and full image (if keys exist) string? thumbnailUrl = document.ThumbS3Key != null - ? _s3Service.GeneratePreSignedUrlAsync(document.ThumbS3Key) + ? _s3Service.GeneratePreSignedUrl(document.ThumbS3Key) : null; string? imageUrl = document.S3Key != null - ? _s3Service.GeneratePreSignedUrlAsync(document.S3Key) + ? _s3Service.GeneratePreSignedUrl(document.S3Key) : null; // Step 5: Prepare the response object diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index 9000cdf..bcc4264 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -10,6 +10,7 @@ using Marco.Pms.Model.ViewModels.Activities; using Marco.Pms.Model.ViewModels.Forum; using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Services.Helpers; +using Marco.Pms.Services.Service.ServiceInterfaces; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; @@ -27,15 +28,20 @@ namespace Marco.Pms.Services.Controllers private readonly UserHelper _userHelper; private readonly ILoggingService _logger; private readonly MasterHelper _masterHelper; - public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, MasterHelper masterHelper) + private readonly IMasterService _masterService; + private readonly Guid tenantId; + public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, MasterHelper masterHelper, IMasterService masterService) { _context = context; _userHelper = userHelper; _logger = logger; _masterHelper = masterHelper; + _masterService = masterService; + tenantId = userHelper.GetTenantId(); } - // -------------------------------- Activity -------------------------------- + #region =================================================================== Activity APIs =================================================================== + [HttpGet] [Route("activities")] public async Task GetActivitiesMaster() @@ -186,7 +192,9 @@ namespace Marco.Pms.Services.Controllers return Ok(ApiResponse.SuccessResponse(new { }, "Activity Deleted Successfully", 200)); } - // -------------------------------- Industry -------------------------------- + #endregion + + #region =================================================================== Industry APIs =================================================================== [HttpGet] [Route("industries")] @@ -199,7 +207,9 @@ namespace Marco.Pms.Services.Controllers return Ok(ApiResponse.SuccessResponse(industries, System.String.Format("{0} industry records fetched successfully", industries.Count), 200)); } - // -------------------------------- Ticket Status -------------------------------- + #endregion + + #region =================================================================== Ticket Status APIs =================================================================== [HttpGet("ticket-status")] public async Task GetTicketStatusMaster() @@ -286,7 +296,9 @@ namespace Marco.Pms.Services.Controllers } } - // -------------------------------- Ticket Type -------------------------------- + #endregion + + #region =================================================================== Ticket Type APIs =================================================================== [HttpGet("ticket-types")] public async Task GetTicketTypeMaster() @@ -374,7 +386,9 @@ namespace Marco.Pms.Services.Controllers } } - // -------------------------------- Ticket Priority -------------------------------- + #endregion + + #region =================================================================== Ticket Priority APIs =================================================================== [HttpGet("ticket-priorities")] public async Task GetTicketPriorityMaster() @@ -462,7 +476,9 @@ namespace Marco.Pms.Services.Controllers } } - // -------------------------------- Ticket Tag -------------------------------- + #endregion + + #region =================================================================== Ticket Tag APIs =================================================================== [HttpGet("ticket-tags")] public async Task GetTicketTagMaster() @@ -550,7 +566,9 @@ namespace Marco.Pms.Services.Controllers } } - // -------------------------------- Work Category -------------------------------- + #endregion + + #region =================================================================== Work Category APIs =================================================================== [HttpGet("work-categories")] public async Task GetWorkCategoryMasterList() @@ -671,7 +689,9 @@ namespace Marco.Pms.Services.Controllers } } - // -------------------------------- Work Status -------------------------------- + #endregion + + #region =================================================================== Work Status APIs =================================================================== [HttpGet("work-status")] public async Task GetWorkStatusMasterList() @@ -710,7 +730,9 @@ namespace Marco.Pms.Services.Controllers return StatusCode(response.StatusCode, response); } - // -------------------------------- Contact Category -------------------------------- + #endregion + + #region =================================================================== Contact Category APIs =================================================================== [HttpGet("contact-categories")] public async Task GetContactCategoryMasterList() @@ -779,7 +801,9 @@ namespace Marco.Pms.Services.Controllers return Ok(response); } - // -------------------------------- Contact Tag -------------------------------- + #endregion + + #region =================================================================== Contact Tag APIs =================================================================== [HttpGet("contact-tags")] public async Task GetContactTagMasterList() @@ -788,12 +812,6 @@ namespace Marco.Pms.Services.Controllers return Ok(response); } - //[HttpGet("contact-tag/{id}")] - //public async Task GetContactTagMaster(Guid id) - //{ - // return Ok(); - //} - [HttpPost("contact-tag")] public async Task CreateContactTagMaster([FromBody] CreateContactTagDto contactTagDto) { @@ -846,5 +864,90 @@ namespace Marco.Pms.Services.Controllers var response = await _masterHelper.DeleteContactTag(id); return Ok(response); } + #endregion + + #region =================================================================== Expenses Type APIs =================================================================== + + [HttpGet("expenses-types")] + public async Task GetExpenseTypeList([FromQuery] bool isActive = true) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.GetExpenseTypeListAsync(loggedInEmployee, tenantId, isActive); + return StatusCode(response.StatusCode, response); + } + + [HttpPost("expenses-type")] + public async Task CreateExpenseType([FromBody] ExpensesTypeMasterDto dto) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.CreateExpenseTypeAsync(dto, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpPut("expenses-type/edit/{id}")] + public async Task UpdateExpenseType(Guid id, [FromBody] ExpensesTypeMasterDto dto) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.UpdateExpenseTypeAsync(id, dto, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpDelete("expenses-type/delete/{id}")] + public async Task DeleteExpenseType(Guid id, [FromQuery] bool isActive = false) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.DeleteExpenseTypeAsync(id, isActive, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + #endregion + + #region =================================================================== Expenses Status APIs =================================================================== + + [HttpGet("expenses-status")] + public async Task GetExpensesStatusList([FromQuery] bool isActive = true) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.GetExpensesStatusListAsync(loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + #endregion + + #region =================================================================== Payment mode APIs =================================================================== + + [HttpGet("payment-modes")] + public async Task GetPaymentModeList([FromQuery] bool isActive = true) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.GetPaymentModeListAsync(loggedInEmployee, tenantId, isActive); + return StatusCode(response.StatusCode, response); + } + + [HttpPost("payment-mode")] + public async Task CreatePaymentMode([FromBody] PaymentModeMatserDto dto) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.CreatePaymentModeAsync(dto, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpPut("payment-mode/edit/{id}")] + public async Task UpdatePaymentMode(Guid id, [FromBody] PaymentModeMatserDto dto) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.UpdatePaymentModeAsync(id, dto, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpDelete("payment-mode/delete/{id}")] + public async Task DeletePaymentMode(Guid id, [FromQuery] bool isActive = false) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.DeletePaymentModeAsync(id, isActive, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + #endregion } } diff --git a/Marco.Pms.Services/Controllers/ReportController.cs b/Marco.Pms.Services/Controllers/ReportController.cs index a46c391..e71061c 100644 --- a/Marco.Pms.Services/Controllers/ReportController.cs +++ b/Marco.Pms.Services/Controllers/ReportController.cs @@ -1,7 +1,7 @@ using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Dtos.Mail; using Marco.Pms.Model.Mail; -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Utility; using Marco.Pms.Model.Utilities; using Marco.Pms.Services.Helpers; using MarcoBMS.Services.Helpers; diff --git a/Marco.Pms.Services/Controllers/TaskController.cs b/Marco.Pms.Services/Controllers/TaskController.cs index b764f00..9f648ac 100644 --- a/Marco.Pms.Services/Controllers/TaskController.cs +++ b/Marco.Pms.Services/Controllers/TaskController.cs @@ -230,8 +230,8 @@ namespace MarcoBMS.Services.Controllers : image.Base64Data; var fileType = _s3Service.GetContentTypeFromBase64(base64); - var fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report"); - var objectKey = $"tenant-{tenantId}/project-{projectId}/Actitvity/{fileName}"; + var fileName = _s3Service.GenerateFileName(fileType, taskAllocation.Id, "task_report"); + var objectKey = $"tenant-{tenantId}/project-{projectId}/Activity/{fileName}"; await _s3Service.UploadFileAsync(base64, fileType, objectKey); @@ -336,7 +336,7 @@ namespace MarcoBMS.Services.Controllers : image.Base64Data; var fileType = _s3Service.GetContentTypeFromBase64(base64); - var fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_comment"); + var fileName = _s3Service.GenerateFileName(fileType, comment.Id, "task_comment"); var objectKey = $"tenant-{tenantId}/project-{projectId}/Activity/{fileName}"; await _s3Service.UploadFileAsync(base64, fileType, objectKey); @@ -499,7 +499,7 @@ namespace MarcoBMS.Services.Controllers .ToList(); response.ReportedPreSignedUrls = taskDocs - .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .Select(d => _s3Service.GeneratePreSignedUrl(d.S3Key)) .ToList(); // Add team members @@ -532,7 +532,7 @@ namespace MarcoBMS.Services.Controllers var commentVm = comment.ToCommentVMFromTaskComment(); commentVm.PreSignedUrls = commentDocs - .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .Select(d => _s3Service.GeneratePreSignedUrl(d.S3Key)) .ToList(); commentVMs.Add(commentVm); @@ -649,7 +649,7 @@ namespace MarcoBMS.Services.Controllers .ToList(); taskVM.PreSignedUrls = taskDocuments - .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .Select(d => _s3Service.GeneratePreSignedUrl(d.S3Key)) .ToList(); // Construct CommentVM list with document URLs @@ -667,7 +667,7 @@ namespace MarcoBMS.Services.Controllers var commentVM = comment.ToCommentVMFromTaskComment(); commentVM.PreSignedUrls = commentDocs - .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .Select(d => _s3Service.GeneratePreSignedUrl(d.S3Key)) .ToList(); return commentVM; diff --git a/Marco.Pms.Services/Controllers/WeatherForecastController.cs b/Marco.Pms.Services/Controllers/WeatherForecastController.cs index fae8c73..2ffd222 100644 --- a/Marco.Pms.Services/Controllers/WeatherForecastController.cs +++ b/Marco.Pms.Services/Controllers/WeatherForecastController.cs @@ -39,7 +39,7 @@ namespace MarcoBMS.Services.Controllers // return BadRequest("Base64 data is missing"); // var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, 1, "Forum"); // //var objectKey = await _s3Service.UploadFileAsync(Image.FileName, Image.ContentType); - // var preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey); + // var preSignedUrl = _s3Service.GeneratePreSignedUrl(objectKey); // return Ok(new // { diff --git a/Marco.Pms.Services/Dockerfile b/Marco.Pms.Services/Dockerfile index 2aa24ea..50b9865 100644 --- a/Marco.Pms.Services/Dockerfile +++ b/Marco.Pms.Services/Dockerfile @@ -19,7 +19,7 @@ COPY ["Marco.Pms.Services/Marco.Pms.Services.csproj", "Marco.Pms.Services/"] COPY ["Marco.Pms.DataAccess/Marco.Pms.DataAccess.csproj", "Marco.Pms.DataAccess/"] COPY ["Marco.Pms.Model/Marco.Pms.Model.csproj", "Marco.Pms.Model/"] COPY ["Marco.Pms.Utility/Marco.Pms.Utility.csproj", "Marco.Pms.Utility/"] -COPY ["Marco.Pms.CacheHelper/Marco.Pms.CacheHelper.csproj", "Marco.Pms.CacheHelper/"] +COPY ["Marco.Pms.Helpers/Marco.Pms.Helpers.csproj", "Marco.Pms.Helpers/"] RUN dotnet restore "./Marco.Pms.Services/Marco.Pms.Services.csproj" COPY . . WORKDIR "/src/Marco.Pms.Services" diff --git a/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs b/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs index d942ab1..cbd7b6e 100644 --- a/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs +++ b/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs @@ -1,37 +1,60 @@ -using Marco.Pms.CacheHelper; +using AutoMapper; using Marco.Pms.DataAccess.Data; +using Marco.Pms.Helpers; +using Marco.Pms.Helpers.CacheHelper; +using Marco.Pms.Model.Expenses; using Marco.Pms.Model.Master; using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Employees; +using Marco.Pms.Model.MongoDBModels.Expenses; +using Marco.Pms.Model.MongoDBModels.Masters; +using Marco.Pms.Model.MongoDBModels.Project; +using Marco.Pms.Model.MongoDBModels.Utility; using Marco.Pms.Model.Projects; +using Marco.Pms.Model.Utilities; using MarcoBMS.Services.Service; using Microsoft.EntityFrameworkCore; +using MongoDB.Driver; using Project = Marco.Pms.Model.Projects.Project; namespace Marco.Pms.Services.Helpers { public class CacheUpdateHelper { + private readonly IDbContextFactory _dbContextFactory; + private readonly ApplicationDbContext _context; + private readonly IMapper _mapper; private readonly ProjectCache _projectCache; private readonly EmployeeCache _employeeCache; private readonly ReportCache _reportCache; + private readonly ExpenseCache _expenseCache; private readonly ILoggingService _logger; - private readonly IDbContextFactory _dbContextFactory; - private readonly ApplicationDbContext _context; private readonly GeneralHelper _generalHelper; + private static readonly Guid Draft = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8"); + private static readonly Guid Rejected = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729"); - public CacheUpdateHelper(ProjectCache projectCache, EmployeeCache employeeCache, ReportCache reportCache, ILoggingService logger, - IDbContextFactory dbContextFactory, ApplicationDbContext context, GeneralHelper generalHelper) + public CacheUpdateHelper( + IMapper mapper, + ProjectCache projectCache, + EmployeeCache employeeCache, + ReportCache reportCache, + ExpenseCache expenseCache, + ILoggingService logger, + IDbContextFactory dbContextFactory, + ApplicationDbContext context, + GeneralHelper generalHelper) { + _mapper = mapper; _projectCache = projectCache; _employeeCache = employeeCache; _reportCache = reportCache; + _expenseCache = expenseCache; _logger = logger; _dbContextFactory = dbContextFactory; _context = context; _generalHelper = generalHelper; } - - // ------------------------------------ Project Details Cache --------------------------------------- + #region ======================================================= Project Details Cache ======================================================= public async Task AddProjectDetails(Project project) { @@ -504,7 +527,9 @@ namespace Marco.Pms.Services.Helpers } } - // ------------------------------------ Project Infrastructure Cache --------------------------------------- + #endregion + + #region ======================================================= Project Infrastructure Cache ======================================================= public async Task AddBuildngInfra(Guid projectId, Building? building = null, Floor? floor = null, WorkArea? workArea = null, Guid? buildingId = null) { @@ -570,7 +595,9 @@ namespace Marco.Pms.Services.Helpers } } - // ------------------------------------------------------- WorkItem ------------------------------------------------------- + #endregion + + #region ======================================================= WorkItem Cache ======================================================= public async Task?> GetWorkItemsByWorkAreaIds(List workAreaIds) { @@ -677,8 +704,10 @@ namespace Marco.Pms.Services.Helpers } } + #endregion + + #region ======================================================= Employee Profile Cache ======================================================= - // ------------------------------------ Employee Profile Cache --------------------------------------- public async Task AddApplicationRole(Guid employeeId, List roleIds) { // 1. Guard Clause: Avoid unnecessary database work if there are no roles to add. @@ -836,8 +865,134 @@ namespace Marco.Pms.Services.Helpers } } + #endregion - // ------------------------------------ Report Cache --------------------------------------- + #region ======================================================= Expenses Cache ======================================================= + public async Task AddExpenseByObjectAsync(Expenses expense) + { + var expenseCache = await GetAllExpnesRelatedTablesForSingle(expense, expense.TenantId); + + try + { + await _expenseCache.AddExpenseToCacheAsync(expenseCache); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurd while storing expense related table in cahce"); + return; + } + + return; + } + public async Task AddExpenseByIdAsync(Guid Id, Guid tenantId) + { + var expense = await _context.Expenses.AsNoTracking().FirstOrDefaultAsync(e => e.Id == Id && e.TenantId == tenantId); + + if (expense == null) + { + return null; + } + var expenseCache = await GetAllExpnesRelatedTablesForSingle(expense, expense.TenantId); + + try + { + await _expenseCache.AddExpenseToCacheAsync(expenseCache); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurd while storing expense related table in cahce"); + return null; + } + + return expenseCache; + + + } + public async Task AddExpensesListToCache(List expenses, Guid tenantId) + { + var expensesCache = await GetAllExpnesRelatedTablesForList(expenses, tenantId); + + try + { + await _expenseCache.AddExpensesListToCacheAsync(expensesCache); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while saving the list of expenses to Cache"); + } + } + + public async Task<(int totalPages, long totalCount, List? expenseList)> GetExpenseListAsync(Guid tenantId, Guid loggedInEmployeeId, bool viewAll, + bool viewSelf, int pageNumber, int pageSize, ExpensesFilter? filter, string? searchString) + { + try + { + var (totalPages, totalCount, expenseList) = await _expenseCache.GetExpenseListFromCacheAsync(tenantId, loggedInEmployeeId, viewAll, viewSelf, pageNumber, pageSize, filter, searchString); + if (expenseList.Any()) + { + + + return (totalPages, totalCount, expenseList); + } + + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while fetching the list of expenses to Cache"); + } + return (0, 0, null); + } + + public async Task GetExpenseDetailsById(Guid id, Guid tenantId) + { + try + { + var response = await _expenseCache.GetExpenseDetailsByIdAsync(id, tenantId); + if (response != null && response.Id != string.Empty) + { + return response; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while fetching expense details from cache"); + } + return null; + } + + public async Task ReplaceExpenseAsync(Expenses expense) + { + bool response = false; + try + { + response = await _expenseCache.DeleteExpenseFromCacheAsync(expense.Id, expense.TenantId); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while deleting expense from cache"); + } + if (response) + { + await AddExpenseByObjectAsync(expense); + } + + } + public async Task DeleteExpenseAsync(Guid id, Guid tenantId) + { + try + { + var response = await _expenseCache.DeleteExpenseFromCacheAsync(id, tenantId); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while deleting expense from cache"); + } + + } + + #endregion + + #region ======================================================= Report Cache ======================================================= public async Task?> GetProjectReportMail(bool IsSend) { @@ -863,5 +1018,283 @@ namespace Marco.Pms.Services.Helpers _logger.LogError(ex, "Error occured while adding project report mail bodys"); } } + + #endregion + + + #region ======================================================= Helper Functions ======================================================= + private async Task> GetAllExpnesRelatedTablesForList(List model, Guid tenantId) + { + List expenseList = new List(); + var expenseIds = model.Select(m => m.Id).ToList(); + var projectIds = model.Select(m => m.ProjectId).ToList(); + var statusIds = model.Select(m => m.StatusId).ToList(); + var expensesTypeIds = model.Select(m => m.ExpensesTypeId).ToList(); + var paymentModeIds = model.Select(m => m.PaymentModeId).ToList(); + var createdByIds = model.Select(m => m.CreatedById).ToList(); + var reviewedByIds = model.Select(m => m.ReviewedById).ToList(); + var approvedByIds = model.Select(m => m.ApprovedById).ToList(); + var processedByIds = model.Select(m => m.ProcessedById).ToList(); + var paidByIds = model.Select(m => m.PaidById).ToList(); + + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Projects.AsNoTracking().Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync(); + }); + var paidByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().Where(e => paidByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var createdByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().Where(e => createdByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var reviewedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().Where(e => reviewedByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var approvedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().Where(e => approvedByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var processedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().Where(e => processedByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var expenseTypeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesTypeMaster.AsNoTracking().Where(et => expensesTypeIds.Contains(et.Id) && et.TenantId == tenantId).ToListAsync(); + }); + var paymentModeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.PaymentModeMatser.AsNoTracking().Where(pm => paymentModeIds.Contains(pm.Id) && pm.TenantId == tenantId).ToListAsync(); + }); + var statusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMapping + .Include(s => s.Status) + .Include(s => s.NextStatus) + .AsNoTracking() + .Where(es => statusIds.Contains(es.StatusId) && es.Status != null) + .GroupBy(s => s.StatusId) + .Select(g => new + { + StatusId = g.Key, + Status = g.Select(s => s.Status).FirstOrDefault(), + NextStatus = g.Select(s => s.NextStatus).OrderBy(s => s!.Name).ToList() + }).ToListAsync(); + }); + var statusTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMaster + .AsNoTracking() + .Where(es => statusIds.Contains(es.Id)) + .ToListAsync(); + }); + var billAttachmentsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.BillAttachments + .Include(ba => ba.Document) + .AsNoTracking() + .Where(ba => expenseIds.Contains(ba.ExpensesId) && ba.Document != null) + .GroupBy(ba => ba.ExpensesId) + .Select(g => new + { + ExpensesId = g.Key, + Documents = g.Select(ba => new DocumentMongoDB + { + DocumentId = ba.Document!.Id.ToString(), + FileName = ba.Document.FileName, + ContentType = ba.Document.ContentType, + S3Key = ba.Document.S3Key, + ThumbS3Key = ba.Document.ThumbS3Key ?? ba.Document.S3Key + }).ToList() + }) + .ToListAsync(); + }); + + // Await all prerequisite checks at once. + await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask, + processedByTask, statusTask, billAttachmentsTask); + + var projects = projectTask.Result; + var expenseTypes = expenseTypeTask.Result; + var paymentModes = paymentModeTask.Result; + var statusMappings = statusMappingTask.Result; + var paidBys = paidByTask.Result; + var createdBys = createdByTask.Result; + var reviewedBys = reviewedByTask.Result; + var approvedBys = approvedByTask.Result; + var processedBy = processedByTask.Result; + var billAttachments = billAttachmentsTask.Result; + + expenseList = model.Select(m => + { + var response = _mapper.Map(m); + + response.Project = projects.Where(p => p.Id == m.ProjectId).Select(p => _mapper.Map(p)).FirstOrDefault() ?? new ProjectBasicMongoDB(); + response.PaidBy = paidBys.Where(p => p.Id == m.PaidById).Select(p => _mapper.Map(p)).FirstOrDefault() ?? new BasicEmployeeMongoDB(); + response.CreatedBy = createdBys.Where(e => e.Id == m.CreatedById).Select(e => _mapper.Map(e)).FirstOrDefault() ?? new BasicEmployeeMongoDB(); + response.ReviewedBy = reviewedBys.Where(e => e.Id == m.CreatedById).Select(e => _mapper.Map(e)).FirstOrDefault(); + response.ApprovedBy = approvedBys.Where(e => e.Id == m.CreatedById).Select(e => _mapper.Map(e)).FirstOrDefault(); + response.ProcessedBy = processedBy.Where(e => e.Id == m.CreatedById).Select(e => _mapper.Map(e)).FirstOrDefault(); + response.Status = statusMappings.Where(s => s.StatusId == m.StatusId).Select(s => _mapper.Map(s.Status)).FirstOrDefault() ?? new ExpensesStatusMasterMongoDB(); + if (response.Status.Id == string.Empty) + { + var status = statusTask.Result; + response.Status = status.Where(s => s.Id == m.StatusId).Select(s => _mapper.Map(s)).FirstOrDefault() ?? new ExpensesStatusMasterMongoDB(); + } + + response.NextStatus = statusMappings.Where(s => s.StatusId == m.StatusId).Select(s => _mapper.Map>(s.NextStatus)).FirstOrDefault() ?? new List(); + response.PaymentMode = paymentModes.Where(pm => pm.Id == m.PaymentModeId).Select(pm => _mapper.Map(pm)).FirstOrDefault() ?? new PaymentModeMatserMongoDB(); + response.ExpensesType = expenseTypes.Where(et => et.Id == m.ExpensesTypeId).Select(et => _mapper.Map(et)).FirstOrDefault() ?? new ExpensesTypeMasterMongoDB(); + response.Documents = billAttachments.Where(ba => ba.ExpensesId == m.Id).Select(ba => ba.Documents).FirstOrDefault() ?? new List(); + return response; + }).ToList(); + + return expenseList; + } + private async Task GetAllExpnesRelatedTablesForSingle(Expenses model, Guid tenantId) + { + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId); + }); + var paidByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.PaidById && e.TenantId == tenantId); + }); + var createdByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.CreatedById && e.TenantId == tenantId); + }); + var reviewedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ReviewedById && e.TenantId == tenantId); + }); + var approvedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ApprovedById && e.TenantId == tenantId); + }); + var processedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ProcessedById && e.TenantId == tenantId); + }); + var expenseTypeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesTypeMaster.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.ExpensesTypeId && et.TenantId == tenantId); + }); + var paymentModeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(pm => pm.Id == model.PaymentModeId && pm.TenantId == tenantId); + }); + var statusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMapping + .Include(s => s.Status) + .Include(s => s.NextStatus) + .AsNoTracking() + .Where(es => es.StatusId == model.StatusId && es.Status != null) + .GroupBy(s => s.StatusId) + .Select(g => new + { + StatusId = g.Key, + Status = g.Select(s => s.Status).FirstOrDefault(), + NextStatus = g.Select(s => s.NextStatus).OrderBy(s => s!.Name).ToList() + }).FirstOrDefaultAsync(); + }); + var statusTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMaster + .AsNoTracking() + .FirstOrDefaultAsync(es => es.Id == model.StatusId); + }); + var billAttachmentsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.BillAttachments + .Include(ba => ba.Document) + .AsNoTracking() + .Where(ba => ba.ExpensesId == model.Id && ba.Document != null) + .GroupBy(ba => ba.ExpensesId) + .Select(g => new + { + ExpensesId = g.Key, + Documents = g.Select(ba => new DocumentMongoDB + { + DocumentId = ba.Document!.Id.ToString(), + FileName = ba.Document.FileName, + ContentType = ba.Document.ContentType, + S3Key = ba.Document.S3Key, + ThumbS3Key = ba.Document.ThumbS3Key ?? ba.Document.S3Key + }).ToList() + }) + .FirstOrDefaultAsync(); + }); + + // Await all prerequisite checks at once. + await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask, + processedByTask, statusTask, billAttachmentsTask); + + var project = projectTask.Result; + var expenseType = expenseTypeTask.Result; + var paymentMode = paymentModeTask.Result; + var statusMapping = statusMappingTask.Result; + var paidBy = paidByTask.Result; + var createdBy = createdByTask.Result; + var reviewedBy = reviewedByTask.Result; + var approvedBy = approvedByTask.Result; + var processedBy = processedByTask.Result; + var billAttachment = billAttachmentsTask.Result; + + + var response = _mapper.Map(model); + + response.Project = _mapper.Map(project); + response.PaidBy = _mapper.Map(paidBy); + response.CreatedBy = _mapper.Map(createdBy); + response.ReviewedBy = _mapper.Map(reviewedBy); + response.ApprovedBy = _mapper.Map(approvedBy); + response.ProcessedBy = _mapper.Map(processedBy); + if (statusMapping != null) + { + response.Status = _mapper.Map(statusMapping.Status); + response.NextStatus = _mapper.Map>(statusMapping.NextStatus); + } + if (response.Status == null) + { + var status = statusTask.Result; + response.Status = _mapper.Map(status); + } + response.PaymentMode = _mapper.Map(paymentMode); + response.ExpensesType = _mapper.Map(expenseType); + if (billAttachment != null) response.Documents = billAttachment.Documents; + + return response; + + } + + #endregion } } diff --git a/Marco.Pms.Services/Helpers/GeneralHelper.cs b/Marco.Pms.Services/Helpers/GeneralHelper.cs index c2f8fe4..8669811 100644 --- a/Marco.Pms.Services/Helpers/GeneralHelper.cs +++ b/Marco.Pms.Services/Helpers/GeneralHelper.cs @@ -1,5 +1,6 @@ using Marco.Pms.DataAccess.Data; -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Masters; +using Marco.Pms.Model.MongoDBModels.Project; using MarcoBMS.Services.Service; using Microsoft.EntityFrameworkCore; diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 83bc007..d50a603 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -19,20 +19,21 @@ namespace Marco.Pms.Services.Helpers private readonly ApplicationDbContext _context; private readonly ILoggingService _logger; private readonly UserHelper _userHelper; - private readonly PermissionServices _permissionService; + private readonly PermissionServices _permission; + private readonly Guid tenantId; - - public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permissionServices) + public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permission) { _context = context; _logger = logger; _userHelper = userHelper; - _permissionService = permissionServices; + _permission = permission; + tenantId = userHelper.GetTenantId(); } - // -------------------------------- Contact Category -------------------------------- + #region =================================================================== Contact Category APIs =================================================================== + public async Task> CreateContactCategory(CreateContactCategoryDto contactCategoryDto) { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); if (contactCategoryDto != null) { @@ -55,7 +56,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> UpdateContactCategory(Guid id, UpdateContactCategoryDto contactCategoryDto) { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); if (contactCategoryDto != null && id == contactCategoryDto.Id) { @@ -86,7 +86,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> GetContactCategoriesList() { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var categoryList = await _context.ContactCategoryMasters.Where(c => c.TenantId == tenantId).ToListAsync(); @@ -101,7 +100,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> GetContactCategoryById(Guid id) { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var category = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId); @@ -117,7 +115,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> DeleteContactCategory(Guid id) { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); ContactCategoryMaster? contactCategory = await _context.ContactCategoryMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId); if (contactCategory != null) @@ -148,14 +145,12 @@ namespace Marco.Pms.Services.Helpers _logger.LogWarning("Employee {EmployeeId} tries to delete Category {CategoryId} but not found in database", LoggedInEmployee.Id, id); return ApiResponse.SuccessResponse(new { }, "Category deleted successfully", 200); } + #endregion - // -------------------------------- Contact Tag -------------------------------- - + #region =================================================================== Contact Tag APIs =================================================================== public async Task> GetContactTags() { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var taglist = await _context.ContactTagMasters.Where(t => t.TenantId == tenantId).ToListAsync(); @@ -170,7 +165,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> CreateContactTag(CreateContactTagDto contactTagDto) { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); if (contactTagDto != null) { @@ -193,7 +187,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> UpdateContactTag(Guid id, UpdateContactTagDto contactTagDto) { - var tenantId = _userHelper.GetTenantId(); Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); if (contactTagDto != null && contactTagDto.Id == id) { @@ -226,7 +219,6 @@ namespace Marco.Pms.Services.Helpers } public async Task> DeleteContactTag(Guid id) { - Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); ContactTagMaster? contactTag = await _context.ContactTagMasters.FirstOrDefaultAsync(c => c.Id == id && c.TenantId == tenantId); if (contactTag != null) @@ -252,19 +244,21 @@ namespace Marco.Pms.Services.Helpers return ApiResponse.SuccessResponse(new { }, "Tag deleted successfully", 200); } - // -------------------------------- Work Status -------------------------------- + #endregion + + #region =================================================================== Work Status APIs =================================================================== + public async Task> GetWorkStatusList() { _logger.LogInfo("GetWorkStatusList called."); try { - // Step 1: Get tenant and logged-in employee info - Guid tenantId = _userHelper.GetTenantId(); + // Step 1: Get logged-in employee info var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); // Step 2: Check permission to view master data - bool hasViewPermission = await _permissionService.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id); + bool hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewMasters, loggedInEmployee.Id); if (!hasViewPermission) { _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); @@ -294,7 +288,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occurred while fetching work status list : {Error}", ex.Message); + _logger.LogError(ex, "Error occurred while fetching work status list"); return ApiResponse.ErrorResponse("An error occurred", "Unable to fetch work status list", 500); } } @@ -304,12 +298,11 @@ namespace Marco.Pms.Services.Helpers try { - // Step 1: Get tenant and logged-in employee - Guid tenantId = _userHelper.GetTenantId(); + // Step 1: Get logged-in employee var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); // Step 2: Check if user has permission to manage master data - var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManageMasterPermission) { _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); @@ -343,7 +336,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occurred while creating work status : {Error}", ex.Message); + _logger.LogError(ex, "Error occurred while creating work status"); return ApiResponse.ErrorResponse("An error occurred", "Unable to create work status", 500); } } @@ -360,12 +353,11 @@ namespace Marco.Pms.Services.Helpers return ApiResponse.ErrorResponse("Invalid data provided", "The provided work status ID is invalid", 400); } - // Step 2: Get tenant and logged-in employee - Guid tenantId = _userHelper.GetTenantId(); + // Step 2: Get logged-in employee var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); // Step 3: Check permissions - var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManageMasterPermission) { _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); @@ -413,12 +405,11 @@ namespace Marco.Pms.Services.Helpers try { - // Step 1: Get current tenant and logged-in employee - Guid tenantId = _userHelper.GetTenantId(); + // Step 1: Get logged-in employee var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); // Step 2: Check permission to manage master data - var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + var hasManageMasterPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManageMasterPermission) { _logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id); @@ -462,5 +453,7 @@ namespace Marco.Pms.Services.Helpers return ApiResponse.ErrorResponse("An error occurred", "Unable to delete work status", 500); } } + + #endregion } } diff --git a/Marco.Pms.Services/Helpers/ReportHelper.cs b/Marco.Pms.Services/Helpers/ReportHelper.cs index 35dcf8b..5a174e6 100644 --- a/Marco.Pms.Services/Helpers/ReportHelper.cs +++ b/Marco.Pms.Services/Helpers/ReportHelper.cs @@ -2,7 +2,7 @@ using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Mail; -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Project; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Report; using MarcoBMS.Services.Service; diff --git a/Marco.Pms.Services/MappingProfiles/MappingProfile.cs b/Marco.Pms.Services/MappingProfiles/MappingProfile.cs index bf3777c..a5fc445 100644 --- a/Marco.Pms.Services/MappingProfiles/MappingProfile.cs +++ b/Marco.Pms.Services/MappingProfiles/MappingProfile.cs @@ -1,10 +1,22 @@ using AutoMapper; +using Marco.Pms.Model.Dtos.Expenses; +using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Dtos.Project; using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Expenses; using Marco.Pms.Model.Master; using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Employees; +using Marco.Pms.Model.MongoDBModels.Expenses; +using Marco.Pms.Model.MongoDBModels.Masters; +using Marco.Pms.Model.MongoDBModels.Project; using Marco.Pms.Model.Projects; +using Marco.Pms.Model.ViewModels.Activities; +using Marco.Pms.Model.ViewModels.DocumentManager; using Marco.Pms.Model.ViewModels.Employee; +using Marco.Pms.Model.ViewModels.Expanses; +using Marco.Pms.Model.ViewModels.Expenses; +using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Model.ViewModels.Projects; namespace Marco.Pms.Services.MappingProfiles @@ -29,6 +41,23 @@ namespace Marco.Pms.Services.MappingProfiles opt => opt.MapFrom(src => new Guid(src.Id)) ); + CreateMap() + .ForMember( + dest => dest.Id, + // Explicitly and safely convert Guid Id to string Id + opt => opt.MapFrom(src => src.Id.ToString())) + .ForMember( + dest => dest.TenantId, + opt => opt.MapFrom(src => src.TenantId.ToString())); + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => new Guid(src.Id))) + .ForMember( + dest => dest.ProjectStatusId, + opt => opt.MapFrom(src => Guid.Empty) + ); + CreateMap() .ForMember( dest => dest.Id, @@ -60,8 +89,153 @@ namespace Marco.Pms.Services.MappingProfiles opt => opt.MapFrom(src => src.Comment)); #endregion - #region ======================================================= Projects ======================================================= + #region ======================================================= Employee ======================================================= CreateMap(); + CreateMap() + .ForMember( + dest => dest.JobRoleName, + opt => opt.MapFrom(src => src.JobRole != null ? src.JobRole.Name : "")); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => src.Id.ToString())) + .ForMember( + dest => dest.JobRoleName, + opt => opt.MapFrom(src => src.JobRole != null ? src.JobRole.Name : "")) + .ForMember( + dest => dest.JobRoleId, + opt => opt.MapFrom(src => src.JobRoleId.ToString())) + .ForMember( + dest => dest.TenantId, + opt => opt.MapFrom(src => src.TenantId.ToString())); + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => string.IsNullOrWhiteSpace(src.Id) ? Guid.Empty : Guid.Parse(src.Id))) + .ForMember( + dest => dest.JobRoleId, + opt => opt.MapFrom(src => Guid.Parse(src.JobRoleId ?? ""))); + #endregion + + #region ======================================================= Expenses ======================================================= + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => src.Id.ToString())) + .ForMember( + dest => dest.TenantId, + opt => opt.MapFrom(src => src.TenantId.ToString())); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => Guid.Parse(src.Id))) + .ForMember( + dest => dest.TenantId, + opt => opt.MapFrom(src => Guid.Parse(src.TenantId))); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => Guid.Parse(src.Id))); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => Guid.Parse(src.Id))); + + #endregion + + #region ======================================================= Master ======================================================= + + #region ======================================================= Expenses Type Master ======================================================= + + CreateMap() + .ForMember( + dest => dest.Id, + // Explicitly and safely convert nullable Guid to non-nullable Guid + opt => opt.MapFrom(src => src.Id ?? Guid.Empty) + ); + CreateMap(); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => src.Id.ToString())) + .ForMember( + dest => dest.TenantId, + opt => opt.MapFrom(src => src.TenantId.ToString())); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => Guid.Parse(src.Id))); + #endregion + + #region ======================================================= Expenses Status Master ======================================================= + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => src.Id ?? Guid.Empty)) + .ForMember( + dest => dest.DisplayName, + opt => opt.MapFrom(src => string.IsNullOrWhiteSpace(src.DisplayName) ? src.Name : src.DisplayName)); + CreateMap(); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => src.Id.ToString())); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => Guid.Parse(src.Id))); + #endregion + + #region ======================================================= Payment Mode Matser ======================================================= + + CreateMap() + .ForMember( + dest => dest.Id, + // Explicitly and safely convert nullable Guid to non-nullable Guid + opt => opt.MapFrom(src => src.Id ?? Guid.Empty) + ); + CreateMap(); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => src.Id.ToString())) + .ForMember( + dest => dest.TenantId, + opt => opt.MapFrom(src => src.TenantId.ToString())); + + CreateMap() + .ForMember( + dest => dest.Id, + opt => opt.MapFrom(src => Guid.Parse(src.Id))); + + #endregion + + #endregion + + #region ======================================================= Document ======================================================= + + CreateMap() + .ForMember( + dest => dest.DocumentId, + opt => opt.MapFrom(src => Guid.Parse(src.DocumentId))); + #endregion } } diff --git a/Marco.Pms.Services/Marco.Pms.Services.csproj b/Marco.Pms.Services/Marco.Pms.Services.csproj index 2feafaf..5b30ba4 100644 --- a/Marco.Pms.Services/Marco.Pms.Services.csproj +++ b/Marco.Pms.Services/Marco.Pms.Services.csproj @@ -1,52 +1,52 @@ - - net8.0 - enable - enable - True - False - 55935cea-fc40-40f8-be42-da094f06b11f - Linux - + + net8.0 + enable + enable + True + False + 55935cea-fc40-40f8-be42-da094f06b11f + Linux + - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + - - - - - - + + + + + + PreserveNewest diff --git a/Marco.Pms.Services/Program.cs b/Marco.Pms.Services/Program.cs index 5549702..2f8bbac 100644 --- a/Marco.Pms.Services/Program.cs +++ b/Marco.Pms.Services/Program.cs @@ -1,5 +1,7 @@ -using Marco.Pms.CacheHelper; using Marco.Pms.DataAccess.Data; +using Marco.Pms.Helpers; +using Marco.Pms.Helpers.CacheHelper; +using Marco.Pms.Helpers.Utility; using Marco.Pms.Model.Authentication; using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Utilities; @@ -172,6 +174,8 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); #endregion #region Helpers @@ -183,12 +187,14 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); #endregion #region Cache Services builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); #endregion // Singleton services (one instance for the app's lifetime) diff --git a/Marco.Pms.Services/Service/ExpensesService.cs b/Marco.Pms.Services/Service/ExpensesService.cs new file mode 100644 index 0000000..cfcac91 --- /dev/null +++ b/Marco.Pms.Services/Service/ExpensesService.cs @@ -0,0 +1,1490 @@ +using AutoMapper; +using Marco.Pms.DataAccess.Data; +using Marco.Pms.Helpers.Utility; +using Marco.Pms.Model.Dtos.Expenses; +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Entitlements; +using Marco.Pms.Model.Expenses; +using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Employees; +using Marco.Pms.Model.MongoDBModels.Expenses; +using Marco.Pms.Model.MongoDBModels.Masters; +using Marco.Pms.Model.MongoDBModels.Project; +using Marco.Pms.Model.MongoDBModels.Utility; +using Marco.Pms.Model.Utilities; +using Marco.Pms.Model.ViewModels.Activities; +using Marco.Pms.Model.ViewModels.Expanses; +using Marco.Pms.Model.ViewModels.Expenses; +using Marco.Pms.Model.ViewModels.Master; +using Marco.Pms.Model.ViewModels.Projects; +using Marco.Pms.Services.Helpers; +using Marco.Pms.Services.Service.ServiceInterfaces; +using MarcoBMS.Services.Service; +using Microsoft.CodeAnalysis; +using Microsoft.EntityFrameworkCore; +using System.Text.Json; +using Document = Marco.Pms.Model.DocumentManager.Document; + +namespace Marco.Pms.Services.Service +{ + public class ExpensesService : IExpensesService + { + private readonly IDbContextFactory _dbContextFactory; + private readonly ApplicationDbContext _context; + private readonly ILoggingService _logger; + private readonly S3UploadService _s3Service; + private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly UtilityMongoDBHelper _updateLogHelper; + private readonly CacheUpdateHelper _cache; + private readonly IMapper _mapper; + private static readonly Guid Draft = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8"); + private static readonly Guid Review = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7"); + private static readonly Guid RejectedByReviewer = Guid.Parse("965eda62-7907-4963-b4a1-657fb0b2724b"); + private static readonly Guid Approve = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8"); + private static readonly Guid RejectedByApprover = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729"); + private static readonly Guid ProcessPending = Guid.Parse("f18c5cfd-7815-4341-8da2-2c2d65778e27"); + private static readonly Guid Processed = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95"); + private static readonly string Collection = "ExpensesModificationLog"; + public ExpensesService( + IDbContextFactory dbContextFactory, + ApplicationDbContext context, + IServiceScopeFactory serviceScopeFactory, + UtilityMongoDBHelper updateLogHelper, + CacheUpdateHelper cache, + ILoggingService logger, + S3UploadService s3Service, + IMapper mapper) + { + _dbContextFactory = dbContextFactory; + _context = context; + _logger = logger; + _cache = cache; + _serviceScopeFactory = serviceScopeFactory; + _updateLogHelper = updateLogHelper; + _s3Service = s3Service; + _mapper = mapper; + } + + #region =================================================================== Get Functions =================================================================== + + /// + /// Retrieves a paginated list of expenses based on user permissions and optional filters. + /// + /// A URL-encoded JSON string containing filter criteria. See . + /// The number of records to return per page. + /// The page number to retrieve. + /// A paginated list of expenses. + public async Task> GetExpensesListAsync(Employee loggedInEmployee, Guid tenantId, string? searchString, string? filter, int pageSize, int pageNumber) + { + try + { + _logger.LogInfo( + "Attempting to fetch expenses list for PageNumber: {PageNumber}, PageSize: {PageSize} with Filter: {Filter}", + pageNumber, pageSize, filter ?? ""); + + // 1. --- Get User Permissions --- + if (loggedInEmployee == null) + { + // This is an authentication/authorization issue. The user should be logged in. + _logger.LogWarning("Could not find an employee for the current logged-in user."); + return ApiResponse.ErrorResponse("User not found or not authenticated.", 403); + } + Guid loggedInEmployeeId = loggedInEmployee.Id; + List expenseVM = new List(); + var totalEntites = 0; + var hasViewSelfPermissionTask = Task.Run(async () => + { + using var scope = _serviceScopeFactory.CreateScope(); + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ExpenseViewSelf, loggedInEmployeeId); + }); + + var hasViewAllPermissionTask = Task.Run(async () => + { + using var scope = _serviceScopeFactory.CreateScope(); + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ExpenseViewAll, loggedInEmployeeId); + }); + + await Task.WhenAll(hasViewSelfPermissionTask, hasViewAllPermissionTask); + + if (!hasViewAllPermissionTask.Result && !hasViewSelfPermissionTask.Result) + { + // User has neither required permission. Deny access. + _logger.LogWarning("Access DENIED for employee {EmployeeId} attempting to get expenses list.", loggedInEmployeeId); + return ApiResponse.SuccessResponse(new List(), "You do not have permission to view any expenses.", 200); + } + + + // 2. --- Deserialize Filter and Apply --- + ExpensesFilter? expenseFilter = TryDeserializeFilter(filter); + + var (totalPages, totalCount, cacheList) = await _cache.GetExpenseListAsync(tenantId, loggedInEmployeeId, hasViewAllPermissionTask.Result, hasViewSelfPermissionTask.Result, + pageNumber, pageSize, expenseFilter, searchString); + + // 3. --- Build Base Query and Apply Permissions --- + // Start with a base IQueryable. Filters will be chained onto this. + var expensesQuery = _context.Expenses + .Where(e => e.TenantId == tenantId); // Always filter by TenantId first. + + if (cacheList == null) + { + await _cache.AddExpensesListToCache(expenses: await expensesQuery.ToListAsync(), tenantId); + + // Apply permission-based filtering BEFORE any other filters or pagination. + if (hasViewAllPermissionTask.Result) + { + expensesQuery = expensesQuery.Where(e => e.CreatedById == loggedInEmployeeId || e.StatusId != Draft); + } + else if (hasViewSelfPermissionTask.Result) + { + // User only has 'View Self' permission, so restrict the query to their own expenses. + _logger.LogInfo("User {EmployeeId} has 'View Self' permission. Restricting query to their expenses.", loggedInEmployeeId); + expensesQuery = expensesQuery.Where(e => e.CreatedById == loggedInEmployeeId); + } + + if (expenseFilter != null) + { + if (expenseFilter.StartDate.HasValue && expenseFilter.EndDate.HasValue) + { + if (expenseFilter.IsTransactionDate) + { + expensesQuery = expensesQuery.Where(e => e.TransactionDate.Date >= expenseFilter.StartDate.Value.Date && e.TransactionDate.Date <= expenseFilter.EndDate.Value.Date); + } + else + { + expensesQuery = expensesQuery.Where(e => e.CreatedAt.Date >= expenseFilter.StartDate.Value.Date && e.CreatedAt.Date <= expenseFilter.EndDate.Value.Date); + } + + } + + if (expenseFilter.ProjectIds?.Any() == true) + { + expensesQuery = expensesQuery.Where(e => expenseFilter.ProjectIds.Contains(e.ProjectId)); + } + + if (expenseFilter.StatusIds?.Any() == true) + { + expensesQuery = expensesQuery.Where(e => expenseFilter.StatusIds.Contains(e.StatusId)); + } + + if (expenseFilter.PaidById?.Any() == true) + { + expensesQuery = expensesQuery.Where(e => expenseFilter.PaidById.Contains(e.PaidById)); + } + + // Only allow filtering by 'CreatedBy' if the user has 'View All' permission. + if (expenseFilter.CreatedByIds?.Any() == true && hasViewAllPermissionTask.Result) + { + expensesQuery = expensesQuery.Where(e => expenseFilter.CreatedByIds.Contains(e.CreatedById)); + } + } + + if (!string.IsNullOrWhiteSpace(searchString)) + { + var searchStringLower = searchString.ToLower(); + expensesQuery = expensesQuery.Include(e => e.PaidBy).Include(e => e.CreatedBy) + .Where(e => e.Description.ToLower().Contains(searchStringLower) || + (e.TransactionId != null && e.TransactionId.ToLower().Contains(searchStringLower)) || + (e.PaidBy != null && (e.PaidBy.FirstName + " " + e.PaidBy.LastName).ToLower().Contains(searchStringLower)) || + (e.CreatedBy != null && (e.CreatedBy.FirstName + " " + e.CreatedBy.LastName).ToLower().Contains(searchStringLower))); + } + + // 4. --- Apply Ordering and Pagination --- + // This should be the last step before executing the query. + + totalEntites = await expensesQuery.CountAsync(); + + var paginatedQuery = expensesQuery + .OrderByDescending(e => e.CreatedAt) + .Skip((pageNumber - 1) * pageSize) + .Take(pageSize); + + // 5. --- Execute Query and Map Results --- + var expensesList = await paginatedQuery.ToListAsync(); + + if (!expensesList.Any()) + { + _logger.LogInfo("No expenses found matching the criteria for employee {EmployeeId}.", loggedInEmployeeId); + return ApiResponse.SuccessResponse(new List(), "No expenses found for the given criteria.", 200); + } + + expenseVM = await GetAllExpnesRelatedTables(expensesList, tenantId); + totalPages = (int)Math.Ceiling((double)totalEntites / pageSize); + + } + else + { + var permissionStatusMapping = await _context.StatusPermissionMapping + .GroupBy(ps => ps.StatusId) + .Select(g => new + { + StatusId = g.Key, + PermissionIds = g.Select(ps => ps.PermissionId).ToList() + }).ToListAsync(); + + expenseVM = cacheList.Select(m => + { + var response = _mapper.Map(m); + if (response.Status != null && (response.NextStatus?.Any() ?? false)) + { + response.Status.PermissionIds = permissionStatusMapping.Where(ps => ps.StatusId == Guid.Parse(m.Status.Id)).Select(ps => ps.PermissionIds).FirstOrDefault(); + foreach (var status in response.NextStatus) + { + status.PermissionIds = permissionStatusMapping.Where(ps => ps.StatusId == status.Id).Select(ps => ps.PermissionIds).FirstOrDefault(); + } + } + return response; + }).ToList(); + totalEntites = (int)totalCount; + } + // 7. --- Return Final Success Response --- + var message = $"{expenseVM.Count} expense records fetched successfully."; + _logger.LogInfo(message); + + + var response = new + { + CurrentFilter = expenseFilter, + CurrentPage = pageNumber, + TotalPages = totalPages, + TotalEntites = totalEntites, + Data = expenseVM, + }; + return ApiResponse.SuccessResponse(response, message, 200); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Databsae Exception occured while fetching list expenses"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while fetching list expenses"); + return ApiResponse.ErrorResponse("Error Occured", ExceptionMapper(ex), 500); + } + } + public async Task> GetExpenseDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId) + { + try + { + var expenseDetails = await _cache.GetExpenseDetailsById(id, tenantId); + if (expenseDetails == null) + { + var expense = await _context.Expenses.AsNoTracking().FirstOrDefaultAsync(e => e.Id == id && e.TenantId == tenantId); + + if (expense == null) + { + _logger.LogWarning("User attempted to fetch expense details with ID {ExpenseId}, but not found in both database and cache", id); + return ApiResponse.ErrorResponse("Expense Not Found", "Expense Not Found", 404); + } + expenseDetails = await GetAllExpnesRelatedTablesForSingle(expense, expense.TenantId); + } + var vm = _mapper.Map(expenseDetails); + + var permissionStatusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.StatusPermissionMapping + .GroupBy(ps => ps.StatusId) + .Select(g => new + { + StatusId = g.Key, + PermissionIds = g.Select(ps => ps.PermissionId).ToList() + }).ToListAsync(); + }); + var expenseReimburseTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesReimburseMapping + .Include(er => er.ExpensesReimburse) + .ThenInclude(er => er!.ReimburseBy) + .ThenInclude(e => e!.JobRole) + .Where(er => er.TenantId == tenantId && er.ExpensesId == vm.Id) + .Select(er => er.ExpensesReimburse).FirstOrDefaultAsync(); + }); + var permissionStatusMappings = permissionStatusMappingTask.Result; + var expensesReimburse = expenseReimburseTask.Result; + + if (vm.Status != null && (vm.NextStatus?.Any() ?? false)) + { + vm.Status.PermissionIds = permissionStatusMappings.Where(ps => ps.StatusId == vm.Status.Id).Select(ps => ps.PermissionIds).FirstOrDefault(); + foreach (var status in vm.NextStatus) + { + status.PermissionIds = permissionStatusMappings.Where(ps => ps.StatusId == status.Id).Select(ps => ps.PermissionIds).FirstOrDefault(); + } + } + vm.ExpensesReimburse = _mapper.Map(expensesReimburse); + + foreach (var document in expenseDetails.Documents) + { + var response = vm.Documents.FirstOrDefault(d => d.DocumentId == Guid.Parse(document.DocumentId)); + + response!.PreSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key); + response!.ThumbPreSignedUrl = _s3Service.GeneratePreSignedUrl(document.ThumbS3Key); + } + + var expenselogs = await _context.ExpenseLogs.Include(el => el.UpdatedBy).Where(el => el.ExpenseId == vm.Id).Select(el => _mapper.Map(el)).ToListAsync(); + + vm.ExpenseLogs = expenselogs; + + _logger.LogInfo("Employee {EmployeeId} successfully fetched expense details with ID {ExpenseId}", loggedInEmployee.Id, vm.Id); + return ApiResponse.SuccessResponse(vm, "Successfully fetched the details of expense", 200); + + } + catch (Exception ex) + { + _logger.LogError(ex, "An unhandled exception occurred while fetching an expense details {ExpenseId}.", id); + return ApiResponse.ErrorResponse("An internal server error occurred.", ExceptionMapper(ex), 500); + } + } + public async Task> GetSupplerNameListAsync(Employee loggedInEmployee, Guid tenantId) + { + try + { + var supplerNameList = await _context.Expenses.Where(e => e.TenantId == tenantId).Select(e => e.SupplerName).Distinct().ToListAsync(); + _logger.LogInfo("Employee {EmployeeId} fetched list of suppler names from expenses in a tenant {TenantId}", loggedInEmployee.Id, tenantId); + return ApiResponse.SuccessResponse(supplerNameList, $"{supplerNameList.Count} records of suppler names fetched from expense", 200); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Databsae Exception occured while fetching suppler name list from expense"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + } + } + public async Task> GetFilterObjectAsync(Employee loggedInEmployee, Guid tenantId) + { + try + { + // Task 1: Get all distinct projects associated with the tenant's expenses. + var projectsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Expenses + .Where(e => e.TenantId == tenantId && e.Project != null) + .Select(e => e.Project!) + .Distinct() + .Select(p => new { p.Id, Name = $"{p.Name}" }) + .ToListAsync(); + }); + + // Task 2: Get all distinct users who paid for the tenant's expenses. + var paidByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Expenses + .Where(e => e.TenantId == tenantId && e.PaidBy != null) + .Select(e => e.PaidBy!) + .Distinct() + .Select(u => new { u.Id, Name = $"{u.FirstName} {u.LastName}" }) + .ToListAsync(); + }); + + // Task 3: Get all distinct users who created the tenant's expenses. + var createdByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Expenses + .Where(e => e.TenantId == tenantId && e.CreatedBy != null) + .Select(e => e.CreatedBy!) + .Distinct() + .Select(u => new { u.Id, Name = $"{u.FirstName} {u.LastName}" }) + .ToListAsync(); + }); + + // Task 4: Get all distinct statuses associated with the tenant's expenses. + var statusTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Expenses + .Where(e => e.TenantId == tenantId && e.Status != null) + .Select(e => e.Status!) + .Distinct() + .Select(s => new { s.Id, s.Name }) + .ToListAsync(); + }); + + // Execute all four queries concurrently. The total wait time will be determined + // by the longest-running query, not the sum of all four. + await Task.WhenAll(projectsTask, paidByTask, createdByTask, statusTask); + + // Construct the final object from the results of the completed tasks. + return ApiResponse.SuccessResponse(new + { + Projects = await projectsTask, + PaidBy = await paidByTask, + CreatedBy = await createdByTask, + Status = await statusTask + }, "Successfully fetched the filter list", 200); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while fetching the list filters for expenses"); + return ApiResponse.ErrorResponse("Internal Exception Occured", ExceptionMapper(ex), 500); + } + } + + #endregion + + #region =================================================================== Post Functions =================================================================== + + /// + /// Creates a new expense entry along with its bill attachments. + /// This operation is transactional and performs validations and file uploads concurrently for optimal performance + /// by leveraging async/await without unnecessary thread-pool switching via Task.Run. + /// + /// The data transfer object containing expense details and attachments. + /// An IActionResult indicating the result of the creation operation. + public async Task> CreateExpenseAsync(CreateExpensesDto dto, Employee loggedInEmployee, Guid tenantId) + { + _logger.LogDebug("Starting CreateExpense for Project {ProjectId}", dto.ProjectId); + // The entire operation is wrapped in a transaction to ensure data consistency. + await using var transaction = await _context.Database.BeginTransactionAsync(); + + try + { + // 1. Authorization & Validation: Run all I/O-bound checks concurrently using factories for safety. + + // PERMISSION CHECKS: Use IServiceScopeFactory for thread-safe access to scoped services. + var hasUploadPermissionTask = Task.Run(async () => // Task.Run is acceptable here to create a new scope, but let's do it cleaner. + { + using var scope = _serviceScopeFactory.CreateScope(); + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ExpenseUpload, loggedInEmployee.Id); + }); + + var hasProjectPermissionTask = Task.Run(async () => + { + using var scope = _serviceScopeFactory.CreateScope(); + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasProjectPermission(loggedInEmployee, dto.ProjectId); + }); + + // VALIDATION CHECKS: Use IDbContextFactory for thread-safe, parallel database queries. + // Each task gets its own DbContext instance. + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == dto.ProjectId); + }); + var paidByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.AsNoTracking().FirstOrDefaultAsync(e => e.Id == dto.PaidById); + }); + var expenseTypeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesTypeMaster.AsNoTracking().FirstOrDefaultAsync(et => et.Id == dto.ExpensesTypeId); + }); + var paymentModeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(pm => pm.Id == dto.PaymentModeId); + }); + var statusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMapping + .Include(s => s.Status) + .Include(s => s.NextStatus) + .AsNoTracking() + .Where(es => es.StatusId == Draft && es.Status != null) + .GroupBy(s => s.StatusId) + .Select(g => new + { + Status = g.Select(s => s.Status).FirstOrDefault(), + NextStatus = g.Select(s => s.NextStatus).ToList() + }) + .FirstOrDefaultAsync(); + }); + + + // Await all prerequisite checks at once. + await Task.WhenAll( + hasUploadPermissionTask, hasProjectPermissionTask, + projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask + ); + + // 2. Aggregate and Check Results + if (!await hasUploadPermissionTask || !await hasProjectPermissionTask) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} on project {ProjectId}.", loggedInEmployee.Id, dto.ProjectId); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to upload expenses for this project.", 403); + } + + var validationErrors = new List(); + var project = await projectTask; + var expenseType = await expenseTypeTask; + var paymentMode = await paymentModeTask; + var statusMapping = await statusMappingTask; + var paidBy = await paidByTask; + + if (project == null) validationErrors.Add("Project not found."); + if (paidBy == null) validationErrors.Add("Paid by employee not found"); + if (expenseType == null) validationErrors.Add("Expense Type not found."); + if (paymentMode == null) validationErrors.Add("Payment Mode not found."); + if (statusMapping == null) validationErrors.Add("Default status 'Draft' not found."); + + if (validationErrors.Any()) + { + await transaction.RollbackAsync(); + var errorMessage = string.Join(" ", validationErrors); + _logger.LogWarning("Expense creation failed due to validation errors: {ValidationErrors}", errorMessage); + return ApiResponse.ErrorResponse("Invalid input data.", errorMessage, 400); + } + + // 3. Entity Creation + var expense = _mapper.Map(dto); + expense.CreatedById = loggedInEmployee.Id; + expense.CreatedAt = DateTime.UtcNow; + expense.TenantId = tenantId; + expense.IsActive = true; + expense.StatusId = Draft; + + _context.Expenses.Add(expense); + + // 4. Process Attachments + if (dto.BillAttachments?.Any() ?? false) + { + await ProcessAndUploadAttachmentsAsync(dto.BillAttachments, expense, loggedInEmployee.Id, tenantId); + } + + // 5. Database Commit + await _context.SaveChangesAsync(); + + // 6. Transaction Commit + await transaction.CommitAsync(); + + await _cache.AddExpenseByObjectAsync(expense); + + var response = _mapper.Map(expense); + response.PaidBy = _mapper.Map(paidBy); + response.Project = _mapper.Map(project); + response.Status = _mapper.Map(statusMapping!.Status); + response.NextStatus = _mapper.Map>(statusMapping.NextStatus); + response.PaymentMode = _mapper.Map(paymentMode); + response.ExpensesType = _mapper.Map(expenseType); + + _logger.LogInfo("Successfully created Expense {ExpenseId} for Project {ProjectId}.", expense.Id, expense.ProjectId); + return ApiResponse.SuccessResponse(response, "Expense created successfully.", 201); + } + catch (DbUpdateException dbEx) + { + await transaction.RollbackAsync(); + _logger.LogError(dbEx, "Databsae Exception occured while adding expense"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + } + catch (ArgumentException ex) // Catches bad Base64 from attachment pre-validation + { + _logger.LogError(ex, "Invalid argument during expense creation for project {ProjectId}.", dto.ProjectId); + return ApiResponse.ErrorResponse("Invalid Request Data.", ExceptionMapper(ex), 400); + } + catch (Exception ex) // General-purpose catch for unexpected errors (e.g., S3 or DB connection failure) + { + _logger.LogError(ex, "An unhandled exception occurred while creating an expense for project {ProjectId}.", dto.ProjectId); + return ApiResponse.ErrorResponse("An internal server error occurred.", ExceptionMapper(ex), 500); + } + } + + /// + /// Changes the status of an expense record, performing validation, permission checks, and logging. + /// + /// The DTO containing the expense ID and the target status ID. + /// The employee performing the action. + /// The ID of the tenant owning the expense. + /// An ApiResponse containing the updated expense details or an error. + public async Task> ChangeStatusAsync(ExpenseRecordDto model, Employee loggedInEmployee, Guid tenantId) + { + // 1. Fetch Existing Expense with Related Entities (Single Query) + var expense = await _context.Expenses + .Include(e => e.ExpensesType) + .Include(e => e.Project) + .Include(e => e.PaidBy).ThenInclude(e => e!.JobRole) + .Include(e => e.PaymentMode) + .Include(e => e.Status) + .Include(e => e.CreatedBy) + .Include(e => e.ReviewedBy) + .Include(e => e.ApprovedBy) + .Include(e => e.ProcessedBy) + .FirstOrDefaultAsync(e => + e.Id == model.ExpenseId && + e.StatusId != model.StatusId && + e.TenantId == tenantId + ); + + if (expense == null) + { + _logger.LogWarning("ChangeStatus: Expense not found or already at target status. ExpenseId={ExpenseId}, TenantId={TenantId}", model.ExpenseId, tenantId); + return ApiResponse.ErrorResponse("Expense not found or status is already set.", "Expense not found", 404); + } + + _logger.LogInfo("ChangeStatus: Requested status change. ExpenseId={ExpenseId} FromStatus={FromStatusId} ToStatus={ToStatusId}", + expense.Id, expense.StatusId, model.StatusId); + + // 2. Run Prerequisite Checks in Parallel (Status transition + Permissions) + var statusTransitionTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMapping + .Include(m => m.NextStatus) + .FirstOrDefaultAsync(m => m.StatusId == expense.StatusId && m.NextStatusId == model.StatusId); + }); + + var targetStatusPermissionsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.StatusPermissionMapping + .Where(spm => spm.StatusId == model.StatusId) + .ToListAsync(); + }); + + await Task.WhenAll(statusTransitionTask, targetStatusPermissionsTask); + var statusTransition = await statusTransitionTask; + var requiredPermissions = await targetStatusPermissionsTask; + + // 3. Validate Transition and Required Fields + if (statusTransition == null) + { + _logger.LogWarning("ChangeStatus: Invalid status transition. ExpenseId={ExpenseId}, FromStatus={FromStatus}, ToStatus={ToStatus}", + expense.Id, expense.StatusId, model.StatusId); + return ApiResponse.ErrorResponse("Status change is not permitted.", "Invalid Transition", 400); + } + + // Validate special logic for "Processed" + if (statusTransition.NextStatusId == Processed && + (string.IsNullOrWhiteSpace(model.ReimburseTransactionId) || + !model.ReimburseDate.HasValue || + model.ReimburseById == null || + model.ReimburseById == Guid.Empty)) + { + _logger.LogWarning("ChangeStatus: Missing reimbursement fields for 'Processed'. ExpenseId={ExpenseId}", expense.Id); + return ApiResponse.ErrorResponse("Reimbursement details are missing or invalid.", "Invalid Reimbursement", 400); + } + + // 4. Permission Check (CreatedBy -> Reviewer bypass, else required permissions) + bool hasPermission = false; + if (model.StatusId == Review && expense.CreatedById == loggedInEmployee.Id) + { + hasPermission = true; + } + else if (requiredPermissions.Any()) + { + using var scope = _serviceScopeFactory.CreateScope(); + var permissionService = scope.ServiceProvider.GetRequiredService(); + foreach (var permission in requiredPermissions) + { + if (await permissionService.HasPermission(permission.PermissionId, loggedInEmployee.Id) && model.StatusId != Review) + { + hasPermission = true; + break; + } + } + } + + if (!hasPermission) + { + _logger.LogWarning("ChangeStatus: Permission denied. EmployeeId={EmployeeId} ExpenseId={ExpenseId} ToStatus={ToStatusId}", + loggedInEmployee.Id, expense.Id, model.StatusId); + return ApiResponse.ErrorResponse("You do not have permission for this action.", "Access Denied", 403); + } + + // 5. Prepare for update (Audit snapshot) + var expenseStateBeforeChange = _updateLogHelper.EntityToBsonDocument(expense); + + // 6. Apply Status Transition + expense.StatusId = statusTransition.NextStatusId; + expense.Status = statusTransition.NextStatus; + + // Handle reviewer/approver/processor fields based on target StatusId (Guid) + if (model.StatusId == Approve || model.StatusId == RejectedByReviewer) + { + expense.ReviewedById = loggedInEmployee.Id; + } + else if (model.StatusId == ProcessPending || model.StatusId == RejectedByApprover) + { + expense.ApprovedById = loggedInEmployee.Id; + } + else if (model.StatusId == Processed) + { + expense.ProcessedById = loggedInEmployee.Id; + } + + // 7. Add Reimbursement if applicable + if (model.StatusId == Processed) + { + var reimbursement = new ExpensesReimburse + { + ReimburseTransactionId = model.ReimburseTransactionId!, + ReimburseDate = model.ReimburseDate!.Value, + ReimburseById = model.ReimburseById!.Value, + ReimburseNote = model.Comment ?? string.Empty, + TenantId = tenantId + }; + _context.ExpensesReimburse.Add(reimbursement); + _context.ExpensesReimburseMapping.Add(new ExpensesReimburseMapping + { + ExpensesId = expense.Id, + ExpensesReimburseId = reimbursement.Id, + TenantId = tenantId + }); + } + + // 8. Add Expense Log Entry + _context.ExpenseLogs.Add(new ExpenseLog + { + ExpenseId = expense.Id, + Action = $"Status changed to '{statusTransition.NextStatus?.Name}'", + UpdatedById = loggedInEmployee.Id, + UpdateAt = DateTime.UtcNow, + Comment = model.Comment, + TenantId = tenantId + }); + + // 9. Commit database transaction + try + { + await _context.SaveChangesAsync(); + _logger.LogInfo("ChangeStatus: Status updated successfully. ExpenseId={ExpenseId} NewStatus={NewStatusId}", expense.Id, expense.StatusId); + } + catch (DbUpdateConcurrencyException ex) + { + _logger.LogError(ex, "ChangeStatus: Concurrency error. ExpenseId={ExpenseId}", expense.Id); + return ApiResponse.ErrorResponse("Expense was modified by another user. Please refresh and try again.", "Concurrency Error", 409); + } + + // 10. Post-processing (audit log, cache, fetch next states) + try + { + var auditLogTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = expense.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = expenseStateBeforeChange, + UpdatedAt = DateTime.UtcNow + }, Collection); + + var cacheUpdateTask = _cache.ReplaceExpenseAsync(expense); + + var getNextStatusesTask = _dbContextFactory.CreateDbContextAsync().ContinueWith(async t => + { + var dbContext = t.Result; + var nextStatuses = await dbContext.ExpensesStatusMapping + .Include(m => m.NextStatus) + .Where(m => m.StatusId == expense.StatusId && m.NextStatus != null) + .Select(m => m.NextStatus) + .ToListAsync(); + await dbContext.DisposeAsync(); + return nextStatuses; + }).Unwrap(); + + await Task.WhenAll(auditLogTask, getNextStatusesTask, cacheUpdateTask); + + // Prepare response with possible next states + var nextPossibleStatuses = await getNextStatusesTask; + var responseDto = _mapper.Map(expense); + if (nextPossibleStatuses is { Count: > 0 }) + responseDto.NextStatus = _mapper.Map>(nextPossibleStatuses); + + return ApiResponse.SuccessResponse(responseDto); + } + catch (Exception ex) + { + _logger.LogError(ex, "ChangeStatus: Post-operation error (e.g. audit logging). ExpenseId={ExpenseId}", expense.Id); + var responseDto = _mapper.Map(expense); + return ApiResponse.SuccessResponse(responseDto, "Status updated, but audit logging or cache update failed."); + } + } + + #endregion + + #region =================================================================== Put Functions =================================================================== + + public async Task> UpdateExpanseAsync(Guid id, UpdateExpensesDto model, Employee loggedInEmployee, Guid tenantId) + { + if (id != model.Id) + { + _logger.LogWarning("Id provided by path parameter and Id from body not matches for employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Invalid Parameters", "Invalid Parameters", 400); + } + var existingExpense = await _context.Expenses + .Include(e => e.ExpensesType) + .Include(e => e.Project) + .Include(e => e.PaidBy) + .ThenInclude(e => e!.JobRole) + .Include(e => e.PaymentMode) + .Include(e => e.Status) + .Include(e => e.CreatedBy) + .Include(e => e.ReviewedBy) + .Include(e => e.ApprovedBy) + .Include(e => e.ProcessedBy) + .FirstOrDefaultAsync(e => + e.Id == model.Id && + e.TenantId == tenantId); + + + if (existingExpense == null) + { + _logger.LogWarning("User attempted to update expense with ID {ExpenseId}, but not found in database", id); + return ApiResponse.ErrorResponse("Expense not found", "Expense not found", 404); + } + + if (existingExpense.StatusId != Draft && existingExpense.StatusId != RejectedByReviewer && existingExpense.StatusId != RejectedByApprover) + { + _logger.LogWarning("User attempted to update expense with ID {ExpenseId}, but donot have status of DRAFT or REJECTED, but is {StatusId}", existingExpense.Id, existingExpense.StatusId); + return ApiResponse.ErrorResponse("Expense connot be updated", "Expense connot be updated", 400); + } + if (existingExpense.CreatedById != loggedInEmployee.Id) + { + _logger.LogWarning("User attempted to update expense with ID {ExpenseId} which not created by them", existingExpense.Id); + return ApiResponse.ErrorResponse("You donot have access to update this expense", "You donot have access to update this expense", 400); + } + + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(existingExpense); // Capture state for audit log BEFORE changes + _mapper.Map(model, existingExpense); + _context.Entry(existingExpense).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + _logger.LogInfo("Successfully updated Expense {ExpenseId} by user {UserId}.", id, loggedInEmployee.Id); + } + catch (DbUpdateConcurrencyException ex) + { + // --- Step 3: Handle Concurrency Conflicts --- + // This happens if another user modified the project after we fetched it. + _logger.LogError(ex, "Concurrency conflict while updating project {ProjectId} ", id); + return ApiResponse.ErrorResponse("Conflict occurred.", "This project has been modified by someone else. Please refresh and try again.", 409); + } + + if (model.BillAttachments?.Any() ?? false) + { + var newBillAttachments = model.BillAttachments.Where(ba => ba.DocumentId == null && ba.IsActive).ToList(); + if (newBillAttachments.Any()) + { + await ProcessAndUploadAttachmentsAsync(newBillAttachments, existingExpense, loggedInEmployee.Id, tenantId); + try + { + await _context.SaveChangesAsync(); + _logger.LogInfo("{Count} New attachments added while updating expense {ExpenseId} by employee {EmployeeId}", + newBillAttachments.Count, existingExpense.Id, loggedInEmployee.Id); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Databsae Exception occured while adding new attachments during updating expense"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + + } + } + + var deleteBillAttachments = model.BillAttachments.Where(ba => ba.DocumentId != null && !ba.IsActive).ToList(); + if (deleteBillAttachments.Any()) + { + var documentIds = deleteBillAttachments.Select(d => d.DocumentId!.Value).ToList(); + try + { + await DeleteAttachemnts(documentIds); + _logger.LogInfo("{Count} Attachments deleted while updating expense {ExpenseId} by employee {EmployeeId}", + deleteBillAttachments.Count, existingExpense.Id, loggedInEmployee.Id); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Databsae Exception occured while deleting attachments during updating expense"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while deleting attachments during updating expense"); + return ApiResponse.ErrorResponse("Exception occured while deleting attachments during updating expense ", ExceptionMapper(ex), 500); + } + } + } + + + try + { + // Task to save the detailed audit log to a separate system (e.g., MongoDB). + var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = existingExpense.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, Collection); + + // Task to get all possible next statuses from the *new* current state to help the UI. + // NOTE: This now fetches a list of all possible next states, which is more useful for a UI. + var getNextStatusesTask = _dbContextFactory.CreateDbContextAsync().ContinueWith(t => + { + var dbContext = t.Result; + return dbContext.ExpensesStatusMapping + .Include(s => s.NextStatus) + .Where(s => s.StatusId == existingExpense.StatusId && s.NextStatus != null) + .Select(s => s.NextStatus) // Select only the status object + .ToListAsync() + .ContinueWith(res => + { + dbContext.Dispose(); // Ensure the context is disposed + return res.Result; + }); + }).Unwrap(); + + var cacheUpdateTask = _cache.ReplaceExpenseAsync(existingExpense); + + await Task.WhenAll(mongoDBTask, getNextStatusesTask, cacheUpdateTask); + + var nextPossibleStatuses = getNextStatusesTask.Result; + + var response = _mapper.Map(existingExpense); + if (nextPossibleStatuses != null) + { + // The response DTO should have a property like: public List NextAvailableStatuses { get; set; } + response.NextStatus = _mapper.Map>(nextPossibleStatuses); + } + + return ApiResponse.SuccessResponse(response, "Expense Updated Successfully", 200); + } + catch (Exception ex) + { + // This catch block handles errors from post-save operations like MongoDB logging. + // The primary update was successful, but we must log this failure. + _logger.LogError(ex, "Error occurred during post-save operations for ExpenseId: {ExpenseId} (e.g., audit logging). The primary status change was successful.", existingExpense.Id); + + // We can still return a success response because the main operation succeeded, + // but we should not block the user for a failed audit log. + // Alternatively, if audit logging is critical, you could return an error. + // Here, we choose to return success but log the ancillary failure. + var response = _mapper.Map(existingExpense); + return ApiResponse.SuccessResponse(response, "Status updated, but a post-processing error occurred."); + } + } + + #endregion + + #region =================================================================== Delete Functions =================================================================== + + public async Task> DeleteExpanseAsync(Guid id, Employee loggedInEmployee, Guid tenantId) + { + var expenseTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Expenses.Where(e => e.Id == id && e.StatusId == Draft && e.TenantId == tenantId).FirstOrDefaultAsync(); + }); + + var hasAprrovePermissionTask = Task.Run(async () => + { + using var scope = _serviceScopeFactory.CreateScope(); + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ExpenseApprove, loggedInEmployee.Id); + }); + + await Task.WhenAll(expenseTask, hasAprrovePermissionTask); + + var hasAprrovePermission = hasAprrovePermissionTask.Result; + var existingExpense = expenseTask.Result; + + if (existingExpense == null) + { + var message = hasAprrovePermission ? "Expenses not found" : "Expense cannot be deleted"; + if (hasAprrovePermission) + { + _logger.LogWarning("Employee {EmployeeId} attempted to delete expense {ExpenseId}, but not found in database", loggedInEmployee.Id, id); + } + else + { + _logger.LogWarning("Employee {EmployeeId} attempted to delete expense {ExpenseId}, Which is created by another employee", loggedInEmployee.Id, id); + } + return ApiResponse.ErrorResponse(message, message, 400); + } + if (existingExpense.StatusId != Draft) + { + _logger.LogWarning("User attempted to delete expense with ID {ExpenseId}, but donot have status of DRAFT or REJECTED", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Expense connot be deleted", "Expense connot be deleted", 400); + } + + if (!hasAprrovePermission && existingExpense.CreatedById != loggedInEmployee.Id) + { + _logger.LogWarning("User attempted to delete expense with ID {ExpenseId} which not created by them", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You donot have access to delete this expense", "You donot have access to delete this expense", 400); + + } + + var documentIds = await _context.BillAttachments + .Where(ba => ba.ExpensesId == existingExpense.Id) + .Select(ba => ba.DocumentId) + .ToListAsync(); + + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(existingExpense); + + _context.Expenses.Remove(existingExpense); + try + { + await _context.SaveChangesAsync(); + _logger.LogInfo("Employeee {EmployeeId} successfully deleted the expense {EmpenseId}", loggedInEmployee.Id, id); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Databsae Exception occured while deleting expense"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + } + try + { + var attachmentDeletionTask = Task.Run(async () => + { + await DeleteAttachemnts(documentIds); + }); + + var cacheTask = Task.Run(async () => + { + await _cache.DeleteExpenseAsync(id, tenantId); + }); + var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = existingExpense.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, Collection); + + await Task.WhenAll(attachmentDeletionTask, cacheTask, mongoDBTask); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Databsae Exception occured while deleting attachments during updating expense"); + return ApiResponse.ErrorResponse("Databsae Exception", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while deleting attachments during updating expense"); + return ApiResponse.ErrorResponse("Exception occured while deleting attachments during updating expense ", ExceptionMapper(ex), 500); + } + return ApiResponse.SuccessResponse("Success", "Expense Deleted Successfully", 200); + } + + #endregion + + #region =================================================================== Helper Functions =================================================================== + private static object ExceptionMapper(Exception ex) + { + return new + { + Message = ex.Message, + StackTrace = ex.StackTrace, + Source = ex.Source, + InnerException = new + { + Message = ex.InnerException?.Message, + StackTrace = ex.InnerException?.StackTrace, + Source = ex.InnerException?.Source, + } + }; + } + private async Task> GetAllExpnesRelatedTables(List model, Guid tenantId) + { + List expenseList = new List(); + var projectIds = model.Select(m => m.ProjectId).ToList(); + var statusIds = model.Select(m => m.StatusId).ToList(); + var expensesTypeIds = model.Select(m => m.ExpensesTypeId).ToList(); + var paymentModeIds = model.Select(m => m.PaymentModeId).ToList(); + var createdByIds = model.Select(m => m.CreatedById).ToList(); + var paidByIds = model.Select(m => m.PaidById).ToList(); + + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Projects.AsNoTracking().Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync(); + }); + var paidByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.AsNoTracking().Where(e => paidByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var createdByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.AsNoTracking().Where(e => createdByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync(); + }); + var expenseTypeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesTypeMaster.AsNoTracking().Where(et => expensesTypeIds.Contains(et.Id) && et.TenantId == tenantId).ToListAsync(); + }); + var paymentModeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.PaymentModeMatser.AsNoTracking().Where(pm => paymentModeIds.Contains(pm.Id) && pm.TenantId == tenantId).ToListAsync(); + }); + var statusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMapping + .Include(s => s.Status) + .Include(s => s.NextStatus) + .AsNoTracking() + .Where(es => statusIds.Contains(es.StatusId) && es.Status != null) + .GroupBy(s => s.StatusId) + .Select(g => new + { + StatusId = g.Key, + Status = g.Select(s => s.Status).FirstOrDefault(), + NextStatus = g.Select(s => s.NextStatus).OrderBy(s => s!.Name).ToList() + }).ToListAsync(); + }); + var statusTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMaster + .AsNoTracking() + .Where(es => statusIds.Contains(es.Id)) + .ToListAsync(); + }); + var permissionStatusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.StatusPermissionMapping + .GroupBy(ps => ps.StatusId) + .Select(g => new + { + StatusId = g.Key, + PermissionIds = g.Select(ps => ps.PermissionId).ToList() + }).ToListAsync(); + }); + + // Await all prerequisite checks at once. + await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, statusTask, permissionStatusMappingTask); + + var projects = projectTask.Result; + var expenseTypes = expenseTypeTask.Result; + var paymentModes = paymentModeTask.Result; + var statusMappings = statusMappingTask.Result; + var permissionStatusMappings = permissionStatusMappingTask.Result; + var paidBys = paidByTask.Result; + var createdBys = createdByTask.Result; + + expenseList = model.Select(m => + { + var response = _mapper.Map(m); + + response.Project = projects.Where(p => p.Id == m.ProjectId).Select(p => _mapper.Map(p)).FirstOrDefault(); + response.PaidBy = paidBys.Where(p => p.Id == m.PaidById).Select(p => _mapper.Map(p)).FirstOrDefault(); + response.CreatedBy = createdBys.Where(e => e.Id == m.CreatedById).Select(e => _mapper.Map(e)).FirstOrDefault(); + response.Status = statusMappings.Where(s => s.StatusId == m.StatusId).Select(s => _mapper.Map(s.Status)).FirstOrDefault(); + if (response.Status == null) + { + var status = statusTask.Result; + response.Status = status.Where(s => s.Id == m.StatusId).Select(s => _mapper.Map(s)).FirstOrDefault(); + } + if (response.Status != null) + { + response.Status.PermissionIds = permissionStatusMappings.Where(ps => ps.StatusId == m.StatusId).Select(ps => ps.PermissionIds).FirstOrDefault(); + } + response.NextStatus = statusMappings.Where(s => s.StatusId == m.StatusId).Select(s => _mapper.Map>(s.NextStatus)).FirstOrDefault(); + if (response.NextStatus != null) + { + foreach (var status in response.NextStatus) + { + status.PermissionIds = permissionStatusMappings.Where(ps => ps.StatusId == status.Id).Select(ps => ps.PermissionIds).FirstOrDefault(); + } + } + response.PaymentMode = paymentModes.Where(pm => pm.Id == m.PaymentModeId).Select(pm => _mapper.Map(pm)).FirstOrDefault(); + response.ExpensesType = expenseTypes.Where(et => et.Id == m.ExpensesTypeId).Select(et => _mapper.Map(et)).FirstOrDefault(); + + return response; + }).ToList(); + + return expenseList; + } + + private async Task GetAllExpnesRelatedTablesForSingle(Expenses model, Guid tenantId) + { + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId); + }); + var paidByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.PaidById && e.TenantId == tenantId); + }); + var createdByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.CreatedById && e.TenantId == tenantId); + }); + var reviewedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ReviewedById && e.TenantId == tenantId); + }); + var approvedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ApprovedById && e.TenantId == tenantId); + }); + var processedByTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ProcessedById && e.TenantId == tenantId); + }); + var expenseTypeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesTypeMaster.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.ExpensesTypeId && et.TenantId == tenantId); + }); + var paymentModeTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(pm => pm.Id == model.PaymentModeId && pm.TenantId == tenantId); + }); + var statusMappingTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMapping + .Include(s => s.Status) + .Include(s => s.NextStatus) + .AsNoTracking() + .Where(es => es.StatusId == model.StatusId && es.Status != null) + .GroupBy(s => s.StatusId) + .Select(g => new + { + StatusId = g.Key, + Status = g.Select(s => s.Status).FirstOrDefault(), + NextStatus = g.Select(s => s.NextStatus).OrderBy(s => s!.Name).ToList() + }).FirstOrDefaultAsync(); + }); + var statusTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMaster + .AsNoTracking() + .FirstOrDefaultAsync(es => es.Id == model.StatusId); + }); + var billAttachmentsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.BillAttachments + .Include(ba => ba.Document) + .AsNoTracking() + .Where(ba => ba.ExpensesId == model.Id && ba.Document != null) + .GroupBy(ba => ba.ExpensesId) + .Select(g => new + { + ExpensesId = g.Key, + Documents = g.Select(ba => new DocumentMongoDB + { + DocumentId = ba.Document!.Id.ToString(), + FileName = ba.Document.FileName, + ContentType = ba.Document.ContentType, + S3Key = ba.Document.S3Key, + ThumbS3Key = ba.Document.ThumbS3Key ?? ba.Document.S3Key + }).ToList() + }) + .FirstOrDefaultAsync(); + }); + + // Await all prerequisite checks at once. + await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask, + processedByTask, statusTask, billAttachmentsTask); + + var project = projectTask.Result; + var expenseType = expenseTypeTask.Result; + var paymentMode = paymentModeTask.Result; + var statusMapping = statusMappingTask.Result; + var paidBy = paidByTask.Result; + var createdBy = createdByTask.Result; + var reviewedBy = reviewedByTask.Result; + var approvedBy = approvedByTask.Result; + var processedBy = processedByTask.Result; + var billAttachment = billAttachmentsTask.Result; + + + var response = _mapper.Map(model); + + response.Project = _mapper.Map(project); + response.PaidBy = _mapper.Map(paidBy); + response.CreatedBy = _mapper.Map(createdBy); + response.ReviewedBy = _mapper.Map(reviewedBy); + response.ApprovedBy = _mapper.Map(approvedBy); + response.ProcessedBy = _mapper.Map(processedBy); + if (statusMapping != null) + { + response.Status = _mapper.Map(statusMapping.Status); + response.NextStatus = _mapper.Map>(statusMapping.NextStatus); + } + if (response.Status == null) + { + var status = statusTask.Result; + response.Status = _mapper.Map(status); + } + response.PaymentMode = _mapper.Map(paymentMode); + response.ExpensesType = _mapper.Map(expenseType); + if (billAttachment != null) response.Documents = billAttachment.Documents; + + return response; + + } + + + /// + /// Deserializes the filter string, handling multiple potential formats (e.g., direct JSON vs. escaped JSON string). + /// + /// The JSON filter string from the request. + /// An object or null if deserialization fails. + private ExpensesFilter? TryDeserializeFilter(string? filter) + { + if (string.IsNullOrWhiteSpace(filter)) + { + return null; + } + + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + ExpensesFilter? expenseFilter = null; + + try + { + // First, try to deserialize directly. This is the expected case (e.g., from a web client). + expenseFilter = JsonSerializer.Deserialize(filter, options); + } + catch (JsonException ex) + { + _logger.LogError(ex, "[{MethodName}] Failed to directly deserialize filter. Attempting to unescape and re-parse. Filter: {Filter}", nameof(TryDeserializeFilter), filter); + + // If direct deserialization fails, it might be an escaped string (common with tools like Postman or some mobile clients). + try + { + // Unescape the string first, then deserialize the result. + string unescapedJsonString = JsonSerializer.Deserialize(filter, options) ?? ""; + if (!string.IsNullOrWhiteSpace(unescapedJsonString)) + { + expenseFilter = JsonSerializer.Deserialize(unescapedJsonString, options); + } + } + catch (JsonException ex1) + { + // If both attempts fail, log the final error and return null. + _logger.LogError(ex1, "[{MethodName}] All attempts to deserialize the filter failed. Filter will be ignored. Filter: {Filter}", nameof(TryDeserializeFilter), filter); + return null; + } + } + return expenseFilter; + } + + /// + /// Processes and uploads attachments concurrently, then adds the resulting entities to the main DbContext. + /// + private async Task ProcessAndUploadAttachmentsAsync(IEnumerable attachments, Expenses expense, Guid employeeId, Guid tenantId) + { + // Pre-validate all attachments to fail fast before any uploads. + foreach (var attachment in attachments) + { + if (string.IsNullOrWhiteSpace(attachment.Base64Data) || !_s3Service.IsBase64String(attachment.Base64Data)) + { + throw new ArgumentException($"Invalid or missing Base64 data for attachment: {attachment.FileName ?? "N/A"}"); + } + } + + var batchId = Guid.NewGuid(); + + // Create a list of tasks to be executed concurrently. + var processingTasks = attachments.Select(attachment => + ProcessSingleAttachmentAsync(attachment, expense, employeeId, tenantId, batchId) + ).ToList(); + + var results = await Task.WhenAll(processingTasks); + + // This part is thread-safe as it runs after all concurrent tasks are complete. + foreach (var (document, billAttachment) in results) + { + _context.Documents.Add(document); + _context.BillAttachments.Add(billAttachment); + } + _logger.LogInfo("{AttachmentCount} attachments processed and staged for saving.", results.Length); + } + + /// + /// Handles the logic for a single attachment: upload to S3 and create corresponding entities. + /// + private async Task<(Document document, BillAttachments billAttachment)> ProcessSingleAttachmentAsync( + FileUploadModel attachment, Expenses expense, Guid employeeId, Guid tenantId, Guid batchId) + { + var base64Data = attachment.Base64Data!.Contains(',') ? attachment.Base64Data[(attachment.Base64Data.IndexOf(",") + 1)..] : attachment.Base64Data; + var fileType = _s3Service.GetContentTypeFromBase64(base64Data); + var fileName = _s3Service.GenerateFileName(fileType, expense.Id, "Expense"); + var objectKey = $"tenant-{tenantId}/project-{expense.ProjectId}/Expenses/{fileName}"; + + // Await the I/O-bound upload operation directly. + await _s3Service.UploadFileAsync(base64Data, fileType, objectKey); + _logger.LogInfo("Uploaded file to S3 with key: {ObjectKey}", objectKey); + + return CreateAttachmentEntities(batchId, expense.Id, employeeId, tenantId, objectKey, attachment); + } + + + /// + /// A private static helper method to create Document and BillAttachment entities. + /// This remains unchanged as it's a pure data-shaping method. + /// + private static (Document document, BillAttachments billAttachment) CreateAttachmentEntities( + Guid batchId, Guid expenseId, Guid uploadedById, Guid tenantId, string s3Key, FileUploadModel attachmentDto) + { + var document = new Document + { + BatchId = batchId, + UploadedById = uploadedById, + FileName = attachmentDto.FileName ?? "", + ContentType = attachmentDto.ContentType ?? "", + S3Key = s3Key, + FileSize = attachmentDto.FileSize, + UploadedAt = DateTime.UtcNow, + TenantId = tenantId + }; + var billAttachment = new BillAttachments { Document = document, ExpensesId = expenseId, TenantId = tenantId }; + return (document, billAttachment); + } + + private async Task DeleteAttachemnts(List documentIds) + { + var attachmentTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + var attachments = await dbContext.BillAttachments.AsNoTracking().Where(ba => documentIds.Contains(ba.DocumentId)).ToListAsync(); + + dbContext.BillAttachments.RemoveRange(attachments); + await dbContext.SaveChangesAsync(); + }); + var documentsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + var documents = await dbContext.Documents.AsNoTracking().Where(ba => documentIds.Contains(ba.Id)).ToListAsync(); + + if (documents.Any()) + { + dbContext.Documents.RemoveRange(documents); + await dbContext.SaveChangesAsync(); + + List deletionObject = new List(); + foreach (var document in documents) + { + deletionObject.Add(new S3DeletionObject + { + Key = document.S3Key + }); + if (!string.IsNullOrWhiteSpace(document.ThumbS3Key) && document.ThumbS3Key != document.S3Key) + { + deletionObject.Add(new S3DeletionObject + { + Key = document.ThumbS3Key + }); + } + } + await _updateLogHelper.PushToS3DeletionAsync(deletionObject); + } + }); + + await Task.WhenAll(attachmentTask, documentsTask); + } + + #endregion + } +} diff --git a/Marco.Pms.Services/Service/MasterService.cs b/Marco.Pms.Services/Service/MasterService.cs new file mode 100644 index 0000000..88467d1 --- /dev/null +++ b/Marco.Pms.Services/Service/MasterService.cs @@ -0,0 +1,512 @@ +using AutoMapper; +using Marco.Pms.DataAccess.Data; +using Marco.Pms.Helpers.Utility; +using Marco.Pms.Model.Dtos.Master; +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Entitlements; +using Marco.Pms.Model.Master; +using Marco.Pms.Model.MongoDBModels.Utility; +using Marco.Pms.Model.Utilities; +using Marco.Pms.Model.ViewModels.Master; +using Marco.Pms.Services.Helpers; +using Marco.Pms.Services.Service.ServiceInterfaces; +using MarcoBMS.Services.Service; +using Microsoft.CodeAnalysis; +using Microsoft.EntityFrameworkCore; + +namespace Marco.Pms.Services.Service +{ + public class MasterService : IMasterService + { + private readonly IDbContextFactory _dbContextFactory; + private readonly ApplicationDbContext _context; + private readonly ILoggingService _logger; + private readonly PermissionServices _permission; + private readonly IMapper _mapper; + private readonly UtilityMongoDBHelper _updateLogHelper; + private readonly CacheUpdateHelper _cache; + + public MasterService( + IDbContextFactory dbContextFactory, + ApplicationDbContext context, + ILoggingService logger, + PermissionServices permission, + IMapper mapper, + UtilityMongoDBHelper updateLogHelper, + CacheUpdateHelper cache) + { + _dbContextFactory = dbContextFactory; + _context = context; + _logger = logger; + _permission = permission; + _mapper = mapper; + _updateLogHelper = updateLogHelper; + _cache = cache; + } + + #region =================================================================== Expenses Type APIs =================================================================== + + public async Task> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of expense type from different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Featching the list of Expenses Type. + var typeList = await _context.ExpensesTypeMaster.Where(et => et.TenantId == tenantId && et.IsActive == isActive).ToListAsync(); + var response = _mapper.Map>(typeList); + + _logger.LogInfo("{Count} records of expense type have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id); + return ApiResponse.SuccessResponse(response, $"{response.Count} records of expense type have been fetched successfully.", 200); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while fetching list of expense type list by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + + } + public async Task> CreateExpenseTypeAsync(ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to add new expense type in different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + } + var expensesType = _mapper.Map(model); + expensesType.TenantId = tenantId; + + _context.ExpensesTypeMaster.Add(expensesType); + await _context.SaveChangesAsync(); + + _logger.LogInfo("New Expense Type {ExpensesTypeId} was added by employee {EmployeeId}", expensesType.Id, loggedInEmployee.Id); + + var response = _mapper.Map(expensesType); + return ApiResponse.SuccessResponse(response, "Expense type craeted Successfully", 201); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while adding new expense type by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while adding new expense type by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + public async Task> UpdateExpenseTypeAsync(Guid id, ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to update expense type in different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Checking permssion for managing masters + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + } + + // Validating the prvided data + if (model.Id != id) + { + _logger.LogWarning("Employee {EmployeeId} provide different Ids in payload and path variable", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Invalid Data", "User has send invalid payload", 400); + } + + var expensesType = await _context.ExpensesTypeMaster.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId); + + // Checking if expense type exists + if (expensesType == null) + { + _logger.LogWarning("Employee {EmployeeId} tries to update expense type, but not found in database", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Expense Type not found", "Expense Type not found", 404); + } + + // Mapping ExpensesTypeMaster to BsonDocument + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expensesType); + + // Mapping ExpensesTypeMasterDto to ExpensesTypeMaster + _mapper.Map(model, expensesType); + + _context.ExpensesTypeMaster.Update(expensesType); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Expense Type {ExpensesTypeId} was updated by employee {EmployeeId}", expensesType.Id, loggedInEmployee.Id); + + // Saving the old entity in mongoDB + + var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = expensesType.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, "ExpensesTypeMasterModificationLog"); + + // Mapping ExpensesTypeMaster to ExpensesTypeMasterVM + var response = _mapper.Map(expensesType); + return ApiResponse.SuccessResponse(response, "Expense type updated Successfully", 200); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while updating expense type by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while updating expense type by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + public async Task> DeleteExpenseTypeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId) + { + string action = isActive ? "restore" : "delete"; + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to {Action} expense type in different tenant", loggedInEmployee.Id, action); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Checking permssion for managing masters + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + } + + var expensesType = await _context.ExpensesTypeMaster.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId); + + // Checking if expense type exists + if (expensesType == null) + { + _logger.LogWarning("Employee {EmployeeId} tries to {Action} expense type, but not found in database", loggedInEmployee.Id, action); + return ApiResponse.ErrorResponse("Expense Type not found", "Expense Type not found", 404); + } + + // Mapping ExpensesTypeMaster to BsonDocument + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expensesType); + + expensesType.IsActive = isActive; + await _context.SaveChangesAsync(); + + _logger.LogInfo("Expense Type {ExpensesTypeId} was {Action}d by employee {EmployeeId}", expensesType.Id, action, loggedInEmployee.Id); + + // Saving the old entity in mongoDB + + var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = expensesType.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, "ExpensesTypeMasterModificationLog"); + + // Mapping ExpensesTypeMaster to ExpensesTypeMasterVM + var response = _mapper.Map(expensesType); + return ApiResponse.SuccessResponse(response, $"Expense type {action}d Successfully", 200); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while {Action}ing expense type by employee {EmployeeId}", action, loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while {Action}ing expense type by employee {EmployeeId}", action, loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + + #endregion + + #region =================================================================== Expenses Status APIs =================================================================== + public async Task> GetExpensesStatusListAsync(Employee loggedInEmployee, Guid tenantId) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of expense status from different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Featching the list of Expenses Status. + var statusList = await _context.ExpensesStatusMaster.ToListAsync(); + var response = _mapper.Map>(statusList); + + var statusIds = statusList.Select(s => s.Id).ToList(); + var permissionStatusMapping = await _context.StatusPermissionMapping + .Where(ps => statusIds.Contains(ps.StatusId)) + .GroupBy(ps => ps.StatusId) + .Select(g => new + { + StatusId = g.Key, + PermissionIds = g.Select(ps => ps.PermissionId).ToList() + }).ToListAsync(); + + foreach (var status in response) + { + status.PermissionIds = permissionStatusMapping.Where(ps => ps.StatusId == status.Id).Select(ps => ps.PermissionIds).FirstOrDefault(); + } + + _logger.LogInfo("{Count} records of expense status have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id); + return ApiResponse.SuccessResponse(response, $"{response.Count} records of expense status have been fetched successfully.", 200); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while fetching list of expense sattus list by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + #endregion + + #region =================================================================== Payment mode APIs =================================================================== + public async Task> GetPaymentModeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of payment modes from different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Featching the list of Payment Modes. + var paymentModes = await _context.PaymentModeMatser.Where(pm => pm.TenantId == tenantId && pm.IsActive == isActive).ToListAsync(); + var response = _mapper.Map>(paymentModes); + + _logger.LogInfo("{Count} records of payment modes have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id); + return ApiResponse.SuccessResponse(response, $"{response.Count} records of payment modes have been fetched successfully.", 200); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while featching list of payment modes list by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured while featching list of payment modes list", ExceptionMapper(ex), 500); + } + } + public async Task> CreatePaymentModeAsync(PaymentModeMatserDto model, Employee loggedInEmployee, Guid tenantId) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to add new payment mode in different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing PAYMENT MODE MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + + } + // Mapping the DTO to PaymentModeMatser Model + var paymentMode = _mapper.Map(model); + paymentMode.TenantId = tenantId; + + _context.PaymentModeMatser.Add(paymentMode); + await _context.SaveChangesAsync(); + + _logger.LogInfo("New Payment Mode {PaymentModeId} was added by employee {EmployeeId}", paymentMode.Id, loggedInEmployee.Id); + + // Mapping the PaymentModeMatser Model to View Model + var response = _mapper.Map(paymentMode); + return ApiResponse.SuccessResponse(response, "Payment Mode craeted Successfully", 201); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while adding new payment mode by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while adding new payment mode by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + public async Task> UpdatePaymentModeAsync(Guid id, PaymentModeMatserDto model, Employee loggedInEmployee, Guid tenantId) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to update Payment Mode in different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Checking permssion for managing masters + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing PAYMENT MODE MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + } + + // Validating the prvided data + if (model.Id != id) + { + _logger.LogWarning("Employee {EmployeeId} provide different Ids in payload and path variable", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Invalid Data", "User has send invalid payload", 400); + } + + var paymentMode = await _context.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId); + + // Checking if Payment Mode exists + if (paymentMode == null) + { + _logger.LogWarning("Employee {EmployeeId} tries to update Payment Mode, but not found in database", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Payment Mode not found", "Payment Mode not found", 404); + } + + // Mapping PaymentModeMatser to BsonDocument + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(paymentMode); + + // Mapping PaymentModeMatserDto to PaymentModeMatser + _mapper.Map(model, paymentMode); + + _context.PaymentModeMatser.Update(paymentMode); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Payment Mode {PaymentModeId} was updated by employee {EmployeeId}", paymentMode.Id, loggedInEmployee.Id); + + // Saving the old entity in mongoDB + + var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = paymentMode.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, "PaymentModeMasterModificationLog"); + + // Mapping PaymentModeMatser to PaymentModeMatserVM + var response = _mapper.Map(paymentMode); + return ApiResponse.SuccessResponse(response, "Payment Mode updated Successfully", 200); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while updating Payment Mode by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while updating Payment Mode by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + public async Task> DeletePaymentModeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId) + { + string action = isActive ? "restore" : "delete"; + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to {Action} Payment Mode in different tenant", loggedInEmployee.Id, action); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Checking permssion for managing masters + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPENSE STATUS MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + } + + var paymentMode = await _context.PaymentModeMatser.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId); + + // Checking if Payment Mode exists + if (paymentMode == null) + { + _logger.LogWarning("Employee {EmployeeId} tries to {Action} Payment Mode, but not found in database", loggedInEmployee.Id, action); + return ApiResponse.ErrorResponse("Payment Mode not found", "Payment Mode not found", 404); + } + + // Mapping PaymentModeMatser to BsonDocument + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(paymentMode); + + paymentMode.IsActive = isActive; + await _context.SaveChangesAsync(); + + _logger.LogInfo("Payment Mode {PaymentModeId} was {Action}d by employee {EmployeeId}", paymentMode.Id, action, loggedInEmployee.Id); + + // Saving the old entity in mongoDB + + var mongoDBTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = paymentMode.Id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, "PaymentModeMatserModificationLog"); + + // Mapping PaymentModeMatser to PaymentModeMatserVM + var response = _mapper.Map(paymentMode); + return ApiResponse.SuccessResponse(response, $"Payment Mode {action}d Successfully", 200); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while {Action}ing Payment Mode by employee {EmployeeId}", action, loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while {Action}ing Payment Mode by employee {EmployeeId}", action, loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } + + #endregion + + #region =================================================================== Helper Function =================================================================== + private static object ExceptionMapper(Exception ex) + { + return new + { + Message = ex.Message, + StackTrace = ex.StackTrace, + Source = ex.Source, + InnerException = new + { + Message = ex.InnerException?.Message, + StackTrace = ex.InnerException?.StackTrace, + Source = ex.InnerException?.Source, + } + }; + } + + + #endregion + } +} diff --git a/Marco.Pms.Services/Service/ProjectServices.cs b/Marco.Pms.Services/Service/ProjectServices.cs index 9406ec9..894ba81 100644 --- a/Marco.Pms.Services/Service/ProjectServices.cs +++ b/Marco.Pms.Services/Service/ProjectServices.cs @@ -5,7 +5,7 @@ using Marco.Pms.Model.Activities; using Marco.Pms.Model.Dtos.Project; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; -using Marco.Pms.Model.MongoDBModels; +using Marco.Pms.Model.MongoDBModels.Project; using Marco.Pms.Model.Projects; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Employee; diff --git a/Marco.Pms.Services/Service/S3UploadService.cs b/Marco.Pms.Services/Service/S3UploadService.cs index 4ce7a4b..79c5fa7 100644 --- a/Marco.Pms.Services/Service/S3UploadService.cs +++ b/Marco.Pms.Services/Service/S3UploadService.cs @@ -5,6 +5,7 @@ using Marco.Pms.Model.Utilities; using MarcoBMS.Services.Service; using Microsoft.Extensions.Options; using MimeDetective; +using System.Text.RegularExpressions; namespace Marco.Pms.Services.Service { @@ -12,7 +13,7 @@ namespace Marco.Pms.Services.Service public class S3UploadService { private readonly IAmazonS3 _s3Client; - private readonly string _bucketName = "your-bucket-name"; + private readonly string _bucketName; private readonly ILoggingService _logger; private readonly IConfiguration _configuration; @@ -40,7 +41,9 @@ namespace Marco.Pms.Services.Service if (allowedFilesType == null || !allowedFilesType.Contains(fileType)) { - throw new InvalidOperationException("Unsupported file type."); + _logger.LogWarning("Unsupported file type. {FileType}", fileType); + //throw new InvalidOperationException("Unsupported file type."); + return; } fileBytes = Convert.FromBase64String(base64); @@ -64,13 +67,14 @@ namespace Marco.Pms.Services.Service } catch (Exception ex) { - _logger.LogError(ex, "error occured while uploading file to S3"); + _logger.LogError(ex, "Error ocurred while uploading file to S3", ex.Message); } } - public string GeneratePreSignedUrlAsync(string objectKey) + public string GeneratePreSignedUrl(string objectKey) { + int expiresInMinutes = 10; var request = new GetPreSignedUrlRequest { @@ -87,7 +91,7 @@ namespace Marco.Pms.Services.Service } catch (Exception ex) { - _logger.LogError(ex, "error occured while requesting presigned url from Amazon S3", ex.Message); + _logger.LogError(ex, "Error occured while requesting presigned url from Amazon S3"); return string.Empty; } } @@ -107,17 +111,17 @@ namespace Marco.Pms.Services.Service } catch (Exception ex) { - _logger.LogError(ex, "error ocured while deleting from Amazon S3"); + _logger.LogError(ex, "while deleting from Amazon S3"); return false; } } - public string GenerateFileName(string contentType, Guid tenantId, string? name) + public string GenerateFileName(string contentType, Guid entityId, string? name) { string extenstion = GetExtensionFromMimeType(contentType); if (string.IsNullOrEmpty(name)) - return $"{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}"; - return $"{name}_{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}"; + return $"{entityId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}"; + return $"{name}_{entityId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}"; } public string GetExtensionFromMimeType(string contentType) @@ -220,9 +224,38 @@ namespace Marco.Pms.Services.Service catch (Exception ex) { // Handle other potential errors during decoding or inspection - _logger.LogError(ex, "errors during decoding or inspection"); + _logger.LogError(ex, "An error occurred while decoding base64"); return string.Empty; } } + public bool IsBase64String(string? input) + { + if (string.IsNullOrWhiteSpace(input)) + return false; + + // Normalize string + input = input.Trim(); + + // Length must be multiple of 4 + if (input.Length % 4 != 0) + return false; + + // Valid Base64 characters with correct padding + var base64Regex = new Regex(@"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"); + if (!base64Regex.IsMatch(input)) + return false; + + try + { + // Decode and re-encode to confirm validity + var bytes = Convert.FromBase64String(input); + var reEncoded = Convert.ToBase64String(bytes); + return input == reEncoded; + } + catch + { + return false; + } + } } } \ No newline at end of file diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IExpensesService.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IExpensesService.cs new file mode 100644 index 0000000..5d84eab --- /dev/null +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IExpensesService.cs @@ -0,0 +1,18 @@ +using Marco.Pms.Model.Dtos.Expenses; +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Services.Service.ServiceInterfaces +{ + public interface IExpensesService + { + Task> GetExpensesListAsync(Employee loggedInEmployee, Guid tenantId, string? searchString, string? filter, int pageSize, int pageNumber); + Task> GetExpenseDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId); + Task> GetSupplerNameListAsync(Employee loggedInEmployee, Guid tenantId); + Task> GetFilterObjectAsync(Employee loggedInEmployee, Guid tenantId); + Task> CreateExpenseAsync(CreateExpensesDto dto, Employee loggedInEmployee, Guid tenantId); + Task> ChangeStatusAsync(ExpenseRecordDto model, Employee loggedInEmployee, Guid tenantId); + Task> UpdateExpanseAsync(Guid id, UpdateExpensesDto model, Employee loggedInEmployee, Guid tenantId); + Task> DeleteExpanseAsync(Guid id, Employee loggedInEmployee, Guid tenantId); + } +} diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs new file mode 100644 index 0000000..2cde277 --- /dev/null +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs @@ -0,0 +1,30 @@ +using Marco.Pms.Model.Dtos.Master; +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Services.Service.ServiceInterfaces +{ + public interface IMasterService + { + #region =================================================================== Expenses Type APIs =================================================================== + Task> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive); + Task> CreateExpenseTypeAsync(ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId); + Task> UpdateExpenseTypeAsync(Guid id, ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId); + Task> DeleteExpenseTypeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId); + + #endregion + + #region =================================================================== Expenses Status APIs =================================================================== + Task> GetExpensesStatusListAsync(Employee loggedInEmployee, Guid tenantId); + + #endregion + + #region =================================================================== Payment mode APIs =================================================================== + Task> GetPaymentModeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive); + Task> CreatePaymentModeAsync(PaymentModeMatserDto model, Employee loggedInEmployee, Guid tenantId); + Task> UpdatePaymentModeAsync(Guid id, PaymentModeMatserDto model, Employee loggedInEmployee, Guid tenantId); + Task> DeletePaymentModeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId); + + #endregion + } +} diff --git a/Marco.Pms.Services/Service/StartupDataSeeder.cs b/Marco.Pms.Services/Service/StartupDataSeeder.cs index 10d6f71..d2496fc 100644 --- a/Marco.Pms.Services/Service/StartupDataSeeder.cs +++ b/Marco.Pms.Services/Service/StartupDataSeeder.cs @@ -4,134 +4,211 @@ using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Roles; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; // For configuration +using System.Linq.Expressions; namespace Marco.Pms.Services.Service { + // A configuration class to hold settings from appsettings.json + // This avoids hardcoding sensitive information. + public class SuperAdminSettings + { + public const string CONFIG_SECTION_NAME = "SuperAdminAccount"; + public string Email { get; set; } = "admin@marcoaiot.com"; + public string Password { get; set; } = "User@123"; + public string TenantId { get; set; } = "b3466e83-7e11-464c-b93a-daf047838b26"; + } + public class StartupUserSeeder : IHostedService { private readonly IServiceProvider _serviceProvider; + private readonly ILogger _logger; - public StartupUserSeeder(IServiceProvider serviceProvider) + // Constants to avoid "magic strings" + private const string AdminJobRoleName = "Admin"; + private const string SuperUserRoleName = "Super User"; + + public StartupUserSeeder(IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider; + _logger = logger; } public async Task StartAsync(CancellationToken cancellationToken) { + _logger.LogInformation("Starting database seeding process..."); + using var scope = _serviceProvider.CreateScope(); - var userManager = scope.ServiceProvider.GetRequiredService>(); - var dbContext = scope.ServiceProvider.GetRequiredService(); + var serviceProvider = scope.ServiceProvider; - var userEmail = "admin@marcoaiot.com"; + // Get services from the scoped provider + var userManager = serviceProvider.GetRequiredService>(); + var dbContext = serviceProvider.GetRequiredService(); + var adminSettings = serviceProvider.GetRequiredService>().Value; + var tenantId = Guid.Parse(adminSettings.TenantId); - var user = await userManager.FindByEmailAsync(userEmail); - var newUser = new ApplicationUser + // Use a database transaction to ensure all operations succeed or none do. + await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken); + + try { - UserName = userEmail, - Email = userEmail, - EmailConfirmed = true, - IsRootUser = true, - TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - }; - var result = new IdentityResult(); + // 1. Seed the Application User (Super Admin) + var user = await SeedSuperAdminUserAsync(userManager, adminSettings, tenantId); + // 2. Seed the Job Role + var jobRole = await GetOrCreateAsync( + dbContext.JobRoles, + j => j.Name == AdminJobRoleName && j.TenantId == tenantId, + () => new JobRole + { + Name = AdminJobRoleName, + Description = "Administrator with full system access.", + TenantId = tenantId + }); + + // 3. Seed the Application Role + var appRole = await GetOrCreateAsync( + dbContext.ApplicationRoles, + a => a.Role == SuperUserRoleName && a.TenantId == tenantId, + () => new ApplicationRole + { + Role = SuperUserRoleName, + Description = "System role with all permissions.", + IsSystem = true, + TenantId = tenantId + }); + + // 4. Seed the Employee record linked to the user and job role + var employee = await GetOrCreateAsync( + dbContext.Employees, + e => e.Email == adminSettings.Email && e.TenantId == tenantId, + () => new Employee + { + ApplicationUserId = user.Id, + FirstName = "Admin", + LastName = "User", + Email = adminSettings.Email, + TenantId = tenantId, + PhoneNumber = "9876543210", + JobRoleId = jobRole.Id, + IsSystem = true, + JoiningDate = DateTime.UtcNow, + BirthDate = new DateTime(1970, 1, 1) + // Set other non-nullable fields to sensible defaults + }); + + // 5. Seed the Employee-Role Mapping + await GetOrCreateAsync( + dbContext.EmployeeRoleMappings, + erm => erm.EmployeeId == employee.Id && erm.RoleId == appRole.Id, + () => new EmployeeRoleMapping + { + EmployeeId = employee.Id, + RoleId = appRole.Id, + TenantId = tenantId, + IsEnabled = true + }); + + // 6. Seed Role Permissions (Efficiently) + await SeedRolePermissionsAsync(dbContext, appRole.Id); + + // All entities are now tracked by the DbContext. + // A single SaveChanges call is more efficient. + await dbContext.SaveChangesAsync(cancellationToken); + + // If all operations were successful, commit the transaction. + await transaction.CommitAsync(cancellationToken); + _logger.LogInformation("Database seeding process completed successfully."); + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred during database seeding. Rolling back changes."); + await transaction.RollbackAsync(cancellationToken); + // Optionally re-throw or handle the exception as needed + throw; + } + } + + private async Task SeedSuperAdminUserAsync(UserManager userManager, SuperAdminSettings settings, Guid tenantId) + { + _logger.LogInformation("Seeding Super Admin user: {Email}", settings.Email); + var user = await userManager.FindByEmailAsync(settings.Email); if (user == null) { - result = await userManager.CreateAsync(newUser, "User@123"); - } - else - { - newUser = user; - } - - var jobRole = new JobRole - { - Id = Guid.Empty, - Name = "Admin", - Description = "Admin", - TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"), - }; - - if (!await dbContext.JobRoles.Where(j => j.Name == "Admin").AnyAsync()) - { - await dbContext.JobRoles.AddAsync(jobRole); - } - else - { - jobRole = await dbContext.JobRoles.Where(j => j.Name == "Admin").FirstOrDefaultAsync(); - } - var role = new ApplicationRole - { - Role = "Super User", - Description = "Super User", - IsSystem = true, - TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") - }; - if (!await dbContext.ApplicationRoles.Where(a => a.Role == "Super User").AnyAsync()) - { - await dbContext.ApplicationRoles.AddAsync(role); - } - else - { - role = await dbContext.ApplicationRoles.Where(a => a.Role == "Super User").FirstOrDefaultAsync(); - } - await dbContext.SaveChangesAsync(); - var employee = new Employee - { - ApplicationUserId = newUser.Id, - FirstName = "Admin", - LastName = "", - Email = userEmail, - TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"), - CurrentAddress = "", - BirthDate = Convert.ToDateTime("1965-04-20 10:11:17.588000"), - EmergencyPhoneNumber = "", - EmergencyContactPerson = "", - AadharNumber = "", - Gender = "", - MiddleName = "", - PanNumber = "", - PermanentAddress = "", - PhoneNumber = "9876543210", - Photo = null, // GetFileDetails(model.Photo).Result.FileData, - JobRoleId = jobRole != null ? jobRole.Id : Guid.Empty, - IsSystem = true, - JoiningDate = Convert.ToDateTime("2000-04-20 10:11:17.588000"), - }; - if ((!await dbContext.Employees.Where(e => e.Email == "admin@marcoaiot.com").AnyAsync()) && jobRole?.Id != Guid.Empty) - { - await dbContext.Employees.AddAsync(employee); - } - else - { - employee = await dbContext.Employees.Where(e => e.Email == "admin@marcoaiot.com").FirstOrDefaultAsync(); - } - await dbContext.SaveChangesAsync(); - if (!await dbContext.EmployeeRoleMappings.AnyAsync()) - { - await dbContext.EmployeeRoleMappings.AddAsync(new EmployeeRoleMapping + user = new ApplicationUser { - EmployeeId = employee?.Id ?? Guid.Empty, - IsEnabled = true, - TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"), - RoleId = role?.Id ?? Guid.Empty - }); - } - if (!await dbContext.RolePermissionMappings.AnyAsync()) - { - List permissions = await dbContext.FeaturePermissions.ToListAsync(); - List rolesMapping = new List(); - foreach (var permission in permissions) + UserName = settings.Email, + Email = settings.Email, + EmailConfirmed = true, + IsRootUser = true, + TenantId = tenantId + }; + var result = await userManager.CreateAsync(user, settings.Password); + + if (!result.Succeeded) { - rolesMapping.Add(new RolePermissionMappings - { - ApplicationRoleId = role != null ? role.Id : Guid.Empty, - FeaturePermissionId = permission.Id - }); + // If user creation fails, it's a critical error. + var errors = string.Join(", ", result.Errors.Select(e => e.Description)); + _logger.LogError("Failed to create super admin user. Errors: {Errors}", errors); + throw new InvalidOperationException($"Failed to create super admin user: {errors}"); } - await dbContext.RolePermissionMappings.AddRangeAsync(rolesMapping); + _logger.LogInformation("Super Admin user created successfully."); } - await dbContext.SaveChangesAsync(); + else + { + _logger.LogInformation("Super Admin user already exists."); + } + return user; + } + + private async Task SeedRolePermissionsAsync(ApplicationDbContext dbContext, Guid superUserRoleId) + { + _logger.LogInformation("Seeding permissions for Super User role (ID: {RoleId})", superUserRoleId); + + var allPermissionIds = await dbContext.FeaturePermissions + .Select(p => p.Id) + .ToListAsync(); + + var permissionIdsFromDb = await dbContext.RolePermissionMappings + .Where(pm => pm.ApplicationRoleId == superUserRoleId) + .Select(pm => pm.FeaturePermissionId) + .ToListAsync(); // 1. Fetch data from DB into a List + + var existingPermissionIds = new HashSet(permissionIdsFromDb); // 2. Convert the List to a HashSet in memory + + var missingPermissionIds = allPermissionIds.Except(existingPermissionIds).ToList(); + + if (missingPermissionIds.Any()) + { + var newMappings = missingPermissionIds.Select(permissionId => new RolePermissionMappings + { + ApplicationRoleId = superUserRoleId, + FeaturePermissionId = permissionId + }); + + await dbContext.RolePermissionMappings.AddRangeAsync(newMappings); + _logger.LogInformation("Added {Count} new permission mappings to the Super User role.", missingPermissionIds.Count); + } + else + { + _logger.LogInformation("Super User role already has all available permissions."); + } + } + + /// + /// A generic helper to find an entity by a predicate or create, add, and return it if not found. + /// This promotes code reuse and makes the main logic cleaner. + /// + private async Task GetOrCreateAsync(DbSet dbSet, Expression> predicate, Func factory) where T : class + { + var entity = await dbSet.FirstOrDefaultAsync(predicate); + if (entity == null) + { + entity = factory(); + await dbSet.AddAsync(entity); + _logger.LogInformation("Creating new entity of type {EntityType}.", typeof(T).Name); + } + return entity; } public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/Marco.Pms.Services/appsettings.Development.json b/Marco.Pms.Services/appsettings.Development.json index 030c450..579b059 100644 --- a/Marco.Pms.Services/appsettings.Development.json +++ b/Marco.Pms.Services/appsettings.Development.json @@ -46,8 +46,9 @@ "Region": "us-east-1", "BucketName": "testenv-marco-pms-documents" }, - "MongoDB": { - "SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs", - "ConnectionString": "mongodb://localhost:27017/MarcoBMS_Caches?socketTimeoutMS=500&serverSelectionTimeoutMS=500&connectTimeoutMS=500" - } + "MongoDB": { + "SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs", + "ConnectionString": "mongodb://localhost:27017/MarcoBMS_Caches?socketTimeoutMS=500&serverSelectionTimeoutMS=500&connectTimeoutMS=500", + "ModificationConnectionString": "mongodb://localhost:27017/ModificationLog?socketTimeoutMS=500&serverSelectionTimeoutMS=500&connectTimeoutMS=500" + } } diff --git a/Marco.Pms.Services/appsettings.Production.json b/Marco.Pms.Services/appsettings.Production.json index 0abe3f1..f164fdf 100644 --- a/Marco.Pms.Services/appsettings.Production.json +++ b/Marco.Pms.Services/appsettings.Production.json @@ -1,46 +1,47 @@ { - "Cors": { - "AllowedOrigins": "https://app.marcoaiot.com", - "AllowedMethods": "*", - "AllowedHeaders": "*" - }, - "Environment": { - "Name": "Production", - "Title": "" - }, - "ConnectionStrings": { - "DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1" - }, - "SmtpSettings": { - "SmtpServer": "smtp.gmail.com", - "Port": 587, - "SenderName": "MarcoAIOT", - "SenderEmail": "marcoioitsoft@gmail.com", - "Password": "qrtq wfuj hwpp fhqr" - }, - "AppSettings": { - "WebFrontendUrl": "https://app.marcoaiot.com", - "ImagesBaseUrl": "https://app.marcoaiot.com" - }, - "Jwt": { - "Issuer": "https://app.marcoaiot.com", - "Audience": "https://app.marcoaiot.com", - "Key": "sworffishhkjfa9dnfdndfu33infnajfj", - "ExpiresInMinutes": 60, - "RefreshTokenExpiresInDays": 7 - }, - "MailingList": { - "RequestDemoReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com", - "ProjectStatisticsReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com" - }, - "AWS": { - "AccessKey": "AKIARZDBH3VDMSUUY2FX", - "SecretKey": "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", - "Region": "us-east-1", - "BucketName": "testenv-marco-pms-documents" - }, - "MongoDB": { - "SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs", - "ConnectionString": "mongodb://localhost:27017/MarcoBMS_Caches" - } + "Cors": { + "AllowedOrigins": "https://app.marcoaiot.com", + "AllowedMethods": "*", + "AllowedHeaders": "*" + }, + "Environment": { + "Name": "Production", + "Title": "" + }, + "ConnectionStrings": { + "DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1" + }, + "SmtpSettings": { + "SmtpServer": "smtp.gmail.com", + "Port": 587, + "SenderName": "MarcoAIOT", + "SenderEmail": "marcoioitsoft@gmail.com", + "Password": "qrtq wfuj hwpp fhqr" + }, + "AppSettings": { + "WebFrontendUrl": "https://app.marcoaiot.com", + "ImagesBaseUrl": "https://app.marcoaiot.com" + }, + "Jwt": { + "Issuer": "https://app.marcoaiot.com", + "Audience": "https://app.marcoaiot.com", + "Key": "sworffishhkjfa9dnfdndfu33infnajfj", + "ExpiresInMinutes": 60, + "RefreshTokenExpiresInDays": 7 + }, + "MailingList": { + "RequestDemoReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com", + "ProjectStatisticsReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com" + }, + "AWS": { + "AccessKey": "AKIARZDBH3VDMSUUY2FX", + "SecretKey": "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", + "Region": "us-east-1", + "BucketName": "testenv-marco-pms-documents" + }, + "MongoDB": { + "SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs", + "ConnectionString": "mongodb://localhost:27017/MarcoBMS_Caches", + "ModificationConnectionString": "mongodb://localhost:27017/ModificationLog?authSource=admin&socketTimeoutMS=500&serverSelectionTimeoutMS=500&connectTimeoutMS=500" + } } \ No newline at end of file diff --git a/marco.pms.api.sln b/marco.pms.api.sln index 424b709..cb6aefe 100644 --- a/marco.pms.api.sln +++ b/marco.pms.api.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marco.Pms.Utility", "Marco. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marco.Pms.Services", "Marco.Pms.Services\Marco.Pms.Services.csproj", "{27A83653-5B7F-4135-9886-01594D54AFAE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marco.Pms.CacheHelper", "Marco.Pms.CacheHelper\Marco.Pms.CacheHelper.csproj", "{1A105C22-4ED7-4F54-8834-6923DDD96852}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marco.Pms.Helpers", "Marco.Pms.Helpers\Marco.Pms.Helpers.csproj", "{1A105C22-4ED7-4F54-8834-6923DDD96852}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution