shoc-backend/Api.SeaHavenIndustries/Controllers/VendorController.cs
Adam Moussa d24c4643f5 Add vendor dispatch workflow backend
- Create Vendor model with company info, trade specialties, active flag
- Create Dispatch model (doubles as Vendor PO) with PO number, NTE, status, reply-to address
- VendorController: CRUD, paginated list, dropdown endpoint with trade filtering
- DispatchToVendor endpoint: multi-vendor dispatch, auto-generated PO numbers (VPO-00001),
  HTML email with full WO details via SendGrid, reply-to wo-{number}@int.seahaven.com
- GetDispatches endpoint for listing dispatches by WO
- Include dispatches in GetWorkorderById response
- SendMessage.SendDispatchEmail with reply-to support
- Audit log entry for each dispatch
2026-04-17 11:37:35 -04:00

176 lines
5.9 KiB
C#

using Api.SeaHavenIndustries.DTOs;
using Data.SeaHavenIndustries;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace Api.SeaHavenIndustries.Controllers
{
[Authorize]
[ApiController]
[Route("api/[controller]")]
[Route("api/vendors")]
public class VendorController : Controller
{
private readonly ApplicationDbContext _db;
public VendorController(ApplicationDbContext db)
{
_db = db;
}
[HttpGet("GetVendorList")]
public IActionResult GetVendorList(string? search = "", int page = 1, int pageSize = 10)
{
var query = _db.Vendors.Where(v => v.IsActive);
if (!string.IsNullOrWhiteSpace(search))
{
var s = search.ToLower();
query = query.Where(v =>
(v.CompanyName ?? "").ToLower().Contains(s) ||
(v.ContactName ?? "").ToLower().Contains(s) ||
(v.Email ?? "").ToLower().Contains(s) ||
(v.TradeSpecialties ?? "").ToLower().Contains(s));
}
var totalCount = query.Count();
var data = query.OrderByDescending(v => v.Id)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(v => new
{
v.Id,
v.CompanyName,
v.ContactName,
v.Email,
v.Phone,
v.TradeSpecialties,
v.IsActive
})
.ToList();
return Ok(new Pagination_DTO
{
Data = data,
PageNumber = page,
PageSize = pageSize,
TotalCount = totalCount,
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
});
}
[HttpGet("{id}")]
public async Task<IActionResult> GetVendorById(int id)
{
var vendor = await _db.Vendors.Where(v => v.Id == id).Select(v => new
{
v.Id,
v.CompanyName,
v.ContactName,
v.Email,
v.Phone,
v.Address,
v.City,
v.State,
v.Zip,
v.TradeSpecialties,
v.IsActive
}).FirstOrDefaultAsync();
if (vendor == null)
return NotFound(new Response { Status = "Error", Message = "Vendor not found" });
return Ok(vendor);
}
[HttpPost]
public async Task<IActionResult> Create([FromBody] Vendor_DTO model)
{
try
{
var vendor = new Vendor
{
CompanyName = model.CompanyName,
ContactName = model.ContactName,
Email = model.Email,
Phone = model.Phone,
Address = model.Address,
City = model.City,
State = model.State,
Zip = model.Zip,
TradeSpecialties = model.TradeSpecialties,
IsActive = model.IsActive
};
_db.Vendors.Add(vendor);
await _db.SaveChangesAsync();
return Ok(new DataResponse { Message = "Vendor Created", Status = "200" });
}
catch (Exception ex)
{
return BadRequest(new Response { Status = "Error", Message = ex.Message });
}
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody] EditVendor_DTO model)
{
try
{
var exist = await _db.Vendors.FindAsync(id);
if (exist == null)
return BadRequest(new Response { Status = "Error", Message = "Vendor not found" });
exist.CompanyName = model.CompanyName;
exist.ContactName = model.ContactName;
exist.Email = model.Email;
exist.Phone = model.Phone;
exist.Address = model.Address;
exist.City = model.City;
exist.State = model.State;
exist.Zip = model.Zip;
exist.TradeSpecialties = model.TradeSpecialties;
exist.IsActive = model.IsActive;
await _db.SaveChangesAsync();
return Ok(new DataResponse { Message = "Vendor Updated", Status = "200" });
}
catch (Exception ex)
{
return BadRequest(new Response { Status = "Error", Message = ex.Message });
}
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var exist = await _db.Vendors.FindAsync(id);
if (exist == null)
return BadRequest(new Response { Status = "Error", Message = "Vendor not found" });
_db.Vendors.Remove(exist);
await _db.SaveChangesAsync();
return Ok(new DataResponse { Message = "Vendor Deleted", Status = "200" });
}
[HttpGet("Dropdown")]
public async Task<IActionResult> GetDropdown([FromQuery] string? trade = null)
{
var query = _db.Vendors.Where(v => v.IsActive);
var vendors = await query.OrderBy(v => v.CompanyName)
.Select(v => new { v.Id, v.CompanyName, v.TradeSpecialties })
.ToListAsync();
if (!string.IsNullOrWhiteSpace(trade))
{
var tradeMatched = vendors.Where(v => (v.TradeSpecialties ?? "").Contains(trade)).ToList();
var rest = vendors.Where(v => !(v.TradeSpecialties ?? "").Contains(trade)).ToList();
vendors = tradeMatched.Concat(rest).ToList();
}
return Ok(vendors);
}
}
}