ruby-on-railssubscriptionrecurring-billingbraintreebraintree-rails

Add Discount to Braintree Rails Subscription


I'm trying to add a discount object to a subscription with the braintree-rails gem, but it is not applied. I'm guessing my code must be wrong, but I can't find a working example.

discount = BraintreeRails::Discount.find(params[:subscription_promo])
subscription = @plan.subscriptions.build permitted_params[:subscription]
subscription.discounts << discount
# ...
subscription.save

When I dump discount, it is loaded properly. The subscription is created just fine, but at full price. The discount is not there. How can I add the discount to the subscription?

Update: I tried modifying the direct query, but that has not helped.

@subscription.raw_object.discounts = {add:[{inherited_from_id: discount.id}]}

Update 2: I also ran a direct Braintree request against the API with the request expected of the above code, and it worked. There's something wrong happening between setting it and saving.

Update 3: A workaround is possible by extracting the attributes of the BraintreeRails::Subscription object, using Braintree::Subscription to call the API, and using BraintreeRails::Subscription.find to load it back into the object. This is definitely not optimal, though, since it's not very clean, and requires an extra API call.


Solution

  • gem author here.

    Unfortunately neither BraintreeRails nor the Braintree ruby gem supports the subscription.discounts << discount style of adding discounts to subscriptions at the moment.

    As you can see in braintree ruby doc, the adding/updating/overriding addon/discounts API is a little too flexible to be wrapped in a single subscription.discounts << discount line.

    If your setup of addon/discounts for subscription is simple and doesn't vary much, you can try create one plan for each desired combination, and then use the right plan to create the subscription.

    If your setup is quite dynamic(in terms of price, billing cycle, quantity etc), use the Braintree API directly is probably your best option. E.g.:

    result = Braintree::Subscription.create(
      :payment_method_token => "the_payment_method_token",
      :plan_id => "the_plan_id",
      :add_ons => {
        :add => [
          {
            :inherited_from_id => "add_on_id_1",
            :amount => BigDecimal.new("20.00")
          }
        ],
        :update => [
          {
            :existing_id => "add_on_id_2",
            :quantity => 2
          }
        ],
        :remove => ["add_on_id_3"]
      },
      :discounts => {
        :add => [
          {
            :inherited_from_id => "discount_id_1",
            :amount => BigDecimal.new("15.00")
          }
        ],
        :update => [
          {
            :existing_id => "discount_id_2",
            :quantity => 3
          }
        ],
        :remove => ["discount_id_3"]
      }
    )