118 lines
3.8 KiB
PHP
118 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Core\Database;
|
|
|
|
/**
|
|
* CompanySubscriptionUsage Model
|
|
* Tracks API usage stats per company dynamically linked to active billing cycles.
|
|
*/
|
|
class CompanySubscriptionUsage extends BaseModel
|
|
{
|
|
protected static string $table = 'company_subscription_usage';
|
|
|
|
/**
|
|
* Get or initialize usage record for the active billing cycle of a company
|
|
*/
|
|
public static function getOrCreateCurrentUsage(int $companyId, array $activeSubscription): array
|
|
{
|
|
$billingStart = date('Y-m-d', strtotime($activeSubscription['starts_at']));
|
|
$billingEnd = date('Y-m-d', strtotime($activeSubscription['ends_at']));
|
|
|
|
// Check if usage record already exists
|
|
$usage = Database::selectOne(
|
|
"SELECT * FROM " . static::$table . "
|
|
WHERE company_id = ? AND billing_start = ? AND billing_end = ?
|
|
LIMIT 1",
|
|
[$companyId, $billingStart, $billingEnd]
|
|
);
|
|
|
|
if (!$usage) {
|
|
// Initialize new record
|
|
try {
|
|
$id = self::create([
|
|
'company_id' => $companyId,
|
|
'billing_start' => $billingStart,
|
|
'billing_end' => $billingEnd,
|
|
'request_count' => 0,
|
|
'voice_count' => 0,
|
|
'ocr_count' => 0
|
|
]);
|
|
return [
|
|
'id' => $id,
|
|
'company_id' => $companyId,
|
|
'billing_start' => $billingStart,
|
|
'billing_end' => $billingEnd,
|
|
'request_count' => 0,
|
|
'voice_count' => 0,
|
|
'ocr_count' => 0
|
|
];
|
|
} catch (\Exception $e) {
|
|
// Handle concurrent insertions gracefully
|
|
$usage = Database::selectOne(
|
|
"SELECT * FROM " . static::$table . "
|
|
WHERE company_id = ? AND billing_start = ? AND billing_end = ?
|
|
LIMIT 1",
|
|
[$companyId, $billingStart, $billingEnd]
|
|
);
|
|
if (!$usage) {
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $usage;
|
|
}
|
|
|
|
/**
|
|
* Increment usage counts for the current billing cycle
|
|
*/
|
|
public static function incrementUsage(int $companyId, string $type = 'request', int $amount = 1): bool
|
|
{
|
|
$activeSub = CompanySubscription::findActiveByCompany($companyId);
|
|
if (!$activeSub) {
|
|
return false;
|
|
}
|
|
|
|
$currentUsage = self::getOrCreateCurrentUsage($companyId, $activeSub);
|
|
|
|
$column = 'request_count';
|
|
if ($type === 'voice') {
|
|
$column = 'voice_count';
|
|
} elseif ($type === 'ocr') {
|
|
$column = 'ocr_count';
|
|
}
|
|
|
|
return Database::execute(
|
|
"UPDATE " . static::$table . "
|
|
SET {$column} = {$column} + ?
|
|
WHERE id = ?",
|
|
[$amount, $currentUsage['id']]
|
|
) > 0;
|
|
}
|
|
|
|
/**
|
|
* Check if a company has exceeded its plan limits for a certain action
|
|
*/
|
|
public static function hasRemainingLimit(int $companyId, string $type = 'request'): bool
|
|
{
|
|
$activeSub = CompanySubscription::findActiveByCompany($companyId);
|
|
if (!$activeSub) {
|
|
return false; // No active subscription means no requests allowed
|
|
}
|
|
|
|
$usage = self::getOrCreateCurrentUsage($companyId, $activeSub);
|
|
|
|
if ($type === 'request') {
|
|
return $usage['request_count'] < $activeSub['max_requests'];
|
|
} elseif ($type === 'voice') {
|
|
return $usage['voice_count'] < $activeSub['max_voice_requests'];
|
|
} elseif ($type === 'ocr') {
|
|
return $usage['ocr_count'] < $activeSub['max_ocr_requests'];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|