feat: implement annual subscription model across backend quota system and flutter UI
This commit is contained in:
@@ -57,10 +57,10 @@ final class QuotaMiddleware
|
||||
json_error('اشتراكك متأخر الدفع. يرجى تسوية المبلغ المستحق للمتابعة.', 403);
|
||||
}
|
||||
|
||||
// Auto-reset monthly counter if billing period has ended
|
||||
// Auto-reset period counter if billing period has ended
|
||||
if (!empty($sub['current_period_end']) && strtotime($sub['current_period_end']) < time()) {
|
||||
$newStart = date('Y-m-d H:i:s');
|
||||
$newEnd = date('Y-m-d H:i:s', strtotime('+30 days'));
|
||||
$newEnd = date('Y-m-d H:i:s', strtotime('+1 year')); // Changed to annual
|
||||
|
||||
$resetStmt = $db->prepare("
|
||||
UPDATE subscriptions
|
||||
@@ -76,15 +76,15 @@ final class QuotaMiddleware
|
||||
$sub['current_period_start'] = $newStart;
|
||||
$sub['current_period_end'] = $newEnd;
|
||||
|
||||
error_log("QuotaMiddleware: Auto-reset monthly counter for tenant {$tenantId}");
|
||||
error_log("QuotaMiddleware: Auto-reset annual counter for tenant {$tenantId}");
|
||||
}
|
||||
|
||||
// Check invoice quota
|
||||
$used = (int)$sub['invoices_used_this_month'];
|
||||
$limit = (int)$sub['max_invoices_per_month'];
|
||||
$limit = (int)$sub['max_invoices_per_month']; // Keeping the DB column name the same for compatibility
|
||||
|
||||
if ($used >= $limit) {
|
||||
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
|
||||
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة في باقتك الحالية (' . $limit . ' فاتورة). يرجى ترقية باقتك للاستمرار.', 429, [
|
||||
'quota_type' => 'invoices',
|
||||
'used' => $used,
|
||||
'limit' => $limit,
|
||||
|
||||
@@ -57,10 +57,10 @@ final class QuotaMiddleware
|
||||
json_error('اشتراكك متأخر الدفع. يرجى تسوية المبلغ المستحق للمتابعة.', 403);
|
||||
}
|
||||
|
||||
// Auto-reset monthly counter if billing period has ended
|
||||
// Auto-reset period counter if billing period has ended
|
||||
if (!empty($sub['current_period_end']) && strtotime($sub['current_period_end']) < time()) {
|
||||
$newStart = date('Y-m-d H:i:s');
|
||||
$newEnd = date('Y-m-d H:i:s', strtotime('+30 days'));
|
||||
$newEnd = date('Y-m-d H:i:s', strtotime('+1 year')); // Changed to annual
|
||||
|
||||
$resetStmt = $db->prepare("
|
||||
UPDATE subscriptions
|
||||
@@ -76,15 +76,15 @@ final class QuotaMiddleware
|
||||
$sub['current_period_start'] = $newStart;
|
||||
$sub['current_period_end'] = $newEnd;
|
||||
|
||||
error_log("QuotaMiddleware: Auto-reset monthly counter for tenant {$tenantId}");
|
||||
error_log("QuotaMiddleware: Auto-reset annual counter for tenant {$tenantId}");
|
||||
}
|
||||
|
||||
// Check invoice quota
|
||||
$used = (int)$sub['invoices_used_this_month'];
|
||||
$limit = (int)$sub['max_invoices_per_month'];
|
||||
$limit = (int)$sub['max_invoices_per_month']; // Keeping the DB column name the same for compatibility
|
||||
|
||||
if ($used >= $limit) {
|
||||
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
|
||||
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة في باقتك الحالية (' . $limit . ' فاتورة). يرجى ترقية باقتك للاستمرار.', 429, [
|
||||
'quota_type' => 'invoices',
|
||||
'used' => $used,
|
||||
'limit' => $limit,
|
||||
|
||||
@@ -302,7 +302,7 @@ class SubscriptionView extends StatelessWidget {
|
||||
children: [
|
||||
_buildPlanStat(Icons.business, '${plan['max_companies'] ?? 0} شركات'),
|
||||
const SizedBox(width: 8),
|
||||
_buildPlanStat(Icons.receipt_long, '${plan['max_invoices_month'] ?? 0} فاتورة/شهر'),
|
||||
_buildPlanStat(Icons.receipt_long, '${plan['max_invoices_month'] ?? 0} فاتورة/سنة'),
|
||||
const SizedBox(width: 8),
|
||||
_buildPlanStat(Icons.people, '${plan['max_users'] ?? 0} مستخدمين'),
|
||||
],
|
||||
|
||||
46
update_annual_plans.sql
Normal file
46
update_annual_plans.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- 1. Update existing plans to annual quotas and pricing
|
||||
-- We'll assume the basic plan ID is 'basic' and pro is 'pro'. If they are different, they will need adjusting.
|
||||
|
||||
-- Basic Plan (Annual)
|
||||
UPDATE subscription_plans
|
||||
SET
|
||||
name_ar = 'الباقة الأساسية (سنوي)',
|
||||
name_en = 'Basic Plan (Annual)',
|
||||
price = 120.00,
|
||||
max_invoices_per_month = 12000,
|
||||
max_companies = 1,
|
||||
max_users = 1
|
||||
WHERE id = 'basic';
|
||||
|
||||
-- Pro Plan (Annual)
|
||||
UPDATE subscription_plans
|
||||
SET
|
||||
name_ar = 'الباقة الاحترافية (سنوي)',
|
||||
name_en = 'Pro Plan (Annual)',
|
||||
price = 250.00,
|
||||
max_invoices_per_month = 50000,
|
||||
max_companies = 9999, -- unlimited
|
||||
max_users = 5
|
||||
WHERE id = 'pro';
|
||||
|
||||
-- Free Trial Plan
|
||||
UPDATE subscription_plans
|
||||
SET
|
||||
name_ar = 'التجربة المجانية',
|
||||
name_en = 'Free Trial',
|
||||
price = 0.00,
|
||||
max_invoices_per_month = 15,
|
||||
max_companies = 1,
|
||||
max_users = 1
|
||||
WHERE id = 'free';
|
||||
|
||||
-- 2. Update existing active subscriptions to match the new annual quota limits so no one gets blocked
|
||||
UPDATE subscriptions s
|
||||
JOIN subscription_plans sp ON s.plan_id = sp.id
|
||||
SET
|
||||
s.max_invoices_per_month = sp.max_invoices_per_month,
|
||||
s.max_companies = sp.max_companies,
|
||||
s.max_users = sp.max_users,
|
||||
-- Adjust the period end to +1 year if it's currently set to a month (for paid plans only)
|
||||
s.current_period_end = IF(s.plan_id != 'free', DATE_ADD(s.current_period_start, INTERVAL 1 YEAR), s.current_period_end);
|
||||
|
||||
6
update_plans.php
Normal file
6
update_plans.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/app/bootstrap/init.php';
|
||||
use App\Core\Database;
|
||||
$db = Database::getInstance();
|
||||
$plans = $db->query("SELECT * FROM subscription_plans")->fetchAll();
|
||||
print_r($plans);
|
||||
Reference in New Issue
Block a user