Initial commit
This commit is contained in:
@@ -0,0 +1,354 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using PowderCoating.Core.Enums;
|
||||
|
||||
namespace PowderCoating.Application.DTOs.Wizard;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks the current user's wizard progress (read from CompanyPreferences)
|
||||
/// </summary>
|
||||
public class WizardProgressDto
|
||||
{
|
||||
public bool Started { get; set; }
|
||||
public bool Completed { get; set; }
|
||||
public List<int> DoneSteps { get; set; } = new();
|
||||
public List<int> SkippedSteps { get; set; } = new();
|
||||
public const int TotalSteps = 10;
|
||||
|
||||
public bool IsStepDone(int step) => DoneSteps.Contains(step);
|
||||
public bool IsStepSkipped(int step) => SkippedSteps.Contains(step);
|
||||
public bool IsStepTouched(int step) => IsStepDone(step) || IsStepSkipped(step);
|
||||
|
||||
public int CompletedCount => DoneSteps.Count + SkippedSteps.Count;
|
||||
public int ProgressPercent => TotalSteps == 0 ? 0 : (int)Math.Round((double)CompletedCount / TotalSteps * 100);
|
||||
}
|
||||
|
||||
// ─── Step 1: Company Profile ────────────────────────────────────────────────
|
||||
public class WizardStep1Dto
|
||||
{
|
||||
[Required, MaxLength(200)]
|
||||
[Display(Name = "Company Name")]
|
||||
public string CompanyName { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(200)]
|
||||
[Display(Name = "Primary Contact Name")]
|
||||
public string? PrimaryContactName { get; set; }
|
||||
|
||||
[EmailAddress, MaxLength(200)]
|
||||
[Display(Name = "Primary Contact Email")]
|
||||
public string? PrimaryContactEmail { get; set; }
|
||||
|
||||
[Phone, MaxLength(50)]
|
||||
[Display(Name = "Phone")]
|
||||
public string? Phone { get; set; }
|
||||
|
||||
[MaxLength(300)]
|
||||
[Display(Name = "Address")]
|
||||
public string? Address { get; set; }
|
||||
|
||||
[MaxLength(100)]
|
||||
[Display(Name = "City")]
|
||||
public string? City { get; set; }
|
||||
|
||||
[MaxLength(100)]
|
||||
[Display(Name = "State")]
|
||||
public string? State { get; set; }
|
||||
|
||||
[MaxLength(20)]
|
||||
[Display(Name = "ZIP Code")]
|
||||
public string? ZipCode { get; set; }
|
||||
|
||||
[MaxLength(100)]
|
||||
[Display(Name = "Time Zone")]
|
||||
public string? TimeZone { get; set; }
|
||||
|
||||
[MaxLength(10)]
|
||||
[Display(Name = "Default Currency")]
|
||||
public string DefaultCurrency { get; set; } = "USD";
|
||||
|
||||
[Display(Name = "Use Metric System (metres / kilograms)")]
|
||||
public bool UseMetricSystem { get; set; } = false;
|
||||
}
|
||||
|
||||
// ─── Step 2: QuickBooks Migration ───────────────────────────────────────────
|
||||
public class WizardStep2QbDto
|
||||
{
|
||||
public bool MigratingFromQuickBooks { get; set; } = false;
|
||||
}
|
||||
|
||||
// ─── Step 3: Operating Costs (was Step 2) ───────────────────────────────────
|
||||
public class WizardStep2Dto
|
||||
{
|
||||
[Range(0, 10000)]
|
||||
[Display(Name = "Standard Labor Rate ($/hr)")]
|
||||
public decimal StandardLaborRate { get; set; }
|
||||
|
||||
[Range(0, 10000)]
|
||||
[Display(Name = "Sandblaster Cost ($/hr)")]
|
||||
public decimal SandblasterCostPerHour { get; set; }
|
||||
|
||||
[Range(0, 10000)]
|
||||
[Display(Name = "Coating Booth Cost ($/hr)")]
|
||||
public decimal CoatingBoothCostPerHour { get; set; }
|
||||
|
||||
[Range(0, 10000)]
|
||||
[Display(Name = "Oven Operating Cost ($/hr)")]
|
||||
public decimal OvenOperatingCostPerHour { get; set; }
|
||||
|
||||
[Range(0, 1000)]
|
||||
[Display(Name = "Powder Coating Cost ($/sq ft)")]
|
||||
public decimal PowderCoatingCostPerSqFt { get; set; }
|
||||
|
||||
[Range(0, 100)]
|
||||
[Display(Name = "General Markup (%)")]
|
||||
public decimal GeneralMarkupPercentage { get; set; }
|
||||
|
||||
[Range(0, 100)]
|
||||
[Display(Name = "Tax Rate (%)")]
|
||||
public decimal TaxPercent { get; set; }
|
||||
|
||||
[Range(0, 100000)]
|
||||
[Display(Name = "Shop Minimum Charge ($)")]
|
||||
public decimal ShopMinimumCharge { get; set; }
|
||||
|
||||
[Display(Name = "Shop Capability Tier")]
|
||||
public ShopCapabilityTier ShopCapabilityTier { get; set; } = ShopCapabilityTier.Small;
|
||||
}
|
||||
|
||||
// ─── Step 3: Branding & Numbering ───────────────────────────────────────────
|
||||
public class WizardStep3Dto
|
||||
{
|
||||
[MaxLength(10)]
|
||||
[Display(Name = "Quote Number Prefix")]
|
||||
public string QuoteNumberPrefix { get; set; } = "QT";
|
||||
|
||||
[MaxLength(10)]
|
||||
[Display(Name = "Job Number Prefix")]
|
||||
public string JobNumberPrefix { get; set; } = "JOB";
|
||||
|
||||
[MaxLength(10)]
|
||||
[Display(Name = "Invoice Number Prefix")]
|
||||
public string InvoiceNumberPrefix { get; set; } = "INV";
|
||||
|
||||
[MaxLength(7)]
|
||||
[Display(Name = "Quote Accent Color")]
|
||||
public string QtAccentColor { get; set; } = "#374151";
|
||||
|
||||
[MaxLength(7)]
|
||||
[Display(Name = "Invoice Accent Color")]
|
||||
public string InAccentColor { get; set; } = "#374151";
|
||||
|
||||
[MaxLength(7)]
|
||||
[Display(Name = "Work Order Accent Color")]
|
||||
public string WoAccentColor { get; set; } = "#374151";
|
||||
}
|
||||
|
||||
// ─── Step 4: Invoice & Quote Defaults ───────────────────────────────────────
|
||||
public class WizardStep4Dto
|
||||
{
|
||||
[MaxLength(100)]
|
||||
[Display(Name = "Default Payment Terms")]
|
||||
public string DefaultPaymentTerms { get; set; } = "Net 30";
|
||||
|
||||
[Range(1, 365)]
|
||||
[Display(Name = "Quote Validity (days)")]
|
||||
public int DefaultQuoteValidityDays { get; set; } = 30;
|
||||
|
||||
[Range(1, 365)]
|
||||
[Display(Name = "Default Turnaround (days)")]
|
||||
public int DefaultTurnaroundDays { get; set; } = 7;
|
||||
|
||||
[MaxLength(2000)]
|
||||
[Display(Name = "Default Quote Terms & Conditions")]
|
||||
public string? QtDefaultTerms { get; set; }
|
||||
|
||||
[MaxLength(500)]
|
||||
[Display(Name = "Quote Footer Note")]
|
||||
public string? QtFooterNote { get; set; }
|
||||
}
|
||||
|
||||
// ─── Step 5: Job & Workflow ──────────────────────────────────────────────────
|
||||
public class WizardStep5Dto
|
||||
{
|
||||
[Display(Name = "Default Job Priority")]
|
||||
public string DefaultJobPriority { get; set; } = "Normal";
|
||||
|
||||
[Display(Name = "Require Customer PO Number")]
|
||||
public bool RequireCustomerPO { get; set; } = false;
|
||||
|
||||
[Display(Name = "Allow Customer Approval via Link")]
|
||||
public bool AllowCustomerApproval { get; set; } = true;
|
||||
|
||||
}
|
||||
|
||||
// ─── Step 6: Chart of Accounts (review only) ────────────────────────────────
|
||||
public class WizardStep6Dto
|
||||
{
|
||||
public int AccountCount { get; set; }
|
||||
public int RevenueAccounts { get; set; }
|
||||
public int ExpenseAccounts { get; set; }
|
||||
public int AssetAccounts { get; set; }
|
||||
}
|
||||
|
||||
// ─── Step 7: Notification Preferences ───────────────────────────────────────
|
||||
public class WizardStep7Dto
|
||||
{
|
||||
[Display(Name = "Enable Email Notifications")]
|
||||
public bool EmailNotificationsEnabled { get; set; } = true;
|
||||
|
||||
[EmailAddress, MaxLength(200)]
|
||||
[Display(Name = "Send Emails From Address")]
|
||||
public string? EmailFromAddress { get; set; }
|
||||
|
||||
[MaxLength(200)]
|
||||
[Display(Name = "From Display Name")]
|
||||
public string? EmailFromName { get; set; }
|
||||
|
||||
[Display(Name = "Notify on New Job Created")]
|
||||
public bool NotifyOnNewJob { get; set; } = true;
|
||||
|
||||
[Display(Name = "Notify on New Quote Created")]
|
||||
public bool NotifyOnNewQuote { get; set; } = true;
|
||||
|
||||
[Display(Name = "Notify on Job Status Change")]
|
||||
public bool NotifyOnJobStatusChange { get; set; } = true;
|
||||
|
||||
[Display(Name = "Notify on Quote Approval")]
|
||||
public bool NotifyOnQuoteApproval { get; set; } = true;
|
||||
|
||||
[Display(Name = "Notify on Payment Received")]
|
||||
public bool NotifyOnPaymentReceived { get; set; } = true;
|
||||
|
||||
[Display(Name = "Enable Automated Payment Reminders")]
|
||||
public bool PaymentRemindersEnabled { get; set; } = false;
|
||||
|
||||
[MaxLength(50)]
|
||||
[Display(Name = "Reminder Days (comma-separated, days past due)")]
|
||||
public string PaymentReminderDays { get; set; } = "7,14,30";
|
||||
|
||||
// Alert Thresholds
|
||||
[Range(0, 90)]
|
||||
[Display(Name = "Quote Expiry Warning (days before expiry)")]
|
||||
public int QuoteExpiryWarningDays { get; set; } = 3;
|
||||
|
||||
[Range(0, 90)]
|
||||
[Display(Name = "Due Date Warning (days before due)")]
|
||||
public int DueDateWarningDays { get; set; } = 2;
|
||||
|
||||
[Range(0, 90)]
|
||||
[Display(Name = "Maintenance Alert (days before scheduled date)")]
|
||||
public int MaintenanceAlertDays { get; set; } = 7;
|
||||
}
|
||||
|
||||
// ─── Step 8: Inventory / Powder Colors ──────────────────────────────────────
|
||||
public class WizardStep8Dto
|
||||
{
|
||||
/// <summary>JSON array of WizardInventoryItemDto submitted as a hidden field</summary>
|
||||
public string? ItemsJson { get; set; }
|
||||
}
|
||||
|
||||
public class WizardInventoryItemDto
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? ColorName { get; set; }
|
||||
public string? ColorCode { get; set; }
|
||||
public string? Manufacturer { get; set; }
|
||||
public string? Finish { get; set; }
|
||||
public decimal UnitCost { get; set; }
|
||||
public decimal QuantityOnHand { get; set; }
|
||||
}
|
||||
|
||||
// ─── Step 9: Team Members ────────────────────────────────────────────────────
|
||||
public class WizardStep9Dto
|
||||
{
|
||||
/// <summary>JSON array of WizardTeamMemberDto submitted as a hidden field</summary>
|
||||
public string? MembersJson { get; set; }
|
||||
}
|
||||
|
||||
public class WizardTeamMemberDto
|
||||
{
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string CompanyRole { get; set; } = "Worker";
|
||||
}
|
||||
|
||||
// ─── Step 10: Vendors & Suppliers ────────────────────────────────────────────
|
||||
public class WizardStep10Dto
|
||||
{
|
||||
/// <summary>JSON array of WizardVendorDto submitted as a hidden field</summary>
|
||||
public string? VendorsJson { get; set; }
|
||||
}
|
||||
|
||||
public class WizardVendorDto
|
||||
{
|
||||
public string CompanyName { get; set; } = string.Empty;
|
||||
public string? ContactName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string? Website { get; set; }
|
||||
}
|
||||
|
||||
// ─── Step 14: Equipment / Named Ovens + Blast Setups ────────────────────────
|
||||
public class WizardOvensStepDto
|
||||
{
|
||||
/// <summary>JSON array of WizardOvenDto submitted as a hidden field</summary>
|
||||
public string? OvensJson { get; set; }
|
||||
|
||||
/// <summary>JSON array of WizardBlastSetupDto submitted as a hidden field</summary>
|
||||
public string? BlastSetupsJson { get; set; }
|
||||
}
|
||||
|
||||
public class WizardOvenDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public decimal CostPerHour { get; set; }
|
||||
public decimal? MaxLoadSqFt { get; set; }
|
||||
public int? DefaultCycleMinutes { get; set; }
|
||||
}
|
||||
|
||||
public class WizardBlastSetupDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
/// <summary>Maps to BlastSetupType enum: 0=SiphonCabinet, 1=SiphonPot, 2=PressurePot, 3=WetBlasting</summary>
|
||||
public int SetupType { get; set; } = 2;
|
||||
public decimal CompressorCfm { get; set; }
|
||||
/// <summary>Nozzle orifice number 2–8.</summary>
|
||||
public int BlastNozzleSize { get; set; } = 5;
|
||||
/// <summary>Maps to BlastSubstrateType enum: 0=Paint, 1=PowderCoat, 2=RustAndScale, 3=Mixed</summary>
|
||||
public int PrimarySubstrate { get; set; } = 3;
|
||||
public decimal? BlastRateSqFtPerHourOverride { get; set; }
|
||||
public bool IsDefault { get; set; }
|
||||
}
|
||||
|
||||
// ─── Step 15: Pricing Tiers ──────────────────────────────────────────────────
|
||||
public class WizardPricingTiersStepDto
|
||||
{
|
||||
/// <summary>JSON array of WizardPricingTierDto submitted as a hidden field</summary>
|
||||
public string? TiersJson { get; set; }
|
||||
}
|
||||
|
||||
public class WizardPricingTierDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string TierName { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public decimal DiscountPercent { get; set; }
|
||||
}
|
||||
|
||||
// ─── Step 16: Service Catalog ────────────────────────────────────────────────
|
||||
public class WizardCatalogStepDto
|
||||
{
|
||||
/// <summary>JSON array of WizardCatalogItemDto submitted as a hidden field</summary>
|
||||
public string? ItemsJson { get; set; }
|
||||
}
|
||||
|
||||
public class WizardCatalogItemDto
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public decimal DefaultPrice { get; set; }
|
||||
public decimal? ApproximateArea { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user