mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 11:53:12 +00:00
Add vendor accept via email link
- DispatchPublicController with public GET /api/dispatch/accept/{token}
- Updates dispatch status to Acknowledged with timestamp
- Returns styled HTML confirmation page
- Dispatch email now includes green Accept Dispatch button
- Logs vendor acceptance to audit trail
This commit is contained in:
parent
3a25fa8559
commit
c482fa0558
2 changed files with 93 additions and 0 deletions
|
|
@ -0,0 +1,89 @@
|
|||
using Data.SeaHavenIndustries;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Api.SeaHavenIndustries.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/dispatch")]
|
||||
public class DispatchPublicController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _db;
|
||||
|
||||
public DispatchPublicController(ApplicationDbContext db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
[HttpGet("accept/{token}")]
|
||||
public async Task<IActionResult> Accept(string token)
|
||||
{
|
||||
var dispatch = await _db.Dispatches
|
||||
.Include(d => d.Vendor)
|
||||
.FirstOrDefaultAsync(d => d.AcceptToken == token);
|
||||
|
||||
if (dispatch == null)
|
||||
{
|
||||
return Content(BuildHtml("Dispatch Not Found", "This dispatch link is invalid or has expired.", "#dc3545"), "text/html");
|
||||
}
|
||||
|
||||
if (dispatch.Status != "Sent")
|
||||
{
|
||||
var alreadyMsg = dispatch.AcknowledgedAt.HasValue
|
||||
? $"This dispatch was already accepted on {dispatch.AcknowledgedAt.Value:MMMM dd, yyyy 'at' h:mm tt} UTC."
|
||||
: "This dispatch has already been processed.";
|
||||
return Content(BuildHtml("Already Accepted", alreadyMsg, "#ffc107"), "text/html");
|
||||
}
|
||||
|
||||
dispatch.Status = "Acknowledged";
|
||||
dispatch.AcknowledgedAt = DateTime.UtcNow;
|
||||
|
||||
_db.WorkOrderAuditLogs.Add(new WorkOrderAuditLog
|
||||
{
|
||||
WorkOrderId = dispatch.WorkOrderId ?? 0,
|
||||
FieldName = $"Dispatch {dispatch.DispatchNumber} Status",
|
||||
OldValue = "Sent",
|
||||
NewValue = "Acknowledged",
|
||||
Action = "vendor_accept",
|
||||
CreatedAt = DateTime.UtcNow
|
||||
});
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
var vendorName = dispatch.Vendor?.CompanyName ?? "Vendor";
|
||||
return Content(BuildHtml(
|
||||
"Dispatch Accepted",
|
||||
$"<strong>{vendorName}</strong> has accepted dispatch <strong>{dispatch.DispatchNumber}</strong>.<br/><br/>Thank you for confirming. The dispatcher has been notified.",
|
||||
"#28a745"
|
||||
), "text/html");
|
||||
}
|
||||
|
||||
private static string BuildHtml(string title, string message, string color)
|
||||
{
|
||||
return $@"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'/>
|
||||
<title>{title} - Sea Haven Industries</title>
|
||||
<style>
|
||||
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #f5f5f5; }}
|
||||
.card {{ background: white; border-radius: 12px; padding: 40px; max-width: 480px; text-align: center; box-shadow: 0 4px 20px rgba(0,0,0,0.1); }}
|
||||
.icon {{ width: 60px; height: 60px; border-radius: 50%; background: {color}; color: white; font-size: 28px; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; }}
|
||||
h1 {{ font-size: 22px; color: #333; margin: 0 0 12px; }}
|
||||
p {{ font-size: 15px; color: #666; line-height: 1.6; margin: 0; }}
|
||||
.footer {{ margin-top: 30px; font-size: 12px; color: #999; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='card'>
|
||||
<div class='icon'>✓</div>
|
||||
<h1>{title}</h1>
|
||||
<p>{message}</p>
|
||||
<div class='footer'>Sea Haven Industries</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1136,6 +1136,10 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
</table>
|
||||
<h3>Description</h3>
|
||||
<p>{model.Description ?? primaryWO.Description}</p>
|
||||
<br/>
|
||||
<div style='text-align:center;margin:20px 0;'>
|
||||
<a href='{Request.Scheme}://{Request.Host}/api/dispatch/accept/{dispatch.AcceptToken}' style='display:inline-block;padding:12px 32px;background:#28a745;color:white;text-decoration:none;border-radius:6px;font-weight:bold;font-size:16px;'>Accept Dispatch</a>
|
||||
</div>
|
||||
<br/><p style='color:#666;font-size:13px;'>{senderName}<br/>Sea Haven Industries</p>
|
||||
<hr/><p style='color:#999;font-size:12px;'>Reply to this email to communicate about this dispatch.</p>";
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue