feat(plans): Stage 3b — DB-driven gates for reviews/styling/limits
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m0s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 42s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 38s
CI/CD / CI · Website (tsc) (push) Successful in 45s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Successful in 2m51s
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m0s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 42s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 38s
CI/CD / CI · Website (tsc) (push) Successful in 45s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Successful in 2m51s
Make more plan rules read the admin-editable catalog instead of hardcoded values: - Review reply gated by the `review_reply` feature (Starter+) — 403 if not in plan. - Custom menu styling gated by `custom_menu_styling` (Starter+): only blocks an actual theme change, so a normal settings save re-sending the current theme is fine. - Menu categories/items limits now read catalog.GetLimitsAsync (Free categories editable; message no longer hardcodes a number). - Terminals limit reads the catalog (enforcement in TerminalRegistryService + the displayed max in TerminalsController). Remaining (small): menu watermark (Free shows it, `watermark_removed` removes it — needs the public-menu render), report-history (static ReportPlanGate) and AI-3D routing — these already enforce the correct matrix values, just not yet editable. 86 tests pass; build clean.
This commit is contained in:
@@ -3,10 +3,12 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Meezi.API.Models.Cafes;
|
||||
using Meezi.API.Services;
|
||||
using Meezi.Core.Enums;
|
||||
using Meezi.Core.Interfaces;
|
||||
using Meezi.Core.Utilities;
|
||||
using Meezi.Infrastructure.Branding;
|
||||
using Meezi.Infrastructure.Data;
|
||||
using Meezi.Infrastructure.Services.Platform;
|
||||
using Meezi.Shared;
|
||||
|
||||
namespace Meezi.API.Controllers;
|
||||
@@ -16,11 +18,16 @@ public class CafeSettingsController : CafeApiControllerBase
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
private readonly IValidator<PatchCafeSettingsRequest> _validator;
|
||||
private readonly IPlatformCatalogService _catalog;
|
||||
|
||||
public CafeSettingsController(AppDbContext db, IValidator<PatchCafeSettingsRequest> validator)
|
||||
public CafeSettingsController(
|
||||
AppDbContext db,
|
||||
IValidator<PatchCafeSettingsRequest> validator,
|
||||
IPlatformCatalogService catalog)
|
||||
{
|
||||
_db = db;
|
||||
_validator = validator;
|
||||
_catalog = catalog;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
@@ -81,7 +88,19 @@ public class CafeSettingsController : CafeApiControllerBase
|
||||
if (request.CoverImageUrl is not null) cafe.CoverImageUrl = request.CoverImageUrl.Trim();
|
||||
if (request.SnappfoodVendorId is not null) cafe.SnappfoodVendorId = request.SnappfoodVendorId.Trim();
|
||||
if (request.Theme is not null)
|
||||
cafe.ThemeJson = CafeThemeSerializer.Serialize(CafeThemeMapping.FromDto(request.Theme));
|
||||
{
|
||||
// Custom menu styling is a paid feature (Starter+). Only block an actual change,
|
||||
// so a normal settings save that re-sends the current theme isn't rejected.
|
||||
var newThemeJson = CafeThemeSerializer.Serialize(CafeThemeMapping.FromDto(request.Theme));
|
||||
if (newThemeJson != cafe.ThemeJson)
|
||||
{
|
||||
var styleTier = tenant.PlanTier ?? PlanTier.Free;
|
||||
if (!await _catalog.IsFeatureEnabledForCafeAsync(cafeId, styleTier, "custom_menu_styling", ct))
|
||||
return StatusCode(403, new ApiResponse<object>(false, null,
|
||||
new ApiError("PLAN_FEATURE_DISABLED", "Custom menu styling is not included in your plan. Please upgrade.")));
|
||||
cafe.ThemeJson = newThemeJson;
|
||||
}
|
||||
}
|
||||
if (request.DefaultTaxRate is decimal taxRate)
|
||||
cafe.DefaultTaxRate = taxRate;
|
||||
if (request.AllowBranchTaxOverride is bool allowTax)
|
||||
|
||||
Reference in New Issue
Block a user