diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..00951a5 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,21 @@ +name: Deploy to EC2 +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: SSH and deploy + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + key: ${{ secrets.EC2_KEY }} + script: | + cd /home/ec2-user/ValuationBackend + git pull + dotnet restore + sudo dotnet publish -c Release -o /var/app + sudo systemctl restart valuation-backend diff --git a/Controllers/ImageDataController.cs b/Controllers/ImageDataController.cs index 9f07966..e6b12bc 100644 --- a/Controllers/ImageDataController.cs +++ b/Controllers/ImageDataController.cs @@ -19,7 +19,7 @@ public ImageDataController(AppDbContext context) [HttpPost] public IActionResult SendImageData([FromBody] SendImageDataRequest request) { - if (string.IsNullOrWhiteSpace(request.ReportId) || request.Images == null || !request.Images.Any()) + if (request.ReportId <= 0 || request.Images == null || !request.Images.Any()) { return BadRequest("Missing reportId or images."); } @@ -38,9 +38,9 @@ public IActionResult SendImageData([FromBody] SendImageDataRequest request) // ✅ 2. Accept actual image files via form-data [HttpPost("upload")] - public async Task UploadImages([FromForm] string reportId, [FromForm] List files) + public async Task UploadImages([FromForm] int reportId, [FromForm] List files) { - if (string.IsNullOrWhiteSpace(reportId) || files == null || !files.Any()) + if (reportId <= 0 || files == null || !files.Any()) return BadRequest("Missing reportId or files."); foreach (var file in files) diff --git a/Controllers/LAMasterfileController.cs b/Controllers/LAMasterfileController.cs index 05f983a..e6fa967 100644 --- a/Controllers/LAMasterfileController.cs +++ b/Controllers/LAMasterfileController.cs @@ -16,33 +16,33 @@ public LAMasterfileController(ILAMasterfileService service) } [HttpGet] - public ActionResult GetAll([FromQuery] int pageNumber = 0, [FromQuery] int pageSize = 15) + public ActionResult GetAll([FromQuery] int pageNumber = 0, [FromQuery] int pageSize = 15, [FromQuery] string sortBy = "", [FromQuery] int? assignedToUserId = null) { // Adjust pageNumber to be 1-based for internal logic var page = pageNumber + 1; - return Ok(_service.GetPaged(page, pageSize)); + return Ok(_service.GetPaged(page, pageSize, sortBy, assignedToUserId)); } [HttpGet("paged")] - public ActionResult GetPaged([FromQuery] int page = 1, [FromQuery] int pageSize = 10) + public ActionResult GetPaged([FromQuery] int page = 1, [FromQuery] int pageSize = 10, [FromQuery] string sortBy = "", [FromQuery] int? assignedToUserId = null) { - return Ok(_service.GetPaged(page, pageSize)); + return Ok(_service.GetPaged(page, pageSize, sortBy, assignedToUserId)); } [HttpPost("search")] [HttpPost("filter")] - public ActionResult Search([FromBody] LAQueryRequest request) + public ActionResult Search([FromBody] LAQueryRequest request, [FromQuery] string sortBy = "", [FromQuery] int? assignedToUserId = null) { var query = request.Query.ToLower(); - var response = _service.Search(query); + var response = _service.Search(query, sortBy, assignedToUserId); return Ok(response); } [HttpPost("search/paged")] - public ActionResult SearchPaged([FromBody] LAQueryRequest request, [FromQuery] int page = 1, [FromQuery] int pageSize = 10) + public ActionResult SearchPaged([FromBody] LAQueryRequest request, [FromQuery] int page = 1, [FromQuery] int pageSize = 10, [FromQuery] string sortBy = "", [FromQuery] int? assignedToUserId = null) { var query = request.Query.ToLower(); - var response = _service.SearchPaged(query, page, pageSize); + var response = _service.SearchPaged(query, page, pageSize, sortBy, assignedToUserId); return Ok(response); } } diff --git a/Controllers/ProfileController.cs b/Controllers/ProfileController.cs index 4e9877f..384ddd1 100644 --- a/Controllers/ProfileController.cs +++ b/Controllers/ProfileController.cs @@ -28,7 +28,8 @@ public IActionResult GetUserProfile([FromBody] UserProfileRequest request) empEmail = user.EmpEmail, empId = user.EmpId, position = user.Position, - assignedDivision = user.AssignedDivision + assignedDivision = user.AssignedDivision, + profilePicture = user.ProfilePicture != null ? Convert.ToBase64String(user.ProfilePicture) : null }); } } diff --git a/Controllers/UserProfileController.cs b/Controllers/UserProfileController.cs new file mode 100644 index 0000000..e3766fe --- /dev/null +++ b/Controllers/UserProfileController.cs @@ -0,0 +1,43 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using ValuationBackend.Data; + +namespace ValuationBackend.Controllers +{ + public class ProfilePictureUploadDto + { + public int UserId { get; set; } + public IFormFile Image { get; set; } + } + + [ApiController] + [Route("api/[controller]")] + public class UserProfileController : ControllerBase + { + private readonly AppDbContext _context; + + public UserProfileController(AppDbContext context) + { + _context = context; + } + + [HttpPost("upload-profile-picture")] + public async Task UploadProfilePicture([FromForm] ProfilePictureUploadDto dto) + { + if (dto.Image == null || dto.Image.Length == 0) + return BadRequest("No image uploaded."); + + var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == dto.UserId); + if (user == null) + return NotFound("User not found."); + + using var ms = new MemoryStream(); + await dto.Image.CopyToAsync(ms); + user.ProfilePicture = ms.ToArray(); + + await _context.SaveChangesAsync(); + + return Ok("Profile picture updated."); + } + } +} \ No newline at end of file diff --git a/Data/DBInitializer.cs b/Data/DBInitializer.cs index 2099030..5716f1d 100644 --- a/Data/DBInitializer.cs +++ b/Data/DBInitializer.cs @@ -32,7 +32,7 @@ public static void Initialize(AppDbContext context) UpdateUserTaskUserIds(context); // Remove UserTasks that are not LM (Land Miscellaneous) - RemoveNonLMUserTasks(context); + // RemoveNonLMUserTasks(context); // Initialize Master Data InitializeMasterData(context); // Initialize Land Aquisition Master Files diff --git a/Migrations/20250720082954_AddProfilePictureToUser.Designer.cs b/Migrations/20250720082954_AddProfilePictureToUser.Designer.cs new file mode 100644 index 0000000..41010fa --- /dev/null +++ b/Migrations/20250720082954_AddProfilePictureToUser.Designer.cs @@ -0,0 +1,1713 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using ValuationBackend.Data; + +#nullable disable + +namespace ValuationBackend.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20250720082954_AddProfilePictureToUser")] + partial class AddProfilePictureToUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LandAquisitionMasterFile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("MasterFileNo") + .HasColumnType("integer"); + + b.Property("MasterFilesRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("PlanNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("PlanType") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequestingAuthorityReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LandAquisitionMasterFiles"); + }); + + modelBuilder.Entity("ValuationBackend.Models.Asset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssetNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("integer"); + + b.Property("IsRatingCard") + .HasColumnType("boolean"); + + b.Property("Owner") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RdSt") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequestId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Ward") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("Id"); + + b.HasIndex("RequestId"); + + b.ToTable("Assets"); + }); + + modelBuilder.Entity("ValuationBackend.Models.AssetDivision", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Area") + .HasColumnType("numeric"); + + b.Property("AssetId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("LandType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NewAssetNo") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AssetId"); + + b.ToTable("AssetDivisions"); + }); + + modelBuilder.Entity("ValuationBackend.Models.AssetNumberChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChangedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfChange") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("FieldSize") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("FieldType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("NewAssetNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OldAssetNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Reason") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("AssetNumberChanges"); + }); + + modelBuilder.Entity("ValuationBackend.Models.BuildingRatesLA", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssessmentNumber") + .HasColumnType("text"); + + b.Property("ConstructedBy") + .HasColumnType("text"); + + b.Property("Cost") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DescriptionOfProperty") + .HasColumnType("text"); + + b.Property("FloorAreaSQFT") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("MasterFileId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Owner") + .HasColumnType("text"); + + b.Property("RatePerSQFT") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("YearOfConstruction") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("BuildingRatesLA"); + }); + + modelBuilder.Entity("ValuationBackend.Models.ConditionReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccessCategory") + .IsRequired() + .HasColumnType("text"); + + b.Property("AccessCategoryDescription") + .IsRequired() + .HasColumnType("text"); + + b.Property("AcquiredExtent") + .IsRequired() + .HasColumnType("text"); + + b.Property("AcquiringOfficerSignature") + .IsRequired() + .HasColumnType("text"); + + b.Property("AcquisitionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("AssessmentNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("AtLotNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("AtPlanNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BoundaryBottom") + .IsRequired() + .HasColumnType("text"); + + b.Property("BoundaryEast") + .IsRequired() + .HasColumnType("text"); + + b.Property("BoundaryNorth") + .IsRequired() + .HasColumnType("text"); + + b.Property("BoundarySouth") + .IsRequired() + .HasColumnType("text"); + + b.Property("BoundaryWest") + .IsRequired() + .HasColumnType("text"); + + b.Property("BuildingDescription") + .IsRequired() + .HasColumnType("text"); + + b.Property("BuildingInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChiefValuerRepresentativeSignature") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfSection3BA") + .IsRequired() + .HasColumnType("text"); + + b.Property("DatePrepared") + .IsRequired() + .HasColumnType("text"); + + b.Property("DepthOfLand") + .IsRequired() + .HasColumnType("text"); + + b.Property("DescriptionOfLand") + .IsRequired() + .HasColumnType("text"); + + b.Property("DetailsOfBusiness") + .IsRequired() + .HasColumnType("text"); + + b.Property("Frontage") + .IsRequired() + .HasColumnType("text"); + + b.Property("GramasewakaSignature") + .IsRequired() + .HasColumnType("text"); + + b.Property("LandUseDescription") + .IsRequired() + .HasColumnType("text"); + + b.Property("LandUseType") + .IsRequired() + .HasColumnType("text"); + + b.Property("LevelWithAccess") + .IsRequired() + .HasColumnType("text"); + + b.Property("MasterFileId") + .IsRequired() + .HasColumnType("text"); + + b.Property("NameOfTheLand") + .IsRequired() + .HasColumnType("text"); + + b.Property("NameOfTheVillage") + .IsRequired() + .HasColumnType("text"); + + b.Property("OtherConstructionsDescription") + .IsRequired() + .HasColumnType("text"); + + b.Property("OtherConstructionsInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("PlantationDetails") + .IsRequired() + .HasColumnType("text"); + + b.Property("PpCadLotNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("PpCadNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("RoadName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("ConditionReports"); + }); + + modelBuilder.Entity("ValuationBackend.Models.DomesticRatingCard", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Access") + .HasColumnType("text"); + + b.Property("Age") + .HasColumnType("integer"); + + b.Property("AssetId") + .HasColumnType("integer"); + + b.Property("Condition") + .HasColumnType("text"); + + b.Property("Conveniences") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Floor") + .HasColumnType("text"); + + b.Property("NewNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("Occupier") + .HasColumnType("text"); + + b.Property("Owner") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParkingSpace") + .HasColumnType("text"); + + b.Property("Plantations") + .HasColumnType("text"); + + b.Property("PropertySubCategory") + .HasColumnType("text"); + + b.Property("PropertyType") + .HasColumnType("text"); + + b.Property("RentPM") + .HasColumnType("numeric"); + + b.Property("RoadName") + .HasColumnType("text"); + + b.Property("SelectWalls") + .HasColumnType("text"); + + b.Property("SuggestedRate") + .HasColumnType("numeric"); + + b.Property("Terms") + .HasColumnType("text"); + + b.Property("TsBop") + .HasColumnType("text"); + + b.Property("WardNumber") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AssetId"); + + b.ToTable("DomesticRatingCards"); + }); + + modelBuilder.Entity("ValuationBackend.Models.ImageData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ImageBase64") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ImageData"); + }); + + modelBuilder.Entity("ValuationBackend.Models.InspectionBuilding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AgeYears") + .HasColumnType("text"); + + b.Property("BathroomToilet") + .HasColumnType("text"); + + b.Property("BathroomToiletDoorsFittings") + .HasColumnType("text"); + + b.Property("BuildingCategory") + .HasColumnType("text"); + + b.Property("BuildingClass") + .HasColumnType("text"); + + b.Property("BuildingConditions") + .HasColumnType("text"); + + b.Property("BuildingId") + .HasColumnType("text"); + + b.Property("BuildingName") + .HasColumnType("text"); + + b.Property("Ceiling") + .HasColumnType("text"); + + b.Property("Condition") + .HasColumnType("text"); + + b.Property("Conveniences") + .HasColumnType("text"); + + b.Property("Design") + .HasColumnType("text"); + + b.Property("DetailOfBuilding") + .HasColumnType("text"); + + b.Property("Door") + .HasColumnType("text"); + + b.Property("ExpectedLifePeriodYears") + .HasColumnType("text"); + + b.Property("FloorFinisher") + .HasColumnType("text"); + + b.Property("FloorStructure") + .HasColumnType("text"); + + b.Property("FoundationStructure") + .HasColumnType("text"); + + b.Property("HandRail") + .HasColumnType("text"); + + b.Property("InspectionReportId") + .HasColumnType("integer"); + + b.Property("NatureOfConstruction") + .HasColumnType("text"); + + b.Property("NoOfFloorsAboveGround") + .HasColumnType("text") + .HasColumnName("NoOfFloorsAboveGround"); + + b.Property("NoOfFloorsBelowGround") + .HasColumnType("text") + .HasColumnName("NoOfFloorsBelowGround"); + + b.Property("OtherDoors") + .HasColumnType("text"); + + b.Property("PantryCupboard") + .HasColumnType("text"); + + b.Property("ParkingSpace") + .HasColumnType("text"); + + b.Property("RoofFinisher") + .HasColumnType("text"); + + b.Property("RoofFrame") + .HasColumnType("text"); + + b.Property("RoofMaterial") + .HasColumnType("text"); + + b.Property("Services") + .HasColumnType("text"); + + b.Property("Structure") + .HasColumnType("text"); + + b.Property("WallFinisher") + .HasColumnType("text"); + + b.Property("WallStructure") + .HasColumnType("text"); + + b.Property("Window") + .HasColumnType("text"); + + b.Property("WindowProtection") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("InspectionReportId"); + + b.ToTable("InspectionBuildings"); + }); + + modelBuilder.Entity("ValuationBackend.Models.InspectionReport", b => + { + b.Property("InspectionReportId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InspectionReportId")); + + b.Property("DetailsOfAssestsInventoryItems") + .HasColumnType("text") + .HasColumnName("DetailsOfAssestsInventoryItems"); + + b.Property("DetailsOfBusiness") + .HasColumnType("text"); + + b.Property("District") + .HasColumnType("text"); + + b.Property("DsDivision") + .HasColumnType("text"); + + b.Property("GnDivision") + .HasColumnType("text"); + + b.Property("InspectionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("MasterFileId") + .IsRequired() + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("OtherConstructionDetails") + .HasColumnType("text"); + + b.Property("OtherInformation") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Remark") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Village") + .HasColumnType("text"); + + b.HasKey("InspectionReportId"); + + b.HasIndex("ReportId"); + + b.ToTable("InspectionReports"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMBuildingRates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssessmentNumber") + .HasColumnType("text"); + + b.Property("ConstructedBy") + .HasColumnType("text"); + + b.Property("Cost") + .HasColumnType("text"); + + b.Property("DescriptionOfProperty") + .HasColumnType("text"); + + b.Property("FloorArea") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Owner") + .HasColumnType("text"); + + b.Property("RatePerSQFT") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("YearOfConstruction") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("LMBuildingRates"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMPastValuation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateOfValuation") + .HasColumnType("text"); + + b.Property("Extent") + .HasColumnType("text"); + + b.Property("FileNo_GnDivision") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("PlanOfParticulars") + .HasColumnType("text"); + + b.Property("PurposeOfValuation") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("text"); + + b.Property("RateType") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Situation") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("LMPastValuations"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMRentalEvidence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssessmentNo") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("FloorRate") + .HasColumnType("text"); + + b.Property("HeadOfTerms") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Occupier") + .HasColumnType("text"); + + b.Property("Owner") + .HasColumnType("text"); + + b.Property("RatePer") + .HasColumnType("text"); + + b.Property("RatePerMonth") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Situation") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("LMRentalEvidences"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMSalesEvidence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssetNumber") + .HasColumnType("text"); + + b.Property("Consideration") + .HasColumnType("text"); + + b.Property("DeedAttestedNumber") + .HasColumnType("text"); + + b.Property("DeedNumber") + .HasColumnType("text"); + + b.Property("DescriptionOfProperty") + .HasColumnType("text"); + + b.Property("Extent") + .HasColumnType("text"); + + b.Property("LandRegistryReferences") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("LotNumber") + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("NotaryName") + .HasColumnType("text"); + + b.Property("PlanDate") + .HasColumnType("text"); + + b.Property("PlanNumber") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("text"); + + b.Property("RateType") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Road") + .HasColumnType("text"); + + b.Property("Situation") + .HasColumnType("text"); + + b.Property("Vendor") + .HasColumnType("text"); + + b.Property("Village") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("LMSalesEvidences"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LandMiscellaneousMasterFile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Lots") + .HasColumnType("integer"); + + b.Property("MasterFileNo") + .HasColumnType("integer"); + + b.Property("PlanNo") + .HasColumnType("text"); + + b.Property("PlanType") + .HasColumnType("text"); + + b.Property("RequestingAuthorityReferenceNo") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LandMiscellaneousMasterFiles"); + }); + + modelBuilder.Entity("ValuationBackend.Models.MasterDataItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MasterDataItems"); + }); + + modelBuilder.Entity("ValuationBackend.Models.PastValuationsLA", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfValuation") + .HasColumnType("text"); + + b.Property("Extent") + .HasColumnType("text"); + + b.Property("FileNoGNDivision") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("MasterFileId") + .IsRequired() + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("PlanOfParticulars") + .HasColumnType("text"); + + b.Property("PurposeOfValuation") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("text"); + + b.Property("RateType") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Situation") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("PastValuationsLA"); + }); + + modelBuilder.Entity("ValuationBackend.Models.PropertyCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("PropertyCategories"); + }); + + modelBuilder.Entity("ValuationBackend.Models.RatingRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LocalAuthority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RatingReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequestType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("YearOfRevision") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("RatingRequests"); + }); + + modelBuilder.Entity("ValuationBackend.Models.Reconciliation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssetId") + .HasColumnType("integer"); + + b.Property("NewNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ObsoleteNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("StreetName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AssetId"); + + b.ToTable("Reconciliations"); + }); + + modelBuilder.Entity("ValuationBackend.Models.RentalEvidenceLA", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssessmentNo") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("FloorRateSQFT") + .HasColumnType("text"); + + b.Property("HeadOfTerms") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("MasterFileId") + .IsRequired() + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Occupier") + .HasColumnType("text"); + + b.Property("Owner") + .HasColumnType("text"); + + b.Property("RatePerMonth") + .HasColumnType("text"); + + b.Property("RatePerSqft") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Situation") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("RentalEvidencesLA", (string)null); + }); + + modelBuilder.Entity("ValuationBackend.Models.Report", b => + { + b.Property("ReportId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReportId")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ReportId"); + + b.ToTable("Reports"); + }); + + modelBuilder.Entity("ValuationBackend.Models.Request", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LocalAuthority") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RatingReferenceNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RequestTypeId") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("YearOfRevision") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("RequestTypeId"); + + b.ToTable("Requests"); + }); + + modelBuilder.Entity("ValuationBackend.Models.RequestType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("RequestTypes"); + }); + + modelBuilder.Entity("ValuationBackend.Models.SalesEvidenceLA", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssetNumber") + .HasColumnType("text"); + + b.Property("Consideration") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeedAttestedNumber") + .HasColumnType("text"); + + b.Property("DeedNumber") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DescriptionOfProperty") + .HasColumnType("text"); + + b.Property("Extent") + .HasColumnType("text"); + + b.Property("FloorRate") + .HasColumnType("text"); + + b.Property("LandRegistryReferences") + .HasColumnType("text"); + + b.Property("LocationLatitude") + .HasColumnType("text"); + + b.Property("LocationLongitude") + .HasColumnType("text"); + + b.Property("LotNumber") + .HasColumnType("text"); + + b.Property("MasterFileId") + .IsRequired() + .HasColumnType("text"); + + b.Property("MasterFileRefNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("NotaryName") + .HasColumnType("text"); + + b.Property("Occupier") + .HasColumnType("text"); + + b.Property("Owner") + .HasColumnType("text"); + + b.Property("PlanDate") + .HasColumnType("text"); + + b.Property("PlanNumber") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("text"); + + b.Property("RateType") + .HasColumnType("text"); + + b.Property("Remarks") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("integer"); + + b.Property("Road") + .HasColumnType("text"); + + b.Property("Situation") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Vendor") + .HasColumnType("text"); + + b.Property("Village") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.ToTable("SalesEvidencesLA", (string)null); + }); + + modelBuilder.Entity("ValuationBackend.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssignedDivision") + .IsRequired() + .HasColumnType("text"); + + b.Property("EmpEmail") + .IsRequired() + .HasColumnType("text"); + + b.Property("EmpId") + .IsRequired() + .HasColumnType("text"); + + b.Property("EmpName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("PasswordSalt") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("Position") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProfilePicture") + .HasColumnType("bytea"); + + b.Property("Username") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("ValuationBackend.Models.UserTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssignedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("IsCompleted") + .HasColumnType("boolean"); + + b.Property("LandAcquisitionId") + .HasColumnType("integer"); + + b.Property("LandMiscellaneousId") + .HasColumnType("integer"); + + b.Property("ReferenceNumber") + .HasColumnType("text"); + + b.Property("RequestId") + .HasColumnType("integer"); + + b.Property("TaskType") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Username") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkItemDescription") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserTasks"); + }); + + modelBuilder.Entity("ValuationBackend.Models.Asset", b => + { + b.HasOne("ValuationBackend.Models.Request", "Request") + .WithMany() + .HasForeignKey("RequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Request"); + }); + + modelBuilder.Entity("ValuationBackend.Models.AssetDivision", b => + { + b.HasOne("ValuationBackend.Models.Asset", "Asset") + .WithMany() + .HasForeignKey("AssetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Asset"); + }); + + modelBuilder.Entity("ValuationBackend.Models.BuildingRatesLA", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.ConditionReport", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.DomesticRatingCard", b => + { + b.HasOne("ValuationBackend.Models.Asset", "Asset") + .WithMany() + .HasForeignKey("AssetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Asset"); + }); + + modelBuilder.Entity("ValuationBackend.Models.InspectionBuilding", b => + { + b.HasOne("ValuationBackend.Models.InspectionReport", "InspectionReport") + .WithMany("Buildings") + .HasForeignKey("InspectionReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("InspectionReport"); + }); + + modelBuilder.Entity("ValuationBackend.Models.InspectionReport", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMBuildingRates", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMPastValuation", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMRentalEvidence", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.LMSalesEvidence", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.PastValuationsLA", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.Reconciliation", b => + { + b.HasOne("ValuationBackend.Models.Asset", "Asset") + .WithMany() + .HasForeignKey("AssetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Asset"); + }); + + modelBuilder.Entity("ValuationBackend.Models.RentalEvidenceLA", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.Request", b => + { + b.HasOne("ValuationBackend.Models.RequestType", "RequestType") + .WithMany() + .HasForeignKey("RequestTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RequestType"); + }); + + modelBuilder.Entity("ValuationBackend.Models.SalesEvidenceLA", b => + { + b.HasOne("ValuationBackend.Models.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Report"); + }); + + modelBuilder.Entity("ValuationBackend.Models.UserTask", b => + { + b.HasOne("ValuationBackend.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ValuationBackend.Models.InspectionReport", b => + { + b.Navigation("Buildings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20250720082954_AddProfilePictureToUser.cs b/Migrations/20250720082954_AddProfilePictureToUser.cs new file mode 100644 index 0000000..ae9c3de --- /dev/null +++ b/Migrations/20250720082954_AddProfilePictureToUser.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ValuationBackend.Migrations +{ + /// + public partial class AddProfilePictureToUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Migrations/AppDbContextModelSnapshot.cs b/Migrations/AppDbContextModelSnapshot.cs index fadf802..bf53bd9 100644 --- a/Migrations/AppDbContextModelSnapshot.cs +++ b/Migrations/AppDbContextModelSnapshot.cs @@ -515,9 +515,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); - b.Property("ReportId") - .IsRequired() - .HasColumnType("text"); + b.Property("ReportId") + .HasColumnType("integer"); b.HasKey("Id"); @@ -1455,6 +1454,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("ProfilePicture") + .HasColumnType("bytea"); + b.Property("Username") .IsRequired() .HasColumnType("text"); diff --git a/Models/ImageData.cs b/Models/ImageData.cs index 5eb9da1..a591d05 100644 --- a/Models/ImageData.cs +++ b/Models/ImageData.cs @@ -1,15 +1,17 @@ +using System.ComponentModel.DataAnnotations.Schema; + namespace ValuationBackend.Models { public class ImageData { public int Id { get; set; } - public string ReportId { get; set; } = string.Empty; + public int ReportId { get; set; } // Changed to int to match Reports.ReportId public string ImageBase64 { get; set; } = string.Empty; } public class SendImageDataRequest { - public string ReportId { get; set; } = string.Empty; + public int ReportId { get; set; } // Changed to int public List Images { get; set; } = new(); } } diff --git a/Models/LAMasterfileResponse.cs b/Models/LAMasterfileResponse.cs index 8238a13..43dfa25 100644 --- a/Models/LAMasterfileResponse.cs +++ b/Models/LAMasterfileResponse.cs @@ -11,5 +11,7 @@ public class LAMasterfileResponse public int TotalPages { get; set; } public bool HasPrevious => CurrentPage > 1; public bool HasNext => CurrentPage < TotalPages; + public string? SortBy { get; set; } + public string? SearchTerm { get; set; } } } \ No newline at end of file diff --git a/Models/LoginModels.cs b/Models/LoginModels.cs index c978556..7540db1 100644 --- a/Models/LoginModels.cs +++ b/Models/LoginModels.cs @@ -13,6 +13,8 @@ public class User public required string EmpId { get; set; } public required string Position { get; set; } public required string AssignedDivision { get; set; } + + public byte[]? ProfilePicture { get; set; } } public class LoginRequest diff --git a/repositories/ILAMasterfileRepository.cs b/repositories/ILAMasterfileRepository.cs index d056652..24d2b8a 100644 --- a/repositories/ILAMasterfileRepository.cs +++ b/repositories/ILAMasterfileRepository.cs @@ -5,9 +5,9 @@ namespace ValuationBackend.Repositories { public interface ILAMasterfileRepository { - List GetAll(); - (List Items, int TotalCount) GetPaged(int page, int pageSize); - List Search(string query); - (List Items, int TotalCount) SearchPaged(string query, int page, int pageSize); + List GetAll(string sortBy = "", int? assignedToUserId = null); + (List Items, int TotalCount) GetPaged(int page, int pageSize, string sortBy = "", int? assignedToUserId = null); + List Search(string query, string sortBy = "", int? assignedToUserId = null); + (List Items, int TotalCount) SearchPaged(string query, int page, int pageSize, string sortBy = "", int? assignedToUserId = null); } } diff --git a/repositories/LAMasterfileRepository.cs b/repositories/LAMasterfileRepository.cs index bb3a231..5e629d7 100644 --- a/repositories/LAMasterfileRepository.cs +++ b/repositories/LAMasterfileRepository.cs @@ -13,14 +13,19 @@ public LAMasterfileRepository(AppDbContext context) _context = context; } - public List GetAll() + public List GetAll(string sortBy = "", int? assignedToUserId = null) { - return _context.LandAquisitionMasterFiles.ToList(); + var query = _context.LandAquisitionMasterFiles.AsQueryable(); + query = ApplyUserFiltering(query, assignedToUserId); + query = ApplySorting(query, sortBy); + return query.ToList(); } - public (List Items, int TotalCount) GetPaged(int page, int pageSize) + public (List Items, int TotalCount) GetPaged(int page, int pageSize, string sortBy = "", int? assignedToUserId = null) { - var query = _context.LandAquisitionMasterFiles; + var query = _context.LandAquisitionMasterFiles.AsQueryable(); + query = ApplyUserFiltering(query, assignedToUserId); + query = ApplySorting(query, sortBy); var totalCount = query.Count(); var items = query.Skip((page - 1) * pageSize) .Take(pageSize) @@ -28,21 +33,22 @@ public List GetAll() return (items, totalCount); } - public List Search(string query) + public List Search(string query, string sortBy = "", int? assignedToUserId = null) { query = query.ToLower(); - return _context - .LandAquisitionMasterFiles.Where(f => - f.MasterFileNo.ToString().Contains(query) - || f.PlanNo.ToLower().Contains(query) - || f.PlanType.ToLower().Contains(query) - || f.RequestingAuthorityReferenceNo.ToLower().Contains(query) - || f.Status.ToLower().Contains(query) - ) - .ToList(); + var baseQuery = _context.LandAquisitionMasterFiles.Where(f => + f.MasterFileNo.ToString().Contains(query) + || f.PlanNo.ToLower().Contains(query) + || f.PlanType.ToLower().Contains(query) + || f.RequestingAuthorityReferenceNo.ToLower().Contains(query) + || f.Status.ToLower().Contains(query) + ); + baseQuery = ApplyUserFiltering(baseQuery, assignedToUserId); + baseQuery = ApplySorting(baseQuery, sortBy); + return baseQuery.ToList(); } - public (List Items, int TotalCount) SearchPaged(string query, int page, int pageSize) + public (List Items, int TotalCount) SearchPaged(string query, int page, int pageSize, string sortBy = "", int? assignedToUserId = null) { query = query.ToLower(); var baseQuery = _context.LandAquisitionMasterFiles @@ -53,12 +59,45 @@ public List Search(string query) f.PlanType.ToLower().Contains(query) || f.RequestingAuthorityReferenceNo.ToLower().Contains(query) || f.Status.ToLower().Contains(query)); - + baseQuery = ApplyUserFiltering(baseQuery, assignedToUserId); + baseQuery = ApplySorting(baseQuery, sortBy); var totalCount = baseQuery.Count(); var items = baseQuery.Skip((page - 1) * pageSize) .Take(pageSize) .ToList(); return (items, totalCount); } + + private IQueryable ApplySorting(IQueryable query, string sortBy) + { + if (string.IsNullOrWhiteSpace(sortBy)) + { + return query.OrderBy(x => x.Id); // Default sorting + } + + return sortBy.ToLower() switch + { + "id" => query.OrderBy(x => x.Id), + "masterfileno" => query.OrderBy(x => x.MasterFileNo), + "plantype" => query.OrderBy(x => x.PlanType), + "planno" => query.OrderBy(x => x.PlanNo), + "requestingauthorityreferenceno" => query.OrderBy(x => x.RequestingAuthorityReferenceNo), + "status" => query.OrderBy(x => x.Status), + _ => query.OrderBy(x => x.Id) // Default fallback + }; + } + + private IQueryable ApplyUserFiltering(IQueryable query, int? assignedToUserId) + { + if (!assignedToUserId.HasValue) + { + return query; // No filtering if no user specified + } + // Join with UserTasks to filter by assigned user ID for LA tasks + return query.Where(la => _context.UserTasks + .Any(ut => ut.UserId == assignedToUserId.Value && + ut.TaskType == "LA" && + ut.LandAcquisitionId == la.Id)); + } } } diff --git a/services/ILAMasterfileService.cs b/services/ILAMasterfileService.cs index afd943d..b5584cc 100644 --- a/services/ILAMasterfileService.cs +++ b/services/ILAMasterfileService.cs @@ -4,9 +4,9 @@ namespace ValuationBackend.Services { public interface ILAMasterfileService { - LAMasterfileResponse GetAll(); - LAMasterfileResponse GetPaged(int page, int pageSize); - LAMasterfileResponse Search(string query); - LAMasterfileResponse SearchPaged(string query, int page, int pageSize); + LAMasterfileResponse GetAll(string sortBy = "", int? assignedToUserId = null); + LAMasterfileResponse GetPaged(int page, int pageSize, string sortBy = "", int? assignedToUserId = null); + LAMasterfileResponse Search(string query, string sortBy = "", int? assignedToUserId = null); + LAMasterfileResponse SearchPaged(string query, int page, int pageSize, string sortBy = "", int? assignedToUserId = null); } } diff --git a/services/LAMasterfileService.cs b/services/LAMasterfileService.cs index f9fba44..6968d68 100644 --- a/services/LAMasterfileService.cs +++ b/services/LAMasterfileService.cs @@ -13,18 +13,18 @@ public LAMasterfileService(ILAMasterfileRepository repository) _repository = repository; } - public LAMasterfileResponse GetAll() + public LAMasterfileResponse GetAll(string sortBy = "", int? assignedToUserId = null) { - var data = _repository.GetAll(); + var data = _repository.GetAll(sortBy, assignedToUserId); return new LAMasterfileResponse { MasterFiles = data }; } - public LAMasterfileResponse GetPaged(int page, int pageSize) + public LAMasterfileResponse GetPaged(int page, int pageSize, string sortBy = "", int? assignedToUserId = null) { if (page < 1) page = 1; if (pageSize < 1) pageSize = 10; - var (items, totalCount) = _repository.GetPaged(page, pageSize); + var (items, totalCount) = _repository.GetPaged(page, pageSize, sortBy, assignedToUserId); var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize); return new LAMasterfileResponse @@ -33,22 +33,23 @@ public LAMasterfileResponse GetPaged(int page, int pageSize) TotalCount = totalCount, CurrentPage = page, PageSize = pageSize, - TotalPages = totalPages + TotalPages = totalPages, + SortBy = sortBy }; } - public LAMasterfileResponse Search(string query) + public LAMasterfileResponse Search(string query, string sortBy = "", int? assignedToUserId = null) { - var data = _repository.Search(query); + var data = _repository.Search(query, sortBy, assignedToUserId); return new LAMasterfileResponse { MasterFiles = data }; } - public LAMasterfileResponse SearchPaged(string query, int page, int pageSize) + public LAMasterfileResponse SearchPaged(string query, int page, int pageSize, string sortBy = "", int? assignedToUserId = null) { if (page < 1) page = 1; if (pageSize < 1) pageSize = 10; - var (items, totalCount) = _repository.SearchPaged(query, page, pageSize); + var (items, totalCount) = _repository.SearchPaged(query, page, pageSize, sortBy, assignedToUserId); var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize); return new LAMasterfileResponse @@ -57,7 +58,8 @@ public LAMasterfileResponse SearchPaged(string query, int page, int pageSize) TotalCount = totalCount, CurrentPage = page, PageSize = pageSize, - TotalPages = totalPages + TotalPages = totalPages, + SortBy = sortBy }; } }