diff --git a/Dockerfile b/Dockerfile
index 902cec7..c6d7f86 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -14,8 +14,7 @@ RUN install-php-extensions \
opcache \
zip \
gd \
- intl \
- bcmath
+ intl
# Install Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
diff --git a/Dockerfile.dev b/Dockerfile.dev
index c36d143..f2a67c5 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -18,7 +18,6 @@ RUN install-php-extensions \
zip \
gd \
intl \
- bcmath \
xdebug
# Install Composer
diff --git a/app/Enums/AppModeEnum.php b/app/Enums/AppModeEnum.php
deleted file mode 100644
index 9a75881..0000000
--- a/app/Enums/AppModeEnum.php
+++ /dev/null
@@ -1,24 +0,0 @@
-user();
-
- if ($planner->subscribed()) {
- return redirect()->route('dashboard');
- }
-
- $plan = $request->input('plan', 'monthly');
- $priceId = $plan === 'yearly'
- ? config('services.stripe.price_yearly')
- : config('services.stripe.price_monthly');
-
- return $planner->newSubscription('default', $priceId)
- ->checkout([
- 'success_url' => route('subscription.success') . '?session_id={CHECKOUT_SESSION_ID}',
- 'cancel_url' => route('subscription.index'),
- ]);
- }
-
- public function success(Request $request): RedirectResponse
- {
- $sessionId = $request->query('session_id');
-
- if ($sessionId) {
- $planner = $request->user();
- $session = Cashier::stripe()->checkout->sessions->retrieve($sessionId, [
- 'expand' => ['subscription'],
- ]);
-
- if ($session->subscription && ! $planner->subscribed()) {
- $subscription = $session->subscription;
-
- $planner->subscriptions()->create([
- 'type' => 'default',
- 'stripe_id' => $subscription->id,
- 'stripe_status' => $subscription->status,
- 'stripe_price' => $subscription->items->data[0]->price->id ?? null,
- 'quantity' => $subscription->items->data[0]->quantity ?? 1,
- 'trial_ends_at' => $subscription->trial_end ? now()->setTimestamp($subscription->trial_end) : null,
- 'ends_at' => null,
- ]);
- }
- }
-
- return redirect()->route('dashboard')->with('success', 'Subscription activated!');
- }
-
- public function billing(Request $request)
- {
- $planner = $request->user();
- $subscription = $planner->subscription();
-
- if (! $subscription) {
- return redirect()->route('subscription.index');
- }
-
- $planType = match ($subscription->stripe_price) {
- config('services.stripe.price_yearly') => 'Yearly',
- config('services.stripe.price_monthly') => 'Monthly',
- default => 'Unknown',
- };
-
- $nextBillingDate = null;
- if ($subscription->stripe_status === 'active') {
- try {
- $stripeSubscription = Cashier::stripe()->subscriptions->retrieve($subscription->stripe_id);
- $nextBillingDate = $stripeSubscription->current_period_end
- ? now()->setTimestamp($stripeSubscription->current_period_end)
- : null;
- } catch (\Exception $e) {
- // Stripe API error - continue without next billing date
- }
- }
-
- return view('billing.index', [
- 'subscription' => $subscription,
- 'planner' => $planner,
- 'planType' => $planType,
- 'nextBillingDate' => $nextBillingDate,
- ]);
- }
-
- public function cancel(Request $request): RedirectResponse
- {
- $planner = $request->user();
-
- if (! $planner->subscribed()) {
- return back()->with('error', 'No active subscription found.');
- }
-
- $planner->subscription()->cancel();
-
- return back()->with('success', 'Subscription canceled. Access will continue until the end of your billing period.');
- }
-
- public function billingPortal(Request $request)
- {
- return $request->user()->redirectToBillingPortal(route('billing'));
- }
-}
diff --git a/app/Http/Middleware/RequireSaasMode.php b/app/Http/Middleware/RequireSaasMode.php
deleted file mode 100644
index 0950eb6..0000000
--- a/app/Http/Middleware/RequireSaasMode.php
+++ /dev/null
@@ -1,19 +0,0 @@
-user();
-
- if (! $planner?->subscribed()) {
- return redirect()->route('subscription.index');
- }
-
- return $next($request);
- }
-}
diff --git a/app/Models/Planner.php b/app/Models/Planner.php
index f8307fd..16614bb 100644
--- a/app/Models/Planner.php
+++ b/app/Models/Planner.php
@@ -6,7 +6,6 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
-use Laravel\Cashier\Billable;
use Laravel\Sanctum\HasApiTokens;
/**
@@ -16,7 +15,7 @@
*/
class Planner extends Authenticatable
{
- use Billable, HasApiTokens, HasFactory, Notifiable;
+ use HasApiTokens, HasFactory, Notifiable;
protected $fillable = [
'name', 'email', 'password',
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 3067e8c..0bbbb1e 100755
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -4,12 +4,10 @@
use App\Exceptions\CustomException;
use App\Models\Dish;
-use App\Models\Planner;
use App\Models\Schedule;
use App\Models\ScheduledUserDish;
use App\Models\User;
use App\Models\UserDish;
-use Laravel\Cashier\Cashier;
use DishPlanner\Dish\Policies\DishPolicy;
use DishPlanner\Schedule\Policies\SchedulePolicy;
use DishPlanner\ScheduledUserDish\Policies\ScheduledUserDishPolicy;
@@ -47,8 +45,6 @@ public function render($request, Throwable $e)
public function boot(): void
{
- Cashier::useCustomerModel(Planner::class);
-
Gate::policy(Dish::class, DishPolicy::class);
Gate::policy(Schedule::class, SchedulePolicy::class);
Gate::policy(ScheduledUserDish::class, ScheduledUserDishPolicy::class);
diff --git a/app/helpers.php b/app/helpers.php
deleted file mode 100644
index 59bc43a..0000000
--- a/app/helpers.php
+++ /dev/null
@@ -1,17 +0,0 @@
-isApp();
- }
-}
-
-if (! function_exists('is_mode_saas')) {
- function is_mode_saas(): bool
- {
- return AppModeEnum::current()->isSaas();
- }
-}
\ No newline at end of file
diff --git a/bootstrap/app.php b/bootstrap/app.php
index 7fb61b3..c6a8eab 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -1,15 +1,17 @@
group(base_path('routes/web/subscription.php'));
- },
)
->withMiddleware(function (Middleware $middleware) {
// Apply ForceJsonResponse only to API routes
$middleware->api(ForceJsonResponse::class);
-
- $middleware->alias([
- 'subscription' => RequireSubscription::class,
- 'saas' => RequireSaasMode::class,
- ]);
-
- // Exclude Stripe webhook from CSRF verification
- $middleware->validateCsrfTokens(except: [
- 'stripe/webhook',
- ]);
})
->withExceptions(function (Exceptions $exceptions) {
$exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
@@ -77,4 +65,7 @@
}
});
})
+ ->withCommands([
+ GenerateScheduleCommand::class,
+ ])
->create();
diff --git a/composer.json b/composer.json
index 2ecb17b..a4197fb 100644
--- a/composer.json
+++ b/composer.json
@@ -10,7 +10,6 @@
"license": "MIT",
"require": {
"php": "^8.2",
- "laravel/cashier": "^16.1",
"laravel/framework": "^12.9.2",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
@@ -27,9 +26,6 @@
"phpunit/phpunit": "^11.0.1"
},
"autoload": {
- "files": [
- "app/helpers.php"
- ],
"psr-4": {
"App\\": "app/",
"DishPlanner\\": "src/DishPlanner/",
diff --git a/config/app.php b/config/app.php
index 09dd952..df3f5f0 100644
--- a/config/app.php
+++ b/config/app.php
@@ -28,18 +28,6 @@
'env' => env('APP_ENV', 'production'),
- /*
- |--------------------------------------------------------------------------
- | Application Mode
- |--------------------------------------------------------------------------
- |
- | Determines the application deployment mode: 'app' for self-hosted,
- | 'saas' for multi-tenant SaaS, 'demo' for demonstration instances.
- |
- */
-
- 'mode' => env('APP_MODE', 'app'),
-
/*
|--------------------------------------------------------------------------
| Application Debug Mode
diff --git a/config/services.php b/config/services.php
index cf3ce61..27a3617 100644
--- a/config/services.php
+++ b/config/services.php
@@ -35,14 +35,4 @@
],
],
- 'stripe' => [
- 'key' => env('STRIPE_KEY'),
- 'secret' => env('STRIPE_SECRET'),
- 'webhook' => [
- 'secret' => env('STRIPE_WEBHOOK_SECRET'),
- ],
- 'price_monthly' => env('STRIPE_PRICE_MONTHLY'),
- 'price_yearly' => env('STRIPE_PRICE_YEARLY'),
- ],
-
];
diff --git a/database/migrations/2026_01_06_000525_create_customer_columns.php b/database/migrations/2026_01_06_000525_create_customer_columns.php
deleted file mode 100644
index 131d232..0000000
--- a/database/migrations/2026_01_06_000525_create_customer_columns.php
+++ /dev/null
@@ -1,34 +0,0 @@
-string('stripe_id')->nullable()->index();
- $table->string('pm_type')->nullable();
- $table->string('pm_last_four', 4)->nullable();
- $table->timestamp('trial_ends_at')->nullable();
- });
- }
-
- public function down(): void
- {
- Schema::table('planners', function (Blueprint $table) {
- $table->dropIndex([
- 'stripe_id',
- ]);
-
- $table->dropColumn([
- 'stripe_id',
- 'pm_type',
- 'pm_last_four',
- 'trial_ends_at',
- ]);
- });
- }
-};
diff --git a/database/migrations/2026_01_06_000526_create_subscriptions_table.php b/database/migrations/2026_01_06_000526_create_subscriptions_table.php
deleted file mode 100644
index 9043296..0000000
--- a/database/migrations/2026_01_06_000526_create_subscriptions_table.php
+++ /dev/null
@@ -1,37 +0,0 @@
-id();
- $table->foreignId('planner_id');
- $table->string('type');
- $table->string('stripe_id')->unique();
- $table->string('stripe_status');
- $table->string('stripe_price')->nullable();
- $table->integer('quantity')->nullable();
- $table->timestamp('trial_ends_at')->nullable();
- $table->timestamp('ends_at')->nullable();
- $table->timestamps();
-
- $table->index(['planner_id', 'stripe_status']);
- });
- }
-
- /**
- * Reverse the migrations.
- */
- public function down(): void
- {
- Schema::dropIfExists('subscriptions');
- }
-};
diff --git a/database/migrations/2026_01_06_000527_create_subscription_items_table.php b/database/migrations/2026_01_06_000527_create_subscription_items_table.php
deleted file mode 100644
index 420e23f..0000000
--- a/database/migrations/2026_01_06_000527_create_subscription_items_table.php
+++ /dev/null
@@ -1,34 +0,0 @@
-id();
- $table->foreignId('subscription_id');
- $table->string('stripe_id')->unique();
- $table->string('stripe_product');
- $table->string('stripe_price');
- $table->integer('quantity')->nullable();
- $table->timestamps();
-
- $table->index(['subscription_id', 'stripe_price']);
- });
- }
-
- /**
- * Reverse the migrations.
- */
- public function down(): void
- {
- Schema::dropIfExists('subscription_items');
- }
-};
diff --git a/database/migrations/2026_01_06_000528_add_meter_id_to_subscription_items_table.php b/database/migrations/2026_01_06_000528_add_meter_id_to_subscription_items_table.php
deleted file mode 100644
index 033bb82..0000000
--- a/database/migrations/2026_01_06_000528_add_meter_id_to_subscription_items_table.php
+++ /dev/null
@@ -1,28 +0,0 @@
-string('meter_id')->nullable()->after('stripe_price');
- });
- }
-
- /**
- * Reverse the migrations.
- */
- public function down(): void
- {
- Schema::table('subscription_items', function (Blueprint $table) {
- $table->dropColumn('meter_id');
- });
- }
-};
diff --git a/database/migrations/2026_01_06_000529_add_meter_event_name_to_subscription_items_table.php b/database/migrations/2026_01_06_000529_add_meter_event_name_to_subscription_items_table.php
deleted file mode 100644
index b157b3a..0000000
--- a/database/migrations/2026_01_06_000529_add_meter_event_name_to_subscription_items_table.php
+++ /dev/null
@@ -1,28 +0,0 @@
-string('meter_event_name')->nullable()->after('quantity');
- });
- }
-
- /**
- * Reverse the migrations.
- */
- public function down(): void
- {
- Schema::table('subscription_items', function (Blueprint $table) {
- $table->dropColumn('meter_event_name');
- });
- }
-};
diff --git a/resources/views/billing/index.blade.php b/resources/views/billing/index.blade.php
deleted file mode 100644
index 00c8900..0000000
--- a/resources/views/billing/index.blade.php
+++ /dev/null
@@ -1,106 +0,0 @@
- {{ session('success') }} {{ session('error') }}
- Are you sure you want to cancel your subscription? You will retain access until the end of your current billing period.
- BILLING
-
- @if (session('success'))
- Subscription Details
-
- Cancel Subscription?
-