using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; namespace ODCWeb.Models { public class Subtask { [Key] public int SubtaskId { get; set; } [Required] public int TaskId { get; set; } [Required] public int ProjectId { get; set; } [Required(ErrorMessage = "Subtask description is required")] [DataType(DataType.MultilineText)] [Display(Name = "Description")] public string SubTaskD { get; set; } [Required(ErrorMessage = "Start time is required")] [Display(Name = "Start Time")] public DateTime StartTimeStamp { get; set; } [Required(ErrorMessage = "End time is required")] [Display(Name = "End Time")] public DateTime EndTimeStamp { get; set; } [DataType(DataType.MultilineText)] public string? Comments { get; set; } [NotMapped] [MaxFileSize(2 * 1024 * 1024)] [AllowedExtensions(new string[] { ".pdf", ".jpg", ".jpeg", ".png", ".mp4" })] [Display(Name = "Upload Proof")] public IFormFile? FileUpload { get; set; } public byte[]? FileData { get; set; } public string? FileContentType { get; set; } public string? FileName { get; set; } // NEW: Navigation property for materials used in this construction activity [ValidateNever] public virtual ICollection MaterialsUsed { get; set; } = new List(); // NEW: Computed properties for enhanced functionality [NotMapped] public double? TotalMaterialCost => MaterialsUsed? .Where(m => m.Actual_Qty.HasValue && m.Unit_Cost.HasValue) .Sum(m => m.Actual_Qty * m.Unit_Cost); [NotMapped] public int MaterialCount => MaterialsUsed?.Count ?? 0; [NotMapped] public bool HasMaterialsRecorded => MaterialsUsed?.Any(m => m.Actual_Qty.HasValue) ?? false; } } // Keep your existing validation attributes as they are public class MaxFileSizeAttribute : ValidationAttribute { private readonly int _maxFileSize; public MaxFileSizeAttribute(int maxFileSize) { _maxFileSize = maxFileSize; } protected override ValidationResult IsValid( object value, ValidationContext validationContext) { var file = value as IFormFile; if (file != null) { if (file.Length > _maxFileSize) { return new ValidationResult(GetErrorMessage()); } } return ValidationResult.Success; } public string GetErrorMessage() { return $"Maximum allowed file size is {_maxFileSize} bytes."; } } public class AllowedExtensionsAttribute : ValidationAttribute { private readonly string[] _extensions; public AllowedExtensionsAttribute(string[] extensions) { _extensions = extensions; } protected override ValidationResult IsValid( object value, ValidationContext validationContext) { var file = value as IFormFile; if (file != null) { var extension = Path.GetExtension(file.FileName); if (!_extensions.Contains(extension.ToLower())) { return new ValidationResult(GetErrorMessage()); } } return ValidationResult.Success; } public string GetErrorMessage() { return $"This file extension is not allowed."; } }