1a44133a63
Removes the ShopWorker and ShopWorkerRoleCost entities, all related DTOs, mappings, controllers, views, and import/export paths. Worker identity is now handled entirely through ApplicationUser with per-user LaborCostPerHour. ShopWorkerRoleCosts table remains in production pending manual data migration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
159 lines
6.8 KiB
C#
159 lines
6.8 KiB
C#
using System.ComponentModel.DataAnnotations;
|
||
using PowderCoating.Core.Enums;
|
||
|
||
namespace PowderCoating.Core.Entities
|
||
{
|
||
public class CompanyOperatingCosts : BaseEntity
|
||
{
|
||
// Navigation
|
||
public new int CompanyId { get; set; }
|
||
public virtual Company Company { get; set; } = null!;
|
||
|
||
// Labor Rates (per hour, in currency)
|
||
[Range(0, 10000)]
|
||
public decimal StandardLaborRate { get; set; }
|
||
|
||
/// <summary>
|
||
/// Actual labor cost per hour (wages + burden) used exclusively for internal job costing and profit/margin display.
|
||
/// This is NOT the billing rate — it should reflect what you actually pay workers.
|
||
/// When null, the costing engine defaults to 20% of StandardLaborRate.
|
||
/// </summary>
|
||
[Range(0, 10000)]
|
||
public decimal? LaborCostPerHour { get; set; }
|
||
|
||
// Additional Coat Labor Percentage (percentage of base labor for each additional coat beyond the first)
|
||
[Range(0, 100)]
|
||
public decimal AdditionalCoatLaborPercent { get; set; } = 30m;
|
||
|
||
// Equipment Operating Costs (per hour)
|
||
[Range(0, 10000)]
|
||
public decimal OvenOperatingCostPerHour { get; set; }
|
||
|
||
[Range(0, 10000)]
|
||
public decimal SandblasterCostPerHour { get; set; }
|
||
|
||
[Range(0, 10000)]
|
||
public decimal CoatingBoothCostPerHour { get; set; }
|
||
|
||
// Material Costs
|
||
[Range(0, 1000)]
|
||
public decimal PowderCoatingCostPerSqFt { get; set; } // per square foot
|
||
|
||
// Markup / Margin
|
||
/// <summary>Whether markup is applied to material only, or margin is applied to total item cost.</summary>
|
||
public PricingMode PricingMode { get; set; } = PricingMode.MarkupOnMaterial;
|
||
|
||
/// <summary>Markup % added on top of material costs (used when PricingMode = MarkupOnMaterial).</summary>
|
||
[Range(0, 100)]
|
||
public decimal GeneralMarkupPercentage { get; set; }
|
||
|
||
/// <summary>Target gross margin % applied to total item cost (used when PricingMode = MarginOnTotalCost).</summary>
|
||
[Range(0, 99)]
|
||
public decimal TargetMarginPercent { get; set; }
|
||
|
||
// Tax Percentage
|
||
[Range(0, 100)]
|
||
public decimal TaxPercent { get; set; }
|
||
|
||
// Shop Supplies Rate (percentage applied to materials/labor)
|
||
[Range(0, 100)]
|
||
public decimal ShopSuppliesRate { get; set; }
|
||
|
||
// Oven batch defaults
|
||
[Range(1, 1440)]
|
||
public int DefaultOvenCycleMinutes { get; set; } = 45;
|
||
|
||
// Rush Charge
|
||
public string RushChargeType { get; set; } = "Percentage"; // "Percentage" or "FixedAmount"
|
||
|
||
[Range(0, 100)]
|
||
public decimal RushChargePercentage { get; set; }
|
||
|
||
[Range(0, 100000)]
|
||
public decimal RushChargeFixedAmount { get; set; }
|
||
|
||
// Shop Minimum
|
||
[Range(0, 100000)]
|
||
public decimal ShopMinimumCharge { get; set; }
|
||
|
||
// Part Complexity Multipliers (% added to calculated item price)
|
||
[Range(0, 500)]
|
||
public decimal ComplexitySimplePercent { get; set; } = 0m;
|
||
|
||
[Range(0, 500)]
|
||
public decimal ComplexityModeratePercent { get; set; } = 5m;
|
||
|
||
[Range(0, 500)]
|
||
public decimal ComplexityComplexPercent { get; set; } = 15m;
|
||
|
||
[Range(0, 500)]
|
||
public decimal ComplexityExtremePercent { get; set; } = 25m;
|
||
|
||
/// <summary>
|
||
/// Free-text description of this shop's specialties, typical item types, and pricing style.
|
||
/// Injected into the AI system prompt so the model can calibrate estimates for this company.
|
||
/// Example: "We specialize in automotive restoration parts — wheels, frames, brackets.
|
||
/// We charge premium rates and rarely work on items over 20 sqft."
|
||
/// </summary>
|
||
[StringLength(2000)]
|
||
public string? AiContextProfile { get; set; }
|
||
|
||
// ── Shop Capability / Quoting Calibration ─────────────────────────────────────
|
||
// These fields drive the derived BlastRateSqFtPerHour used in AI photo quoting
|
||
// and calculated item time suggestions. The Override field lets a shop bypass the
|
||
// formula and enter their real-world number directly.
|
||
|
||
/// <summary>Broad capability tier chosen in Setup Wizard; sets sensible defaults for all fields below.</summary>
|
||
public ShopCapabilityTier ShopCapabilityTier { get; set; } = ShopCapabilityTier.Small;
|
||
|
||
/// <summary>Type of blasting setup — biggest single factor in blast throughput.</summary>
|
||
public BlastSetupType BlastSetupType { get; set; } = BlastSetupType.SiphonCabinet;
|
||
|
||
/// <summary>Compressor CFM available for the blast setup.</summary>
|
||
[Range(0, 2000)]
|
||
public decimal CompressorCfm { get; set; } = 0m;
|
||
|
||
/// <summary>Blast nozzle size (#3 – #8). Larger nozzle = more media flow.</summary>
|
||
[Range(3, 8)]
|
||
public int BlastNozzleSize { get; set; } = 4;
|
||
|
||
/// <summary>Primary substrate being removed; affects passes required per sqft.</summary>
|
||
public BlastSubstrateType PrimaryBlastSubstrate { get; set; } = BlastSubstrateType.Mixed;
|
||
|
||
/// <summary>
|
||
/// Manual blast rate override (sqft/hr). When set, the formula is bypassed entirely.
|
||
/// Useful for dialed-in shops who know their exact throughput.
|
||
/// </summary>
|
||
[Range(0, 5000)]
|
||
public decimal? BlastRateSqFtPerHourOverride { get; set; }
|
||
|
||
/// <summary>Coating gun technology — affects application speed on complex parts.</summary>
|
||
public CoatingGunType CoatingGunType { get; set; } = CoatingGunType.Corona;
|
||
|
||
/// <summary>
|
||
/// Manual coating application rate override (sqft/hr). When set, bypasses the formula.
|
||
/// </summary>
|
||
[Range(0, 5000)]
|
||
public decimal? CoatingRateSqFtPerHourOverride { get; set; }
|
||
|
||
// ── Facility Overhead ─────────────────────────────────────────────────────
|
||
// Monthly fixed costs divided by billable hours to derive a per-hour overhead
|
||
// rate, which is then applied to each quote based on estimated labor time.
|
||
|
||
/// <summary>Monthly shop lease / rent payment.</summary>
|
||
[Range(0, 1000000)]
|
||
public decimal MonthlyRent { get; set; } = 0m;
|
||
|
||
/// <summary>Monthly utilities combined (electricity, gas, water, internet).</summary>
|
||
[Range(0, 1000000)]
|
||
public decimal MonthlyUtilities { get; set; } = 0m;
|
||
|
||
/// <summary>
|
||
/// Estimated billable shop hours per month used to amortise facility overhead.
|
||
/// Defaults to 160 (4 weeks × 40 hrs). Must be at least 1 to avoid division by zero.
|
||
/// </summary>
|
||
[Range(1, 10000)]
|
||
public int MonthlyBillableHours { get; set; } = 160;
|
||
}
|
||
}
|