mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 06:03:12 +00:00
Seed an organization-wide Area catalogue (East, Central, West, California) with stable ids, add a nullable AreaId to VendorCompany, allow only Admins to change it through the roster endpoints, expose areas facet metadata and an areas[n] company-directory filter with the __unassigned__ sentinel.
142 lines
5 KiB
C#
142 lines
5 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace SeaHaven.Services.DTOs
|
|
{
|
|
public class VendorRosterDTO
|
|
{
|
|
public int CompanyId { get; set; }
|
|
public string Name { get; set; } = string.Empty;
|
|
public string? CompanyPhone { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? Address { get; set; }
|
|
public string? City { get; set; }
|
|
public string? State { get; set; }
|
|
public string? Zip { get; set; }
|
|
public string? GoogleMapsUrl { get; set; }
|
|
public string? Notes { get; set; }
|
|
public int? AreaId { get; set; }
|
|
public string? AreaName { get; set; }
|
|
public string? RowVersion { get; set; }
|
|
public List<VendorRosterTechnicianDTO> Technicians { get; set; } = new();
|
|
}
|
|
|
|
public class VendorRosterTechnicianDTO
|
|
{
|
|
public int? Id { get; set; }
|
|
public string? ContactName { get; set; }
|
|
public string? Phone { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? PreferredContact { get; set; }
|
|
public string? TradeSpecialties { get; set; }
|
|
public bool IsActive { get; set; }
|
|
public int TotalJobs { get; set; }
|
|
}
|
|
|
|
public class RosterTechnicianInputDTO
|
|
{
|
|
public int? Id { get; set; }
|
|
public string? ContactName { get; set; }
|
|
public string? Phone { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? PreferredContact { get; set; }
|
|
public string? TradeSpecialties { get; set; }
|
|
public bool? IsActive { get; set; }
|
|
}
|
|
|
|
public class CreateVendorRosterDTO
|
|
{
|
|
public required string Name { get; set; }
|
|
public string? CompanyPhone { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? Address { get; set; }
|
|
public string? City { get; set; }
|
|
public string? State { get; set; }
|
|
public string? Zip { get; set; }
|
|
public string? GoogleMapsUrl { get; set; }
|
|
public string? Notes { get; set; }
|
|
|
|
// SH-278: optional Area id; null leaves the new company Unassigned. Assigning
|
|
// an Area requires the Admin role.
|
|
public int? AreaId { get; set; }
|
|
public List<RosterTechnicianInputDTO> Technicians { get; set; } = new();
|
|
}
|
|
|
|
public class ReconcileVendorRosterDTO
|
|
{
|
|
public required string RowVersion { get; set; }
|
|
public required string Name { get; set; }
|
|
public string? CompanyPhone { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? Address { get; set; }
|
|
public string? City { get; set; }
|
|
public string? State { get; set; }
|
|
public string? Zip { get; set; }
|
|
public string? GoogleMapsUrl { get; set; }
|
|
public string? Notes { get; set; }
|
|
|
|
// SH-278: an omitted areaId leaves the stored Area unchanged, so clients that
|
|
// predate Area never clear it. An explicit null clears it to Unassigned.
|
|
private int? _areaId;
|
|
public int? AreaId
|
|
{
|
|
get => _areaId;
|
|
set
|
|
{
|
|
_areaId = value;
|
|
AreaIdProvided = true;
|
|
}
|
|
}
|
|
|
|
[JsonIgnore]
|
|
public bool AreaIdProvided { get; private set; }
|
|
public List<RosterTechnicianInputDTO> Technicians { get; set; } = new();
|
|
}
|
|
|
|
// Partial, purely additive roster update (SH-250): technicians listed here are
|
|
// inserted; any technician absent from the payload is never removed, soft-deleted
|
|
// or deactivated. Company fields are optional; a null field means "unchanged".
|
|
public class AddTechniciansVendorRosterDTO
|
|
{
|
|
public required string RowVersion { get; set; }
|
|
public List<RosterTechnicianInputDTO> AddTechnicians { get; set; } = new();
|
|
public VendorRosterCompanyFieldsDTO? CompanyFields { get; set; }
|
|
}
|
|
|
|
public class VendorRosterCompanyFieldsDTO
|
|
{
|
|
public string? Name { get; set; }
|
|
public string? CompanyPhone { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? Address { get; set; }
|
|
public string? City { get; set; }
|
|
public string? State { get; set; }
|
|
public string? Zip { get; set; }
|
|
public string? GoogleMapsUrl { get; set; }
|
|
public string? Notes { get; set; }
|
|
|
|
// SH-278: same presence semantics as ReconcileVendorRosterDTO.AreaId.
|
|
private int? _areaId;
|
|
public int? AreaId
|
|
{
|
|
get => _areaId;
|
|
set
|
|
{
|
|
_areaId = value;
|
|
AreaIdProvided = true;
|
|
}
|
|
}
|
|
|
|
[JsonIgnore]
|
|
public bool AreaIdProvided { get; private set; }
|
|
}
|
|
|
|
// SH-278: raised when a caller without the Admin role tries to change a vendor
|
|
// company's Area. Mapped to a stable 403 by the API.
|
|
public sealed class VendorAreaAssignmentForbiddenException : Exception
|
|
{
|
|
public VendorAreaAssignmentForbiddenException()
|
|
: base("Only administrators can assign a vendor company Area.")
|
|
{
|
|
}
|
|
}
|
|
}
|