Initial commit
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace PowderCoating.Application.DTOs.Customer;
|
||||
|
||||
public class CustomerDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? CompanyName { get; set; }
|
||||
public string? ContactFirstName { get; set; }
|
||||
public string? ContactLastName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string? MobilePhone { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Country { get; set; }
|
||||
public bool IsCommercial { get; set; }
|
||||
public string? TaxId { get; set; }
|
||||
public decimal CreditLimit { get; set; }
|
||||
public decimal CurrentBalance { get; set; }
|
||||
public decimal CreditBalance { get; set; }
|
||||
public string? PaymentTerms { get; set; }
|
||||
public int? PricingTierId { get; set; }
|
||||
public string? PricingTierName { get; set; }
|
||||
public bool IsTaxExempt { get; set; }
|
||||
public bool HasTaxExemptCertificate { get; set; }
|
||||
public string? TaxExemptCertificateFileName { get; set; }
|
||||
public string? GeneralNotes { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public DateTime? LastContactDate { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public bool NotifyByEmail { get; set; }
|
||||
public bool NotifyBySms { get; set; }
|
||||
public DateTime? SmsConsentedAt { get; set; }
|
||||
public string? SmsConsentMethod { get; set; }
|
||||
}
|
||||
|
||||
public class CreateCustomerDto : IValidatableObject
|
||||
{
|
||||
[Display(Name = "Company Name")]
|
||||
[StringLength(200)]
|
||||
public string? CompanyName { get; set; }
|
||||
|
||||
[Display(Name = "First Name")]
|
||||
[StringLength(100)]
|
||||
public string? ContactFirstName { get; set; }
|
||||
|
||||
[Display(Name = "Last Name")]
|
||||
[StringLength(100)]
|
||||
public string? ContactLastName { get; set; }
|
||||
|
||||
[Display(Name = "Email")]
|
||||
[EmailAddress(ErrorMessage = "Please enter a valid email address")]
|
||||
[StringLength(200)]
|
||||
public string? Email { get; set; }
|
||||
|
||||
[Display(Name = "Phone")]
|
||||
[Phone(ErrorMessage = "Please enter a valid phone number")]
|
||||
[StringLength(20)]
|
||||
public string? Phone { get; set; }
|
||||
|
||||
[Display(Name = "Mobile Phone")]
|
||||
[Phone(ErrorMessage = "Please enter a valid mobile phone number")]
|
||||
[StringLength(20)]
|
||||
public string? MobilePhone { get; set; }
|
||||
|
||||
[Display(Name = "Street Address")]
|
||||
[StringLength(500)]
|
||||
public string? Address { get; set; }
|
||||
|
||||
[Display(Name = "City")]
|
||||
[StringLength(100)]
|
||||
public string? City { get; set; }
|
||||
|
||||
[Display(Name = "State")]
|
||||
[StringLength(50)]
|
||||
public string? State { get; set; }
|
||||
|
||||
[Display(Name = "Zip Code")]
|
||||
[StringLength(20)]
|
||||
public string? ZipCode { get; set; }
|
||||
|
||||
[Display(Name = "Country")]
|
||||
[StringLength(100)]
|
||||
public string? Country { get; set; } = "USA";
|
||||
|
||||
[Display(Name = "Customer Type")]
|
||||
public bool IsCommercial { get; set; }
|
||||
|
||||
[Display(Name = "Tax ID / EIN")]
|
||||
[StringLength(50)]
|
||||
public string? TaxId { get; set; }
|
||||
|
||||
[Display(Name = "Credit Limit")]
|
||||
[Range(0, 9999999.99)]
|
||||
public decimal CreditLimit { get; set; }
|
||||
|
||||
[Display(Name = "Payment Terms")]
|
||||
[StringLength(50)]
|
||||
public string? PaymentTerms { get; set; }
|
||||
|
||||
[Display(Name = "Pricing Tier")]
|
||||
public int? PricingTierId { get; set; }
|
||||
|
||||
[Display(Name = "Tax Exempt")]
|
||||
public bool IsTaxExempt { get; set; }
|
||||
|
||||
[Display(Name = "General Notes")]
|
||||
[StringLength(2000)]
|
||||
public string? GeneralNotes { get; set; }
|
||||
|
||||
[Display(Name = "Notify by Email")]
|
||||
public bool NotifyByEmail { get; set; } = true;
|
||||
|
||||
[Display(Name = "Notify by SMS")]
|
||||
public bool NotifyBySms { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Form-only flag: staff checks this to record that the customer gave verbal consent to receive SMS.
|
||||
/// Not mapped to any entity field — the controller handles setting SmsConsentedAt and SmsConsentMethod.
|
||||
/// </summary>
|
||||
[Display(Name = "Customer has verbally consented to receive SMS notifications")]
|
||||
public bool SmsConsentGranted { get; set; } = false;
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
// At least one name field is required (Company Name OR Contact First/Last Name)
|
||||
if (string.IsNullOrWhiteSpace(CompanyName) &&
|
||||
string.IsNullOrWhiteSpace(ContactFirstName) &&
|
||||
string.IsNullOrWhiteSpace(ContactLastName))
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"Please provide either a Company Name or a Contact Name (First and/or Last Name)",
|
||||
new[] { nameof(CompanyName), nameof(ContactFirstName), nameof(ContactLastName) });
|
||||
}
|
||||
|
||||
// At least one contact method is required (Email OR Phone)
|
||||
if (string.IsNullOrWhiteSpace(Email) && string.IsNullOrWhiteSpace(Phone))
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"Please provide at least one contact method (Email or Phone)",
|
||||
new[] { nameof(Email), nameof(Phone) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCustomerDto : CreateCustomerDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public bool HasTaxExemptCertificate { get; set; }
|
||||
public string? TaxExemptCertificateFileName { get; set; }
|
||||
// Read from entity so the Edit view can display consent status
|
||||
public DateTime? SmsConsentedAt { get; set; }
|
||||
public string? SmsConsentMethod { get; set; }
|
||||
}
|
||||
|
||||
public class CustomerListDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? CompanyName { get; set; }
|
||||
public string ContactName { get; set; } = string.Empty;
|
||||
public string? Phone { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public bool IsCommercial { get; set; }
|
||||
public decimal CurrentBalance { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public DateTime? LastContactDate { get; set; }
|
||||
}
|
||||
|
||||
public class AddCreditDto
|
||||
{
|
||||
[Required]
|
||||
[Range(0.01, 99999.99, ErrorMessage = "Amount must be between $0.01 and $99,999.99")]
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(200, ErrorMessage = "Reason cannot exceed 200 characters")]
|
||||
[Display(Name = "Reason")]
|
||||
public string Reason { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(1000)]
|
||||
[Display(Name = "Notes")]
|
||||
public string? Notes { get; set; }
|
||||
|
||||
[Display(Name = "Expiry Date (optional)")]
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace PowderCoating.Application.DTOs.Customer;
|
||||
|
||||
public class PricingTierDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string TierName { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public decimal DiscountPercent { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public int CustomerCount { get; set; }
|
||||
}
|
||||
|
||||
public class CreatePricingTierDto
|
||||
{
|
||||
[Required(ErrorMessage = "Tier name is required")]
|
||||
[MaxLength(100)]
|
||||
[Display(Name = "Tier Name")]
|
||||
public string TierName { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(500)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[Required]
|
||||
[Range(0, 100, ErrorMessage = "Discount must be between 0 and 100")]
|
||||
[Display(Name = "Discount %")]
|
||||
public decimal DiscountPercent { get; set; }
|
||||
|
||||
[Display(Name = "Active")]
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
|
||||
public class UpdatePricingTierDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "Tier name is required")]
|
||||
[MaxLength(100)]
|
||||
[Display(Name = "Tier Name")]
|
||||
public string TierName { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(500)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[Required]
|
||||
[Range(0, 100, ErrorMessage = "Discount must be between 0 and 100")]
|
||||
[Display(Name = "Discount %")]
|
||||
public decimal DiscountPercent { get; set; }
|
||||
|
||||
[Display(Name = "Active")]
|
||||
public bool IsActive { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user