How to enter coupon codes via the API

680 views
Skip to first unread message

Jeremy Kaplan

unread,
Dec 24, 2012, 8:29:58 AM12/24/12
to spree...@googlegroups.com
Can someone point me in the right direction? I'd thought to use the demo to figure out what it was doing to enter coupon codes but I can't get beyond the cc and address step of the order w/o some server error. 

Are coupons another form of payment, meaning we have to have one for the coupon and another/others for other forms of payment?

thanks,
jd

Nate Lowrie

unread,
Dec 26, 2012, 8:24:11 AM12/26/12
to spree...@googlegroups.com
JD,

Coupons are treated as promotions.  You can set the promotion system up to accept Coupon Codes and that will produce an adjustment on the order.  The never get logged as payments.

Regards,

Nate

Ryan Bigg

unread,
Dec 27, 2012, 11:37:22 PM12/27/12
to spree...@googlegroups.com
There currently isn't a way to take coupon codes for the order through the API. This is mainly because we didn't need the feature in the first place for the API. If you would still like this feature, please open a new issue on GitHub about it and it will be addressed most likely in time for the next Spree release.


--
You received this message because you are subscribed to the Google Groups "Spree" group.
To view this discussion on the web visit https://groups.google.com/d/msg/spree-user/-/a6t5SUie69AJ.

To post to this group, send email to spree...@googlegroups.com.
To unsubscribe from this group, send email to spree-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/spree-user?hl=en.

john

unread,
Jan 8, 2013, 5:26:42 PM1/8/13
to spree...@googlegroups.com
We use this but needs a lot of cleanup.

 [17:16:51] $ cat app/controllers/coupon_controller.rb 
      class CouponController < Spree::Api::V1::BaseController
      #  before_filter :authorize_read!

        def show
        end

        def search
          @orders = Order.ransack(params[:q]).result.page(params[:page])
          render :index
        end

        def check
          @coupon_code = params[:id]
          if Spree::Promotion.exists?(:code => @coupon_code)
            puts 'code:'+@coupon_code
            render :text => "OK", :status => 200
          else
            puts 'code failed:'+@coupon_code
            render :text => "FAIL", :status => 422
          end            
        end
        

        
  def update
    @order = Order.find_by_number!(params[:id])
    if @order.update_attributes(params[:order])
      if @order.coupon_code.present?
        if apply_coupon_code
          # flash[:notice] = t(:coupon_code_applied)
        else
          # flash[:error] = t(:promotion_not_found)
          render respond_with(@order) and return
        end
      end
      @order.line_items = @order.line_items.select {|li| li.quantity > 0 }
      fire_event('spree.order.contents_changed')
      respond_with(@order) { |format| format.html { redirect_to cart_path } }
    else
      respond_with(@order)
    end
  end

  def apply_coupon_code
    return if @order.coupon_code.blank?
    if Spree::Promotion.exists?(:code => @order.coupon_code)
      fire_event('spree.checkout.coupon_code_added', :coupon_code => @order.coupon_code)
      true
    end
  end
end

17:23:41] $ cat app/controllers/spree/api/v1/orders_controller_decorator.rb 
Spree::Api::V1::OrdersController.class_eval do
# include Spree::Core::ControllerHelpers

  def update
    # @order = Order.find_by_number!(params[:id])
    puts "coupon: step 1"
    if @order.update_attributes(params[:order])
    puts "coupon: step 2"
      if @order.coupon_code.present?
          puts "coupon: step 3"
        if apply_coupon_code
       puts "coupon: step 4a"
          # flash[:notice] = t(:coupon_code_applied)
        else
      puts "coupon: step 4b"
          #flash[:error] = t(:promotion_not_found)
          #render :edit and return
        end
      end
      @order.line_items = @order.line_items.select {|li| li.quantity > 0 }
      fire_event('spree.order.contents_changed')
    puts "coupon: step 5"
      render :show, :status => 200
    else
      render :show, :status => 422
    end
  end

  def apply_coupon_code
      puts "coupon: step 6"
    return if @order.coupon_code.blank?
    if Spree::Promotion.exists?(:code => @order.coupon_code)
    puts "coupon: step 7"
      fire_event('spree.checkout.coupon_code_added', :coupon_code => @order.coupon_code)
      true
    end
  end

      def fire_event(name, extra_payload = {})
        ActiveSupport::Notifications.instrument(name, default_notification_payload.merge(extra_payload))
      end

      # Creates the hash that is sent as the payload for all notifications. Specific notifications will
      # add additional keys as appropriate. Override this method if you need additional data when
      # responding to a notification
      def default_notification_payload
        {:user => try_spree_current_user, :order => @order}
      end

      def try_spree_current_user
        respond_to?(:spree_current_user) ? spree_current_user : nil
      end


