From 5d5579882f3c4715bb67321c68c9f31fb7edfda1 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 15:57:04 +0530 Subject: [PATCH] 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 a168483..66e9f51 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; } @@ -434,6 +435,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 187d2a6..9bf43db 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"); }); @@ -1926,6 +1950,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") @@ -2435,12 +2512,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") @@ -2453,11 +2538,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 => @@ -3058,6 +3153,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)); } } }