Initial commit

This commit is contained in:
2026-04-23 21:38:24 -04:00
commit 63e12a9636
1762 changed files with 1672620 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
using PowderCoating.Core.Enums;
namespace PowderCoating.Core.Entities;
/// <summary>
/// Represents a company/tenant in the multi-tenant system
/// </summary>
public class Company : BaseEntity
{
// Basic Information
public string CompanyName { get; set; } = string.Empty;
public string? CompanyCode { get; set; } // Short code (e.g., ABC)
// Contact Information
public string PrimaryContactName { get; set; } = string.Empty;
public string PrimaryContactEmail { get; set; } = string.Empty;
public string? Phone { get; set; }
// Address
public string? Address { get; set; }
public string? City { get; set; }
public string? State { get; set; }
public string? ZipCode { get; set; }
// Subscription/Status
public bool IsActive { get; set; } = true;
public DateTime SubscriptionStartDate { get; set; } = DateTime.UtcNow;
public DateTime? SubscriptionEndDate { get; set; }
public int SubscriptionPlan { get; set; } = 0;
public SubscriptionStatus SubscriptionStatus { get; set; } = SubscriptionStatus.Active;
public string? StripeCustomerId { get; set; }
public string? StripeSubscriptionId { get; set; }
/// <summary>
/// When true the company has complimentary/internal access.
/// All plan limits are treated as unlimited and the subscription
/// expiry banner/lockout is suppressed regardless of SubscriptionEndDate.
/// </summary>
public bool IsComped { get; set; } = false;
// Stripe Connect — online invoice payments
public string? StripeAccountId { get; set; } // acct_xxx from OAuth
public StripeConnectStatus StripeConnectStatus { get; set; } = StripeConnectStatus.NotConnected;
public OnlinePaymentSurchargeType OnlinePaymentSurchargeType { get; set; } = OnlinePaymentSurchargeType.None;
public decimal OnlinePaymentSurchargeValue { get; set; } = 0; // % or flat $ depending on type
public bool OnlineSurchargeAcknowledged { get; set; } = false; // shop accepted compliance disclaimer
/// <summary>Internal notes about manual subscription changes (not shown to the company).</summary>
public string? SubscriptionNotes { get; set; }
// Per-company limit overrides. null = use plan config default. -1 = unlimited.
public int? MaxUsersOverride { get; set; }
public int? MaxActiveJobsOverride { get; set; }
public int? MaxCustomersOverride { get; set; }
public int? MaxQuotesOverride { get; set; }
public int? MaxCatalogItemsOverride { get; set; }
public int? MaxJobPhotosOverride { get; set; }
public int? MaxQuotePhotosOverride { get; set; }
/// <summary>null = use plan config default. -1 = unlimited. 0 = disabled for this company.</summary>
public int? MaxAiPhotoQuotesPerMonthOverride { get; set; }
// AI Feature Flags (SuperAdmin-controlled per company)
/// <summary>Enables/disables AI Photo Quote analysis for this company.</summary>
public bool AiPhotoQuotesEnabled { get; set; } = true;
/// <summary>Enables/disables the AI Inventory Assist lookup for this company.</summary>
public bool AiInventoryAssistEnabled { get; set; } = true;
/// <summary>
/// Stores the billing period the customer selected at registration (or last changed on the Billing page).
/// true = annual billing, false = monthly billing.
/// Used when redirecting to Stripe Checkout at trial-end so the right price ID is used automatically.
/// </summary>
public bool IsAnnualBilling { get; set; } = false;
// Per-company feature overrides (SuperAdmin-controlled)
/// <summary>
/// null = use plan config default.
/// true = force-enable online payments for this company regardless of plan.
/// false = force-disable online payments for this company regardless of plan.
/// </summary>
public bool? OnlinePaymentsOverride { get; set; }
/// <summary>
/// null = use plan config default.
/// true = force-enable accounting module for this company regardless of plan.
/// false = force-disable accounting module for this company regardless of plan.
/// </summary>
public bool? AccountingOverride { get; set; }
// Email marketing opt-out (CAN-SPAM compliance for platform broadcast emails)
public bool MarketingEmailOptOut { get; set; } = false;
public string MarketingUnsubscribeToken { get; set; } = Guid.NewGuid().ToString("N");
// Settings
public string? TimeZone { get; set; } = "America/New_York";
public byte[]? LogoData { get; set; } // Legacy - kept for backward compatibility
public string? LogoContentType { get; set; } // Legacy - kept for backward compatibility
public string? LogoFilePath { get; set; } // Filesystem path: /media/{CompanyId}/company-logo.{ext}
// Navigation Properties
public virtual ICollection<ApplicationUser> Users { get; set; } = new List<ApplicationUser>();
public virtual ICollection<Customer> Customers { get; set; } = new List<Customer>();
public virtual ICollection<Job> Jobs { get; set; } = new List<Job>();
public virtual ICollection<Equipment> Equipment { get; set; } = new List<Equipment>();
public virtual ICollection<Quote> Quotes { get; set; } = new List<Quote>();
public virtual ICollection<InventoryItem> InventoryItems { get; set; } = new List<InventoryItem>();
public virtual ICollection<Vendor> Vendors { get; set; } = new List<Vendor>();
public virtual ICollection<ShopWorker> ShopWorkers { get; set; } = new List<ShopWorker>();
public virtual ICollection<PricingTier> PricingTiers { get; set; } = new List<PricingTier>();
public virtual CompanyOperatingCosts? OperatingCosts { get; set; }
public virtual CompanyPreferences? Preferences { get; set; }
}