feat: Add Stripe payment integration and subscription management
- Add Stripe.net SDK for payment processing - Implement StripeService with checkout sessions, customer portal, webhooks - Implement SubscriptionService for quota management - Add quota enforcement to CVCheckService - Create Pricing, Billing, Settings pages - Add checkout success/cancel pages - Update Check and Dashboard with usage indicators - Add ResetMonthlyUsageJob for billing cycle resets - Add database migration for subscription fields Plan tiers: Free (3 checks), Professional £49/mo (30), Enterprise £199/mo (unlimited) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ using TrueCV.Application.Interfaces;
|
||||
using TrueCV.Application.Models;
|
||||
using TrueCV.Domain.Entities;
|
||||
using TrueCV.Domain.Enums;
|
||||
using TrueCV.Domain.Exceptions;
|
||||
using TrueCV.Infrastructure.Data;
|
||||
using TrueCV.Infrastructure.Jobs;
|
||||
|
||||
@@ -19,6 +20,7 @@ public sealed class CVCheckService : ICVCheckService
|
||||
private readonly IFileStorageService _fileStorageService;
|
||||
private readonly IBackgroundJobClient _backgroundJobClient;
|
||||
private readonly IAuditService _auditService;
|
||||
private readonly ISubscriptionService _subscriptionService;
|
||||
private readonly ILogger<CVCheckService> _logger;
|
||||
|
||||
public CVCheckService(
|
||||
@@ -26,12 +28,14 @@ public sealed class CVCheckService : ICVCheckService
|
||||
IFileStorageService fileStorageService,
|
||||
IBackgroundJobClient backgroundJobClient,
|
||||
IAuditService auditService,
|
||||
ISubscriptionService subscriptionService,
|
||||
ILogger<CVCheckService> logger)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_fileStorageService = fileStorageService;
|
||||
_backgroundJobClient = backgroundJobClient;
|
||||
_auditService = auditService;
|
||||
_subscriptionService = subscriptionService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -42,6 +46,13 @@ public sealed class CVCheckService : ICVCheckService
|
||||
|
||||
_logger.LogDebug("Creating CV check for user {UserId}, file: {FileName}", userId, fileName);
|
||||
|
||||
// Check quota before proceeding
|
||||
if (!await _subscriptionService.CanPerformCheckAsync(userId))
|
||||
{
|
||||
_logger.LogWarning("User {UserId} quota exceeded - CV check denied", userId);
|
||||
throw new QuotaExceededException();
|
||||
}
|
||||
|
||||
// Upload file to blob storage
|
||||
var blobUrl = await _fileStorageService.UploadAsync(file, fileName);
|
||||
|
||||
@@ -71,6 +82,9 @@ public sealed class CVCheckService : ICVCheckService
|
||||
|
||||
await _auditService.LogAsync(userId, AuditActions.CVUploaded, "CVCheck", cvCheck.Id, $"File: {fileName}");
|
||||
|
||||
// Increment usage after successful creation
|
||||
await _subscriptionService.IncrementUsageAsync(userId);
|
||||
|
||||
return cvCheck.Id;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user