end

cat app/models/spree/order_decorator.rb 
Spree::Order.class_eval do
  checkout_flow do
    # go_to_state :address, :if => lambda { |order| order.payment_required? }
    go_to_state :address
    go_to_state :payment, :if => lambda { |order| order.payment_required? }
    go_to_state :confirm, :if => lambda { |order| order.confirmation_required? }
    go_to_state :complete
  end

  # If true, causes the payment step to happen during the checkout process
  def payment_required?
    return false
  end

  # If true, causes the confirmation step to happen during the checkout process
  def confirmation_required?
    return false
  end

  # Finalizes an in progress order after checkout is complete.
      # Called after transition to complete state when payments will
  # have been processed
  def finalize!
    touch :completed_at
    InventoryUnit.assign_opening_inventory(self)

    # lock all adjustments (coupon promotions, etc.)
    adjustments.each { |adjustment| adjustment.update_column('locked', true) }

    # update payment and shipment(s) states, and save
    updater = OrderUpdater.new(self)
    updater.update_payment_state
    shipments.each { |shipment| shipment.update!(self) }
    updater.update_shipment_state
    save
#FIXME do not send the order confirmation to the user
  #  deliver_order_confirmation_email

    self.state_changes.create({
                                :previous_state => 'cart',
                                :next_state     => 'complete',
                                :name           => 'order' ,
                                :user_id        => self.user_id
                              }, :without_protection => true)
  end

  def deliver_order_confirmation_email
    begin
      OrderMailer.confirm_email(self).deliver
    rescue Exception => e
      logger.error("#{e.class.name}: #{e.message}")
      logger.error(e.backtrace * "\n")
    end
  end
  
end

On Monday, December 24, 2012 8:29:58 AM UTC-5, Jeremy Kaplan wrote:

Thomas Mulloy

unread,
Oct 30, 2014, 3:59:44 PM10/30/14
to spree...@googlegroups.com
is this still the case for 2-3-stable?

Thomas Mulloy

unread,
Oct 30, 2014, 4:13:41 PM10/30/14
to spree...@googlegroups.com

Thomas Mulloy

unread,
Oct 30, 2014, 8:47:45 PM10/30/14
to spree...@googlegroups.com
as a follow up, i can confirm that there is some basic functionality in the spree api 2-3-stable and is the action linked to in my previous reply.

after checking for available api routes i came across two:

apply_coupon_code_api_checkout PUT      /api/checkouts/:id/apply_coupon_code(.:format)   spree/api/checkouts#apply_coupon_code {:format=>"json"}
apply_coupon_code_api_order PUT         /api/orders/:id/apply_coupon_code(.:format)      spree/api/orders#apply_coupon_code {:format=>"json"}

the first route /api/checkouts/:id/apply_coupon_code(.:format) is actually a bad route, there's no action to receive it, which is funky but oh well, so the 2nd route does work and connects to the order action  (https://github.com/spree/spree/blob/2-3-stable/api/app/controllers/spree/api/orders_controller.rb#L83). hitting that route with the following params: "number", "order_token" and "coupon_code" will indeed apply a promotion. the response is very basic, and a little inconsistent with the spree api in general, here is the response for a coupon that has already been applied:

{"success":null,"error":"The coupon code has already been applied to this order","successful":false}

that's about all, there's no coupon remove (?) etc. but it appears as of 2-3-stable it's partially implemented. hope this helps someone else.

Reply all
Reply to author
Forward
0 new messages