Compare commits
No commits in common. "dev" and "v0.0.3" have entirely different histories.
95 changed files with 207 additions and 458 deletions
63
Boot.php
63
Boot.php
|
|
@ -8,32 +8,11 @@ use Core\Events\AdminPanelBooting;
|
|||
use Core\Events\ApiRoutesRegistering;
|
||||
use Core\Events\ConsoleBooting;
|
||||
use Core\Events\WebRoutesRegistering;
|
||||
use Core\Mod\Commerce\Events\OrderPaid;
|
||||
use Core\Mod\Commerce\Events\SubscriptionCreated;
|
||||
use Core\Mod\Commerce\Events\SubscriptionRenewed;
|
||||
use Core\Mod\Commerce\Listeners\ProvisionSocialHostSubscription;
|
||||
use Core\Mod\Commerce\Listeners\RewardAgentReferralOnSubscription;
|
||||
use Core\Mod\Commerce\Services\CheckoutRateLimiter;
|
||||
use Core\Mod\Commerce\Services\CommerceService;
|
||||
use Core\Mod\Commerce\Services\ContentOverrideService;
|
||||
use Core\Mod\Commerce\Services\CouponService;
|
||||
use Core\Mod\Commerce\Services\CreditNoteService;
|
||||
use Core\Mod\Commerce\Services\CurrencyService;
|
||||
use Core\Mod\Commerce\Services\DunningService;
|
||||
use Core\Mod\Commerce\Services\FraudService;
|
||||
use Core\Mod\Commerce\Services\InvoiceService;
|
||||
use Core\Mod\Commerce\Services\PaymentGateway\BTCPayGateway;
|
||||
use Core\Mod\Commerce\Services\PaymentGateway\PaymentGatewayContract;
|
||||
use Core\Mod\Commerce\Services\PaymentGateway\StripeGateway;
|
||||
use Core\Mod\Commerce\Services\PaymentMethodService;
|
||||
use Core\Mod\Commerce\Services\PermissionMatrixService;
|
||||
use Core\Mod\Commerce\Services\ReferralService;
|
||||
use Core\Mod\Commerce\Services\SkuBuilderService;
|
||||
use Core\Mod\Commerce\Services\SkuParserService;
|
||||
use Core\Mod\Commerce\Services\SubscriptionService;
|
||||
use Core\Mod\Commerce\Services\TaxService;
|
||||
use Core\Mod\Commerce\Services\UsageBillingService;
|
||||
use Core\Mod\Commerce\Services\WebhookRateLimiter;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
|
@ -67,9 +46,9 @@ class Boot extends ServiceProvider
|
|||
|
||||
// Laravel event listeners (not lifecycle events)
|
||||
Event::subscribe(ProvisionSocialHostSubscription::class);
|
||||
Event::listen(SubscriptionCreated::class, RewardAgentReferralOnSubscription::class);
|
||||
Event::listen(SubscriptionRenewed::class, Listeners\ResetUsageOnRenewal::class);
|
||||
Event::listen(OrderPaid::class, Listeners\CreateReferralCommission::class);
|
||||
Event::listen(\Core\Mod\Commerce\Events\SubscriptionCreated::class, RewardAgentReferralOnSubscription::class);
|
||||
Event::listen(\Core\Mod\Commerce\Events\SubscriptionRenewed::class, Listeners\ResetUsageOnRenewal::class);
|
||||
Event::listen(\Core\Mod\Commerce\Events\OrderPaid::class, Listeners\CreateReferralCommission::class);
|
||||
}
|
||||
|
||||
public function register(): void
|
||||
|
|
@ -80,24 +59,24 @@ class Boot extends ServiceProvider
|
|||
);
|
||||
|
||||
// Core Services
|
||||
$this->app->singleton(CommerceService::class);
|
||||
$this->app->singleton(SubscriptionService::class);
|
||||
$this->app->singleton(InvoiceService::class);
|
||||
$this->app->singleton(PermissionMatrixService::class);
|
||||
$this->app->singleton(CouponService::class);
|
||||
$this->app->singleton(TaxService::class);
|
||||
$this->app->singleton(CurrencyService::class);
|
||||
$this->app->singleton(ContentOverrideService::class);
|
||||
$this->app->singleton(DunningService::class);
|
||||
$this->app->singleton(SkuParserService::class);
|
||||
$this->app->singleton(SkuBuilderService::class);
|
||||
$this->app->singleton(CreditNoteService::class);
|
||||
$this->app->singleton(PaymentMethodService::class);
|
||||
$this->app->singleton(UsageBillingService::class);
|
||||
$this->app->singleton(ReferralService::class);
|
||||
$this->app->singleton(FraudService::class);
|
||||
$this->app->singleton(CheckoutRateLimiter::class);
|
||||
$this->app->singleton(WebhookRateLimiter::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\CommerceService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\SubscriptionService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\InvoiceService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\PermissionMatrixService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\CouponService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\TaxService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\CurrencyService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\ContentOverrideService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\DunningService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\SkuParserService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\SkuBuilderService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\CreditNoteService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\PaymentMethodService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\UsageBillingService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\ReferralService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\FraudService::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\CheckoutRateLimiter::class);
|
||||
$this->app->singleton(\Core\Mod\Commerce\Services\WebhookRateLimiter::class);
|
||||
|
||||
// Payment Gateways
|
||||
$this->app->singleton('commerce.gateway.btcpay', function ($app) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Console;
|
||||
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Console;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
|
@ -165,7 +164,7 @@ class PlantSubscriberTrees extends Command
|
|||
protected function hasPlantedThisMonth(int $workspaceId, string $month): bool
|
||||
{
|
||||
// Parse the month string (YYYY-MM format)
|
||||
$date = Carbon::createFromFormat('Y-m', $month);
|
||||
$date = \Carbon\Carbon::createFromFormat('Y-m', $month);
|
||||
$startOfMonth = $date->copy()->startOfMonth();
|
||||
$endOfMonth = $date->copy()->endOfMonth();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Console;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Core\Mod\Commerce\Services\DunningService;
|
||||
use Core\Mod\Commerce\Services\SubscriptionService;
|
||||
use Illuminate\Console\Command;
|
||||
|
|
@ -272,7 +269,7 @@ class ProcessDunning extends Command
|
|||
$this->info('Stage 5: Expired Subscriptions');
|
||||
|
||||
if ($dryRun) {
|
||||
$count = Subscription::query()
|
||||
$count = \Core\Mod\Commerce\Models\Subscription::query()
|
||||
->active()
|
||||
->whereNotNull('cancelled_at')
|
||||
->where('current_period_end', '<=', now())
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Console;
|
||||
|
||||
use Core\Mod\Commerce\Models\ExchangeRate;
|
||||
use Core\Mod\Commerce\Services\CurrencyService;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
|
|
@ -31,7 +30,7 @@ class RefreshExchangeRates extends Command
|
|||
$this->line("Provider: {$provider}");
|
||||
|
||||
// Check if rates need refresh
|
||||
if (! $this->option('force') && ! ExchangeRate::needsRefresh()) {
|
||||
if (! $this->option('force') && ! \Core\Mod\Commerce\Models\ExchangeRate::needsRefresh()) {
|
||||
$this->info('Rates are still fresh. Use --force to refresh anyway.');
|
||||
|
||||
return self::SUCCESS;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Console;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Console;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ use Core\Mod\Commerce\Services\CommerceService;
|
|||
use Core\Mod\Commerce\Services\InvoiceService;
|
||||
use Core\Mod\Commerce\Services\SubscriptionService;
|
||||
use Core\Tenant\Models\Package;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Services\EntitlementService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
|
@ -40,7 +38,7 @@ class CommerceController extends Controller
|
|||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (! $user instanceof User) {
|
||||
if (! $user instanceof \Core\Tenant\Models\User) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +200,7 @@ class CommerceController extends Controller
|
|||
return response()->json(['error' => 'No workspace found'], 404);
|
||||
}
|
||||
|
||||
$entitlements = app(EntitlementService::class);
|
||||
$entitlements = app(\Core\Tenant\Services\EntitlementService::class);
|
||||
$summary = $entitlements->getUsageSummary($workspace);
|
||||
|
||||
return response()->json([
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Data;
|
||||
|
||||
use Core\Mod\Commerce\Models\Coupon;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Events;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Events;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Events;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Events;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Listeners;
|
||||
|
||||
use Core\Mod\Commerce\Events\SubscriptionCancelled;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Listeners;
|
||||
|
||||
use Core\Mod\Commerce\Events\SubscriptionRenewed;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Mcp\Tools;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\Coupon;
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
|
|
@ -62,7 +59,7 @@ class CreateCoupon extends Tool
|
|||
'duration' => $duration,
|
||||
'max_uses' => $maxUses,
|
||||
'max_uses_per_workspace' => 1,
|
||||
'valid_until' => $validUntil ? Carbon::parse($validUntil) : null,
|
||||
'valid_until' => $validUntil ? \Carbon\Carbon::parse($validUntil) : null,
|
||||
'is_active' => true,
|
||||
'applies_to' => 'all',
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Mcp\Tools;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Mcp\Tools;
|
||||
|
||||
use Core\Mod\Commerce\Models\Invoice;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Mcp\Tools;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Contracts\Orderable;
|
||||
use Core\Mod\Commerce\Database\Factories\CouponFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
|
@ -31,8 +27,8 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property int $used_count
|
||||
* @property string $duration
|
||||
* @property int|null $duration_months
|
||||
* @property Carbon|null $valid_from
|
||||
* @property Carbon|null $valid_until
|
||||
* @property \Carbon\Carbon|null $valid_from
|
||||
* @property \Carbon\Carbon|null $valid_until
|
||||
* @property bool $is_active
|
||||
*/
|
||||
class Coupon extends Model
|
||||
|
|
@ -40,9 +36,9 @@ class Coupon extends Model
|
|||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
protected static function newFactory(): CouponFactory
|
||||
protected static function newFactory(): \Core\Mod\Commerce\Database\Factories\CouponFactory
|
||||
{
|
||||
return CouponFactory::new();
|
||||
return \Core\Mod\Commerce\Database\Factories\CouponFactory::new();
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -17,7 +14,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property int $workspace_id
|
||||
* @property int $order_id
|
||||
* @property float $discount_amount
|
||||
* @property Carbon $created_at
|
||||
* @property \Carbon\Carbon $created_at
|
||||
*/
|
||||
class CouponUsage extends Model
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -34,9 +31,9 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property string $status
|
||||
* @property float $amount_used
|
||||
* @property int|null $applied_to_order_id
|
||||
* @property Carbon|null $issued_at
|
||||
* @property Carbon|null $applied_at
|
||||
* @property Carbon|null $voided_at
|
||||
* @property \Carbon\Carbon|null $issued_at
|
||||
* @property \Carbon\Carbon|null $applied_at
|
||||
* @property \Carbon\Carbon|null $voided_at
|
||||
* @property int|null $issued_by
|
||||
* @property int|null $voided_by
|
||||
* @property array|null $metadata
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
|
|
@ -16,7 +15,7 @@ use Illuminate\Support\Facades\Cache;
|
|||
* @property string $target_currency
|
||||
* @property float $rate
|
||||
* @property string $source
|
||||
* @property Carbon $fetched_at
|
||||
* @property \Carbon\Carbon $fetched_at
|
||||
*/
|
||||
class ExchangeRate extends Model
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
|
@ -21,8 +20,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
* @property int|null $low_stock_threshold
|
||||
* @property string|null $bin_location
|
||||
* @property string|null $zone
|
||||
* @property Carbon|null $last_counted_at
|
||||
* @property Carbon|null $last_restocked_at
|
||||
* @property \Carbon\Carbon|null $last_counted_at
|
||||
* @property \Carbon\Carbon|null $last_restocked_at
|
||||
* @property int|null $unit_cost
|
||||
* @property array|null $metadata
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -25,7 +24,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property string|null $notes
|
||||
* @property int|null $user_id
|
||||
* @property int|null $unit_cost
|
||||
* @property Carbon $created_at
|
||||
* @property \Carbon\Carbon $created_at
|
||||
*/
|
||||
class InventoryMovement extends Model
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Database\Factories\InvoiceFactory;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
@ -27,9 +23,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
* @property float $total
|
||||
* @property float $amount_paid
|
||||
* @property float $amount_due
|
||||
* @property Carbon $issue_date
|
||||
* @property Carbon $due_date
|
||||
* @property Carbon|null $paid_at
|
||||
* @property \Carbon\Carbon $issue_date
|
||||
* @property \Carbon\Carbon $due_date
|
||||
* @property \Carbon\Carbon|null $paid_at
|
||||
* @property string|null $billing_name
|
||||
* @property array|null $billing_address
|
||||
* @property string|null $tax_id
|
||||
|
|
@ -39,9 +35,9 @@ class Invoice extends Model
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
protected static function newFactory(): InvoiceFactory
|
||||
protected static function newFactory(): \Core\Mod\Commerce\Database\Factories\InvoiceFactory
|
||||
{
|
||||
return InvoiceFactory::new();
|
||||
return \Core\Mod\Commerce\Database\Factories\InvoiceFactory::new();
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
|
|
@ -97,7 +93,7 @@ class Invoice extends Model
|
|||
/**
|
||||
* Get the issued_at attribute (alias for issue_date).
|
||||
*/
|
||||
public function getIssuedAtAttribute(): ?Carbon
|
||||
public function getIssuedAtAttribute(): ?\Carbon\Carbon
|
||||
{
|
||||
return $this->issue_date;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Contracts\Orderable;
|
||||
use Core\Mod\Commerce\Database\Factories\OrderFactory;
|
||||
use Core\Mod\Commerce\Services\CurrencyService;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -43,7 +38,7 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property int|null $coupon_id
|
||||
* @property array|null $billing_address
|
||||
* @property array|null $metadata
|
||||
* @property Carbon|null $paid_at
|
||||
* @property \Carbon\Carbon|null $paid_at
|
||||
* @property-read Orderable|null $orderable
|
||||
*/
|
||||
class Order extends Model
|
||||
|
|
@ -51,9 +46,9 @@ class Order extends Model
|
|||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
protected static function newFactory(): OrderFactory
|
||||
protected static function newFactory(): \Core\Mod\Commerce\Database\Factories\OrderFactory
|
||||
{
|
||||
return OrderFactory::new();
|
||||
return \Core\Mod\Commerce\Database\Factories\OrderFactory::new();
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
|
|
@ -296,7 +291,7 @@ class Order extends Model
|
|||
*/
|
||||
public function getFormattedTotalAttribute(): string
|
||||
{
|
||||
$currencyService = app(CurrencyService::class);
|
||||
$currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class);
|
||||
|
||||
return $currencyService->format($this->total, $this->display_currency);
|
||||
}
|
||||
|
|
@ -306,7 +301,7 @@ class Order extends Model
|
|||
*/
|
||||
public function getFormattedSubtotalAttribute(): string
|
||||
{
|
||||
$currencyService = app(CurrencyService::class);
|
||||
$currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class);
|
||||
|
||||
return $currencyService->format($this->subtotal, $this->display_currency);
|
||||
}
|
||||
|
|
@ -316,7 +311,7 @@ class Order extends Model
|
|||
*/
|
||||
public function getFormattedTaxAmountAttribute(): string
|
||||
{
|
||||
$currencyService = app(CurrencyService::class);
|
||||
$currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class);
|
||||
|
||||
return $currencyService->format($this->tax_amount, $this->display_currency);
|
||||
}
|
||||
|
|
@ -326,7 +321,7 @@ class Order extends Model
|
|||
*/
|
||||
public function getFormattedDiscountAmountAttribute(): string
|
||||
{
|
||||
$currencyService = app(CurrencyService::class);
|
||||
$currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class);
|
||||
|
||||
return $currencyService->format($this->discount_amount, $this->display_currency);
|
||||
}
|
||||
|
|
@ -346,7 +341,7 @@ class Order extends Model
|
|||
return $amount;
|
||||
}
|
||||
|
||||
return ExchangeRate::convert(
|
||||
return \Core\Mod\Commerce\Models\ExchangeRate::convert(
|
||||
$amount,
|
||||
$this->display_currency,
|
||||
$baseCurrency
|
||||
|
|
@ -368,7 +363,7 @@ class Order extends Model
|
|||
return $amount;
|
||||
}
|
||||
|
||||
return ExchangeRate::convert(
|
||||
return \Core\Mod\Commerce\Models\ExchangeRate::convert(
|
||||
$amount,
|
||||
$baseCurrency,
|
||||
$this->display_currency
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Core\Tenant\Models\Package;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Core\Mod\Commerce\Database\Factories\PaymentFactory;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
@ -36,9 +33,9 @@ class Payment extends Model
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
protected static function newFactory(): PaymentFactory
|
||||
protected static function newFactory(): \Core\Mod\Commerce\Database\Factories\PaymentFactory
|
||||
{
|
||||
return PaymentFactory::new();
|
||||
return \Core\Mod\Commerce\Database\Factories\PaymentFactory::new();
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -91,7 +88,7 @@ class PaymentMethod extends Model
|
|||
return false;
|
||||
}
|
||||
|
||||
$expiry = Carbon::createFromDate($this->exp_year, $this->exp_month)->endOfMonth();
|
||||
$expiry = \Carbon\Carbon::createFromDate($this->exp_year, $this->exp_month)->endOfMonth();
|
||||
|
||||
return $expiry->isPast();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
|
|
@ -24,7 +23,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property bool $locked
|
||||
* @property string $source
|
||||
* @property int|null $set_by_entity_id
|
||||
* @property Carbon|null $trained_at
|
||||
* @property \Carbon\Carbon|null $trained_at
|
||||
* @property string|null $trained_route
|
||||
*/
|
||||
class PermissionMatrix extends Model
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -28,7 +27,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property int|null $user_id
|
||||
* @property string $status
|
||||
* @property bool $was_trained
|
||||
* @property Carbon|null $trained_at
|
||||
* @property \Carbon\Carbon|null $trained_at
|
||||
*/
|
||||
class PermissionRequest extends Model
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Core\Mod\Commerce\Concerns\HasContentOverrides;
|
||||
use Core\Mod\Commerce\Services\CurrencyService;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -288,7 +287,7 @@ class Product extends Model
|
|||
public function formatPrice(int $amount, ?string $currency = null): string
|
||||
{
|
||||
$currency = $currency ?? $this->currency;
|
||||
$currencyService = app(CurrencyService::class);
|
||||
$currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class);
|
||||
|
||||
return $currencyService->format($amount, $currency, isCents: true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -31,13 +30,13 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property string|null $ip_address
|
||||
* @property string|null $user_agent
|
||||
* @property string|null $tracking_id
|
||||
* @property Carbon|null $clicked_at
|
||||
* @property Carbon|null $signed_up_at
|
||||
* @property Carbon|null $first_purchase_at
|
||||
* @property Carbon|null $qualified_at
|
||||
* @property Carbon|null $disqualified_at
|
||||
* @property \Carbon\Carbon|null $clicked_at
|
||||
* @property \Carbon\Carbon|null $signed_up_at
|
||||
* @property \Carbon\Carbon|null $first_purchase_at
|
||||
* @property \Carbon\Carbon|null $qualified_at
|
||||
* @property \Carbon\Carbon|null $disqualified_at
|
||||
* @property string|null $disqualification_reason
|
||||
* @property Carbon|null $matured_at
|
||||
* @property \Carbon\Carbon|null $matured_at
|
||||
*/
|
||||
class Referral extends Model
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -25,8 +24,8 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property int $cookie_days
|
||||
* @property int|null $max_uses
|
||||
* @property int $uses_count
|
||||
* @property Carbon|null $valid_from
|
||||
* @property Carbon|null $valid_until
|
||||
* @property \Carbon\Carbon|null $valid_from
|
||||
* @property \Carbon\Carbon|null $valid_until
|
||||
* @property bool $is_active
|
||||
* @property string|null $campaign_name
|
||||
* @property array|null $metadata
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -27,10 +26,10 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property float $commission_amount
|
||||
* @property string $currency
|
||||
* @property string $status
|
||||
* @property Carbon|null $matures_at
|
||||
* @property Carbon|null $matured_at
|
||||
* @property \Carbon\Carbon|null $matures_at
|
||||
* @property \Carbon\Carbon|null $matured_at
|
||||
* @property int|null $payout_id
|
||||
* @property Carbon|null $paid_at
|
||||
* @property \Carbon\Carbon|null $paid_at
|
||||
* @property string|null $notes
|
||||
*/
|
||||
class ReferralCommission extends Model
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
|
@ -28,10 +27,10 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property float|null $btc_amount
|
||||
* @property float|null $btc_rate
|
||||
* @property string $status
|
||||
* @property Carbon|null $requested_at
|
||||
* @property Carbon|null $processed_at
|
||||
* @property Carbon|null $completed_at
|
||||
* @property Carbon|null $failed_at
|
||||
* @property \Carbon\Carbon|null $requested_at
|
||||
* @property \Carbon\Carbon|null $processed_at
|
||||
* @property \Carbon\Carbon|null $completed_at
|
||||
* @property \Carbon\Carbon|null $failed_at
|
||||
* @property string|null $notes
|
||||
* @property string|null $failure_reason
|
||||
* @property int|null $processed_by
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Core\Tenant\Models\User;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Database\Factories\SubscriptionFactory;
|
||||
use Core\Mod\Commerce\Events\SubscriptionCreated;
|
||||
use Core\Mod\Commerce\Events\SubscriptionUpdated;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
|
|
@ -30,12 +26,12 @@ use Spatie\Activitylog\Traits\LogsActivity;
|
|||
* @property string $gateway_customer_id
|
||||
* @property string|null $gateway_price_id
|
||||
* @property string $status
|
||||
* @property Carbon $current_period_start
|
||||
* @property Carbon $current_period_end
|
||||
* @property Carbon|null $trial_ends_at
|
||||
* @property \Carbon\Carbon $current_period_start
|
||||
* @property \Carbon\Carbon $current_period_end
|
||||
* @property \Carbon\Carbon|null $trial_ends_at
|
||||
* @property bool $cancel_at_period_end
|
||||
* @property Carbon|null $cancelled_at
|
||||
* @property Carbon|null $ended_at
|
||||
* @property \Carbon\Carbon|null $cancelled_at
|
||||
* @property \Carbon\Carbon|null $ended_at
|
||||
* @property array|null $metadata
|
||||
*/
|
||||
class Subscription extends Model
|
||||
|
|
@ -43,9 +39,9 @@ class Subscription extends Model
|
|||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
protected static function newFactory(): SubscriptionFactory
|
||||
protected static function newFactory(): \Core\Mod\Commerce\Database\Factories\SubscriptionFactory
|
||||
{
|
||||
return SubscriptionFactory::new();
|
||||
return \Core\Mod\Commerce\Database\Factories\SubscriptionFactory::new();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -235,7 +231,7 @@ class Subscription extends Model
|
|||
$this->update(['status' => 'past_due']);
|
||||
}
|
||||
|
||||
public function renew(Carbon $periodStart, Carbon $periodEnd): void
|
||||
public function renew(\Carbon\Carbon $periodStart, \Carbon\Carbon $periodEnd): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => 'active',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -15,10 +13,10 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property int $subscription_id
|
||||
* @property int $meter_id
|
||||
* @property int $quantity
|
||||
* @property Carbon $period_start
|
||||
* @property Carbon $period_end
|
||||
* @property \Carbon\Carbon $period_start
|
||||
* @property \Carbon\Carbon $period_end
|
||||
* @property string|null $stripe_usage_record_id
|
||||
* @property Carbon|null $synced_at
|
||||
* @property \Carbon\Carbon|null $synced_at
|
||||
* @property bool $billed
|
||||
* @property int|null $invoice_item_id
|
||||
* @property array|null $metadata
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
|
|
@ -20,8 +17,8 @@ use Illuminate\Database\Eloquent\Model;
|
|||
* @property string $type
|
||||
* @property float $rate
|
||||
* @property bool $is_digital_services
|
||||
* @property Carbon $effective_from
|
||||
* @property Carbon|null $effective_until
|
||||
* @property \Carbon\Carbon $effective_from
|
||||
* @property \Carbon\Carbon|null $effective_until
|
||||
* @property bool $is_active
|
||||
* @property string|null $stripe_tax_rate_id
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
@ -19,7 +16,7 @@ use Illuminate\Support\Str;
|
|||
* @property int $meter_id
|
||||
* @property int $workspace_id
|
||||
* @property int $quantity
|
||||
* @property Carbon $event_at
|
||||
* @property \Carbon\Carbon $event_at
|
||||
* @property string|null $idempotency_key
|
||||
* @property int|null $user_id
|
||||
* @property string|null $action
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
|
|
@ -22,8 +21,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property int|null $http_status_code
|
||||
* @property int|null $order_id
|
||||
* @property int|null $subscription_id
|
||||
* @property Carbon $received_at
|
||||
* @property Carbon|null $processed_at
|
||||
* @property \Carbon\Carbon $received_at
|
||||
* @property \Carbon\Carbon|null $processed_at
|
||||
*/
|
||||
class WebhookEvent extends Model
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Invoice;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Refund;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Notifications;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ namespace Core\Mod\Commerce\Services;
|
|||
|
||||
use Core\Mod\Commerce\Contracts\Orderable;
|
||||
use Core\Mod\Commerce\Data\FraudAssessment;
|
||||
use Core\Mod\Commerce\Events\OrderPaid;
|
||||
use Core\Mod\Commerce\Exceptions\CheckoutRateLimitException;
|
||||
use Core\Mod\Commerce\Exceptions\FraudBlockedException;
|
||||
use Core\Mod\Commerce\Models\Coupon;
|
||||
|
|
@ -14,12 +13,9 @@ use Core\Mod\Commerce\Models\Invoice;
|
|||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Mod\Commerce\Models\OrderItem;
|
||||
use Core\Mod\Commerce\Models\Payment;
|
||||
use Core\Mod\Commerce\Models\Refund;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Core\Mod\Commerce\Services\PaymentGateway\PaymentGatewayContract;
|
||||
use Core\Tenant\Models\Boost;
|
||||
use Core\Tenant\Models\Package;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Services\EntitlementService;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
@ -127,7 +123,7 @@ class CommerceService
|
|||
$order = Order::create([
|
||||
'orderable_type' => get_class($orderable),
|
||||
'orderable_id' => $orderable->id,
|
||||
'user_id' => $orderable instanceof User ? $orderable->id : null,
|
||||
'user_id' => $orderable instanceof \Core\Tenant\Models\User ? $orderable->id : null,
|
||||
'order_number' => Order::generateOrderNumber(),
|
||||
'status' => 'pending',
|
||||
'billing_cycle' => $billingCycle,
|
||||
|
|
@ -365,7 +361,7 @@ class CommerceService
|
|||
$order = Order::create([
|
||||
'orderable_type' => get_class($orderable),
|
||||
'orderable_id' => $orderable->id,
|
||||
'user_id' => $orderable instanceof User ? $orderable->id : null,
|
||||
'user_id' => $orderable instanceof \Core\Tenant\Models\User ? $orderable->id : null,
|
||||
'order_number' => Order::generateOrderNumber(),
|
||||
'status' => 'pending',
|
||||
'billing_cycle' => 'onetime',
|
||||
|
|
@ -441,7 +437,7 @@ class CommerceService
|
|||
}
|
||||
|
||||
// Provision boosts for user-level orders
|
||||
if ($order->orderable instanceof User) {
|
||||
if ($order->orderable instanceof \Core\Tenant\Models\User) {
|
||||
foreach ($order->items as $item) {
|
||||
if ($item->item_type === 'boost') {
|
||||
$quantity = $item->metadata['quantity'] ?? $item->quantity ?? 1;
|
||||
|
|
@ -454,28 +450,28 @@ class CommerceService
|
|||
}
|
||||
|
||||
// Dispatch OrderPaid event for referral tracking and other listeners
|
||||
event(new OrderPaid($order, $payment));
|
||||
event(new \Core\Mod\Commerce\Events\OrderPaid($order, $payment));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Provision a boost for a user.
|
||||
*/
|
||||
public function provisionBoostForUser(User $user, string $featureCode, int $quantity = 1, array $metadata = []): Boost
|
||||
public function provisionBoostForUser(\Core\Tenant\Models\User $user, string $featureCode, int $quantity = 1, array $metadata = []): \Core\Tenant\Models\Boost
|
||||
{
|
||||
// Use ADD_LIMIT for quantity-based boosts, ENABLE for boolean boosts
|
||||
$boostType = $quantity > 1 || $this->isQuantityBasedFeature($featureCode)
|
||||
? Boost::BOOST_TYPE_ADD_LIMIT
|
||||
: Boost::BOOST_TYPE_ENABLE;
|
||||
? \Core\Tenant\Models\Boost::BOOST_TYPE_ADD_LIMIT
|
||||
: \Core\Tenant\Models\Boost::BOOST_TYPE_ENABLE;
|
||||
|
||||
return Boost::create([
|
||||
return \Core\Tenant\Models\Boost::create([
|
||||
'user_id' => $user->id,
|
||||
'workspace_id' => null,
|
||||
'feature_code' => $featureCode,
|
||||
'boost_type' => $boostType,
|
||||
'duration_type' => Boost::DURATION_PERMANENT,
|
||||
'limit_value' => $boostType === Boost::BOOST_TYPE_ADD_LIMIT ? $quantity : null,
|
||||
'status' => Boost::STATUS_ACTIVE,
|
||||
'duration_type' => \Core\Tenant\Models\Boost::DURATION_PERMANENT,
|
||||
'limit_value' => $boostType === \Core\Tenant\Models\Boost::BOOST_TYPE_ADD_LIMIT ? $quantity : null,
|
||||
'status' => \Core\Tenant\Models\Boost::STATUS_ACTIVE,
|
||||
'starts_at' => now(),
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
|
|
@ -603,7 +599,7 @@ class CommerceService
|
|||
Payment $payment,
|
||||
?float $amount = null,
|
||||
?string $reason = null
|
||||
): Refund {
|
||||
): \Core\Mod\Commerce\Models\Refund {
|
||||
$amountCents = $amount
|
||||
? (int) ($amount * 100)
|
||||
: (int) (($payment->amount - $payment->amount_refunded) * 100);
|
||||
|
|
@ -664,7 +660,7 @@ class CommerceService
|
|||
// For BTCPay, payment will be 'pending' as it requires customer action
|
||||
// This is expected - automatic retry won't work for crypto payments
|
||||
if ($payment->status === 'pending' && $paymentMethod->gateway === 'btcpay') {
|
||||
Log::info('BTCPay invoice created for retry - requires customer payment', [
|
||||
\Illuminate\Support\Facades\Log::info('BTCPay invoice created for retry - requires customer payment', [
|
||||
'invoice_id' => $invoice->id,
|
||||
'payment_id' => $payment->id,
|
||||
]);
|
||||
|
|
@ -672,7 +668,7 @@ class CommerceService
|
|||
|
||||
return false;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Invoice payment retry failed', [
|
||||
\Illuminate\Support\Facades\Log::error('Invoice payment retry failed', [
|
||||
'invoice_id' => $invoice->id,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use Core\Mod\Commerce\Models\CouponUsage;
|
|||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Tenant\Models\Package;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
|
|
@ -218,7 +217,7 @@ class CouponService
|
|||
/**
|
||||
* Get usage history for a coupon.
|
||||
*/
|
||||
public function getUsageHistory(Coupon $coupon, int $limit = 50): Collection
|
||||
public function getUsageHistory(Coupon $coupon, int $limit = 50): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return $coupon->usages()
|
||||
->with(['workspace', 'order'])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Core\Mod\Commerce\Models\CreditNote;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
|
@ -11,11 +9,8 @@ use Core\Mod\Commerce\Models\InvoiceItem;
|
|||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Mod\Commerce\Models\Payment;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Invoice generation and management service.
|
||||
|
|
@ -179,7 +174,7 @@ class InvoiceService
|
|||
/**
|
||||
* Get PDF download response.
|
||||
*/
|
||||
public function downloadPdf(Invoice $invoice): StreamedResponse
|
||||
public function downloadPdf(Invoice $invoice): \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
{
|
||||
$path = $this->getPdf($invoice);
|
||||
|
||||
|
|
@ -224,7 +219,7 @@ class InvoiceService
|
|||
/**
|
||||
* Get invoices for a workspace.
|
||||
*/
|
||||
public function getForWorkspace(Workspace $workspace, int $limit = 25): LengthAwarePaginator
|
||||
public function getForWorkspace(Workspace $workspace, int $limit = 25): \Illuminate\Pagination\LengthAwarePaginator
|
||||
{
|
||||
return $workspace->invoices()
|
||||
->with('items')
|
||||
|
|
@ -235,7 +230,7 @@ class InvoiceService
|
|||
/**
|
||||
* Get unpaid invoices for a workspace.
|
||||
*/
|
||||
public function getUnpaidForWorkspace(Workspace $workspace): Collection
|
||||
public function getUnpaidForWorkspace(Workspace $workspace): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return $workspace->invoices()
|
||||
->pending()
|
||||
|
|
@ -246,7 +241,7 @@ class InvoiceService
|
|||
/**
|
||||
* Get overdue invoices for a workspace.
|
||||
*/
|
||||
public function getOverdueForWorkspace(Workspace $workspace): Collection
|
||||
public function getOverdueForWorkspace(Workspace $workspace): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return $workspace->invoices()
|
||||
->pending()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use Core\Mod\Commerce\Models\Payment;
|
|||
use Core\Mod\Commerce\Models\PaymentMethod;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
|
|
@ -634,7 +633,7 @@ class BTCPayGateway implements PaymentGatewayContract
|
|||
/**
|
||||
* Extract a safe error message from a failed response.
|
||||
*/
|
||||
protected function sanitiseErrorMessage(Response $response): string
|
||||
protected function sanitiseErrorMessage(\Illuminate\Http\Client\Response $response): string
|
||||
{
|
||||
$json = $response->json();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services\PaymentGateway;
|
||||
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services\PaymentGateway;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Mod\Commerce\Models\Payment;
|
||||
use Core\Mod\Commerce\Models\PaymentMethod;
|
||||
|
|
@ -12,14 +9,7 @@ use Core\Mod\Commerce\Models\Refund;
|
|||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Stripe\Exception\ApiConnectionException;
|
||||
use Stripe\Exception\ApiErrorException;
|
||||
use Stripe\Exception\AuthenticationException;
|
||||
use Stripe\Exception\CardException;
|
||||
use Stripe\Exception\InvalidRequestException;
|
||||
use Stripe\Exception\RateLimitException;
|
||||
use Stripe\StripeClient;
|
||||
use Stripe\Webhook;
|
||||
|
||||
/**
|
||||
* Stripe payment gateway implementation.
|
||||
|
|
@ -153,36 +143,36 @@ class StripeGateway implements PaymentGatewayContract
|
|||
'session_id' => $session->id,
|
||||
'checkout_url' => $session->url,
|
||||
];
|
||||
} catch (CardException $e) {
|
||||
} catch (\Stripe\Exception\CardException $e) {
|
||||
Log::warning('Stripe checkout failed: card error', [
|
||||
'order_id' => $order->id,
|
||||
'error' => $e->getMessage(),
|
||||
'code' => $e->getStripeCode(),
|
||||
]);
|
||||
throw new \RuntimeException('Payment card error: '.$e->getMessage(), 0, $e);
|
||||
} catch (RateLimitException $e) {
|
||||
} catch (\Stripe\Exception\RateLimitException $e) {
|
||||
Log::error('Stripe checkout failed: rate limit', [
|
||||
'order_id' => $order->id,
|
||||
]);
|
||||
throw new \RuntimeException('Payment service temporarily unavailable. Please try again.', 0, $e);
|
||||
} catch (InvalidRequestException $e) {
|
||||
} catch (\Stripe\Exception\InvalidRequestException $e) {
|
||||
Log::error('Stripe checkout failed: invalid request', [
|
||||
'order_id' => $order->id,
|
||||
'error' => $e->getMessage(),
|
||||
'param' => $e->getStripeParam(),
|
||||
]);
|
||||
throw new \RuntimeException('Unable to create checkout session. Please contact support.', 0, $e);
|
||||
} catch (AuthenticationException $e) {
|
||||
} catch (\Stripe\Exception\AuthenticationException $e) {
|
||||
Log::critical('Stripe authentication failed - check API keys', [
|
||||
'order_id' => $order->id,
|
||||
]);
|
||||
throw new \RuntimeException('Payment service configuration error. Please contact support.', 0, $e);
|
||||
} catch (ApiConnectionException $e) {
|
||||
} catch (\Stripe\Exception\ApiConnectionException $e) {
|
||||
Log::error('Stripe checkout failed: connection error', [
|
||||
'order_id' => $order->id,
|
||||
]);
|
||||
throw new \RuntimeException('Unable to connect to payment service. Please try again.', 0, $e);
|
||||
} catch (ApiErrorException $e) {
|
||||
} catch (\Stripe\Exception\ApiErrorException $e) {
|
||||
Log::error('Stripe checkout failed: API error', [
|
||||
'order_id' => $order->id,
|
||||
'error' => $e->getMessage(),
|
||||
|
|
@ -348,10 +338,10 @@ class StripeGateway implements PaymentGatewayContract
|
|||
'gateway_customer_id' => $customerId,
|
||||
'gateway_price_id' => $priceId,
|
||||
'status' => $this->mapSubscriptionStatus($stripeSubscription->status),
|
||||
'current_period_start' => Carbon::createFromTimestamp($stripeSubscription->current_period_start),
|
||||
'current_period_end' => Carbon::createFromTimestamp($stripeSubscription->current_period_end),
|
||||
'current_period_start' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_start),
|
||||
'current_period_end' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_end),
|
||||
'trial_ends_at' => $stripeSubscription->trial_end
|
||||
? Carbon::createFromTimestamp($stripeSubscription->trial_end)
|
||||
? \Carbon\Carbon::createFromTimestamp($stripeSubscription->trial_end)
|
||||
: null,
|
||||
'metadata' => ['stripe_subscription' => $stripeSubscription->toArray()],
|
||||
]);
|
||||
|
|
@ -386,8 +376,8 @@ class StripeGateway implements PaymentGatewayContract
|
|||
'gateway_price_id' => $options['price_id'] ?? $subscription->gateway_price_id,
|
||||
'status' => $this->mapSubscriptionStatus($stripeSubscription->status),
|
||||
'cancel_at_period_end' => $stripeSubscription->cancel_at_period_end,
|
||||
'current_period_start' => Carbon::createFromTimestamp($stripeSubscription->current_period_start),
|
||||
'current_period_end' => Carbon::createFromTimestamp($stripeSubscription->current_period_end),
|
||||
'current_period_start' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_start),
|
||||
'current_period_end' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_end),
|
||||
]);
|
||||
|
||||
return $subscription->fresh();
|
||||
|
|
@ -554,7 +544,7 @@ class StripeGateway implements PaymentGatewayContract
|
|||
public function verifyWebhookSignature(string $payload, string $signature): bool
|
||||
{
|
||||
try {
|
||||
Webhook::constructEvent($payload, $signature, $this->webhookSecret);
|
||||
\Stripe\Webhook::constructEvent($payload, $signature, $this->webhookSecret);
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\PaymentMethod;
|
||||
use Core\Mod\Commerce\Services\PaymentGateway\StripeGateway;
|
||||
use Core\Tenant\Models\User;
|
||||
|
|
@ -256,7 +253,7 @@ class PaymentMethodService
|
|||
return false;
|
||||
}
|
||||
|
||||
$expiry = Carbon::createFromDate(
|
||||
$expiry = \Carbon\Carbon::createFromDate(
|
||||
$paymentMethod->exp_year,
|
||||
$paymentMethod->exp_month
|
||||
)->endOfMonth();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Core\Mod\Commerce\Models\Payment;
|
||||
use Core\Mod\Commerce\Models\Refund;
|
||||
use Core\Mod\Commerce\Notifications\RefundProcessed;
|
||||
use Core\Tenant\Models\User;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
|
@ -163,7 +160,7 @@ class RefundService
|
|||
/**
|
||||
* Get refund history for a payment.
|
||||
*/
|
||||
public function getRefundsForPayment(Payment $payment): Collection
|
||||
public function getRefundsForPayment(Payment $payment): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return $payment->refunds()->latest()->get();
|
||||
}
|
||||
|
|
@ -171,7 +168,7 @@ class RefundService
|
|||
/**
|
||||
* Get all refunds for a workspace.
|
||||
*/
|
||||
public function getRefundsForWorkspace(int $workspaceId): Collection
|
||||
public function getRefundsForWorkspace(int $workspaceId): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Refund::query()
|
||||
->whereHas('payment', function ($query) use ($workspaceId) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -11,7 +9,6 @@ use Core\Tenant\Models\Package;
|
|||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Models\WorkspacePackage;
|
||||
use Core\Tenant\Services\EntitlementService;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
|
@ -417,7 +414,7 @@ class SubscriptionService
|
|||
/**
|
||||
* Get subscriptions expiring soon (for renewal reminders).
|
||||
*/
|
||||
public function getExpiringSoon(int $days = 7): Collection
|
||||
public function getExpiringSoon(int $days = 7): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Subscription::query()
|
||||
->active()
|
||||
|
|
@ -431,7 +428,7 @@ class SubscriptionService
|
|||
/**
|
||||
* Get subscriptions that have failed payment and need dunning.
|
||||
*/
|
||||
public function getFailedPayments(): Collection
|
||||
public function getFailedPayments(): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Subscription::query()
|
||||
->where('status', 'past_due')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Core\Mod\Commerce\Contracts\Orderable;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\Services;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -17,7 +15,6 @@ use Core\Tenant\Models\Workspace;
|
|||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Stripe\StripeClient;
|
||||
|
||||
/**
|
||||
* Usage-based billing service.
|
||||
|
|
@ -334,7 +331,7 @@ class UsageBillingService
|
|||
Subscription $subscription,
|
||||
SubscriptionUsage $usage
|
||||
): void {
|
||||
$stripe = new StripeClient(config('commerce.gateways.stripe.secret'));
|
||||
$stripe = new \Stripe\StripeClient(config('commerce.gateways.stripe.secret'));
|
||||
|
||||
// Find the subscription item for this price
|
||||
$stripeSubscription = $stripe->subscriptions->retrieve(
|
||||
|
|
@ -420,7 +417,7 @@ class UsageBillingService
|
|||
return null;
|
||||
}
|
||||
|
||||
$stripe = new StripeClient($secret);
|
||||
$stripe = new \Stripe\StripeClient($secret);
|
||||
|
||||
// Create or update product in Stripe
|
||||
$product = $stripe->products->create([
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ namespace Core\Mod\Commerce\Services;
|
|||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Core\Mod\Commerce\Models\WebhookEvent;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
|
@ -312,7 +311,7 @@ class WebhookLogger
|
|||
/**
|
||||
* Get recent failed events for debugging.
|
||||
*/
|
||||
public function getRecentFailures(string $gateway, int $limit = 10): Collection
|
||||
public function getRecentFailures(string $gateway, int $limit = 10): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return WebhookEvent::forGateway($gateway)
|
||||
->failed()
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\View\Modal\Admin;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\Coupon;
|
||||
use Core\Mod\Commerce\Services\CouponService;
|
||||
use Core\Tenant\Models\Package;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Title;
|
||||
|
|
@ -336,8 +334,8 @@ class CouponManager extends Component
|
|||
'max_uses_per_workspace' => $this->bulk_max_uses_per_workspace,
|
||||
'duration' => $this->bulk_duration,
|
||||
'duration_months' => $this->bulk_duration === 'repeating' ? $this->bulk_duration_months : null,
|
||||
'valid_from' => $this->bulk_valid_from ? Carbon::parse($this->bulk_valid_from) : null,
|
||||
'valid_until' => $this->bulk_valid_until ? Carbon::parse($this->bulk_valid_until) : null,
|
||||
'valid_from' => $this->bulk_valid_from ? \Carbon\Carbon::parse($this->bulk_valid_from) : null,
|
||||
'valid_until' => $this->bulk_valid_until ? \Carbon\Carbon::parse($this->bulk_valid_until) : null,
|
||||
'is_active' => $this->bulk_is_active,
|
||||
];
|
||||
|
||||
|
|
@ -401,8 +399,8 @@ class CouponManager extends Component
|
|||
'max_uses_per_workspace' => $this->max_uses_per_workspace,
|
||||
'duration' => $this->duration,
|
||||
'duration_months' => $this->duration === 'repeating' ? $this->duration_months : null,
|
||||
'valid_from' => $this->valid_from ? Carbon::parse($this->valid_from) : null,
|
||||
'valid_until' => $this->valid_until ? Carbon::parse($this->valid_until) : null,
|
||||
'valid_from' => $this->valid_from ? \Carbon\Carbon::parse($this->valid_from) : null,
|
||||
'valid_until' => $this->valid_until ? \Carbon\Carbon::parse($this->valid_until) : null,
|
||||
'is_active' => $this->is_active,
|
||||
];
|
||||
|
||||
|
|
@ -589,7 +587,7 @@ class CouponManager extends Component
|
|||
[
|
||||
'lines' => array_filter([
|
||||
['bold' => $c->name],
|
||||
$c->description ? ['muted' => Str::limit($c->description, 30)] : null,
|
||||
$c->description ? ['muted' => \Illuminate\Support\Str::limit($c->description, 30)] : null,
|
||||
]),
|
||||
],
|
||||
['lines' => $discountLines],
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use Core\Mod\Commerce\Models\Coupon;
|
|||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Title;
|
||||
|
|
@ -43,7 +42,7 @@ class Dashboard extends Component
|
|||
}
|
||||
|
||||
#[Computed]
|
||||
public function recentOrders(): Collection
|
||||
public function recentOrders(): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Order::with('workspace')
|
||||
->latest()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Core\Mod\Commerce\View\Modal\Admin;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\Referral;
|
||||
use Core\Mod\Commerce\Models\ReferralCode;
|
||||
use Core\Mod\Commerce\Models\ReferralCommission;
|
||||
|
|
@ -310,8 +309,8 @@ class ReferralManager extends Component
|
|||
'commission_rate' => $this->codeCommissionRate,
|
||||
'cookie_days' => $this->codeCookieDays,
|
||||
'max_uses' => $this->codeMaxUses,
|
||||
'valid_from' => $this->codeValidFrom ? Carbon::parse($this->codeValidFrom) : null,
|
||||
'valid_until' => $this->codeValidUntil ? Carbon::parse($this->codeValidUntil) : null,
|
||||
'valid_from' => $this->codeValidFrom ? \Carbon\Carbon::parse($this->codeValidFrom) : null,
|
||||
'valid_until' => $this->codeValidUntil ? \Carbon\Carbon::parse($this->codeValidUntil) : null,
|
||||
'is_active' => $this->codeIsActive,
|
||||
'campaign_name' => $this->codeCampaignName,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ namespace Core\Mod\Commerce\View\Modal\Admin;
|
|||
use Core\Mod\Commerce\Models\Subscription;
|
||||
use Core\Mod\Commerce\Services\SubscriptionService;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Component;
|
||||
|
|
@ -151,7 +150,7 @@ class SubscriptionManager extends Component
|
|||
$count = Subscription::whereIn('id', $this->selected)
|
||||
->whereNotNull('current_period_end')
|
||||
->update([
|
||||
'current_period_end' => DB::raw('DATE_ADD(current_period_end, INTERVAL 30 DAY)'),
|
||||
'current_period_end' => \Illuminate\Support\Facades\DB::raw('DATE_ADD(current_period_end, INTERVAL 30 DAY)'),
|
||||
]);
|
||||
|
||||
session()->flash('message', __('commerce::commerce.bulk.period_extended', ['count' => $count, 'days' => 30]));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Coupon;
|
||||
|
|
@ -14,11 +12,9 @@ use Core\Mod\Commerce\Services\CurrencyService;
|
|||
use Core\Mod\Commerce\Services\TaxService;
|
||||
use Core\Tenant\Models\Package;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Attributes\Url;
|
||||
use Livewire\Component;
|
||||
|
||||
|
|
@ -147,7 +143,7 @@ class CheckoutPage extends Component
|
|||
/**
|
||||
* Handle currency change event from CurrencySelector component.
|
||||
*/
|
||||
#[On('currency-changed')]
|
||||
#[\Livewire\Attributes\On('currency-changed')]
|
||||
public function onCurrencyChanged(string $currency): void
|
||||
{
|
||||
$this->displayCurrency = $currency;
|
||||
|
|
@ -185,7 +181,7 @@ class CheckoutPage extends Component
|
|||
}
|
||||
|
||||
#[Computed]
|
||||
public function packages(): Collection
|
||||
public function packages(): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Package::active()
|
||||
->public()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
@ -11,7 +9,6 @@ use Illuminate\Auth\Events\Registered;
|
|||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
|
@ -159,9 +156,9 @@ class CheckoutSuccess extends Component
|
|||
*/
|
||||
protected function generateUniqueSlug(string $name): string
|
||||
{
|
||||
$baseSlug = Str::slug($name);
|
||||
$baseSlug = \Illuminate\Support\Str::slug($name);
|
||||
if (str_contains($baseSlug, '@')) {
|
||||
$baseSlug = Str::slug(Str::before($name, '@'));
|
||||
$baseSlug = \Illuminate\Support\Str::slug(\Illuminate\Support\Str::before($name, '@'));
|
||||
}
|
||||
|
||||
$slug = $baseSlug;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Services\CommerceService;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\PaymentMethod;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription as SubscriptionModel;
|
||||
use Core\Mod\Commerce\Notifications\SubscriptionCancelled;
|
||||
use Core\Mod\Commerce\Services\CommerceService;
|
||||
use Core\Mod\Commerce\Services\SubscriptionService;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
|
@ -126,7 +123,7 @@ class Subscription extends Component
|
|||
|
||||
// Notify user
|
||||
$user = Auth::user();
|
||||
if ($user instanceof User) {
|
||||
if ($user instanceof \Core\Tenant\Models\User) {
|
||||
$user->notify(new SubscriptionCancelled($this->activeSubscription));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core\Mod\Commerce\View\Modal\Web;
|
||||
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1,22 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Controllers\InvoiceController;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\CouponManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\CreditNoteManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\EntityManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\OrderManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\PermissionMatrixManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\ProductManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\ReferralManager;
|
||||
use Core\Mod\Commerce\View\Modal\Admin\SubscriptionManager;
|
||||
use Core\Mod\Commerce\View\Modal\Web\ChangePlan;
|
||||
use Core\Mod\Commerce\View\Modal\Web\Dashboard;
|
||||
use Core\Mod\Commerce\View\Modal\Web\Invoices;
|
||||
use Core\Mod\Commerce\View\Modal\Web\PaymentMethods;
|
||||
use Core\Mod\Commerce\View\Modal\Web\ReferralDashboard;
|
||||
use Core\Mod\Commerce\View\Modal\Web\Subscription;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|
|
@ -27,25 +10,25 @@ use Illuminate\Support\Facades\Route;
|
|||
|
||||
// Billing (user-facing hub pages)
|
||||
Route::prefix('hub/billing')->name('hub.billing.')->group(function () {
|
||||
Route::get('/', Dashboard::class)->name('index');
|
||||
Route::get('/invoices', Invoices::class)->name('invoices');
|
||||
Route::get('/invoices/{invoice}/pdf', [InvoiceController::class, 'pdf'])->name('invoices.pdf');
|
||||
Route::get('/invoices/{invoice}/view', [InvoiceController::class, 'view'])->name('invoices.view');
|
||||
Route::get('/payment-methods', PaymentMethods::class)->name('payment-methods');
|
||||
Route::get('/subscription', Subscription::class)->name('subscription');
|
||||
Route::get('/change-plan', ChangePlan::class)->name('change-plan');
|
||||
Route::get('/affiliates', ReferralDashboard::class)->name('affiliates');
|
||||
Route::get('/', \Core\Mod\Commerce\View\Modal\Web\Dashboard::class)->name('index');
|
||||
Route::get('/invoices', \Core\Mod\Commerce\View\Modal\Web\Invoices::class)->name('invoices');
|
||||
Route::get('/invoices/{invoice}/pdf', [\Core\Mod\Commerce\Controllers\InvoiceController::class, 'pdf'])->name('invoices.pdf');
|
||||
Route::get('/invoices/{invoice}/view', [\Core\Mod\Commerce\Controllers\InvoiceController::class, 'view'])->name('invoices.view');
|
||||
Route::get('/payment-methods', \Core\Mod\Commerce\View\Modal\Web\PaymentMethods::class)->name('payment-methods');
|
||||
Route::get('/subscription', \Core\Mod\Commerce\View\Modal\Web\Subscription::class)->name('subscription');
|
||||
Route::get('/change-plan', \Core\Mod\Commerce\View\Modal\Web\ChangePlan::class)->name('change-plan');
|
||||
Route::get('/affiliates', \Core\Mod\Commerce\View\Modal\Web\ReferralDashboard::class)->name('affiliates');
|
||||
});
|
||||
|
||||
// Commerce management (admin only - Hades tier)
|
||||
Route::prefix('hub/commerce')->name('hub.commerce.')->group(function () {
|
||||
Route::get('/', Core\Mod\Commerce\View\Modal\Admin\Dashboard::class)->name('dashboard');
|
||||
Route::get('/orders', OrderManager::class)->name('orders');
|
||||
Route::get('/subscriptions', SubscriptionManager::class)->name('subscriptions');
|
||||
Route::get('/coupons', CouponManager::class)->name('coupons');
|
||||
Route::get('/entities', EntityManager::class)->name('entities');
|
||||
Route::get('/permissions', PermissionMatrixManager::class)->name('permissions');
|
||||
Route::get('/products', ProductManager::class)->name('products');
|
||||
Route::get('/credit-notes', CreditNoteManager::class)->name('credit-notes');
|
||||
Route::get('/referrals', ReferralManager::class)->name('referrals');
|
||||
Route::get('/', \Core\Mod\Commerce\View\Modal\Admin\Dashboard::class)->name('dashboard');
|
||||
Route::get('/orders', \Core\Mod\Commerce\View\Modal\Admin\OrderManager::class)->name('orders');
|
||||
Route::get('/subscriptions', \Core\Mod\Commerce\View\Modal\Admin\SubscriptionManager::class)->name('subscriptions');
|
||||
Route::get('/coupons', \Core\Mod\Commerce\View\Modal\Admin\CouponManager::class)->name('coupons');
|
||||
Route::get('/entities', \Core\Mod\Commerce\View\Modal\Admin\EntityManager::class)->name('entities');
|
||||
Route::get('/permissions', \Core\Mod\Commerce\View\Modal\Admin\PermissionMatrixManager::class)->name('permissions');
|
||||
Route::get('/products', \Core\Mod\Commerce\View\Modal\Admin\ProductManager::class)->name('products');
|
||||
Route::get('/credit-notes', \Core\Mod\Commerce\View\Modal\Admin\CreditNoteManager::class)->name('credit-notes');
|
||||
Route::get('/referrals', \Core\Mod\Commerce\View\Modal\Admin\ReferralManager::class)->name('referrals');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// Console commands are registered via Core modules
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Models\Invoice;
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
use Core\Mod\Commerce\Models\Payment;
|
||||
|
|
@ -11,10 +9,9 @@ use Core\Tenant\Models\Package;
|
|||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Models\WorkspacePackage;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Cache::flush();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Models\Coupon;
|
||||
use Core\Mod\Commerce\Models\CouponUsage;
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
@ -9,9 +7,8 @@ use Core\Mod\Commerce\Services\CouponService;
|
|||
use Core\Tenant\Models\Package;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->user = User::factory()->create();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Models\Invoice;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
@ -14,11 +12,10 @@ use Core\Tenant\Models\Package;
|
|||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Models\WorkspacePackage;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Cache::flush();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Events\SubscriptionRenewed;
|
||||
use Core\Mod\Commerce\Jobs\ProcessSubscriptionRenewal;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
@ -13,11 +11,10 @@ use Core\Tenant\Models\User;
|
|||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Models\WorkspacePackage;
|
||||
use Core\Tenant\Services\EntitlementService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Cache::flush();
|
||||
|
|
|
|||
|
|
@ -1,19 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Models\Payment;
|
||||
use Core\Mod\Commerce\Models\Refund;
|
||||
use Core\Mod\Commerce\Notifications\RefundProcessed;
|
||||
use Core\Mod\Commerce\Services\CommerceService;
|
||||
use Core\Mod\Commerce\Services\PaymentGateway\PaymentGatewayContract;
|
||||
use Core\Mod\Commerce\Services\RefundService;
|
||||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Notification::fake();
|
||||
|
|
@ -40,7 +36,7 @@ beforeEach(function () {
|
|||
]);
|
||||
|
||||
// Mock the gateway
|
||||
$mockGateway = Mockery::mock(PaymentGatewayContract::class);
|
||||
$mockGateway = Mockery::mock(\Core\Mod\Commerce\Services\PaymentGateway\PaymentGatewayContract::class);
|
||||
$mockGateway->shouldReceive('refund')->andReturn([
|
||||
'success' => true,
|
||||
'refund_id' => 're_test_123',
|
||||
|
|
@ -96,15 +92,15 @@ describe('RefundService', function () {
|
|||
|
||||
it('throws exception for refund exceeding available amount', function () {
|
||||
expect(fn () => $this->service->refund($this->payment, 150.00))
|
||||
->toThrow(InvalidArgumentException::class, 'exceeds maximum refundable');
|
||||
->toThrow(\InvalidArgumentException::class, 'exceeds maximum refundable');
|
||||
});
|
||||
|
||||
it('throws exception for zero or negative amount', function () {
|
||||
expect(fn () => $this->service->refund($this->payment, 0))
|
||||
->toThrow(InvalidArgumentException::class, 'greater than zero');
|
||||
->toThrow(\InvalidArgumentException::class, 'greater than zero');
|
||||
|
||||
expect(fn () => $this->service->refund($this->payment, -50.00))
|
||||
->toThrow(InvalidArgumentException::class, 'greater than zero');
|
||||
->toThrow(\InvalidArgumentException::class, 'greater than zero');
|
||||
});
|
||||
|
||||
it('throws exception for non-succeeded payments', function () {
|
||||
|
|
@ -118,7 +114,7 @@ describe('RefundService', function () {
|
|||
]);
|
||||
|
||||
expect(fn () => $this->service->refund($pendingPayment, 50.00))
|
||||
->toThrow(InvalidArgumentException::class, 'only refund successful payments');
|
||||
->toThrow(\InvalidArgumentException::class, 'only refund successful payments');
|
||||
});
|
||||
|
||||
it('allows multiple partial refunds up to full amount', function () {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Core\Mod\Commerce\Exceptions\PauseLimitExceededException;
|
||||
use Core\Mod\Commerce\Models\Subscription;
|
||||
|
|
@ -12,10 +10,9 @@ use Core\Tenant\Models\Package;
|
|||
use Core\Tenant\Models\User;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Models\WorkspacePackage;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Cache::flush();
|
||||
|
|
@ -465,7 +462,7 @@ describe('Proration calculations', function () {
|
|||
$this->subscription->workspacePackage->setRelation('package', null);
|
||||
|
||||
expect(fn () => $this->service->previewPlanChange($this->subscription, $this->agencyPackage))
|
||||
->toThrow(InvalidArgumentException::class, 'no current package');
|
||||
->toThrow(\InvalidArgumentException::class, 'no current package');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Models\TaxRate;
|
||||
use Core\Mod\Commerce\Services\TaxService;
|
||||
use Core\Tenant\Models\Workspace;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->workspace = Workspace::factory()->create([
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
use Core\Mod\Commerce\Services\WebhookRateLimiter;
|
||||
use Illuminate\Cache\RateLimiter;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
// ============================================================================
|
||||
// WebhookRateLimiter Unit Tests
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Mod\Commerce\Controllers\Webhooks\BTCPayWebhookController;
|
||||
use Core\Mod\Commerce\Controllers\Webhooks\StripeWebhookController;
|
||||
use Core\Mod\Commerce\Models\Order;
|
||||
|
|
@ -21,12 +19,10 @@ use Core\Tenant\Models\User;
|
|||
use Core\Tenant\Models\Workspace;
|
||||
use Core\Tenant\Models\WorkspacePackage;
|
||||
use Core\Tenant\Services\EntitlementService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use WebhookPayloadValidationException;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Notification::fake();
|
||||
|
|
@ -128,7 +124,7 @@ describe('StripeWebhookController', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$request->headers->set('Stripe-Signature', 't=123,v1=abc');
|
||||
|
||||
$response = $controller->handle($request);
|
||||
|
|
@ -181,7 +177,7 @@ describe('StripeWebhookController', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -217,7 +213,7 @@ describe('StripeWebhookController', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -274,7 +270,7 @@ describe('StripeWebhookController', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -336,7 +332,7 @@ describe('StripeWebhookController', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -372,7 +368,7 @@ describe('StripeWebhookController', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -464,7 +460,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$request->headers->set('BTCPay-Sig', 'valid_signature');
|
||||
|
||||
$response = $controller->handle($request);
|
||||
|
|
@ -504,7 +500,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -527,7 +523,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -552,7 +548,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -579,7 +575,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -606,7 +602,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -633,7 +629,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -660,7 +656,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -687,7 +683,7 @@ describe('BTCPayWebhookController', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -844,7 +840,7 @@ describe('WebhookLogger service', function () {
|
|||
it('extracts relevant headers', function () {
|
||||
$logger = new WebhookLogger;
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$request->headers->set('Stripe-Signature', 't=123,v1=secret_signature_here');
|
||||
$request->headers->set('Content-Type', 'application/json');
|
||||
$request->headers->set('User-Agent', 'Stripe/1.0');
|
||||
|
|
@ -1239,7 +1235,7 @@ describe('BTCPayWebhookController payload validation integration', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$request->headers->set('BTCPay-Sig', 'valid_signature');
|
||||
|
||||
$response = $controller->handle($request);
|
||||
|
|
@ -1266,7 +1262,7 @@ describe('BTCPayWebhookController payload validation integration', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(400)
|
||||
|
|
@ -1286,7 +1282,7 @@ describe('BTCPayWebhookController payload validation integration', function () {
|
|||
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(400)
|
||||
|
|
@ -1317,7 +1313,7 @@ describe('BTCPayWebhookController payload validation integration', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -1392,7 +1388,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -1427,7 +1423,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () {
|
|||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
// First request - should process
|
||||
$request1 = new Request;
|
||||
$request1 = new \Illuminate\Http\Request;
|
||||
$response1 = $controller->handle($request1);
|
||||
expect($response1->getStatusCode())->toBe(200);
|
||||
|
||||
|
|
@ -1441,7 +1437,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () {
|
|||
// Second request with same event ID - should be rejected as duplicate
|
||||
$webhookLogger2 = new WebhookLogger;
|
||||
$controller2 = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger2);
|
||||
$request2 = new Request;
|
||||
$request2 = new \Illuminate\Http\Request;
|
||||
$response2 = $controller2->handle($request2);
|
||||
|
||||
expect($response2->getStatusCode())->toBe(200)
|
||||
|
|
@ -1521,7 +1517,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () {
|
|||
$webhookLogger
|
||||
);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -1578,7 +1574,7 @@ describe('BTCPay Payment Amount Verification', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -1614,7 +1610,7 @@ describe('BTCPay Payment Amount Verification', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -1657,7 +1653,7 @@ describe('BTCPay Payment Amount Verification', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
@ -1694,7 +1690,7 @@ describe('BTCPay Payment Amount Verification', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200)
|
||||
|
|
@ -1731,7 +1727,7 @@ describe('BTCPay Payment Amount Verification', function () {
|
|||
$webhookLogger = new WebhookLogger;
|
||||
$controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger);
|
||||
|
||||
$request = new Request;
|
||||
$request = new \Illuminate\Http\Request;
|
||||
$response = $controller->handle($request);
|
||||
|
||||
expect($response->getStatusCode())->toBe(200);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Tests;
|
||||
|
||||
use Core\Mod\Commerce\Boot;
|
||||
use Orchestra\Testbench\TestCase as BaseTestCase;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
|
|
@ -12,7 +11,7 @@ abstract class TestCase extends BaseTestCase
|
|||
protected function getPackageProviders($app): array
|
||||
{
|
||||
return [
|
||||
Boot::class,
|
||||
\Core\Mod\Commerce\Boot::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UseCase: Commerce Admin CRUD (Basic Flow)
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue