Add plan upgrade/downgrade, order management, impersonation, and contact form

- Plan upgrade/downgrade flow: UpgradeController with price difference
  calculations, Upgrade.vue with feature comparison and confirmation dialog
- Admin order management: Order model/migration/factory, OrderController
  with process/complete/cancel/notes, Index and Show pages with filters
- Admin impersonation: start/stop endpoints, session-based tracking,
  impersonation banner in AccountLayout, audit logging
- Contact form: ContactRequest validation, ContactController with email,
  marketing route for form submission
- FlashMessages now supports info alerts
- Inertia shared data includes impersonation state
- 114 tests passing (623 assertions)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Dev
2026-02-09 13:55:27 -05:00
parent 89fac519c3
commit 9603803928
24 changed files with 1911 additions and 13 deletions

View File

@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Order extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'plan_id',
'invoice_id',
'service_id',
'order_number',
'status',
'total',
'currency',
'payment_gateway',
'configuration',
'admin_notes',
'completed_at',
'cancelled_at',
];
protected function casts(): array
{
return [
'total' => 'decimal:2',
'configuration' => 'json',
'completed_at' => 'datetime',
'cancelled_at' => 'datetime',
];
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function plan(): BelongsTo
{
return $this->belongsTo(Plan::class);
}
public function invoice(): BelongsTo
{
return $this->belongsTo(Invoice::class);
}
public function service(): BelongsTo
{
return $this->belongsTo(Service::class);
}
}

View File

@@ -38,6 +38,11 @@ class Plan extends Model
];
}
public function orders(): HasMany
{
return $this->hasMany(Order::class);
}
public function services(): HasMany
{
return $this->hasMany(Service::class);

View File

@@ -79,6 +79,11 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->hasMany(SupportTicket::class);
}
public function orders(): HasMany
{
return $this->hasMany(Order::class);
}
public function couponRedemptions(): HasMany
{
return $this->hasMany(CouponRedemption::class);