6c2fe6e1c4
- New EmployeeClockEntry entity (facility-level attendance, separate from job time entries) - KioskPin added to ApplicationUser; TimeclockKioskToken added to Company - TimeclockController: clock in/out, who's in, 14-day history, manager edit/delete, tablet kiosk with device-cookie auth, PIN management via Users edit page - Kiosk UI: employee tile grid + 4-digit PIN pad + auto-detect clock-in vs clock-out - Attendance report at /Reports/Attendance with weekly subtotal rows - Payroll CSV export at /Reports/AttendanceCsv (flat, one row per segment) - AllowCustomFormulas wired through PlatformSubscriptionController + subscription views - Fix soft-delete bug on CustomItemTemplate (missing HasQueryFilter in OnModelCreating) - Help article (Help/Timeclock.cshtml) and AI knowledge base updated - Migrations: AddEmployeeTimeclock, AddTimeclockKioskToken Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
61 lines
3.0 KiB
C#
61 lines
3.0 KiB
C#
namespace PowderCoating.Core.Entities;
|
|
|
|
/// <summary>
|
|
/// Stores plan limits and pricing in the database so SuperAdmins can edit without a code deploy.
|
|
/// Global (not per-company). CompanyId is set to 0 / unused. No tenant query filter applied.
|
|
/// The Plan integer is the identifier that links Company.SubscriptionPlan to a config row.
|
|
/// </summary>
|
|
public class SubscriptionPlanConfig : BaseEntity
|
|
{
|
|
public int Plan { get; set; }
|
|
public string DisplayName { get; set; } = string.Empty;
|
|
public string? Description { get; set; }
|
|
|
|
/// <summary>-1 = unlimited</summary>
|
|
public int MaxUsers { get; set; }
|
|
/// <summary>-1 = unlimited</summary>
|
|
public int MaxActiveJobs { get; set; }
|
|
/// <summary>-1 = unlimited</summary>
|
|
public int MaxCustomers { get; set; }
|
|
/// <summary>-1 = unlimited. Counts active (non-terminal) quotes.</summary>
|
|
public int MaxQuotes { get; set; } = -1;
|
|
/// <summary>-1 = unlimited. Counts total non-deleted catalog items.</summary>
|
|
public int MaxCatalogItems { get; set; } = -1;
|
|
/// <summary>-1 = unlimited. Max job photos per job.</summary>
|
|
public int MaxJobPhotos { get; set; } = -1;
|
|
/// <summary>-1 = unlimited. Max general (non-AI) photos per quote.</summary>
|
|
public int MaxQuotePhotos { get; set; } = -1;
|
|
/// <summary>-1 = unlimited. 0 = AI photo quotes disabled for this plan. Monthly limit per company.</summary>
|
|
public int MaxAiPhotoQuotesPerMonth { get; set; } = -1;
|
|
|
|
public decimal MonthlyPrice { get; set; }
|
|
public decimal AnnualPrice { get; set; }
|
|
|
|
public string? StripePriceIdMonthly { get; set; }
|
|
public string? StripePriceIdAnnual { get; set; }
|
|
|
|
/// <summary>When true, companies on this plan can connect Stripe and accept online invoice payments.</summary>
|
|
public bool AllowOnlinePayments { get; set; } = false;
|
|
|
|
/// <summary>When true, companies on this plan can access accounting features: Chart of Accounts, Bills, Expenses, and Accounting Export.</summary>
|
|
public bool AllowAccounting { get; set; } = false;
|
|
|
|
/// <summary>When true, companies on this plan can use AI Photo Quote analysis (subject to MaxAiPhotoQuotesPerMonth).</summary>
|
|
public bool AllowAiPhotoQuotes { get; set; } = false;
|
|
|
|
/// <summary>When true, companies on this plan can use the AI Inventory Assist lookup feature.</summary>
|
|
public bool AllowAiInventoryAssist { get; set; } = false;
|
|
|
|
/// <summary>When true, companies on this plan can run the AI Catalog Price Check (Enterprise only).</summary>
|
|
public bool AllowAiCatalogPriceCheck { get; set; } = false;
|
|
|
|
/// <summary>When true, companies on this plan can send SMS notifications to customers (subject to platform kill-switch and per-company opt-in).</summary>
|
|
public bool AllowSms { get; set; } = false;
|
|
|
|
/// <summary>When true, companies on this plan can create and use Custom Formula Item Templates in quotes and jobs.</summary>
|
|
public bool AllowCustomFormulas { get; set; } = false;
|
|
|
|
public bool IsActive { get; set; } = true;
|
|
public int SortOrder { get; set; }
|
|
}
|