Subscription Initialization Process

Overview

When a subscription payment is completed, the system asynchronously initializes several key attributes:

  • Copies owed (number of issues the subscriber is entitled to)
  • Deferred amount (revenue to be recognized over the subscription term)
  • Issue shipping basis (how issues are determined for shipping)
  • Shipping information (address and soundex for duplicate detection)

Initialization Flow

1. Payment Completion Hook

The process begins when a payment is completed for a new subscription:

// Hook into payment completion
add_action('woocommerce_subscription_payment_complete', 'subscription_payment_complete', 30, 1);

2. Asynchronous Action Scheduling

The controller schedules an asynchronous action to handle the initialization:

public function subscription_payment_complete($subscription) {
    // Only process original orders, not renewals
    if ($subscription->get_payment_count() > 1 || false === $subscription->get_parent()) {
        return;
    }
    
    // Schedule async action with 20 second delay
    as_schedule_single_action(
        time() + 20, 
        'jc_new_subscription_payment_complete_async', 
        ['subscription_id' => $subscription->get_id()], 
        'jc_subscriptions'
    );
}

3. Hook Registration

The async action handler is registered in the plugin initialization:

// Register the async action handler
$this->loader->add_action(
    'jc_new_subscription_payment_complete_async', 
    $subscription_controller, 
    'new_subscription_payment_complete', 
    10, 
    1
);

4. Copies Owed Calculation

The number of copies owed is calculated based on:

  • The subscription term length
  • Any existing copies owed
  • The issues per term setting
// Increment copies owed by issues per term
$tsj_subscription->set_copies_owed(
    $tsj_subscription->get_copies_owed() + 
    $tsj_subscription->get_issues_per_term()
);

5. Deferred Amount Assignment

The deferred amount is set based on:

  • The parent order’s total
  • Any existing deferred amount
$new_deferred_amount = $last_order->get_total();
$tsj_subscription->set_deferred_amount(
    $tsj_subscription->get_deferred_amount() + 
    $new_deferred_amount
);

6. Post-Initialization Tasks

After saving the subscription, additional async actions are scheduled:

// Save the subscription
$tsj_subscription->save();

// Create detailed notes
$notes = "SKU: " . $tsj_subscription->get_sku() . "<br/>";
$notes .= "expiry issue: " . get_the_title($tsj_subscription->get_expiry_issue_id()) . "<br/>";
$notes .= "copies owed: " . $tsj_subscription->get_copies_owed() . "<br/>";
$notes .= "deferred amount: " . $tsj_subscription->get_deferred_amount();

// Add notes to the subscription
$wc_subscription->add_order_note($notes);

// Schedule post-initialization tasks
as_enqueue_async_action(
    'journal_subscription_created',
    [
        'tsj_subscription' => $tsj_subscription->get_id(),
        'notes' => $notes
    ],
    'jc_subscriptions'
);

Data Storage

The subscription data is stored in a custom table jc_subscriptions with the following relevant fields:

CREATE TABLE {$wpdb->prefix}jc_subscriptions (
    subscription_id BIGINT UNSIGNED NOT NULL,
    copies_owed INT NOT NULL DEFAULT 0,
    deferred_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00,
    -- other fields...
);

Error Handling and Validation

The system includes several safeguards:

  1. Nonce verification for admin operations
  2. Input validation for numeric values
  3. Proper rounding of monetary amounts
  4. Error logging for failed operations
  5. Validation of subscription status before processing

Best Practices

  1. Data Consistency
    • Always validate input before saving
    • Use proper data types for numeric values
    • Round monetary amounts to 2 decimal places
    • Handle existing values when incrementing
  2. Performance
    • Use asynchronous processing for non-critical tasks
    • Batch operations where possible
    • Implement proper indexing on database tables
    • Delay initialization to avoid payment processing conflicts
  3. Monitoring
    • Log initialization events
    • Track deferred amount changes
    • Monitor copies owed adjustments
    • Record detailed notes for audit purposes
  4. Security
    • Validate all user input
    • Implement proper access controls
    • Use WordPress nonces for form submissions
    • Verify subscription ownership and status