feat: plan limits, café location, nearby API, Iran map section
CI/CD / CI · API (dotnet build + test) (push) Successful in 56s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 49s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m4s
CI/CD / CI · Admin Web (tsc) (push) Successful in 34s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 3m15s
CI/CD / CI · API (dotnet build + test) (push) Successful in 56s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 49s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m4s
CI/CD / CI · Admin Web (tsc) (push) Successful in 34s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 3m15s
• PlanLimits: add MaxMenuCategories (Free→3), MaxMenuItems (Free→30), CanAccessCrm and CanAccessStatistics (Pro+ only) • MenuController: enforce category/item limits before create (403 + PLAN_LIMIT_REACHED) • Cafe entity + EF migration: Latitude/Longitude (double?, nullable) • CafeSettingsController: PATCH accepts lat/lng with range validation • PublicController: GET /api/public/map-markers (marketing SVG map feed) and GET /api/public/nearby (Koja nearby-cafés with Haversine sort) • Dashboard settings: location card with OSM iframe preview + Neshan link • Website homepage: IranMapSection — stylised SVG silhouette with SMIL-animated blinking dots at real café coordinates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -54,4 +54,24 @@ public static class PlanLimits
|
||||
PlanTier.Enterprise => 100,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
/// <summary>Maximum active menu categories. Free tier is capped at 3; Pro+ is unlimited.</summary>
|
||||
public static int MaxMenuCategories(PlanTier tier) => tier switch
|
||||
{
|
||||
PlanTier.Free => 3,
|
||||
_ => int.MaxValue
|
||||
};
|
||||
|
||||
/// <summary>Maximum menu items. Free tier is capped at 30; Pro+ is unlimited.</summary>
|
||||
public static int MaxMenuItems(PlanTier tier) => tier switch
|
||||
{
|
||||
PlanTier.Free => 30,
|
||||
_ => int.MaxValue
|
||||
};
|
||||
|
||||
/// <summary>CRM (customers, loyalty) is only available on Pro and above.</summary>
|
||||
public static bool CanAccessCrm(PlanTier tier) => tier >= PlanTier.Pro;
|
||||
|
||||
/// <summary>Statistics and analytics dashboards are only available on Pro and above.</summary>
|
||||
public static bool CanAccessStatistics(PlanTier tier) => tier >= PlanTier.Pro;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ public class Cafe : BaseEntity
|
||||
public string? InstagramHandle { get; set; }
|
||||
/// <summary>Cafe website URL, max 300 chars.</summary>
|
||||
public string? WebsiteUrl { get; set; }
|
||||
/// <summary>WGS-84 latitude (positive = north). Null until owner sets location.</summary>
|
||||
public double? Latitude { get; set; }
|
||||
/// <summary>WGS-84 longitude (positive = east). Null until owner sets location.</summary>
|
||||
public double? Longitude { get; set; }
|
||||
/// <summary>Default VAT/sales tax % for all branches unless branch override is allowed.</summary>
|
||||
public decimal DefaultTaxRate { get; set; } = 9m;
|
||||
public bool AllowBranchTaxOverride { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user