From dc21b9d2c662cf0dddc1fb37b496f338a3066ccb Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 15:57:04 +0530 Subject: [PATCH 1/6] Added Functionality for approving the reported task --- .../Data/ApplicationDbContext.cs | 27 + ...ved_By_In_TaskAllocation_Table.Designer.cs | 3375 +++++++++++++++++ ...ded_Apporved_By_In_TaskAllocation_Table.cs | 188 + .../ApplicationDbContextModelSnapshot.cs | 106 + Marco.Pms.Model/Activities/TaskAllocation.cs | 31 +- .../Activities/WorkStatusMaster.cs | 12 + .../Dtos/Activities/ApproveTaskDto.cs | 13 + .../Dtos/Activities/AssignTaskDto.cs | 1 + .../Dtos/Activities/ReportTaskDto.cs | 1 + Marco.Pms.Model/Mapper/ActivitiesMapper.cs | 22 +- .../ViewModels/Activities/ListTaskVM.cs | 9 +- .../ViewModels/Activities/TaskVM.cs | 15 +- .../Controllers/TaskController.cs | 825 ++-- 13 files changed, 4355 insertions(+), 270 deletions(-) create mode 100644 Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.Designer.cs create mode 100644 Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.cs create mode 100644 Marco.Pms.Model/Activities/WorkStatusMaster.cs create mode 100644 Marco.Pms.Model/Dtos/Activities/ApproveTaskDto.cs diff --git a/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs b/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs index 04cfe61..9d74675 100644 --- a/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs +++ b/Marco.Pms.DataAccess/Data/ApplicationDbContext.cs @@ -69,6 +69,7 @@ namespace Marco.Pms.DataAccess.Data public DbSet Documents { get; set; } public DbSet TicketTags { get; set; } public DbSet WorkCategoryMasters { get; set; } + public DbSet WorkStatusMasters { get; set; } public DbSet Contacts { get; set; } public DbSet ContactCategoryMasters { get; set; } public DbSet ContactsEmails { get; set; } @@ -429,6 +430,32 @@ namespace Marco.Pms.DataAccess.Data TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") } ); + modelBuilder.Entity().HasData( + new WorkStatusMaster + { + Id = new Guid("030bb085-e230-4370-aec7-9a74d652864e"), + Name = "Approve", + Description = "Confirm the tasks are actually finished as reported", + IsSystem = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new WorkStatusMaster + { + Id = new Guid("2a1a5b96-cf93-4111-b4b1-76c19d6333b4"), + Name = "Partially Approve", + Description = "Not all tasks are actually finished as reported", + IsSystem = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new WorkStatusMaster + { + Id = new Guid("00a062e6-62e6-42c5-b6b1-024328651b72"), + Name = "NCR", + Description = "Tasks are not finished as reported or have any issues in al the tasks", + IsSystem = true, + TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26") + } + ); } 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 new file mode 100644 index 0000000..a00f9f1 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.Designer.cs @@ -0,0 +1,3375 @@ +// +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("20250616064217_Added_Apporved_By_In_TaskAllocation_Table")] + partial class Added_Apporved_By_In_TaskAllocation_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.HasKey("Id"); + + b.HasIndex("ContactCategoryId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + 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.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + 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.HasKey("Id"); + + b.HasIndex("TenantId"); + + 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("c7b68e33-72f0-474f-bd96-77636427ecc8"), + Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", + FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), + IsEnabled = true, + Name = "View Project Infra" + }, + new + { + Id = new Guid("f2aee20a-b754-4537-8166-f9507b44585b"), + Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", + FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), + 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("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), + Description = "Grants a user read-only access to details about the individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View Employee" + }, + 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" + }); + }); + + 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.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.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 = "Manage Project" + }, + new + { + Id = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), + Description = "Manage Infra", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Manage Infra" + }, + new + { + 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" + }, + new + { + Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + Description = "Global Masters", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Global 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.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("603e994b-a27f-4e5d-a251-f3d69b0498ba"), + Status = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), + Status = "On Hold", + 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 = "#6c757d", + 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("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.Navigation("ContactCategory"); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + }); + + 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.Navigation("Contact"); + + b.Navigation("Createdby"); + + b.Navigation("Tenant"); + }); + + 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.Navigation("Tenant"); + }); + + 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.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.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.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/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.cs b/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.cs new file mode 100644 index 0000000..62cd405 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250616064217_Added_Apporved_By_In_TaskAllocation_Table.cs @@ -0,0 +1,188 @@ +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_Apporved_By_In_TaskAllocation_Table : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ApprovedById", + table: "TaskAllocations", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "ApprovedDate", + table: "TaskAllocations", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "ParentTaskId", + table: "TaskAllocations", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "ReportedById", + table: "TaskAllocations", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "ReportedTask", + table: "TaskAllocations", + type: "double", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.AddColumn( + name: "WorkStatusId", + table: "TaskAllocations", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.CreateTable( + name: "WorkStatusMasters", + 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"), + IsSystem = table.Column(type: "tinyint(1)", nullable: false), + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_WorkStatusMasters", x => x.Id); + table.ForeignKey( + name: "FK_WorkStatusMasters_Tenants_TenantId", + column: x => x.TenantId, + principalTable: "Tenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "WorkStatusMasters", + columns: new[] { "Id", "Description", "IsSystem", "Name", "TenantId" }, + values: new object[,] + { + { new Guid("00a062e6-62e6-42c5-b6b1-024328651b72"), "Tasks are not finished as reported or have any issues in al the tasks", true, "NCR", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("030bb085-e230-4370-aec7-9a74d652864e"), "Confirm the tasks are actually finished as reported", true, "Approve", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }, + { new Guid("2a1a5b96-cf93-4111-b4b1-76c19d6333b4"), "Not all tasks are actually finished as reported", true, "Partially Approve", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") } + }); + + migrationBuilder.CreateIndex( + name: "IX_TaskAllocations_ApprovedById", + table: "TaskAllocations", + column: "ApprovedById"); + + migrationBuilder.CreateIndex( + name: "IX_TaskAllocations_ReportedById", + table: "TaskAllocations", + column: "ReportedById"); + + migrationBuilder.CreateIndex( + name: "IX_TaskAllocations_WorkStatusId", + table: "TaskAllocations", + column: "WorkStatusId"); + + migrationBuilder.CreateIndex( + name: "IX_WorkStatusMasters_TenantId", + table: "WorkStatusMasters", + column: "TenantId"); + + migrationBuilder.AddForeignKey( + name: "FK_TaskAllocations_Employees_ApprovedById", + table: "TaskAllocations", + column: "ApprovedById", + principalTable: "Employees", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_TaskAllocations_Employees_ReportedById", + table: "TaskAllocations", + column: "ReportedById", + principalTable: "Employees", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_TaskAllocations_WorkStatusMasters_WorkStatusId", + table: "TaskAllocations", + column: "WorkStatusId", + principalTable: "WorkStatusMasters", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_TaskAllocations_Employees_ApprovedById", + table: "TaskAllocations"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskAllocations_Employees_ReportedById", + table: "TaskAllocations"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskAllocations_WorkStatusMasters_WorkStatusId", + table: "TaskAllocations"); + + migrationBuilder.DropTable( + name: "WorkStatusMasters"); + + migrationBuilder.DropIndex( + name: "IX_TaskAllocations_ApprovedById", + table: "TaskAllocations"); + + migrationBuilder.DropIndex( + name: "IX_TaskAllocations_ReportedById", + table: "TaskAllocations"); + + migrationBuilder.DropIndex( + name: "IX_TaskAllocations_WorkStatusId", + table: "TaskAllocations"); + + migrationBuilder.DropColumn( + name: "ApprovedById", + table: "TaskAllocations"); + + migrationBuilder.DropColumn( + name: "ApprovedDate", + table: "TaskAllocations"); + + migrationBuilder.DropColumn( + name: "ParentTaskId", + table: "TaskAllocations"); + + migrationBuilder.DropColumn( + name: "ReportedById", + table: "TaskAllocations"); + + migrationBuilder.DropColumn( + name: "ReportedTask", + table: "TaskAllocations"); + + migrationBuilder.DropColumn( + name: "WorkStatusId", + table: "TaskAllocations"); + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs index 245470a..4988121 100644 --- a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs @@ -28,6 +28,12 @@ namespace Marco.Pms.DataAccess.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); + b.Property("ApprovedById") + .HasColumnType("char(36)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime(6)"); + b.Property("AssignedBy") .HasColumnType("char(36)"); @@ -40,26 +46,44 @@ namespace Marco.Pms.DataAccess.Migrations 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"); }); @@ -1920,6 +1944,59 @@ namespace Marco.Pms.DataAccess.Migrations }); }); + 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") @@ -2429,12 +2506,20 @@ namespace Marco.Pms.DataAccess.Migrations 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") @@ -2447,11 +2532,21 @@ namespace Marco.Pms.DataAccess.Migrations .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 => @@ -3052,6 +3147,17 @@ namespace Marco.Pms.DataAccess.Migrations 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") diff --git a/Marco.Pms.Model/Activities/TaskAllocation.cs b/Marco.Pms.Model/Activities/TaskAllocation.cs index 3347cef..4c8681c 100644 --- a/Marco.Pms.Model/Activities/TaskAllocation.cs +++ b/Marco.Pms.Model/Activities/TaskAllocation.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations.Schema; 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; @@ -10,29 +11,43 @@ namespace Marco.Pms.Model.Activities public class TaskAllocation : TenantRelation { public Guid Id { get; set; } - - + public Guid? ParentTaskId { get; set; } public DateTime AssignmentDate { get; set; } public double PlannedTask { get; set; } public double CompletedTask { get; set; } + public double ReportedTask { get; set; } public DateTime? ReportedDate { get; set; } - + public DateTime? ApprovedDate { get; set; } public string? Description { get; set; } - //public int? WorkItemMappingId { get; set; } - //[ForeignKey("WorkItemMappingId")] - //[ValidateNever] - //public WorkItemMapping? WorkItemMapping { get; set; } + public Guid AssignedBy { get; set; } //Employee Id - public Guid AssignedBy { get; set; } //Employee Id [ForeignKey("AssignedBy")] [ValidateNever] public Employee? Employee { get; set; } + public Guid? ReportedById { get; set; } //Employee Id + + [ForeignKey("ReportedById")] + [ValidateNever] + public Employee? ReportedBy { get; set; } + + public Guid? ApprovedById { get; set; } //Employee Id + + [ForeignKey("ApprovedById")] + [ValidateNever] + public Employee? ApprovedBy { get; set; } + public Guid WorkItemId { get; set; } + [ForeignKey("WorkItemId")] [ValidateNever] public WorkItem? WorkItem { get; set; } + public Guid? WorkStatusId { get; set; } + + [ForeignKey("WorkStatusId")] + [ValidateNever] + public WorkStatusMaster? WorkStatus { get; set; } } } diff --git a/Marco.Pms.Model/Activities/WorkStatusMaster.cs b/Marco.Pms.Model/Activities/WorkStatusMaster.cs new file mode 100644 index 0000000..52074c7 --- /dev/null +++ b/Marco.Pms.Model/Activities/WorkStatusMaster.cs @@ -0,0 +1,12 @@ +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Model.Master +{ + public class WorkStatusMaster : TenantRelation + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public bool IsSystem { get; set; } = false; + } +} diff --git a/Marco.Pms.Model/Dtos/Activities/ApproveTaskDto.cs b/Marco.Pms.Model/Dtos/Activities/ApproveTaskDto.cs new file mode 100644 index 0000000..cada0f5 --- /dev/null +++ b/Marco.Pms.Model/Dtos/Activities/ApproveTaskDto.cs @@ -0,0 +1,13 @@ +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Model.Dtos.Activities +{ + public class ApproveTaskDto + { + public Guid Id { get; set; } + public Guid WorkStatus { get; set; } + public long ApprovedTask { get; set; } + public string? Comment { get; set; } + public List? Images { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Activities/AssignTaskDto.cs b/Marco.Pms.Model/Dtos/Activities/AssignTaskDto.cs index 671902e..a4423f0 100644 --- a/Marco.Pms.Model/Dtos/Activities/AssignTaskDto.cs +++ b/Marco.Pms.Model/Dtos/Activities/AssignTaskDto.cs @@ -3,6 +3,7 @@ public class AssignTaskDto { public DateTime AssignmentDate { get; set; } + public Guid? ParentTaskId { get; set; } public double PlannedTask { get; set; } public string? Description { get; set; } public List? TaskTeam { get; set; } //Employee Ids diff --git a/Marco.Pms.Model/Dtos/Activities/ReportTaskDto.cs b/Marco.Pms.Model/Dtos/Activities/ReportTaskDto.cs index 13eb9b5..d63b653 100644 --- a/Marco.Pms.Model/Dtos/Activities/ReportTaskDto.cs +++ b/Marco.Pms.Model/Dtos/Activities/ReportTaskDto.cs @@ -5,6 +5,7 @@ namespace Marco.Pms.Model.Dtos.Activities public class ReportTaskDto { public Guid Id { get; set; } + public Guid? ParentTaskId { get; set; } public double CompletedTask { get; set; } public DateTime ReportedDate { get; set; } public string? Comment { get; set; } diff --git a/Marco.Pms.Model/Mapper/ActivitiesMapper.cs b/Marco.Pms.Model/Mapper/ActivitiesMapper.cs index f860bac..4083ccf 100644 --- a/Marco.Pms.Model/Mapper/ActivitiesMapper.cs +++ b/Marco.Pms.Model/Mapper/ActivitiesMapper.cs @@ -13,6 +13,7 @@ namespace Marco.Pms.Model.Mapper return new TaskAllocation { AssignmentDate = assignTask.AssignmentDate, + ParentTaskId = assignTask.ParentTaskId, PlannedTask = assignTask.PlannedTask, CompletedTask = 0, Description = assignTask.Description, @@ -43,18 +44,23 @@ namespace Marco.Pms.Model.Mapper TenantId = tenantId }; } - public static TaskVM TaskAllocationToTaskVM(this TaskAllocation taskAllocation, string employeeName) + public static TaskVM TaskAllocationToTaskVM(this TaskAllocation taskAllocation) { return new TaskVM { Id = taskAllocation.Id, AssignmentDate = taskAllocation.AssignmentDate, + ReportedDate = taskAllocation.ReportedDate, + ApprovedDate = taskAllocation.ApprovedDate, PlannedTask = taskAllocation.PlannedTask, CompletedTask = taskAllocation.CompletedTask, - ReportedDate = taskAllocation.ReportedDate, + NotApprovedTask = taskAllocation.ApprovedById == null ? taskAllocation.CompletedTask : (taskAllocation.ReportedTask - taskAllocation.CompletedTask), Description = taskAllocation.Description, - AssignBy = employeeName, - WorkItem = taskAllocation.WorkItem + AssignedBy = taskAllocation.Employee?.ToBasicEmployeeVMFromEmployee(), + ReportedBy = taskAllocation.ReportedBy?.ToBasicEmployeeVMFromEmployee(), + ApprovedBy = taskAllocation.ApprovedBy?.ToBasicEmployeeVMFromEmployee(), + WorkItem = taskAllocation.WorkItem, + WorkStatus = taskAllocation.WorkStatus }; } public static AssignedTaskVM ToAssignTaskVMFromTaskAllocation(this TaskAllocation taskAllocation) @@ -100,12 +106,18 @@ namespace Marco.Pms.Model.Mapper return new ListTaskVM { Id = taskAllocation.Id, + ParentTaskId = taskAllocation.ParentTaskId, AssignmentDate = taskAllocation.AssignmentDate, + ApprovedDate = taskAllocation.ApprovedDate, Description = taskAllocation.Description, PlannedTask = taskAllocation.PlannedTask, ReportedDate = taskAllocation.ReportedDate, + WorkStatus = taskAllocation.WorkStatus, CompletedTask = taskAllocation.CompletedTask, - AssignedBy = taskAllocation.Employee != null ? taskAllocation.Employee.ToBasicEmployeeVMFromEmployee() : new BasicEmployeeVM(), + NotApprovedTask = taskAllocation.ApprovedById == null ? taskAllocation.CompletedTask : (taskAllocation.ReportedTask - taskAllocation.CompletedTask), + AssignedBy = taskAllocation.Employee?.ToBasicEmployeeVMFromEmployee(), + ReportedBy = taskAllocation.ReportedBy?.ToBasicEmployeeVMFromEmployee(), + ApprovedBy = taskAllocation.ApprovedBy?.ToBasicEmployeeVMFromEmployee(), WorkItemId = taskAllocation.WorkItemId, WorkItem = taskAllocation.WorkItem }; diff --git a/Marco.Pms.Model/ViewModels/Activities/ListTaskVM.cs b/Marco.Pms.Model/ViewModels/Activities/ListTaskVM.cs index 9785bd2..c71b813 100644 --- a/Marco.Pms.Model/ViewModels/Activities/ListTaskVM.cs +++ b/Marco.Pms.Model/ViewModels/Activities/ListTaskVM.cs @@ -1,15 +1,22 @@ -using Marco.Pms.Model.Projects; +using Marco.Pms.Model.Master; +using Marco.Pms.Model.Projects; namespace Marco.Pms.Model.ViewModels.Activities { public class ListTaskVM { public Guid Id { get; set; } + public Guid? ParentTaskId { get; set; } public DateTime AssignmentDate { get; set; } public DateTime? ReportedDate { get; set; } + public DateTime? ApprovedDate { get; set; } public double PlannedTask { get; set; } public double CompletedTask { get; set; } + public double NotApprovedTask { get; set; } public BasicEmployeeVM? AssignedBy { get; set; } + public BasicEmployeeVM? ReportedBy { get; set; } + public BasicEmployeeVM? ApprovedBy { get; set; } + public WorkStatusMaster? WorkStatus { get; set; } public string? Description { get; set; } public Guid WorkItemId { get; set; } public List? ReportedPreSignedUrls { get; set; } diff --git a/Marco.Pms.Model/ViewModels/Activities/TaskVM.cs b/Marco.Pms.Model/ViewModels/Activities/TaskVM.cs index 18a29b0..f3373b4 100644 --- a/Marco.Pms.Model/ViewModels/Activities/TaskVM.cs +++ b/Marco.Pms.Model/ViewModels/Activities/TaskVM.cs @@ -1,5 +1,5 @@ -using Marco.Pms.Model.Projects; -using Marco.Pms.Model.ViewModels.Employee; +using Marco.Pms.Model.Master; +using Marco.Pms.Model.Projects; namespace Marco.Pms.Model.ViewModels.Activities { @@ -7,14 +7,19 @@ namespace Marco.Pms.Model.ViewModels.Activities { public Guid Id { get; set; } public DateTime AssignmentDate { get; set; } + public DateTime? ReportedDate { get; set; } + public DateTime? ApprovedDate { get; set; } public double PlannedTask { get; set; } public double CompletedTask { get; set; } - public DateTime? ReportedDate { get; set; } + public double NotApprovedTask { get; set; } public string? Description { get; set; } - public string? AssignBy { get; set; } + public BasicEmployeeVM? AssignedBy { get; set; } + public BasicEmployeeVM? ReportedBy { get; set; } + public BasicEmployeeVM? ApprovedBy { get; set; } + public WorkStatusMaster? WorkStatus { get; set; } public WorkItem? WorkItem { get; set; } public List? PreSignedUrls { get; set; } public List? Comments { get; set; } - public List? TeamMembers { get; set; } + public List? TeamMembers { get; set; } } } diff --git a/Marco.Pms.Services/Controllers/TaskController.cs b/Marco.Pms.Services/Controllers/TaskController.cs index ea4fbf1..ab34561 100644 --- a/Marco.Pms.Services/Controllers/TaskController.cs +++ b/Marco.Pms.Services/Controllers/TaskController.cs @@ -1,15 +1,14 @@ using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Activities; using Marco.Pms.Model.Dtos.Activities; -using Marco.Pms.Model.Employees; 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.Service; using MarcoBMS.Services.Helpers; +using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.CodeAnalysis; @@ -27,13 +26,20 @@ namespace MarcoBMS.Services.Controllers private readonly ApplicationDbContext _context; private readonly UserHelper _userHelper; private readonly S3UploadService _s3Service; + private readonly ILoggingService _logger; + private readonly PermissionServices _permissionServices; + private readonly Guid Approve_Task; + private readonly Guid Assign_Report_Task; - - public TaskController(ApplicationDbContext context, UserHelper userHelper, S3UploadService s3Service) + public TaskController(ApplicationDbContext context, UserHelper userHelper, S3UploadService s3Service, ILoggingService logger, PermissionServices permissionServices) { _context = context; _userHelper = userHelper; _s3Service = s3Service; + _logger = logger; + _permissionServices = permissionServices; + Approve_Task = Guid.Parse("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c"); + Assign_Report_Task = Guid.Parse("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2"); } private Guid GetTenantId() @@ -44,49 +50,68 @@ namespace MarcoBMS.Services.Controllers [HttpPost("assign")] public async Task AssignTask([FromBody] AssignTaskDto assignTask) { + // Validate the incoming model if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); + + _logger.LogWarning("AssignTask failed validation: {@Errors}", errors); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); - } - var tenantId = GetTenantId(); - var Employee = await _userHelper.GetCurrentEmployeeAsync(); - var taskAllocation = assignTask.ToTaskAllocationFromAssignTaskDto(Employee.Id, tenantId); + // Retrieve tenant and employee context + var tenantId = GetTenantId(); + var employee = await _userHelper.GetCurrentEmployeeAsync(); + + // Check for permission to approve tasks + var hasPermission = await _permissionServices.HasPermission(Assign_Report_Task, employee.Id); + if (!hasPermission) + { + _logger.LogWarning("Employee {EmployeeId} attempted to assign Task without permission", employee.Id); + return StatusCode(403, ApiResponse.ErrorResponse("You don't have access", "User not authorized to approve tasks", 403)); + } + + _logger.LogInfo("Employee {EmployeeId} is assigning a new task", employee.Id); + + // Convert DTO to entity and save TaskAllocation + var taskAllocation = assignTask.ToTaskAllocationFromAssignTaskDto(employee.Id, tenantId); _context.TaskAllocations.Add(taskAllocation); await _context.SaveChangesAsync(); + + _logger.LogInfo("Task {TaskId} assigned by Employee {EmployeeId}", taskAllocation.Id, employee.Id); + var response = taskAllocation.ToAssignTaskVMFromTaskAllocation(); - var teamMembers = new List { }; - if (assignTask.TaskTeam != null) + // Map team members + var teamMembers = new List(); + if (assignTask.TaskTeam != null && assignTask.TaskTeam.Any()) { - foreach (var teamMember in assignTask.TaskTeam) + teamMembers = assignTask.TaskTeam.Select(memberId => new TaskMembers { - var result = new TaskMembers - { - TaskAllocationId = taskAllocation.Id, - EmployeeId = teamMember, - TenantId = tenantId, - }; - teamMembers.Add(result); - } - } - _context.TaskMembers.AddRange(teamMembers); - await _context.SaveChangesAsync(); + TaskAllocationId = taskAllocation.Id, + EmployeeId = memberId, + TenantId = tenantId + }).ToList(); - var idList = teamMembers.Select(m => m.EmployeeId); - List employees = await _context.Employees.Where(e => idList.Contains(e.Id)).ToListAsync(); - List team = new List(); - foreach (var employee in employees) - { - team.Add(employee.ToBasicEmployeeVMFromEmployee()); + _context.TaskMembers.AddRange(teamMembers); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Team members added to Task {TaskId}: {@TeamMemberIds}", taskAllocation.Id, assignTask.TaskTeam); } + + // Get team member details + var employeeIds = teamMembers.Select(m => m.EmployeeId).ToList(); + var employees = await _context.Employees + .Where(e => employeeIds.Contains(e.Id)) + .ToListAsync(); + + var team = employees.Select(e => e.ToBasicEmployeeVMFromEmployee()).ToList(); response.teamMembers = team; - return Ok(ApiResponse.SuccessResponse(response, "Task assignned successfully", 200)); + + return Ok(ApiResponse.SuccessResponse(response, "Task assigned successfully", 200)); } [HttpPost("report")] @@ -98,363 +123,661 @@ namespace MarcoBMS.Services.Controllers .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); + + _logger.LogWarning("Task report validation failed: {@Errors}", errors); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); - } + var tenantId = GetTenantId(); - var Employee = await _userHelper.GetCurrentEmployeeAsync(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - var taskAllocation = await _context.TaskAllocations.Include(t => t.WorkItem).FirstOrDefaultAsync(t => t.Id == reportTask.Id); - - var checkListIds = reportTask.CheckList != null ? reportTask.CheckList.Select(c => c.Id).ToList() : new List(); - var checkList = await _context.ActivityCheckLists.Where(c => checkListIds.Contains(c.Id)).ToListAsync(); - if (taskAllocation == null || taskAllocation.WorkItem == null) + var hasPermission = await _permissionServices.HasPermission(Assign_Report_Task, loggedInEmployee.Id); + if (!hasPermission) { + _logger.LogWarning("Unauthorized task report attempt by Employee {EmployeeId} for Task {TaskId}", loggedInEmployee.Id, reportTask.Id); + return StatusCode(403, ApiResponse.ErrorResponse("You don't have access", "User not authorized to report tasks", 403)); + } + + var taskAllocation = await _context.TaskAllocations + .Include(t => t.WorkItem) + .FirstOrDefaultAsync(t => t.Id == reportTask.Id); + + if (taskAllocation == null) + { + _logger.LogWarning("No task allocation found with ID {TaskId}", reportTask.Id); return BadRequest(ApiResponse.ErrorResponse("No such task has been allocated.", "No such task has been allocated.", 400)); } - WorkArea workArea = await _context.WorkAreas.Include(a => a.Floor).FirstOrDefaultAsync(a => a.Id == taskAllocation.WorkItem.WorkAreaId) ?? new WorkArea(); - var bulding = await _context.Buildings.FirstOrDefaultAsync(b => b.Id == (workArea.Floor != null ? workArea.Floor.BuildingId : Guid.Empty)); + var checkListIds = reportTask.CheckList?.Select(c => c.Id).ToList() ?? new List(); + var checkList = await _context.ActivityCheckLists + .Where(c => checkListIds.Contains(c.Id)) + .ToListAsync(); + if (taskAllocation.WorkItem != null) { - if (taskAllocation.CompletedTask != 0) - { + if (taskAllocation.CompletedTask > 0) taskAllocation.WorkItem.CompletedWork -= taskAllocation.CompletedTask; - } - taskAllocation.ReportedDate = reportTask.ReportedDate; - taskAllocation.CompletedTask = reportTask.CompletedTask; + taskAllocation.WorkItem.CompletedWork += reportTask.CompletedTask; } - List checkListMappings = new List(); - List checkListVMs = new List(); + + taskAllocation.ParentTaskId = reportTask.ParentTaskId; + taskAllocation.ReportedDate = reportTask.ReportedDate; + taskAllocation.ReportedById = loggedInEmployee.Id; + taskAllocation.CompletedTask = reportTask.CompletedTask; + taskAllocation.ReportedTask = reportTask.CompletedTask; + + var checkListMappings = new List(); + var checkListVMs = new List(); + if (reportTask.CheckList != null) { + var activityId = taskAllocation.WorkItem?.ActivityId ?? Guid.Empty; + foreach (var checkDto in reportTask.CheckList) { - checkListVMs.Add(checkDto.ToCheckListVMFromReportCheckListDto(taskAllocation.WorkItem != null ? taskAllocation.WorkItem.ActivityId : Guid.Empty)); - if (checkDto.IsChecked) + checkListVMs.Add(checkDto.ToCheckListVMFromReportCheckListDto(activityId)); + + if (checkDto.IsChecked && checkList.Any(c => c.Id == checkDto.Id)) { - var check = checkList.Find(c => c.Id == checkDto.Id); - if (check != null) + checkListMappings.Add(new CheckListMappings { - CheckListMappings checkListMapping = new CheckListMappings - { - CheckListId = check.Id, - TaskAllocationId = reportTask.Id - }; - checkListMappings.Add(checkListMapping); - } + CheckListId = checkDto.Id, + TaskAllocationId = reportTask.Id + }); } } + + _context.CheckListMappings.AddRange(checkListMappings); } - _context.CheckListMappings.AddRange(checkListMappings); - var comment = reportTask.ToCommentFromReportTaskDto(tenantId, Employee.Id); - var Images = reportTask.Images; + var comment = reportTask.ToCommentFromReportTaskDto(tenantId, loggedInEmployee.Id); + _context.TaskComments.Add(comment); - if (Images != null && Images.Count > 0) + if (reportTask.Images?.Any() == true) { + var workAreaId = taskAllocation.WorkItem?.WorkAreaId; + var workArea = await _context.WorkAreas.Include(a => a.Floor) + .FirstOrDefaultAsync(a => a.Id == workAreaId) ?? new WorkArea(); - foreach (var Image in Images) + var buildingId = workArea.Floor?.BuildingId; + + var building = await _context.Buildings + .FirstOrDefaultAsync(b => b.Id == buildingId); + + foreach (var image in reportTask.Images) { - - if (string.IsNullOrEmpty(Image.Base64Data)) + if (string.IsNullOrEmpty(image.Base64Data)) + { + _logger.LogWarning("Image upload failed: Base64 data is missing"); return BadRequest(ApiResponse.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400)); + } - //If base64 has a data URI prefix, strip it - var base64 = Image.Base64Data.Contains(",") - ? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1) - : Image.Base64Data; + var base64 = image.Base64Data.Contains(',') + ? image.Base64Data[(image.Base64Data.IndexOf(",") + 1)..] + : image.Base64Data; - string fileType = _s3Service.GetContentTypeFromBase64(base64); - string fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report"); + var fileType = _s3Service.GetContentTypeFromBase64(base64); + var fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report"); + var objectKey = $"tenant-{tenantId}/project-{building?.ProjectId}/Actitvity/{fileName}"; - string objectKey = $"tenant-{tenantId}/project-{bulding?.ProjectId}/Actitvity/{fileName}"; await _s3Service.UploadFileAsync(base64, fileType, objectKey); - Document document = new Document + var document = new Document { - FileName = Image.FileName ?? "", - ContentType = Image.ContentType ?? "", + FileName = image.FileName ?? "", + ContentType = image.ContentType ?? "", S3Key = objectKey, - Base64Data = Image.Base64Data, - FileSize = Image.FileSize, + Base64Data = image.Base64Data, + FileSize = image.FileSize, UploadedAt = DateTime.UtcNow, TenantId = tenantId }; _context.Documents.Add(document); - TaskAttachment attachment = new TaskAttachment + + var attachment = new TaskAttachment { DocumentId = document.Id, ReferenceId = reportTask.Id }; _context.TaskAttachments.Add(attachment); } - await _context.SaveChangesAsync(); } - _context.TaskComments.Add(comment); await _context.SaveChangesAsync(); var response = taskAllocation.ToReportTaskVMFromTaskAllocation(); - List comments = await _context.TaskComments.Where(c => c.TaskAllocationId == taskAllocation.Id).ToListAsync(); - List resultComments = new List { }; - foreach (var result in comments) - { - resultComments.Add(result.ToCommentVMFromTaskComment()); - } - response.Comments = resultComments; + var comments = await _context.TaskComments + .Where(c => c.TaskAllocationId == taskAllocation.Id) + .ToListAsync(); + + response.Comments = comments.Select(c => c.ToCommentVMFromTaskComment()).ToList(); response.checkList = checkListVMs; + + _logger.LogInfo("Task {TaskId} reported successfully by Employee {EmployeeId}", taskAllocation.Id, loggedInEmployee.Id); + return Ok(ApiResponse.SuccessResponse(response, "Task reported successfully", 200)); } [HttpPost("comment")] public async Task AddCommentForTask([FromBody] CreateCommentDto createComment) { - var tenantId = GetTenantId(); - var Employee = await _userHelper.GetCurrentEmployeeAsync(); + _logger.LogInfo("AddCommentForTask called for TaskAllocationId: {TaskId}", createComment.TaskAllocationId); + + var tenantId = GetTenantId(); + var employee = await _userHelper.GetCurrentEmployeeAsync(); + + // Validate Task Allocation and associated WorkItem + var taskAllocation = await _context.TaskAllocations + .Include(t => t.WorkItem) + .FirstOrDefaultAsync(t => t.Id == createComment.TaskAllocationId); - var taskAllocation = await _context.TaskAllocations.Include(t => t.WorkItem).FirstOrDefaultAsync(t => t.Id == createComment.TaskAllocationId); if (taskAllocation == null || taskAllocation.WorkItem == null) { + _logger.LogWarning("Invalid task allocation or work item not found."); return BadRequest(ApiResponse.ErrorResponse("No such task has been allocated.", "No such task has been allocated.", 400)); } - WorkArea workArea = await _context.WorkAreas.Include(a => a.Floor).FirstOrDefaultAsync(a => a.Id == taskAllocation.WorkItem.WorkAreaId) ?? new WorkArea(); - var bulding = await _context.Buildings.FirstOrDefaultAsync(b => b.Id == (workArea.Floor != null ? workArea.Floor.BuildingId : Guid.Empty)); + // Fetch WorkArea and Building (if available) + var workArea = await _context.WorkAreas + .Include(a => a.Floor) + .FirstOrDefaultAsync(a => a.Id == taskAllocation.WorkItem.WorkAreaId) ?? new WorkArea(); - var comment = createComment.ToCommentFromCommentDto(tenantId, Employee.Id); + var buildingId = workArea.Floor?.BuildingId ?? Guid.Empty; + var building = await _context.Buildings.FirstOrDefaultAsync(b => b.Id == buildingId); + + // Save comment + var comment = createComment.ToCommentFromCommentDto(tenantId, employee.Id); _context.TaskComments.Add(comment); await _context.SaveChangesAsync(); + _logger.LogInfo("Comment saved with Id: {CommentId}", comment.Id); - var Images = createComment.Images; + // Process image uploads + var images = createComment.Images; - if (Images != null && Images.Count > 0) + if (images != null && images.Any()) { - - foreach (var Image in Images) + foreach (var image in images) { - - if (string.IsNullOrEmpty(Image.Base64Data)) - return BadRequest(ApiResponse.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400)); - - //If base64 has a data URI prefix, strip it - var base64 = Image.Base64Data.Contains(",") - ? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1) - : Image.Base64Data; - - string fileType = _s3Service.GetContentTypeFromBase64(base64); - string fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report"); - - string objectKey = $"tenant-{tenantId}/project-{bulding?.ProjectId}/Actitvity/{fileName}"; - await _s3Service.UploadFileAsync(base64, fileType, objectKey); - - Document document = new Document + if (string.IsNullOrWhiteSpace(image.Base64Data)) { - FileName = Image.FileName ?? "", - ContentType = Image.ContentType ?? "", + _logger.LogWarning("Missing Base64 data in one of the images."); + return BadRequest(ApiResponse.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400)); + } + + // Clean base64 string + var base64 = image.Base64Data.Contains(",") + ? image.Base64Data.Substring(image.Base64Data.IndexOf(",") + 1) + : image.Base64Data; + + var fileType = _s3Service.GetContentTypeFromBase64(base64); + var fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_comment"); + var objectKey = $"tenant-{tenantId}/project-{building?.ProjectId}/Activity/{fileName}"; + + await _s3Service.UploadFileAsync(base64, fileType, objectKey); + _logger.LogInfo("Image uploaded to S3 with key: {ObjectKey}", objectKey); + + var document = new Document + { + FileName = image.FileName ?? string.Empty, + ContentType = image.ContentType ?? fileType, S3Key = objectKey, - Base64Data = Image.Base64Data, - FileSize = Image.FileSize, + Base64Data = image.Base64Data, + FileSize = image.FileSize, UploadedAt = DateTime.UtcNow, TenantId = tenantId }; + _context.Documents.Add(document); - TaskAttachment attachment = new TaskAttachment + + var attachment = new TaskAttachment { DocumentId = document.Id, ReferenceId = comment.Id }; + _context.TaskAttachments.Add(attachment); } + await _context.SaveChangesAsync(); + _logger.LogInfo("Documents and attachments saved for commentId: {CommentId}", comment.Id); } - CommentVM response = comment.ToCommentVMFromTaskComment(); + // Convert to view model and return response + var response = comment.ToCommentVMFromTaskComment(); + _logger.LogInfo("Returning response for commentId: {CommentId}", comment.Id); + return Ok(ApiResponse.SuccessResponse(response, "Comment saved successfully", 200)); } [HttpGet("list")] public async Task GetTasksList([FromQuery] Guid projectId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null) { + _logger.LogInfo("GetTasksList called for projectId: {ProjectId}, dateFrom: {DateFrom}, dateTo: {DateTo}", projectId, dateFrom ?? "", dateTo ?? ""); + Guid tenantId = GetTenantId(); DateTime fromDate = new DateTime(); DateTime toDate = new DateTime(); - if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false) + // Parse and validate dateFrom + if (dateFrom != null && !DateTime.TryParse(dateFrom, out fromDate)) { + _logger.LogWarning("Invalid starting date provided: {DateFrom}", dateFrom); return BadRequest(ApiResponse.ErrorResponse("Invalid starting date.", "Invalid starting date.", 400)); - } - if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false) + + // Parse and validate dateTo + if (dateTo != null && !DateTime.TryParse(dateTo, out toDate)) { + _logger.LogWarning("Invalid ending date provided: {DateTo}", dateTo); return BadRequest(ApiResponse.ErrorResponse("Invalid ending date.", "Invalid ending date.", 400)); - } - if (dateFrom == null) fromDate = DateTime.UtcNow.Date; - if (dateTo == null) toDate = fromDate.AddDays(1); - var jobroles = await _context.JobRoles.Where(r => r.TenantId == tenantId).ToListAsync(); - //var taskAllocations = await _context.TaskAllocations.Where(t => t.WorkItem.WorkArea.Floor.Building.ProjectId == projectId && t.AssignmentDate >= fromDate && t.AssignmentDate <= toDate && t.TenantId == tenantId).Include(t => t.WorkItemId).ToListAsync(); - List buildings = await _context.Buildings.Where(b => b.ProjectId == projectId && b.TenantId == tenantId).ToListAsync(); - List idList = buildings.Select(b => b.Id).ToList(); + // Set default date range if not provided + fromDate = dateFrom == null ? DateTime.UtcNow.Date : fromDate; + toDate = dateTo == null ? fromDate.AddDays(1) : toDate; - List floors = await _context.Floor.Where(f => idList.Contains(f.BuildingId) && f.TenantId == tenantId).ToListAsync(); - idList = floors.Select(f => f.Id).ToList(); + // 1. Get all buildings under this project + _logger.LogInfo("Fetching buildings for projectId: {ProjectId}", projectId); + var buildings = await _context.Buildings + .Where(b => b.ProjectId == projectId && b.TenantId == tenantId) + .ToListAsync(); - List workAreas = await _context.WorkAreas.Where(a => idList.Contains(a.FloorId) && a.TenantId == tenantId).ToListAsync(); - idList = workAreas.Select(a => a.Id).ToList(); + var buildingIds = buildings.Select(b => b.Id).ToList(); - List workItems = await _context.WorkItems.Where(i => idList.Contains(i.WorkAreaId) && i.TenantId == tenantId).Include(i => i.ActivityMaster).ToListAsync(); - idList = workItems.Select(i => i.Id).ToList(); - var activityIdList = workItems.Select(i => i.ActivityId).ToList(); + // 2. Get floors under the buildings + var floors = await _context.Floor + .Where(f => buildingIds.Contains(f.BuildingId) && f.TenantId == tenantId) + .ToListAsync(); + var floorIds = floors.Select(f => f.Id).ToList(); - List taskAllocations = await _context.TaskAllocations.Where(t => idList.Contains(t.WorkItemId) && t.AssignmentDate.Date >= fromDate.Date && t.AssignmentDate.Date <= toDate.Date && t.TenantId == tenantId).Include(t => t.WorkItem).Include(t => t.Employee).ToListAsync(); - var taskIdList = taskAllocations.Select(t => t.Id).ToList(); + // 3. Get work areas under the floors + var workAreas = await _context.WorkAreas + .Where(a => floorIds.Contains(a.FloorId) && a.TenantId == tenantId) + .ToListAsync(); + var workAreaIds = workAreas.Select(a => a.Id).ToList(); - List teamMembers = await _context.TaskMembers.Where(t => taskIdList.Contains(t.TaskAllocationId)).ToListAsync(); - var employeeIdList = teamMembers.Select(e => e.EmployeeId).ToList(); + // 4. Get work items under the work areas + var workItems = await _context.WorkItems + .Where(i => workAreaIds.Contains(i.WorkAreaId) && i.TenantId == tenantId) + .Include(i => i.ActivityMaster) + .ToListAsync(); + var workItemIds = workItems.Select(i => i.Id).ToList(); - List employees = await _context.Employees.Where(e => employeeIdList.Contains(e.Id)).Include(e => e.JobRole).ToListAsync(); + _logger.LogInfo("Fetching task allocations between {FromDate} and {ToDate}", fromDate, toDate); - List allComments = await _context.TaskComments.Include(c => c.Employee).Where(c => taskIdList.Contains(c.TaskAllocationId)).ToListAsync(); - var allCommentIds = allComments.Select(c => c.Id).ToList(); + // 5. Get task allocations in the specified date range + var taskAllocations = await _context.TaskAllocations + .Include(t => t.Employee) + .Include(t => t.ReportedBy) + .Include(t => t.ApprovedBy) + .Include(t => t.WorkStatus) + .Include(t => t.WorkItem) + .Where(t => workItemIds.Contains(t.WorkItemId) && + t.AssignmentDate.Date >= fromDate.Date && + t.AssignmentDate.Date <= toDate.Date && + t.TenantId == tenantId) + .ToListAsync(); + + var taskIds = taskAllocations.Select(t => t.Id).ToList(); + + // 6. Load team members + _logger.LogInfo("Loading task members and related employee data."); + var teamMembers = await _context.TaskMembers + .Include(t => t.Employee) + .Where(t => taskIds.Contains(t.TaskAllocationId)) + .ToListAsync(); + + // 7. Load task comments + _logger.LogInfo("Fetching comments and attachments."); + var allComments = await _context.TaskComments + .Include(c => c.Employee) + .Where(c => taskIds.Contains(c.TaskAllocationId)) + .ToListAsync(); + var commentIds = allComments.Select(c => c.Id).ToList(); + + // 8. Load all attachments (task and comment) + var attachments = await _context.TaskAttachments + .Where(t => taskIds.Contains(t.ReferenceId) || commentIds.Contains(t.ReferenceId)) + .ToListAsync(); + + var documentIds = attachments.Select(t => t.DocumentId).ToList(); + + // 9. Load actual documents from attachment references + var documents = await _context.Documents + .Where(d => documentIds.Contains(d.Id)) + .ToListAsync(); + + var tasks = new List(); + + _logger.LogInfo("Constructing task response data."); - var taskAttachments = await _context.TaskAttachments.Where(t => taskIdList.Contains(t.ReferenceId) || allCommentIds.Contains(t.ReferenceId)).ToListAsync(); - var documentIds = taskAttachments.Select(t => t.DocumentId).ToList(); - var documents = await _context.Documents.Where(d => documentIds.Contains(d.Id)).ToListAsync(); - List tasks = new List(); - //foreach (var workItem in workItems) - //{ foreach (var taskAllocation in taskAllocations) { - var response = taskAllocation.ToListTaskVMFromTaskAllocation(); - List comments = allComments.Where(c => c.TaskAllocationId == taskAllocation.Id).ToList(); - List team = new List(); - List taskMembers = teamMembers.Where(m => m.TaskAllocationId == taskAllocation.Id).ToList(); + // Attach documents to the main task + var taskDocIds = attachments + .Where(a => a.ReferenceId == taskAllocation.Id) + .Select(a => a.DocumentId) + .ToList(); - var taskDocumentIds = taskAttachments.Where(t => t.ReferenceId == taskAllocation.Id).Select(t => t.DocumentId).ToList(); - var taskDocuments = documents.Where(d => taskDocumentIds.Contains(d.Id)).ToList(); + var taskDocs = documents + .Where(d => taskDocIds.Contains(d.Id)) + .ToList(); - List taskPreSignedUrls = new List(); - foreach (var document in taskDocuments) - { - string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); - taskPreSignedUrls.Add(preSignedUrl); - } - response.ReportedPreSignedUrls = taskPreSignedUrls; + response.ReportedPreSignedUrls = taskDocs + .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .ToList(); - foreach (var taskMember in taskMembers) - { - var teamMember = employees.Find(e => e.Id == taskMember.EmployeeId); - if (teamMember != null) - { - team.Add(teamMember.ToBasicEmployeeVMFromEmployee()); - } - } - List commentVM = new List { }; - foreach (var comment in comments) - { - var commentDocumentIds = taskAttachments.Where(t => t.ReferenceId == comment.Id).Select(t => t.DocumentId).ToList(); - var commentDocuments = documents.Where(d => commentDocumentIds.Contains(d.Id)).ToList(); - List commentPreSignedUrls = new List(); - foreach (var document in commentDocuments) - { - string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); - commentPreSignedUrls.Add(preSignedUrl); - } - CommentVM commentVm = comment.ToCommentVMFromTaskComment(); - commentVm.PreSignedUrls = commentPreSignedUrls; + // Add team members + var taskMemberEntries = teamMembers + .Where(m => m.TaskAllocationId == taskAllocation.Id) + .ToList(); - commentVM.Add(commentVm); - } - List checkLists = await _context.ActivityCheckLists.Where(x => x.ActivityId == (taskAllocation.WorkItem != null ? taskAllocation.WorkItem.ActivityId : Guid.Empty)).ToListAsync(); - List checkListMappings = await _context.CheckListMappings.Where(c => c.TaskAllocationId == taskAllocation.Id).ToListAsync(); - List checkList = new List(); - foreach (var check in checkLists) + response.teamMembers = taskMemberEntries + .Select(m => m.Employee) + .Where(e => e != null) + .Select(e => e!.ToBasicEmployeeVMFromEmployee()) + .ToList(); + + // Add comments with attachments + var commentVMs = new List(); + var taskComments = allComments + .Where(c => c.TaskAllocationId == taskAllocation.Id) + .ToList(); + + foreach (var comment in taskComments) { - var checkListMapping = checkListMappings.Find(c => c.CheckListId == check.Id); - if (checkListMapping != null) - { - checkList.Add(check.ToCheckListVMFromActivityCheckList(check.ActivityId, true)); - } - else - { - checkList.Add(check.ToCheckListVMFromActivityCheckList(check.ActivityId, false)); - } + var commentDocIds = attachments + .Where(a => a.ReferenceId == comment.Id) + .Select(a => a.DocumentId) + .ToList(); + + var commentDocs = documents + .Where(d => commentDocIds.Contains(d.Id)) + .ToList(); + + var commentVm = comment.ToCommentVMFromTaskComment(); + commentVm.PreSignedUrls = commentDocs + .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .ToList(); + + commentVMs.Add(commentVm); } - response.comments = commentVM; - response.teamMembers = team; - response.CheckList = checkList; + + response.comments = commentVMs; + + // Checklists + var activityId = taskAllocation.WorkItem?.ActivityId ?? Guid.Empty; + + var checkLists = await _context.ActivityCheckLists + .Where(c => c.ActivityId == activityId) + .ToListAsync(); + + var checkListMappings = await _context.CheckListMappings + .Where(c => c.TaskAllocationId == taskAllocation.Id) + .ToListAsync(); + + response.CheckList = checkLists.Select(check => + { + var isChecked = checkListMappings.Any(m => m.CheckListId == check.Id); + return check.ToCheckListVMFromActivityCheckList(check.ActivityId, isChecked); + }).ToList(); + tasks.Add(response); } - //} + _logger.LogInfo("Task list constructed successfully. Returning {Count} tasks.", tasks.Count); + return Ok(ApiResponse.SuccessResponse(tasks, "Success", 200)); } [HttpGet("get/{taskId}")] public async Task GetTask(Guid taskId) { - if (taskId == Guid.Empty) return BadRequest(ApiResponse.ErrorResponse("Invalid data", "Invalid data", 400)); + _logger.LogInfo("GetTask called with taskId: {TaskId}", taskId); - var taskAllocation = await _context.TaskAllocations.Include(t => t.Tenant).Include(t => t.Employee).Include(t => t.WorkItem).FirstOrDefaultAsync(t => t.Id == taskId); - if (taskAllocation != null && taskAllocation.Employee != null && taskAllocation.Tenant != null) + // Validate input + if (taskId == Guid.Empty) { - //var employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == taskAllocation.AssignedBy); - string employeeName = System.String.Format("{0} {1}", taskAllocation.Employee.FirstName, taskAllocation.Employee.LastName); - string tenantName = taskAllocation.Tenant.ContactName ?? string.Empty; - - if (taskAllocation == null) return NotFound(ApiResponse.ErrorResponse("Task Not Found", "Task not found", 404)); - var taskVM = taskAllocation.TaskAllocationToTaskVM(employeeName); - var comments = await _context.TaskComments.Where(c => c.TaskAllocationId == taskAllocation.Id).ToListAsync(); - var commentIds = comments.Select(c => c.Id).ToList(); - var taskAttachments = await _context.TaskAttachments.Where(t => t.ReferenceId == taskAllocation.Id || commentIds.Contains(t.ReferenceId)).ToListAsync(); - var documentIds = taskAttachments.Select(t => t.DocumentId).ToList(); - var documents = await _context.Documents.Where(d => documentIds.Contains(d.Id)).ToListAsync(); - var team = await _context.TaskMembers.Where(m => m.TaskAllocationId == taskAllocation.Id).Include(m => m.Employee).ToListAsync(); - var teamMembers = new List { }; - - var taskDocumentIds = taskAttachments.Where(t => t.ReferenceId == taskAllocation.Id).Select(t => t.DocumentId).ToList(); - var taskDocuments = documents.Where(d => taskDocumentIds.Contains(d.Id)).ToList(); - - List taskPreSignedUrls = new List(); - foreach (var document in taskDocuments) - { - string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); - taskPreSignedUrls.Add(preSignedUrl); - } - taskVM.PreSignedUrls = taskPreSignedUrls; - foreach (var member in team) - { - var result = member.Employee != null ? member.Employee.ToEmployeeVMFromEmployee() : new EmployeeVM(); - teamMembers.Add(result); - } - List Comments = new List { }; - foreach (var comment in comments) - { - var commentDocumentIds = taskAttachments.Where(t => t.ReferenceId == comment.Id).Select(t => t.DocumentId).ToList(); - var commentDocuments = documents.Where(d => commentDocumentIds.Contains(d.Id)).ToList(); - List commentPreSignedUrls = new List(); - foreach (var document in commentDocuments) - { - string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key); - commentPreSignedUrls.Add(preSignedUrl); - } - CommentVM commentVM = comment.ToCommentVMFromTaskComment(); - commentVM.PreSignedUrls = commentPreSignedUrls; - Comments.Add(commentVM); - } - taskVM.Comments = Comments; - taskVM.TeamMembers = teamMembers; - return Ok(ApiResponse.SuccessResponse(taskVM, "Success", 200)); + _logger.LogWarning("Invalid taskId provided."); + return BadRequest(ApiResponse.ErrorResponse("Invalid data", "Invalid data", 400)); } + // Fetch Task Allocation with required related data + var taskAllocation = await _context.TaskAllocations + .Include(t => t.Tenant) + .Include(t => t.Employee) + .Include(t => t.ReportedBy) + .Include(t => t.ApprovedBy) + .Include(t => t.WorkItem) + .Include(t => t.WorkStatus) + .FirstOrDefaultAsync(t => t.Id == taskId); - return NotFound(ApiResponse.ErrorResponse("Task Not Found", "Task not Found", 404)); + if (taskAllocation == null) + { + _logger.LogWarning("Task not found for taskId: {TaskId}", taskId); + return NotFound(ApiResponse.ErrorResponse("Task Not Found", "Task not found", 404)); + } + + if (taskAllocation.Employee == null || taskAllocation.Tenant == null) + { + _logger.LogWarning("Task found but missing Employee or Tenant data for taskId: {TaskId}", taskId); + return NotFound(ApiResponse.ErrorResponse("Task Not Found", "Task not found", 404)); + } + + _logger.LogInfo("Task allocation found. Preparing response."); + + var taskVM = taskAllocation.TaskAllocationToTaskVM(); + + // Fetch comments and attachments + _logger.LogInfo("Fetching comments and attachments for taskId: {TaskId}", taskId); + + var comments = await _context.TaskComments + .Where(c => c.TaskAllocationId == taskId) + .Include(c => c.Employee) + .ToListAsync(); + + var commentIds = comments.Select(c => c.Id).ToList(); + + var taskAttachments = await _context.TaskAttachments + .Where(t => t.ReferenceId == taskId || commentIds.Contains(t.ReferenceId)) + .ToListAsync(); + + var documentIds = taskAttachments.Select(t => t.DocumentId).Distinct().ToList(); + + var documents = await _context.Documents + .Where(d => documentIds.Contains(d.Id)) + .ToListAsync(); + + // Fetch team members + _logger.LogInfo("Fetching team members for taskId: {TaskId}", taskId); + var team = await _context.TaskMembers + .Where(m => m.TaskAllocationId == taskId) + .Include(m => m.Employee) + .ToListAsync(); + + var teamMembers = team + .Where(m => m.Employee != null) + .Select(m => m.Employee!.ToBasicEmployeeVMFromEmployee()) + .ToList(); + + taskVM.TeamMembers = teamMembers; + + // Attach documents to the main task + _logger.LogInfo("Generating presigned URLs for task documents."); + var taskDocumentIds = taskAttachments + .Where(t => t.ReferenceId == taskId) + .Select(t => t.DocumentId) + .ToList(); + + var taskDocuments = documents + .Where(d => taskDocumentIds.Contains(d.Id)) + .ToList(); + + taskVM.PreSignedUrls = taskDocuments + .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .ToList(); + + // Construct CommentVM list with document URLs + _logger.LogInfo("Preparing comment response data."); + var commentVMs = comments.Select(comment => + { + var commentDocIds = taskAttachments + .Where(t => t.ReferenceId == comment.Id) + .Select(t => t.DocumentId) + .ToList(); + + var commentDocs = documents + .Where(d => commentDocIds.Contains(d.Id)) + .ToList(); + + var commentVM = comment.ToCommentVMFromTaskComment(); + commentVM.PreSignedUrls = commentDocs + .Select(d => _s3Service.GeneratePreSignedUrlAsync(d.S3Key)) + .ToList(); + + return commentVM; + }).ToList(); + + taskVM.Comments = commentVMs; + + _logger.LogInfo("Task details prepared successfully for taskId: {TaskId}", taskId); + return Ok(ApiResponse.SuccessResponse(taskVM, "Success", 200)); + } + + /// + /// Approves a reported task after validation, updates status, and stores attachments/comments. + /// + /// DTO containing task approval details. + /// IActionResult indicating success or failure. + [HttpPost("approve")] + public async Task ApproveTask(ApproveTaskDto approveTask) + { + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + _logger.LogInfo("Employee {EmployeeId} is attempting to approve Task {TaskId}", loggedInEmployee.Id, approveTask.Id); + + // Fetch task allocation with work item, only if it's reported + var taskAllocation = await _context.TaskAllocations + .Include(t => t.WorkItem) + .FirstOrDefaultAsync(t => t.Id == approveTask.Id && t.TenantId == tenantId && t.ReportedDate != null); + + if (taskAllocation == null) + { + _logger.LogWarning("Task {TaskId} not found or not reported yet for Tenant {TenantId} by Employee {EmployeeId}", + approveTask.Id, tenantId, loggedInEmployee.Id); + + return NotFound(ApiResponse.ErrorResponse("Task not found", "Task not found", 404)); + } + + // Check for permission to approve tasks + var hasPermission = await _permissionServices.HasPermission(Approve_Task, loggedInEmployee.Id); + if (!hasPermission) + { + _logger.LogWarning("Employee {EmployeeId} attempted to approve Task {TaskId} without permission", loggedInEmployee.Id, approveTask.Id); + return StatusCode(403, ApiResponse.ErrorResponse("You don't have access", "User not authorized to approve tasks", 403)); + } + + // Validation: Approved task count cannot exceed completed task count + if (taskAllocation.CompletedTask < approveTask.ApprovedTask) + { + _logger.LogWarning("Invalid approval attempt on Task {TaskId}: Approved tasks ({ApprovedTask}) > Completed tasks ({CompletedTask})", + approveTask.Id, approveTask.ApprovedTask, taskAllocation.CompletedTask); + + return BadRequest(ApiResponse.ErrorResponse("Approved tasks cannot be greater than completed tasks", + "Approved tasks cannot be greater than completed tasks", 400)); + } + + // Update completed work in the associated work item, if it exists + if (taskAllocation.WorkItem != null && taskAllocation.CompletedTask != approveTask.ApprovedTask) + { + if (taskAllocation.CompletedTask > 0) + { + taskAllocation.WorkItem.CompletedWork -= taskAllocation.CompletedTask; + } + taskAllocation.WorkItem.CompletedWork += approveTask.ApprovedTask; + } + + // Update task allocation details + taskAllocation.ApprovedById = loggedInEmployee.Id; + taskAllocation.ApprovedDate = DateTime.UtcNow; + taskAllocation.WorkStatusId = approveTask.WorkStatus; + taskAllocation.CompletedTask = approveTask.ApprovedTask; + + // Add a comment (optional) + var comment = new TaskComment + { + TaskAllocationId = taskAllocation.Id, + CommentDate = DateTime.UtcNow, + Comment = approveTask.Comment ?? string.Empty, + CommentedBy = loggedInEmployee.Id, + TenantId = tenantId + }; + _context.TaskComments.Add(comment); + + // Handle image attachments, if any + if (approveTask.Images?.Count > 0) + { + var workAreaId = taskAllocation.WorkItem?.WorkAreaId; + var workArea = await _context.WorkAreas.Include(a => a.Floor) + .FirstOrDefaultAsync(a => a.Id == workAreaId) ?? new WorkArea(); + + var buildingId = workArea.Floor?.BuildingId; + + var building = await _context.Buildings + .FirstOrDefaultAsync(b => b.Id == buildingId); + + foreach (var image in approveTask.Images) + { + if (string.IsNullOrEmpty(image.Base64Data)) + { + _logger.LogWarning("Image for Task {TaskId} is missing base64 data", approveTask.Id); + return BadRequest(ApiResponse.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400)); + } + + var base64 = image.Base64Data.Contains(",") ? image.Base64Data[(image.Base64Data.IndexOf(",") + 1)..] : image.Base64Data; + + var fileType = _s3Service.GetContentTypeFromBase64(base64); + var fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_comment"); + var objectKey = $"tenant-{tenantId}/project-{building?.ProjectId}/Activity/{fileName}"; + + await _s3Service.UploadFileAsync(base64, fileType, objectKey); + + var document = new Document + { + FileName = fileName, + ContentType = image.ContentType ?? string.Empty, + S3Key = objectKey, + Base64Data = image.Base64Data, + FileSize = image.FileSize, + UploadedAt = DateTime.UtcNow, + TenantId = tenantId + }; + + _context.Documents.Add(document); + + var attachment = new TaskAttachment + { + DocumentId = document.Id, + ReferenceId = comment.Id + }; + + _context.TaskAttachments.Add(attachment); + + _logger.LogInfo("Attachment uploaded for Task {TaskId}: {FileName}", approveTask.Id, fileName); + } + } + + // Commit all changes to the database + await _context.SaveChangesAsync(); + + _logger.LogInfo("Task {TaskId} successfully approved by Employee {EmployeeId}", approveTask.Id, loggedInEmployee.Id); + + return Ok(ApiResponse.SuccessResponse("Task has been approved", "Task has been approved", 200)); } } } From 1f5614314243069ccf3e79d3b711a6acea21df3f Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 16:24:49 +0530 Subject: [PATCH 2/6] Added new API to get list of work status --- .../Activities/CreateWorkStatusMasterDto.cs | 8 +++ .../Activities/UpdateWorkStatusMasterDto.cs | 9 +++ .../Controllers/MasterController.cs | 62 +++++++++++++++++++ Marco.Pms.Services/Helpers/MasterHelper.cs | 45 +++++++++++++- 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 Marco.Pms.Model/Dtos/Activities/CreateWorkStatusMasterDto.cs create mode 100644 Marco.Pms.Model/Dtos/Activities/UpdateWorkStatusMasterDto.cs diff --git a/Marco.Pms.Model/Dtos/Activities/CreateWorkStatusMasterDto.cs b/Marco.Pms.Model/Dtos/Activities/CreateWorkStatusMasterDto.cs new file mode 100644 index 0000000..b4ff25f --- /dev/null +++ b/Marco.Pms.Model/Dtos/Activities/CreateWorkStatusMasterDto.cs @@ -0,0 +1,8 @@ +namespace Marco.Pms.Model.Dtos.Master +{ + public class CreateWorkStatusMasterDto + { + public string? Name { get; set; } + public string? Description { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Activities/UpdateWorkStatusMasterDto.cs b/Marco.Pms.Model/Dtos/Activities/UpdateWorkStatusMasterDto.cs new file mode 100644 index 0000000..a40052f --- /dev/null +++ b/Marco.Pms.Model/Dtos/Activities/UpdateWorkStatusMasterDto.cs @@ -0,0 +1,9 @@ +namespace Marco.Pms.Model.Dtos.Master +{ + public class UpdateWorkStatusMasterDto + { + public Guid Id { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } + } +} diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index 7835e8d..4e6ad8f 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -671,6 +671,68 @@ namespace Marco.Pms.Services.Controllers } } + // -------------------------------- Work Status -------------------------------- + + [HttpGet("work-status")] + public async Task GetWorkStatusMasterList() + { + var response = await _masterHelper.GetWorkStatusList(); + return StatusCode(response.StatusCode, response); + } + + [HttpPost("work-status")] + public async Task CreateWorkStatusMaster([FromBody] CreateWorkStatusMasterDto createWorkStatusDto) + { + if (!ModelState.IsValid) + { + var errors = ModelState.Values + .SelectMany(v => v.Errors) + .Select(e => e.ErrorMessage) + .ToList(); + _logger.LogError("User sent Invalid Date while marking attendance"); + return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); + } + var response = await _masterHelper.CreateWorkStatus(createWorkStatusDto); + if (response.StatusCode == 200) + { + return Ok(response); + } + else if (response.StatusCode == 409) + { + return Conflict(response); + } + else + { + return BadRequest(response); + } + } + + [HttpPost("work-status/edit/{id}")] + public async Task UpdateWorkStatusMaster(Guid id, [FromBody] UpdateWorkStatusMasterDto updateWorkStatusDto) + { + var response = await _masterHelper.UpdateWorkStatus(id, updateWorkStatusDto); + if (response.StatusCode == 200) + { + return Ok(response); + } + else if (response.StatusCode == 404) + { + return NotFound(response); + } + else + { + return BadRequest(response); + + } + } + + [HttpDelete("work-status/{id}")] + public async Task DeleteWorkStatusMaster(Guid id) + { + var response = await _masterHelper.DeleteWorkStatus(id); + return Ok(response); + } + // -------------------------------- Contact Category -------------------------------- [HttpGet("contact-categories")] diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 60d2385..508205b 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -5,6 +5,7 @@ using Marco.Pms.Model.Employees; using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Master; +using Marco.Pms.Services.Service; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Service; using Microsoft.EntityFrameworkCore; @@ -16,13 +17,19 @@ namespace Marco.Pms.Services.Helpers private readonly ApplicationDbContext _context; private readonly ILoggingService _logger; private readonly UserHelper _userHelper; + private readonly PermissionServices _permissionService; + private readonly Guid View_Master; + private readonly Guid Manage_Master; - public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper) + public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permissionServices) { _context = context; _logger = logger; _userHelper = userHelper; + _permissionService = permissionServices; + View_Master = Guid.Parse("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"); + Manage_Master = Guid.Parse("588a8824-f924-4955-82d8-fc51956cf323"); } // -------------------------------- Contact Category -------------------------------- public async Task> CreateContactCategory(CreateContactCategoryDto contactCategoryDto) @@ -247,5 +254,41 @@ namespace Marco.Pms.Services.Helpers return ApiResponse.SuccessResponse(new { }, "Tag deleted successfully", 200); } + // -------------------------------- Work Status -------------------------------- + public async Task> GetWorkStatusList() + { + Guid tenantId = _userHelper.GetTenantId(); + var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + bool hasViewPermission = await _permissionService.HasPermission(View_Master, LoggedInEmployee.Id); + + if (!hasViewPermission) + { + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + var workStatus = await _context.WorkStatusMasters.Where(ws => ws.TenantId == tenantId).Select(ws => new { ws.Id, ws.Name, ws.Description, ws.IsSystem }).ToListAsync(); + + return ApiResponse.SuccessResponse(workStatus, $"{workStatus.Count} number of work status fetched successfully", 200); + + } + public async Task> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto) + { + Guid tenantId = _userHelper.GetTenantId(); + var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + public async Task> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto contacupdateWorkStatusDtotTagDto) + { + var tenantId = _userHelper.GetTenantId(); + Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + public async Task> DeleteWorkStatus(Guid id) + { + Guid tenantId = _userHelper.GetTenantId(); + var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + + } + } } From e391c82659de7862a1c132a3d7a329871b290843 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 16:58:56 +0530 Subject: [PATCH 3/6] Added CRUD operation APIs for work Status master table --- .../Controllers/MasterController.cs | 29 +-- Marco.Pms.Services/Helpers/MasterHelper.cs | 198 ++++++++++++++++-- 2 files changed, 181 insertions(+), 46 deletions(-) diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index 4e6ad8f..ebd8998 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -693,44 +693,21 @@ namespace Marco.Pms.Services.Controllers return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } var response = await _masterHelper.CreateWorkStatus(createWorkStatusDto); - if (response.StatusCode == 200) - { - return Ok(response); - } - else if (response.StatusCode == 409) - { - return Conflict(response); - } - else - { - return BadRequest(response); - } + return StatusCode(response.StatusCode, response); } [HttpPost("work-status/edit/{id}")] public async Task UpdateWorkStatusMaster(Guid id, [FromBody] UpdateWorkStatusMasterDto updateWorkStatusDto) { var response = await _masterHelper.UpdateWorkStatus(id, updateWorkStatusDto); - if (response.StatusCode == 200) - { - return Ok(response); - } - else if (response.StatusCode == 404) - { - return NotFound(response); - } - else - { - return BadRequest(response); - - } + return StatusCode(response.StatusCode, response); } [HttpDelete("work-status/{id}")] public async Task DeleteWorkStatusMaster(Guid id) { var response = await _masterHelper.DeleteWorkStatus(id); - return Ok(response); + return StatusCode(response.StatusCode, response); } // -------------------------------- Contact Category -------------------------------- diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 508205b..115b4b6 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -3,6 +3,7 @@ using Marco.Pms.Model.Directory; using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Mapper; +using Marco.Pms.Model.Master; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Services.Service; @@ -257,38 +258,195 @@ namespace Marco.Pms.Services.Helpers // -------------------------------- Work Status -------------------------------- public async Task> GetWorkStatusList() { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - bool hasViewPermission = await _permissionService.HasPermission(View_Master, LoggedInEmployee.Id); + _logger.LogInfo("GetWorkStatusList called."); - if (!hasViewPermission) + try { - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + // Step 1: Get tenant and logged-in employee info + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check permission to view master data + bool hasViewPermission = await _permissionService.HasPermission(View_Master, loggedInEmployee.Id); + if (!hasViewPermission) + { + _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + + // Step 3: Fetch work statuses for the tenant + var workStatusList = await _context.WorkStatusMasters + .Where(ws => ws.TenantId == tenantId) + .Select(ws => new + { + ws.Id, + ws.Name, + ws.Description, + ws.IsSystem + }) + .ToListAsync(); + + _logger.LogInfo("{Count} work statuses fetched for tenantId: {TenantId}", workStatusList.Count, tenantId); + + // Step 4: Return successful response + return ApiResponse.SuccessResponse( + workStatusList, + $"{workStatusList.Count} work status records fetched successfully", + 200 + ); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while fetching work status list : {Error}", ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to fetch work status list", 500); } - var workStatus = await _context.WorkStatusMasters.Where(ws => ws.TenantId == tenantId).Select(ws => new { ws.Id, ws.Name, ws.Description, ws.IsSystem }).ToListAsync(); - - return ApiResponse.SuccessResponse(workStatus, $"{workStatus.Count} number of work status fetched successfully", 200); - } public async Task> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto) { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogInfo("CreateWorkStatus called with Name: {Name}", createWorkStatusDto.Name ?? ""); + + try + { + // Step 1: Get tenant and logged-in employee + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check if user has permission to manage master data + var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManageMasterPermission) + { + _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + + // Step 3: Check if work status with the same name already exists + var existingWorkStatus = await _context.WorkStatusMasters + .FirstOrDefaultAsync(ws => ws.Name == createWorkStatusDto.Name && ws.TenantId == tenantId); + + if (existingWorkStatus != null) + { + _logger.LogWarning("Work status already exists: {Name}", createWorkStatusDto.Name ?? ""); + return ApiResponse.ErrorResponse("Work status already exists", "Work status already exists", 400); + } + + // Step 4: Create new WorkStatusMaster entry + var workStatus = new WorkStatusMaster + { + Name = createWorkStatusDto.Name?.Trim() ?? "", + Description = createWorkStatusDto.Description?.Trim() ?? "", + IsSystem = false, + TenantId = tenantId + }; + + _context.WorkStatusMasters.Add(workStatus); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Work status created successfully: {Id}, Name: {Name}", workStatus.Id, workStatus.Name); + return ApiResponse.SuccessResponse(workStatus, "Work status created successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while creating work status : {Error}", ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to create work status", 500); + } } - public async Task> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto contacupdateWorkStatusDtotTagDto) + public async Task> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto updateWorkStatusDto) { - var tenantId = _userHelper.GetTenantId(); - Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogInfo("UpdateWorkStatus called for WorkStatus ID: {Id}, New Name: {Name}", id, updateWorkStatusDto.Name ?? ""); + + try + { + // Step 1: Get tenant and employee info + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check permission to update master + var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManageMasterPermission) + { + _logger.LogWarning("Update denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + + // Step 3: Retrieve existing work status by id and tenant + var workStatus = await _context.WorkStatusMasters + .FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId); + + if (workStatus == null) + { + _logger.LogWarning("Work status not found for Id: {Id}", id); + return ApiResponse.ErrorResponse("Work status not found", "Work status not found", 404); + } + + // Step 4: Update fields + workStatus.Name = updateWorkStatusDto.Name?.Trim() ?? ""; + workStatus.Description = updateWorkStatusDto.Description?.Trim() ?? ""; + + await _context.SaveChangesAsync(); + + _logger.LogInfo("Work status updated successfully. Id: {Id}", workStatus.Id); + return ApiResponse.SuccessResponse(workStatus, "Work status updated successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while updating work status Id: {Id} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to update work status", 500); + } } public async Task> DeleteWorkStatus(Guid id) { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogInfo("DeleteWorkStatus called for Id: {Id}", id); + try + { + // Step 1: Get current tenant and logged-in employee + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check permission to manage master data + var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManageMasterPermission) + { + _logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Access denied for deleting work status", 403); + } + + // Step 3: Find the work status + var workStatus = await _context.WorkStatusMasters + .FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId); + + if (workStatus == null) + { + _logger.LogWarning("Work status not found for Id: {Id}", id); + return ApiResponse.ErrorResponse("Work status not found", "Work status not found", 404); + } + + // Step 4: Check for dependencies in TaskAllocations + bool hasDependency = await _context.TaskAllocations + .AnyAsync(ta => ta.TenantId == tenantId && ta.WorkStatusId == id); + + if (hasDependency) + { + _logger.LogWarning("Cannot delete WorkStatus Id: {Id} due to existing task dependency", id); + return ApiResponse.ErrorResponse( + "Work status has a dependency in assigned tasks and cannot be deleted", + "Deletion failed due to associated tasks", + 400 + ); + } + + // Step 5: Delete and persist + _context.WorkStatusMasters.Remove(workStatus); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Work status deleted successfully. Id: {Id}", id); + return ApiResponse.SuccessResponse(new { }, "Work status deleted successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while deleting WorkStatus Id: {Id} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to delete work status", 500); + } } - } } From ff9c7c94345b9c905622e5b334af18bddd5a1a22 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 17:19:59 +0530 Subject: [PATCH 4/6] Added code to validate the id received by path parameter with id received by payload --- Marco.Pms.Services/Helpers/MasterHelper.cs | 39 ++++++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 115b4b6..0698733 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -356,41 +356,58 @@ namespace Marco.Pms.Services.Helpers try { - // Step 1: Get tenant and employee info + // Step 1: Validate input + if (id == Guid.Empty || id != updateWorkStatusDto.Id) + { + _logger.LogWarning("Invalid ID provided for update. Route ID: {RouteId}, DTO ID: {DtoId}", id, updateWorkStatusDto.Id); + return ApiResponse.ErrorResponse("Invalid data provided", "The provided work status ID is invalid", 400); + } + + // Step 2: Get tenant and logged-in employee Guid tenantId = _userHelper.GetTenantId(); var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - // Step 2: Check permission to update master + // Step 3: Check permissions var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); if (!hasManageMasterPermission) { - _logger.LogWarning("Update denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access denied", "You do not have permission to update this work status", 403); } - // Step 3: Retrieve existing work status by id and tenant + // Step 4: Retrieve the work status record var workStatus = await _context.WorkStatusMasters .FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId); if (workStatus == null) { - _logger.LogWarning("Work status not found for Id: {Id}", id); - return ApiResponse.ErrorResponse("Work status not found", "Work status not found", 404); + _logger.LogWarning("Work status not found for ID: {Id}", id); + return ApiResponse.ErrorResponse("Work status not found", "No work status found with the provided ID", 404); } - // Step 4: Update fields + // Step 5: Check for duplicate name (optional) + var isDuplicate = await _context.WorkStatusMasters + .AnyAsync(ws => ws.Name == updateWorkStatusDto.Name && ws.Id != id && ws.TenantId == tenantId); + + if (isDuplicate) + { + _logger.LogWarning("Duplicate work status name '{Name}' detected during update. ID: {Id}", updateWorkStatusDto.Name ?? "", id); + return ApiResponse.ErrorResponse("Work status with the same name already exists", "Duplicate name", 400); + } + + // Step 6: Update fields workStatus.Name = updateWorkStatusDto.Name?.Trim() ?? ""; workStatus.Description = updateWorkStatusDto.Description?.Trim() ?? ""; await _context.SaveChangesAsync(); - _logger.LogInfo("Work status updated successfully. Id: {Id}", workStatus.Id); + _logger.LogInfo("Work status updated successfully. ID: {Id}", id); return ApiResponse.SuccessResponse(workStatus, "Work status updated successfully", 200); } catch (Exception ex) { - _logger.LogError("Error occurred while updating work status Id: {Id} : {Error}", id, ex.Message); - return ApiResponse.ErrorResponse("An error occurred", "Unable to update work status", 500); + _logger.LogError("Error occurred while updating work status ID: {Id} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to update the work status at this time", 500); } } public async Task> DeleteWorkStatus(Guid id) From 1c58265a9f666a5cadf735a469aea908a4bf2ead Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 18 Jun 2025 17:34:33 +0530 Subject: [PATCH 5/6] added new fields inside workItem- parentTaskId and Description --- ...orkItemForParentId_Description.Designer.cs | 3381 +++++++++++++++++ ...EnhancedWorkItemForParentId_Description.cs | 41 + .../ApplicationDbContextModelSnapshot.cs | 6 + Marco.Pms.Model/Dtos/Projects/WorkItemDot.cs | 2 + Marco.Pms.Model/Mapper/InfraMapper.cs | 4 +- Marco.Pms.Model/Projects/WorkItem.cs | 6 + Marco.Pms.Services/Helpers/DirectoryHelper.cs | 4 +- 7 files changed, 3441 insertions(+), 3 deletions(-) create mode 100644 Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs create mode 100644 Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.cs diff --git a/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs b/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs new file mode 100644 index 0000000..4d39cf1 --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.Designer.cs @@ -0,0 +1,3381 @@ +// +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("20250618112021_EnhancedWorkItemForParentId_Description")] + partial class EnhancedWorkItemForParentId_Description + { + /// + 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.HasKey("Id"); + + b.HasIndex("ContactCategoryId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + 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.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("TenantId"); + + 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.HasKey("Id"); + + b.HasIndex("TenantId"); + + 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("c7b68e33-72f0-474f-bd96-77636427ecc8"), + Description = "Grants a user comprehensive read-only access to all details concerning the project's underlying systems, technologies, resources, and configurations", + FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), + IsEnabled = true, + Name = "View Project Infra" + }, + new + { + Id = new Guid("f2aee20a-b754-4537-8166-f9507b44585b"), + Description = "This allows them to create, modify, and manage all aspects of the supporting infrastructure.", + FeatureId = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), + 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("b82d2b7e-0d52-45f3-997b-c008ea460e7f"), + Description = "Grants a user read-only access to details about the individuals within the system. This typically includes names, contact information, roles, departments, and potentially other relevant employee data", + FeatureId = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), + IsEnabled = true, + Name = "View Employee" + }, + 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" + }); + }); + + 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.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.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 = "Manage Project" + }, + new + { + Id = new Guid("9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c"), + Description = "Manage Infra", + IsActive = true, + ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), + Name = "Manage Infra" + }, + new + { + 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" + }, + new + { + Id = new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), + Description = "Global Masters", + IsActive = true, + ModuleId = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"), + Name = "Global 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.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("603e994b-a27f-4e5d-a251-f3d69b0498ba"), + Status = "In Progress", + TenantId = new Guid("b3466e83-7e11-464c-b93a-daf047838b26") + }, + new + { + Id = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"), + Status = "On Hold", + 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 = "#6c757d", + 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.Navigation("ContactCategory"); + + b.Navigation("CreatedBy"); + + b.Navigation("Tenant"); + }); + + 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.Navigation("Contact"); + + b.Navigation("Createdby"); + + b.Navigation("Tenant"); + }); + + 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.Navigation("Tenant"); + }); + + 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.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.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.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/20250618112021_EnhancedWorkItemForParentId_Description.cs b/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.cs new file mode 100644 index 0000000..c4a12fd --- /dev/null +++ b/Marco.Pms.DataAccess/Migrations/20250618112021_EnhancedWorkItemForParentId_Description.cs @@ -0,0 +1,41 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Marco.Pms.DataAccess.Migrations +{ + /// + public partial class EnhancedWorkItemForParentId_Description : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Description", + table: "WorkItems", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "ParentTaskId", + table: "WorkItems", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Description", + table: "WorkItems"); + + migrationBuilder.DropColumn( + name: "ParentTaskId", + table: "WorkItems"); + } + } +} diff --git a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs index 4988121..1f93208 100644 --- a/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Marco.Pms.DataAccess/Migrations/ApplicationDbContextModelSnapshot.cs @@ -2176,6 +2176,12 @@ namespace Marco.Pms.DataAccess.Migrations b.Property("CompletedWork") .HasColumnType("double"); + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ParentTaskId") + .HasColumnType("char(36)"); + b.Property("PlannedWork") .HasColumnType("double"); diff --git a/Marco.Pms.Model/Dtos/Projects/WorkItemDot.cs b/Marco.Pms.Model/Dtos/Projects/WorkItemDot.cs index c2fc990..e6ba436 100644 --- a/Marco.Pms.Model/Dtos/Projects/WorkItemDot.cs +++ b/Marco.Pms.Model/Dtos/Projects/WorkItemDot.cs @@ -11,5 +11,7 @@ namespace Marco.Pms.Model.Dtos.Project public Guid ActivityID { get; set; } public int PlannedWork { get; set; } public int CompletedWork { get; set; } + public Guid? ParentTaskId { get; set; } + public string? Comment { get; set; } } } diff --git a/Marco.Pms.Model/Mapper/InfraMapper.cs b/Marco.Pms.Model/Mapper/InfraMapper.cs index f6fec5b..4ccb7c8 100644 --- a/Marco.Pms.Model/Mapper/InfraMapper.cs +++ b/Marco.Pms.Model/Mapper/InfraMapper.cs @@ -59,7 +59,9 @@ namespace Marco.Pms.Model.Mapper WorkCategoryId = model.WorkCategoryId, TaskDate = DateTime.Now, TenantId = tenantId, - WorkAreaId = model.WorkAreaID + WorkAreaId = model.WorkAreaID, + ParentTaskId = model.ParentTaskId, + Description = model.Comment }; } diff --git a/Marco.Pms.Model/Projects/WorkItem.cs b/Marco.Pms.Model/Projects/WorkItem.cs index 150ffc2..9596dc3 100644 --- a/Marco.Pms.Model/Projects/WorkItem.cs +++ b/Marco.Pms.Model/Projects/WorkItem.cs @@ -20,11 +20,17 @@ namespace Marco.Pms.Model.Projects [ValidateNever] public ActivityMaster? ActivityMaster { get; set; } + [ForeignKey("WorkCategoryId")] [ValidateNever] public WorkCategoryMaster? WorkCategoryMaster { get; set; } + + public Guid? ParentTaskId { get; set; } + public double PlannedWork { get; set; } public double CompletedWork { get; set; } + + public string? Description { get; set; } public DateTime TaskDate { get; set; } } } diff --git a/Marco.Pms.Services/Helpers/DirectoryHelper.cs b/Marco.Pms.Services/Helpers/DirectoryHelper.cs index d34b0d3..d14e44c 100644 --- a/Marco.Pms.Services/Helpers/DirectoryHelper.cs +++ b/Marco.Pms.Services/Helpers/DirectoryHelper.cs @@ -903,11 +903,11 @@ namespace Marco.Pms.Services.Helpers List notes = new List(); if (active) { - notes = await _context.ContactNotes.Where(n => n.ContactId == contact.Id && n.IsActive && n.TenantId == tenantId).ToListAsync(); + notes = await _context.ContactNotes.Include(n => n.Createdby).Where(n => n.ContactId == contact.Id && n.IsActive && n.TenantId == tenantId).ToListAsync(); } else { - notes = await _context.ContactNotes.Where(n => n.ContactId == contact.Id && n.TenantId == tenantId).ToListAsync(); + notes = await _context.ContactNotes.Include(n => n.Createdby).Where(n => n.ContactId == contact.Id && n.TenantId == tenantId).ToListAsync(); } var noteIds = notes.Select(n => n.Id).ToList(); List? updateLogs = await _context.DirectoryUpdateLogs.Include(l => l.Employee).Where(l => noteIds.Contains(l.RefereanceId)).ToListAsync(); From aa2bc674eb66d0d480a3c47c2d076a106c27d6b3 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Wed, 18 Jun 2025 19:08:06 +0530 Subject: [PATCH 6/6] Optimized the task management API --- .../Controllers/ProjectController.cs | 97 +++++++++++-------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/Marco.Pms.Services/Controllers/ProjectController.cs b/Marco.Pms.Services/Controllers/ProjectController.cs index 18a790b..9f6d083 100644 --- a/Marco.Pms.Services/Controllers/ProjectController.cs +++ b/Marco.Pms.Services/Controllers/ProjectController.cs @@ -13,7 +13,6 @@ using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; namespace MarcoBMS.Services.Controllers { @@ -59,9 +58,9 @@ namespace MarcoBMS.Services.Controllers return Unauthorized(ApiResponse.ErrorResponse("Employee not found.", null, 401)); } - - List projects = await _projectsHelper.GetMyProjects(tenantId, LoggedInEmployee); - + + List projects = await _projectsHelper.GetMyProjects(tenantId, LoggedInEmployee); + // 4. Project projection to ProjectInfoVM // This part is already quite efficient. @@ -84,7 +83,7 @@ namespace MarcoBMS.Services.Controllers return Ok(ApiResponse.SuccessResponse(response, "Success.", 200)); } - + [HttpGet("list")] public async Task GetAll() @@ -573,45 +572,65 @@ namespace MarcoBMS.Services.Controllers } [HttpPost("task")] - public async Task CreateProjectTask(List workItemDot) + public async Task CreateProjectTask(List workItemDtos) { - Guid tenantId = GetTenantId(); - List workItems = new List { }; - string responseMessage = ""; - if (workItemDot != null) - { - foreach (var item in workItemDot) - { - WorkItem workItem = item.ToWorkItemFromWorkItemDto(tenantId); + _logger.LogInfo("CreateProjectTask called with {Count} items", workItemDtos?.Count ?? 0); - if (item.Id != null) - { - //update - _context.WorkItems.Update(workItem); - await _context.SaveChangesAsync(); - responseMessage = "Task Added Successfully"; - } - else - { - //create - _context.WorkItems.Add(workItem); - await _context.SaveChangesAsync(); - responseMessage = "Task Updated Successfully"; - } - var result = new WorkItemVM - { - WorkItemId = workItem.Id, - WorkItem = workItem - }; - workItems.Add(result); - } - var activity = await _context.ActivityMasters.ToListAsync(); - var category = await _context.WorkCategoryMasters.ToListAsync(); - return Ok(ApiResponse.SuccessResponse(workItems, responseMessage, 200)); + // Validate request + if (workItemDtos == null || !workItemDtos.Any()) + { + _logger.LogWarning("No work items provided in the request."); + return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Work Item details are not valid.", 400)); } - return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Work Item Details are not valid.", 400)); + Guid tenantId = GetTenantId(); + var workItemsToCreate = new List(); + var workItemsToUpdate = new List(); + var responseList = new List(); + foreach (var itemDto in workItemDtos) + { + var workItem = itemDto.ToWorkItemFromWorkItemDto(tenantId); + + if (itemDto.Id != null && itemDto.Id != Guid.Empty) + { + // Update existing + workItemsToUpdate.Add(workItem); + } + else + { + // Create new + workItem.Id = Guid.NewGuid(); + workItemsToCreate.Add(workItem); + } + + responseList.Add(new WorkItemVM + { + WorkItemId = workItem.Id, + WorkItem = workItem + }); + } + + // Apply DB changes + if (workItemsToCreate.Any()) + { + _logger.LogInfo("Adding {Count} new work items", workItemsToCreate.Count); + await _context.WorkItems.AddRangeAsync(workItemsToCreate); + } + + if (workItemsToUpdate.Any()) + { + _logger.LogInfo("Updating {Count} existing work items", workItemsToUpdate.Count); + _context.WorkItems.UpdateRange(workItemsToUpdate); + } + + await _context.SaveChangesAsync(); + + _logger.LogInfo("CreateProjectTask completed successfully. Created: {Created}, Updated: {Updated}", workItemsToCreate.Count, workItemsToUpdate.Count); + + string responseMessage = $"{(workItemsToCreate.Any() ? "Task(s) created" : "")}{(workItemsToUpdate.Any() ? (workItemsToCreate.Any() ? " and " : "") + "updated" : "")} successfully."; + + return Ok(ApiResponse.SuccessResponse(responseList, responseMessage, 200)); } [HttpDelete("task/{id}")]