# Subscription Module Plan ## Overview Recurring product subscriptions with flexible billing, integrated as a core plugin module (like Newsletter/Wishlist/Licensing). --- ## Module Architecture ### Core Features - **Recurring billing**: Weekly, monthly, yearly, custom intervals - **Free trials**: X days free before billing starts - **Sign-up fees**: One-time fee on first subscription - **Automatic renewals**: Process payment on renewal date - **Manual renewal**: Allow customers to renew manually - **Proration**: Calculate prorated amounts on plan changes - **Pause/Resume**: Allow customers to pause subscriptions ### Product Integration - Checkbox under "Additional Options": **Enable subscription for this product** - When enabled, show subscription settings: - Billing period (weekly/monthly/yearly/custom) - Billing interval (every X periods) - Free trial days - Sign-up fee - Subscription length (0 = unlimited) - Variable products: Variation-level subscription settings (different durations/prices per variation) ### Integration with Licensing - Licenses can be bound to subscriptions - When subscription is active → license is valid - When subscription expires/cancelled → license is revoked - Auto-renewal keeps license active --- ## Database Schema ### Table: `woonoow_subscriptions` ```sql CREATE TABLE woonoow_subscriptions ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, order_id BIGINT UNSIGNED NOT NULL, product_id BIGINT UNSIGNED NOT NULL, variation_id BIGINT UNSIGNED DEFAULT NULL, status ENUM('pending', 'active', 'on-hold', 'cancelled', 'expired', 'pending-cancel') DEFAULT 'pending', billing_period ENUM('day', 'week', 'month', 'year') NOT NULL, billing_interval INT UNSIGNED DEFAULT 1, start_date DATETIME NOT NULL, trial_end_date DATETIME DEFAULT NULL, next_payment_date DATETIME DEFAULT NULL, end_date DATETIME DEFAULT NULL, last_payment_date DATETIME DEFAULT NULL, payment_method VARCHAR(100) DEFAULT NULL, payment_meta LONGTEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_user_id (user_id), INDEX idx_order_id (order_id), INDEX idx_status (status), INDEX idx_next_payment (next_payment_date) ); ``` ### Table: `woonoow_subscription_orders` Links subscription to renewal orders: ```sql CREATE TABLE woonoow_subscription_orders ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, subscription_id BIGINT UNSIGNED NOT NULL, order_id BIGINT UNSIGNED NOT NULL, order_type ENUM('parent', 'renewal', 'switch', 'resubscribe') DEFAULT 'renewal', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_subscription (subscription_id), INDEX idx_order (order_id) ); ``` --- ## Backend Structure ``` includes/Modules/Subscription/ ├── SubscriptionModule.php # Bootstrap, hooks, product meta ├── SubscriptionManager.php # Core logic ├── SubscriptionScheduler.php # Cron jobs for renewals └── SubscriptionSettings.php # Settings schema includes/Api/SubscriptionsController.php # REST endpoints ``` ### SubscriptionManager Methods ```php - create($order, $product, $user) # Create subscription from order - renew($subscription_id) # Process renewal - cancel($subscription_id, $reason) # Cancel subscription - pause($subscription_id) # Pause subscription - resume($subscription_id) # Resume paused subscription - switch($subscription_id, $new_product) # Switch plan - get_next_payment_date($subscription) # Calculate next date - process_renewal_payment($subscription) # Charge payment ``` ### Cron Jobs - `woonoow_process_subscription_renewals`: Run daily, process due renewals - `woonoow_check_expired_subscriptions`: Mark expired subscriptions --- ## REST API Endpoints ### Admin Endpoints ``` GET /subscriptions # List all subscriptions GET /subscriptions/{id} # Get subscription details PUT /subscriptions/{id} # Update subscription POST /subscriptions/{id}/cancel # Cancel subscription POST /subscriptions/{id}/renew # Force renewal ``` ### Customer Endpoints ``` GET /my-subscriptions # Customer's subscriptions GET /my-subscriptions/{id} # Subscription detail POST /my-subscriptions/{id}/cancel # Request cancellation POST /my-subscriptions/{id}/pause # Pause subscription POST /my-subscriptions/{id}/resume # Resume subscription ``` --- ## Admin SPA ### Subscriptions List (`/subscriptions`) - Table: ID, Customer, Product, Status, Next Payment, Actions - Filters: Status, Product, Date range - Actions: View, Cancel, Renew ### Subscription Detail (`/subscriptions/:id`) - Subscription info card - Related orders list - Payment history - Action buttons: Cancel, Pause, Renew --- ## Customer SPA ### My Subscriptions (`/my-account/subscriptions`) - List of active/past subscriptions - Status badges - Next payment info - Actions: Cancel, Pause, View ### Subscription Detail - Product info - Billing schedule - Payment history - Management actions --- ## Settings Schema ```php return [ 'default_status' => 'active', 'button_text_subscribe' => 'Subscribe Now', 'button_text_renew' => 'Renew Subscription', 'allow_customer_cancel' => true, 'allow_customer_pause' => true, 'max_pause_count' => 3, 'renewal_retry_days' => [1, 3, 5], // Retry failed payments 'expire_after_failed_attempts' => 3, 'send_renewal_reminder' => true, 'reminder_days_before' => 3, ]; ``` --- ## Implementation Priority 1. Database tables and SubscriptionManager 2. Product meta fields for subscription settings 3. Order hook to create subscription 4. Renewal cron job 5. Admin SPA list/detail pages 6. Customer SPA pages 7. Integration with Licensing module