Skip to content

Commit

Permalink
Merge branch 'main' into sweep/Implement-Client-Service-Management-Fe…
Browse files Browse the repository at this point in the history
…atures
  • Loading branch information
curtisdelicata authored Dec 24, 2024
2 parents 12ead68 + 2f4fcb1 commit 6b03049
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 46 deletions.
112 changes: 72 additions & 40 deletions app/Filament/Pages/ManageSubscriptionPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,83 +3,115 @@
namespace App\Filament\Pages;

use Filament\Pages\Page;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Card;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\DatePicker;
use Filament\Notifications\Notification;
use App\Models\Subscription;
use App\Models\PaymentMethod;
use App\Models\Products_Service;
use Illuminate\Support\Facades\Auth;

class ManageSubscriptionPage extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-credit-card';
protected static string $view = 'filament.pages.manage-subscription';

public $subscription;
public $card_number;
public $expiry_month;
public $expiry_year;
public $cvv;
public $selectedProduct;
public $renewalPeriod;
public $autoRenew;
public $startDate;

public function mount()
{
$this->subscription = Auth::user()->subscription;
if ($this->subscription) {
$this->selectedProduct = $this->subscription->product_service_id;
$this->renewalPeriod = $this->subscription->renewal_period;
$this->autoRenew = $this->subscription->auto_renew;
$this->startDate = $this->subscription->start_date;
}
}

protected function getFormSchema(): array
{
return [
TextInput::make('card_number')
->label('Card Number')
->required()
->maxLength(16),
Select::make('expiry_month')
->label('Expiry Month')
->options(array_combine(range(1, 12), range(1, 12)))
->required(),
Select::make('expiry_year')
->label('Expiry Year')
->options(array_combine(range(date('Y'), date('Y') + 10), range(date('Y'), date('Y') + 10)))
->required(),
TextInput::make('cvv')
->label('CVV')
->required()
->maxLength(4),
Card::make()
->schema([
Grid::make(2)
->schema([
Select::make('selectedProduct')
->label('Service')
->options(Products_Service::pluck('name', 'id'))
->required(),

Select::make('renewalPeriod')
->label('Billing Cycle')
->options([
'monthly' => 'Monthly',
'quarterly' => 'Quarterly',
'semi-annually' => 'Semi-annually',
'annually' => 'Annually',
])
->required(),

DatePicker::make('startDate')
->label('Start Date')
->required(),

Toggle::make('autoRenew')
->label('Auto Renew')
->default(true),
]),
]),
];
}

public function updatePaymentMethod()
public function save()
{
$this->validate();

// Here you would typically interact with your payment gateway to update the payment method
// For this example, we'll just create a new PaymentMethod record
PaymentMethod::create([
'user_id' => Auth::id(),
'card_last_four' => substr($this->card_number, -4),
'card_expiration' => $this->expiry_month . '/' . $this->expiry_year,
// Don't store the full card number or CVV for security reasons
$data = $this->validate();

$product = Products_Service::findOrFail($this->selectedProduct);

if (!$this->subscription) {
$this->subscription = new Subscription();
}

$this->subscription->fill([
'customer_id' => Auth::user()->customer->id,
'product_service_id' => $this->selectedProduct,
'start_date' => $this->startDate,
'renewal_period' => $this->renewalPeriod,
'auto_renew' => $this->autoRenew,
'price' => $product->price,
'currency' => $product->currency,
'status' => 'active',
]);


$this->subscription->save();

Notification::make()
->title('Payment method updated successfully')
->title('Subscription updated successfully')
->success()
->send();
}

public function cancelSubscription()
public function cancel()
{
$this->subscription->cancel();

$this->subscription?->cancel();
Notification::make()
->title('Subscription cancelled successfully')
->success()
->send();
}

public function resumeSubscription()
public function resume()
{
$this->subscription->resume();

$this->subscription?->resume();
Notification::make()
->title('Subscription resumed successfully')
->success()
Expand Down
71 changes: 71 additions & 0 deletions app/Filament/Resources/AuditLogResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@


<?php

namespace App\Filament\Resources;

use App\Filament\Resources\AuditLogResource\Pages;
use App\Models\AuditLog;
use Filament\Forms;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class AuditLogResource extends Resource
{
protected static ?string $model = AuditLog::class;

protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-list';

protected static ?string $navigationGroup = 'Settings';

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('user.name')
->label('User')
->searchable(),
Tables\Columns\TextColumn::make('action')
->searchable(),
Tables\Columns\TextColumn::make('entity_type')
->searchable(),
Tables\Columns\TextColumn::make('entity_id')
->searchable(),
Tables\Columns\TextColumn::make('ip_address')
->searchable(),
])
->filters([
Tables\Filters\SelectFilter::make('action')
->options(fn () => AuditLog::distinct()->pluck('action', 'action')),
Tables\Filters\Filter::make('created_at')
->form([
Forms\Components\DatePicker::make('created_from'),
Forms\Components\DatePicker::make('created_until'),
])
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['created_from'],
fn (Builder $query, $date): Builder => $query->whereDate('created_at', '>=', $date),
)
->when(
$data['created_until'],
fn (Builder $query, $date): Builder => $query->whereDate('created_at', '<=', $date),
);
})
])
->defaultSort('created_at', 'desc');
}

public static function getPages(): array
{
return [
'index' => Pages\ListAuditLogs::route('/'),
];
}
}
33 changes: 33 additions & 0 deletions app/Jobs/ProcessSubscriptionBilling.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@


<?php

namespace App\Jobs;

use App\Models\Subscription;
use App\Services\BillingService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessSubscriptionBilling implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public function handle(BillingService $billingService)
{
Subscription::query()
->where('status', 'active')
->where('auto_renew', true)
->get()
->each(function ($subscription) use ($billingService) {
if ($subscription->needsBilling()) {
$invoice = $billingService->generateInvoice($subscription);
$billingService->processAutomaticPayment($invoice);
$subscription->renew();
}
});
}
}
42 changes: 42 additions & 0 deletions app/Models/AuditLog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Traits\HasTeam;

class AuditLog extends Model
{
use HasFactory;
use HasTeam;

protected $fillable = [
'user_id',
'action',
'entity_type',
'entity_id',
'old_values',
'new_values',
'ip_address',
'user_agent',
'team_id'
];

protected $casts = [
'old_values' => 'array',
'new_values' => 'array',
];

public function user()
{
return $this->belongsTo(User::class);
}

public function entity()
{
return $this->morphTo();
}
}
33 changes: 33 additions & 0 deletions app/Models/Invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Database\Eloquent\Model;
use App\Mail\InvoiceGenerated;
use App\Services\CurrencyService;
use App\Services\AuditLogService;
use App\Traits\HasTeam;
use Illuminate\Support\Facades\Mail;
use Carbon\Carbon;
Expand All @@ -15,6 +16,38 @@ class Invoice extends Model
use HasFactory;
use HasTeam;

protected static function boot()
{
parent::boot();

static::created(function ($invoice) {
app(AuditLogService::class)->log(
'invoice_created',
$invoice,
null,
$invoice->toArray()
);
});

static::updated(function ($invoice) {
app(AuditLogService::class)->log(
'invoice_updated',
$invoice,
$invoice->getOriginal(),
$invoice->getChanges()
);
});

static::deleted(function ($invoice) {
app(AuditLogService::class)->log(
'invoice_deleted',
$invoice,
$invoice->toArray(),
null
);
});
}

protected $fillable = [
'customer_id',
'invoice_number',
Expand Down
Loading

0 comments on commit 6b03049

Please sign in to comment.