On a site that sells asynchronous prepaid role-based monthly subscriptions, our customers need to be able to cancel their subscriptions but still have access to the site until their existing prepaid license expires. Therefore their subscriptions should not be prorated.

I haven't been able to find documentation or a tutorial or really anything that explains how this can be done.

I've tried a number of things, but none of them quite work:

  • Suspend the license
    The customer's role access is immediately revoked. The orders and billing cycle are not changed. The customer continues to be billed which is obviously not good. To add insult to injury, the new recurring orders do not reactivate the license.
  • Revoke the license
    The customer's role access is immediately revoked. The orders are not changed. The current billing cycle's status is set to 0. The customer is billed one final time.
  • Delete the license
    The customer's role access is immediately revoked. All of the customer's orders stemming from that license are deleted. The customer's billing cycles stemming from that license are deleted. Consequently all order and billing history is lost; it's as if the customer had never been a subscriber in the first place.
  • Cancel both the "Recurring: Open" and "Pending"/(or "Recurring: Payment pending") orders
    The license is revoked the next time cron/advancedqueue runs regardless of how much time remains in the license or billing cycle. (FYI as far as I can tell, the "Pending" order is the original order before its status changes to "Completed.")
  • Cancel just the "Recurring: Open" order
    The license stays active. When the current billing cycle ends a new "Recurring: Open" order is created. The customer is billed again. A new billing cycle is created. The accompanying "Pending"/(or "Recurring: Payment pending") order is eventually marked "Completed."
  • Cancel just the "Pending"/(or "Recurring: Payment pending") order
    The license is revoked the next time cron/advancedqueue runs regardless of how much time remains in the license or the billing cycle. When the billing cycle ends, cron/advancedqueue attempts to deal with the accompanying "Recurring: Open" order but it can't because of non-object errors that occur inside billing_cycle_close_queue_process(). The existing "Recurring: Open" order remains open (and a new recurring order is not created). The customer is not billed again.

Comments

Lord Pachelbel created an issue. See original summary.

Lord Pachelbel’s picture

Issue summary: View changes
Lord Pachelbel’s picture

Issue summary: View changes
Lord Pachelbel’s picture

Issue summary: View changes
Lord Pachelbel’s picture

I think I've found some documentation, sort of. According to https://www.drupal.org/node/2399173 I can use commerce_license_billing_change_status() to schedule a license change.

Lord Pachelbel’s picture

Yes, that is indeed how subscriptions can be scheduled for cancellation. To use that function I'm calling it in a form submit handler in a custom module:

// schedule the license for cancellation
commerce_license_billing_change_status($license_ent, COMMERCE_LICENSE_REVOKED);

But it's still incomplete. That function will schedule the cancellation of the billing cycle by setting the order line item price to $0.00, but it will not revoke the license when the license period expires.

To handle the revocation I also needed to patch commerce_license_billing with #21 from #2247703: Scheduling cancellations doesn't work properly for prepaid licenses which in turn required a patch to commerce_license from #2736709: Allow modules to back-date $entity->revision_created.

hgoto’s picture

Nice work! This must be really helpful for new users :)

Lord Pachelbel’s picture