From b95e681105734e81a68553e420e5e5fcb4381a2c Mon Sep 17 00:00:00 2001 From: Sanjay Prajapati Date: Mon, 2 Oct 2017 13:45:33 +0530 Subject: [PATCH] Add abandon cart feature, remove cart from mailchimp if remove line items from tfc --- .../spree/chimpy/line_item_decorator.rb | 7 ++ app/models/spree/order_decorator.rb | 10 +- .../chimpy/interface/customer_upserter.rb | 40 ++++++-- lib/spree/chimpy/interface/order_upserter.rb | 97 ++++++++++++++++--- lib/spree_chimpy.rb | 6 +- 5 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 app/models/spree/chimpy/line_item_decorator.rb diff --git a/app/models/spree/chimpy/line_item_decorator.rb b/app/models/spree/chimpy/line_item_decorator.rb new file mode 100644 index 0000000..0d9f416 --- /dev/null +++ b/app/models/spree/chimpy/line_item_decorator.rb @@ -0,0 +1,7 @@ +Spree::LineItem.class_eval do + after_destroy :notify_mail_chimp + + def notify_mail_chimp + Spree::Chimpy.enqueue(:order, order) if order.email.present? && Spree::Chimpy.configured? + end +end \ No newline at end of file diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 121ff8e..9e073a9 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -6,15 +6,21 @@ end around_save :handle_cancelation + after_save :handle_mailchimp_cart def notify_mail_chimp - Spree::Chimpy.enqueue(:order, self) if completed? && Spree::Chimpy.configured? + Spree::Chimpy.enqueue(:order, self) if email.present? && Spree::Chimpy.configured? end -private + private def handle_cancelation canceled = state_changed? && canceled? yield notify_mail_chimp if canceled end + + # Email is not available when transit from registration page to address page. + def handle_mailchimp_cart + notify_mail_chimp if email.present? && state == 'address' + end end diff --git a/lib/spree/chimpy/interface/customer_upserter.rb b/lib/spree/chimpy/interface/customer_upserter.rb index 26af94c..b44b3bf 100644 --- a/lib/spree/chimpy/interface/customer_upserter.rb +++ b/lib/spree/chimpy/interface/customer_upserter.rb @@ -29,7 +29,11 @@ def customer_id_from_eid(mc_eid) .retrieve(params: { "fields" => "customers.id", "email_address" => email }) data = response["customers"].first - data["id"] if data + #data["id"] if data + if data + update_cutomer_orders(data["id"]) + data["id"] + end rescue Gibbon::MailChimpError => e nil end @@ -39,26 +43,46 @@ def customer_id_from_eid(mc_eid) private def upsert_customer - return unless @order.user_id + customer_id = @order.user_id || "#{@order.email.downcase}" - customer_id = self.class.mailchimp_customer_id(@order.user_id) + customer_id = self.class.mailchimp_customer_id(customer_id) begin response = store_api_call .customers(customer_id) .retrieve(params: { "fields" => "id,email_address"}) + update_cutomer_orders(response) if response.present? && response['id'].present? rescue Gibbon::MailChimpError => e # Customer Not Found, so create them response = store_api_call .customers - .create(body: { - id: customer_id, - email_address: @order.email.downcase, - opt_in_status: Spree::Chimpy::Config.subscribe_to_list || false - }) + .create(body: data.merge(id: customer_id)) end customer_id end + def update_cutomer_orders(customer) + store_api_call + .customers(customer['id']) + .update(body: data.merge(id: customer['id'])) + end + + def data + { + email_address: @order.email.downcase, + opt_in_status: true, + orders_count: customer_orders.count, + total_spent: total_spent + } + end + + def total_spent + customer_orders.pluck(:total).sum.round(2) + end + + def customer_orders + Spree::Order.complete.where('email=?', @order.email) + end + end end end \ No newline at end of file diff --git a/lib/spree/chimpy/interface/order_upserter.rb b/lib/spree/chimpy/interface/order_upserter.rb index a0ed0a1..72d0e1b 100644 --- a/lib/spree/chimpy/interface/order_upserter.rb +++ b/lib/spree/chimpy/interface/order_upserter.rb @@ -22,8 +22,8 @@ def upsert private def perform_upsert - data = order_hash - log "Adding order #{@order.number} for #{data[:customer][:id]} with campaign #{data[:campaign_id]}" + data = api_data + log "Adding order/cart #{@order.number} for #{data[:customer][:id]} with campaign #{data[:campaign_id]}" begin find_and_update_order(data) rescue Gibbon::MailChimpError => e @@ -32,19 +32,56 @@ def perform_upsert end end + def api_data + return cart_hash if @order.state != 'complete' + order_hash + end + def find_and_update_order(data) # retrieval is checks if the order exists and raises a Gibbon::MailChimpError when not found - response = store_api_call.orders(@order.number).retrieve(params: { "fields" => "id" }) - log "Order #{@order.number} exists, updating data" - store_api_call.orders(@order.number).update(body: data) + if @order.state != 'complete' + store_api_call.carts(@order.number).retrieve(params: { "fields" => "id" }) + log "Cart #{@order.number} exists, updating data" + if @order.reload.line_items.empty? + remove_cart_from_mailchimp if cart_exist? + else + store_api_call.carts(@order.number).update(body: data) + end + else + store_api_call.orders(@order.number).retrieve(params: { "fields" => "id" }) + log "Order #{@order.number} exists, updating data" + store_api_call.orders(@order.number).update(body: data) + end end def create_order(data) - store_api_call - .orders - .create(body: data) + if @order.state != 'complete' + url = store_api_call.carts + else + url = store_api_call.orders + remove_cart_from_mailchimp if cart_exist? + CustomerUpserter.new(@order).ensure_customer + end + url.create(body: data) rescue Gibbon::MailChimpError => e - log "Unable to create order #{@order.number}. [#{e.raw_body}]" + log "Unable to create cart/order #{@order.number}. [#{e.raw_body}]" + end + + def cart_exist? + begin + response = store_api_call + .carts(@order.number) + .retrieve(params: { "fields" => "id" }) + !response["id"].nil? + rescue Gibbon::MailChimpError => e + log "Cart #{@order.number} Not Found" + false + end + end + + def remove_cart_from_mailchimp + response = store_api_call + .carts(@order.number).delete end def order_variant_hash(line_item) @@ -61,14 +98,9 @@ def order_variant_hash(line_item) def order_hash source = @order.source - lines = @order.line_items.map do |line| - # MC can only associate the order with a single category: associate the order with the category right below the root level taxon - order_variant_hash(line) - end - data = { id: @order.number, - lines: lines, + lines: order_lines, order_total: @order.total.to_f, financial_status: @order.payment_state || "", fulfillment_status: @order.shipment_state || "", @@ -88,6 +120,41 @@ def order_hash data end + + def order_lines + @order.line_items.map do |line| + # MC can only associate the order with a single category: associate the order with the category right below the root level taxon + order_variant_hash(line) + end + end + + def cart_hash + source = @order.source + data = { + id: @order.number, + lines: order_lines, + order_total: @order.total.to_f, + currency_code: @order.currency, + tax_total: @order.try(:included_tax_total).to_f + @order.try(:additional_tax_total).to_f, + checkout_url: checkout_url, + customer: { + id: customer_id + } + } + + if source + data[:campaign_id] = source.campaign_id + end + + data + end + + def checkout_url + URI::HTTP.build({ + host: Rails.application.routes.default_url_options[:host], + :path => "/cart"} + ).to_s + end end end end diff --git a/lib/spree_chimpy.rb b/lib/spree_chimpy.rb index 301c880..081149d 100644 --- a/lib/spree_chimpy.rb +++ b/lib/spree_chimpy.rb @@ -122,7 +122,11 @@ def perform(payload) case event when :order - orders.sync(object) + if object.canceled? + orders.remove(object) + else + orders.sync(object) + end when :subscribe list.subscribe(object.email, merge_vars(object), customer: object.is_a?(Spree.user_class)) when :unsubscribe