table link

This commit is contained in:
misya 2025-05-19 17:06:18 +08:00
parent 9da24c144a
commit 00660345fc
2 changed files with 123 additions and 105 deletions

View File

@ -8,9 +8,34 @@ using QuestPDF.Fluent;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Threading; using System.Threading;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
namespace PSTW_CentralSystem.Areas.MMS.Controllers namespace PSTW_CentralSystem.Areas.MMS.Controllers
{ {
public class SimpleTarballDto
{
// From tbl_marine_tarball
public int Id { get; set; }
public string StationID { get; set; }
public string Longitude { get; set; }
public string Latitude { get; set; }
public DateTime DateSample { get; set; }
public TimeSpan TimeSample { get; set; }
public string ClassifyID { get; set; }
public string OptionalName1 { get; set; }
public string OptionalName2 { get; set; }
public string OptionalName3 { get; set; }
public string OptionalName4 { get; set; }
public string FirstSampler { get; set; }
// From joined tables
public string LocationName { get; set; } // From tbl_marine_station
public string StateName { get; set; } // From tbl_state
public string FullName { get; set; } // From tbl_user
public string LevelName { get; set; } // From tbl_level
}
[Area("MMS")] [Area("MMS")]
public class MarineController : Controller public class MarineController : Controller
{ {
@ -33,7 +58,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
{ {
try try
{ {
var marineTarballs = _context.MarineTarballs var marineTarballs = _context.MarineTarballs //error===========================================
.Where(t => t.StationID != "1") // To remove unusable data with invalid stationID .Where(t => t.StationID != "1") // To remove unusable data with invalid stationID
.Select(t => new .Select(t => new
{ {
@ -197,14 +222,14 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
} }
} }
public IActionResult GenerateReport(int id)//calls GeneratePdfResponse to generate a PDF for inline viewing public async Task<IActionResult> GenerateReport(int id)//calls GeneratePdfResponse to generate a PDF for inline viewing
{ {
return GeneratePdfResponse(id, true); return await GeneratePdfResponse(id, true);
} }
public IActionResult DownloadPDF(int id) public async Task<IActionResult> DownloadPDF(int id)
{ {
return GeneratePdfResponse(id, true); return await GeneratePdfResponse(id, true);
} }
@ -227,11 +252,11 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
} }
} }
private IActionResult GeneratePdfResponse(int id, bool forceDownload) private async Task<IActionResult> GeneratePdfResponse(int id, bool forceDownload)
{ {
Console.WriteLine($"Requested ID in {(forceDownload ? "GenerateReport" : "ViewPDF")}: {id}"); Console.WriteLine($"Requested ID in {(forceDownload ? "GenerateReport" : "ViewPDF")}: {id}");
// Add this temporary check at the start of GeneratePdfResponse // Temporary network connection test
try try
{ {
Console.WriteLine("Testing network connection..."); Console.WriteLine("Testing network connection...");
@ -248,49 +273,38 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
try try
{ {
// Connect to the network path // Connect to the network path
_networkAccessService.ConnectToNetworkPath();//------------------ _networkAccessService.ConnectToNetworkPath();
// 1. Fetch core data from database // ===== 1. NEW SQL QUERY APPROACH =====
var tarballData = (from marine in _context.MarineTarballs var query = @"
join station in _context.MarineStations on marine.StationID equals station.StationID SELECT
join state in _context.States on station.StateID equals state.StateID marine.*, station.LocationName, state.StateName,user.FullName,level.LevelName
join user in _context.Users on marine.FirstSampler equals user.FullName FROM tbl_marine_tarball marine
join level in _context.Levels on user.LevelID equals level.LevelID JOIN tbl_marine_station station ON marine.StationID = station.StationID
where marine.Id == id JOIN tbl_state state ON station.StateID = state.StateID
select new JOIN tbl_user user ON marine.FirstSampler = user.FullName -- Corrected column name
{ JOIN tbl_level level ON user.LevelID = level.LevelID
state.StateName, WHERE marine.Id = @id";
marine.StationID,
station.LocationName,
marine.Longitude,
marine.Latitude,
marine.DateSample,
marine.TimeSample,
marine.ClassifyID,
TarBallYes = marine.ClassifyID != "NO",
TarBallNo = marine.ClassifyID == "NO",
IsSand = marine.ClassifyID == "SD",
IsNonSandy = marine.ClassifyID == "NS",
IsCoquina = marine.ClassifyID == "CO",
marine.OptionalName1,
marine.OptionalName2,
marine.OptionalName3,
marine.OptionalName4,
marine.FirstSampler,
user.FullName,
user.LevelID,
level.LevelName
}).FirstOrDefault(); var tarball = await _context.Database
.SqlQueryRaw<TarballPdfDto>(query, new SqlParameter("@id", id))
.FirstOrDefaultAsync();
if (tarballData == null) if (tarball == null)
return NotFound("Record not found"); return NotFound("Record not found");
// 2. Get photos from station folder (with date matching) //Prepare boolean values for PDF
var sampleDateString = tarballData.DateSample.ToString("yyyyMMdd"); bool tarBallYes = tarball.ClassifyID != "NO";
var sampleTimePrefix = ((int)tarballData.TimeSample.TotalHours).ToString("D2") + bool tarBallNo = tarball.ClassifyID == "NO";
tarballData.TimeSample.Minutes.ToString("D2"); bool isSand = tarball.ClassifyID == "SD";
var stationFolder = Path.Combine(PhotoBasePath, tarballData.StationID); bool isNonSandy = tarball.ClassifyID == "NS";
bool isCoquina = tarball.ClassifyID == "CO";
// ===== 2. Get Images from path =====
var sampleDateString = tarball.DateSample.ToString("yyyyMMdd");
var sampleTimePrefix = ((int)tarball.TimeSample.TotalHours).ToString("D2") +
tarball.TimeSample.Minutes.ToString("D2");
var stationFolder = Path.Combine(PhotoBasePath, tarball.StationID);
var stationImages = new Dictionary<string, string>(); var stationImages = new Dictionary<string, string>();
if (Directory.Exists(stationFolder)) if (Directory.Exists(stationFolder))
@ -300,18 +314,13 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
{ {
var fileName = Path.GetFileNameWithoutExtension(f); var fileName = Path.GetFileNameWithoutExtension(f);
var parts = fileName.Split('_'); var parts = fileName.Split('_');
//Match: StationID_Date_*
return parts.Length >= 3 && return parts.Length >= 3 &&
parts[0] == tarballData.StationID && // 1. StationID parts[0] == tarball.StationID &&
parts[1] == sampleDateString && // 2. Date parts[1] == sampleDateString &&
parts[2].StartsWith(sampleTimePrefix); parts[2].StartsWith(sampleTimePrefix);
}) })
.ToList(); .ToList();
Console.WriteLine($"Found {allImages.Count} images for {tarballData.StationID} on {sampleDateString} at {sampleTimePrefix}");
// Define image priority order
var imageTypes = new List<string> var imageTypes = new List<string>
{ {
"LEFTSIDECOASTALVIEW", "LEFTSIDECOASTALVIEW",
@ -324,7 +333,6 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
"OPTIONAL04" "OPTIONAL04"
}; };
// Match images to their types
foreach (var imagePath in allImages) foreach (var imagePath in allImages)
{ {
var fileName = Path.GetFileNameWithoutExtension(imagePath); var fileName = Path.GetFileNameWithoutExtension(imagePath);
@ -339,7 +347,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
} }
} }
// Validate mandatory images //Mandatory images
var mandatoryImages = new List<string> var mandatoryImages = new List<string>
{ {
"LEFTSIDECOASTALVIEW", "LEFTSIDECOASTALVIEW",
@ -352,25 +360,25 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
{ {
if(!stationImages.ContainsKey(mandatoryType)) if(!stationImages.ContainsKey(mandatoryType))
{ {
return StatusCode(400, $"Missing mandatory image for {tarballData.StationID} on {tarballData.DateSample:yyyy-MM-dd} at {tarballData.TimeSample}: {mandatoryType}"); return StatusCode(400, $"Missing mandatory image: {mandatoryType}");
} }
} }
// 3. Generate PDF // ===== 3. GENERATE PDF (ADAPTED FOR NEW DTO) =====
var pdf = new TarBallPDF( var pdf = new TarBallPDF(
tarballData.StateName, tarball.StateName,
tarballData.StationID, tarball.StationID,
tarballData.LocationName, tarball.LocationName,
tarballData.Longitude, tarball.Longitude,
tarballData.Latitude, tarball.Latitude,
tarballData.DateSample, tarball.DateSample,
tarballData.TimeSample, tarball.TimeSample,
tarballData.ClassifyID, tarball.ClassifyID,
tarballData.TarBallYes, tarBallYes,
tarballData.TarBallNo, tarBallNo,
tarballData.IsSand, isSand,
tarballData.IsNonSandy, isNonSandy,
tarballData.IsCoquina, isCoquina,
stationImages["LEFTSIDECOASTALVIEW"], stationImages["LEFTSIDECOASTALVIEW"],
stationImages["RIGHTSIDECOASTALVIEW"], stationImages["RIGHTSIDECOASTALVIEW"],
stationImages["DRAWINGVERTICALLINES"], stationImages["DRAWINGVERTICALLINES"],
@ -379,18 +387,17 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
stationImages.GetValueOrDefault("OPTIONAL02"), stationImages.GetValueOrDefault("OPTIONAL02"),
stationImages.GetValueOrDefault("OPTIONAL03"), stationImages.GetValueOrDefault("OPTIONAL03"),
stationImages.GetValueOrDefault("OPTIONAL04"), stationImages.GetValueOrDefault("OPTIONAL04"),
tarballData.OptionalName1, tarball.OptionalName1,
tarballData.OptionalName2, tarball.OptionalName2,
tarballData.OptionalName3, tarball.OptionalName3,
tarballData.OptionalName4, tarball.OptionalName4,
tarballData.FirstSampler, tarball.FirstSampler,
tarballData.FullName, tarball.FullName,
tarballData.LevelName tarball.LevelName
).GeneratePdf(); ).GeneratePdf();
// 4. Return file
return forceDownload return forceDownload
? File(pdf, "application/pdf", $"TbReport_{tarballData.StationID}_{tarballData.DateSample:yyyyMMdd}.pdf") ? File(pdf, "application/pdf", $"TbReport_{tarball.StationID}_{tarball.DateSample:yyyyMMdd}.pdf")
: File(pdf, "application/pdf"); : File(pdf, "application/pdf");
} }
catch (Exception ex) catch (Exception ex)
@ -400,14 +407,37 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
: ex.Message; : ex.Message;
return Content($"PDF generation failed: {errorMessage}<br/>{ex.StackTrace}", "text/html"); return Content($"PDF generation failed: {errorMessage}<br/>{ex.StackTrace}", "text/html");
} }
finally finally
{ {
// Disconnect from the network path
_networkAccessService.DisconnectFromNetworkShare(); _networkAccessService.DisconnectFromNetworkShare();
} }
} }
// Add this class outside your controller (e.g., in a DTOs folder)
public class TarballPdfDto
{
public string StateName { get; set; }
public string StationID { get; set; }
public string LocationName { get; set; }
public string Longitude { get; set; }
public string Latitude { get; set; }
public DateTime DateSample { get; set; }
public TimeSpan TimeSample { get; set; }
public string ClassifyID { get; set; }
public int TarBallYes { get; set; } // SQL returns 1/0 for bits
public int TarBallNo { get; set; }
public int IsSand { get; set; }
public int IsNonSandy { get; set; }
public int IsCoquina { get; set; }
public string OptionalName1 { get; set; }
public string OptionalName2 { get; set; }
public string OptionalName3 { get; set; }
public string OptionalName4 { get; set; }
public string FirstSampler { get; set; }
public string FullName { get; set; }
public string LevelName { get; set; }
}
private bool IsImageValid(string imagePath) private bool IsImageValid(string imagePath)
{ {
try try

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics;
using PSTW_CentralSystem.Models; // Add this to use the MarineTarball class using PSTW_CentralSystem.Models; // Add this to use the MarineTarball class
@ -21,12 +22,11 @@ namespace PSTW_CentralSystem.DBContext
{ {
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
// Map MarineTarball to tbl_marine_tarball
modelBuilder.Entity<MarineTarball>().ToTable("tbl_marine_tarball");
// Configure properties if needed // Configure properties if needed
modelBuilder.Entity<MarineTarball>(entity => modelBuilder.Entity<MarineTarball>(entity =>
{ {
entity.ToTable("tbl_marine_tarball");
entity.HasKey(e => e.Id); // Primary key entity.HasKey(e => e.Id); // Primary key
entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.ReportID).HasColumnName("reportID").HasMaxLength(50); entity.Property(e => e.ReportID).HasColumnName("reportID").HasMaxLength(50);
@ -52,20 +52,11 @@ namespace PSTW_CentralSystem.DBContext
.HasForeignKey(m => m.StationID) .HasForeignKey(m => m.StationID)
.HasPrincipalKey(t => t.StationID); .HasPrincipalKey(t => t.StationID);
//use SQL query
//========================================================
entity.HasOne(a => a.User)//Each MarineTarball has ONE User
.WithMany()//Each User can be linked to MANY MarineTarballs
.HasForeignKey(a => a.FirstSampler)//Uses FirstSampler (name string) in MarineTarball as the connector to User
.HasPrincipalKey(b => b.FullName);//match FirstSampler with the FullName in the User table
//========================================================
}); });
// Map TarballStation to tbl_tarball_station
modelBuilder.Entity<MarineStation>().ToTable("tbl_marine_station");
modelBuilder.Entity<MarineStation>(entity => modelBuilder.Entity<MarineStation>(entity =>
{ {
entity.ToTable("tbl_marine_station");
entity.HasKey(e => e.Id); // Primary key entity.HasKey(e => e.Id); // Primary key
entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.StationID).HasColumnName("stationID").HasMaxLength(20); entity.Property(e => e.StationID).HasColumnName("stationID").HasMaxLength(20);
@ -82,21 +73,18 @@ namespace PSTW_CentralSystem.DBContext
.HasPrincipalKey(s => s.StateID); .HasPrincipalKey(s => s.StateID);
}); });
// Map State to tbl_state
modelBuilder.Entity<State>().ToTable("tbl_state");
modelBuilder.Entity<State>(entity => modelBuilder.Entity<State>(entity =>
{ {
entity.ToTable("tbl_state");
entity.HasKey(e => e.Id); // Primary key entity.HasKey(e => e.Id); // Primary key
entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.StateID).HasColumnName("stateID").HasMaxLength(20); entity.Property(e => e.StateID).HasColumnName("stateID").HasMaxLength(20);
entity.Property(e => e.StateName).HasColumnName("stateName").HasMaxLength(50); entity.Property(e => e.StateName).HasColumnName("stateName").HasMaxLength(50);
}); });
modelBuilder.Entity<User>().ToTable("tbl_user");
modelBuilder.Entity<User>(entity => modelBuilder.Entity<User>(entity =>
{ {
entity.ToTable("tbl_user");
entity.HasKey(e => e.Id); // Primary key entity.HasKey(e => e.Id); // Primary key
entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.UserID).HasColumnName("userID").HasMaxLength(20); entity.Property(e => e.UserID).HasColumnName("userID").HasMaxLength(20);
@ -109,7 +97,7 @@ namespace PSTW_CentralSystem.DBContext
entity.HasOne(u => u.Level) entity.HasOne(u => u.Level)
.WithMany() .WithMany()
.HasForeignKey(u => u.LevelID) .HasForeignKey(u => u.LevelID)
.HasPrincipalKey(c => c.LevelID); .HasPrincipalKey(l => l.LevelID);
}); });
modelBuilder.Entity<Level>().ToTable("tbl_level"); modelBuilder.Entity<Level>().ToTable("tbl_level");