omniorder 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +9 -0
- data/lib/omniorder/customer.rb +7 -0
- data/lib/omniorder/customerable.rb +42 -0
- data/lib/omniorder/entity.rb +21 -0
- data/lib/omniorder/import.rb +11 -0
- data/lib/omniorder/import_strategy/base.rb +50 -0
- data/lib/omniorder/import_strategy/groupon.rb +93 -0
- data/lib/omniorder/order.rb +12 -0
- data/lib/omniorder/order_product.rb +7 -0
- data/lib/omniorder/order_productable.rb +11 -0
- data/lib/omniorder/orderable.rb +35 -0
- data/lib/omniorder/product.rb +12 -0
- data/lib/omniorder/purchasable.rb +7 -0
- data/lib/omniorder/version.rb +3 -0
- data/lib/omniorder.rb +55 -0
- data/omniorder.gemspec +27 -0
- data/spec/assets/imports/groupon/base_spec.rb +17 -0
- data/spec/assets/imports/groupon/get_orders.json +82 -0
- data/spec/customerable_spec.rb +37 -0
- data/spec/import_strategy/groupon_spec.rb +88 -0
- data/spec/orderable_spec.rb +55 -0
- data/spec/spec_helper.rb +27 -0
- metadata +148 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: c03ee4b2df4c0589a2a01e7787556544cf5bc382
         | 
| 4 | 
            +
              data.tar.gz: e229b29ba52d8c82adc3b083933c6112f8c20011
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: ce3a0db160edea671d7c571be7251616f7832cf85d842cd0f54f6ec2f2e389540744ca6c6b023042ad87c53fd56293fad8c5ae14b72d2a3976d4b4da913b4d9d
         | 
| 7 | 
            +
              data.tar.gz: 2b70815df33f45e01f465aefec85797e292ef9e33f9caefafba0680f3407194d9acbdc8c4ad4c8ec168daa3eae09986be793ce8be8d8f51baad77e60040bf4f3
         | 
    
        data/.gitignore
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            *.gem
         | 
| 2 | 
            +
            *.rbc
         | 
| 3 | 
            +
            .bundle
         | 
| 4 | 
            +
            .config
         | 
| 5 | 
            +
            .yardoc
         | 
| 6 | 
            +
            Gemfile.lock
         | 
| 7 | 
            +
            InstalledFiles
         | 
| 8 | 
            +
            _yardoc
         | 
| 9 | 
            +
            coverage
         | 
| 10 | 
            +
            doc/
         | 
| 11 | 
            +
            lib/bundler/man
         | 
| 12 | 
            +
            pkg
         | 
| 13 | 
            +
            rdoc
         | 
| 14 | 
            +
            spec/reports
         | 
| 15 | 
            +
            test/tmp
         | 
| 16 | 
            +
            test/version_tmp
         | 
| 17 | 
            +
            tmp
         | 
| 18 | 
            +
            *.bundle
         | 
| 19 | 
            +
            *.so
         | 
| 20 | 
            +
            *.o
         | 
| 21 | 
            +
            *.a
         | 
| 22 | 
            +
            mkmf.log
         | 
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            Copyright (c) 2014 Howard Wilson
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            MIT License
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 6 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 7 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 8 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 9 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 10 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 11 | 
            +
            the following conditions:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 14 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 17 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 18 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 19 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 20 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 21 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 22 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            # Omniorder
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            [](https://travis-ci.org/watsonbox/omniorder)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Import online orders from various channels for fulfillment.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
             | 
| 8 | 
            +
            ## Installation
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Add this line to your application's Gemfile:
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ```ruby
         | 
| 13 | 
            +
            gem 'omniorder'
         | 
| 14 | 
            +
            ```
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            And then execute:
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ```bash
         | 
| 19 | 
            +
            $ bundle
         | 
| 20 | 
            +
            ```
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            Or install it yourself as:
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ```bash
         | 
| 25 | 
            +
            $ gem install omniorder
         | 
| 26 | 
            +
            ```
         | 
| 27 | 
            +
             | 
| 28 | 
            +
             | 
| 29 | 
            +
            ## Usage
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            TODO: Write usage instructions here
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             | 
| 34 | 
            +
            ## Contributing
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            1. Fork it ( https://github.com/watsonbox/omniorder/fork )
         | 
| 37 | 
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
| 38 | 
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         | 
| 39 | 
            +
            4. Push to the branch (`git push origin my-new-feature`)
         | 
| 40 | 
            +
            5. Create a new Pull Request
         | 
    
        data/Rakefile
    ADDED
    
    
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            module Omniorder
         | 
| 2 | 
            +
              module Customerable
         | 
| 3 | 
            +
                def username_is_email?
         | 
| 4 | 
            +
                  username == email
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def first_names
         | 
| 8 | 
            +
                  name.split[0...-1]
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def first_name
         | 
| 12 | 
            +
                  first_names.first
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def last_name
         | 
| 16 | 
            +
                  name.split.last
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def full_address
         | 
| 20 | 
            +
                  fields = [address1, address2, address3, address4, postcode, country]
         | 
| 21 | 
            +
                  fields.reject { |f| f.nil? || f.empty? }.join("\n")
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def self.get_or_new_from_email(email, attributes = {})
         | 
| 25 | 
            +
                  customer = nil
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  if Omniorder.customer_type.respond_to?(:find_by_email)
         | 
| 28 | 
            +
                    customer = Omniorder.customer_type.find_by_email(email)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  if customer
         | 
| 32 | 
            +
                    attributes.each do |name, value|
         | 
| 33 | 
            +
                      customer.send("#{name}=", value)
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  else
         | 
| 36 | 
            +
                    Omniorder.customer_type.new(attributes)
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  customer
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            module Omniorder
         | 
| 2 | 
            +
              class Entity
         | 
| 3 | 
            +
                def self.attributes(*attributes)
         | 
| 4 | 
            +
                  if attributes.empty?
         | 
| 5 | 
            +
                    instance_variable_get('@attributes')
         | 
| 6 | 
            +
                  else
         | 
| 7 | 
            +
                    instance_variable_set('@attributes', attributes)
         | 
| 8 | 
            +
                    attr_accessor *attributes
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def initialize(attributes = {})
         | 
| 13 | 
            +
                  # Initialize known attributes
         | 
| 14 | 
            +
                  attributes.each do |attribute, value|
         | 
| 15 | 
            +
                    if self.class.attributes.include?(attribute.to_sym)
         | 
| 16 | 
            +
                      send("#{attribute}=", value)
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            module Omniorder
         | 
| 2 | 
            +
              class Import
         | 
| 3 | 
            +
                # Allows the import to control how orders are created
         | 
| 4 | 
            +
                # e.g. an account could be assigned if system is multi-tennant
         | 
| 5 | 
            +
                # Use generate not build so as not to conflict with ActiveRecord
         | 
| 6 | 
            +
                # TODO: Move to Importable?
         | 
| 7 | 
            +
                def generate_order(attributes = {})
         | 
| 8 | 
            +
                  Omniorder.order_type.new({ import: self }.merge(attributes))
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Omniorder
         | 
| 2 | 
            +
              module ImportStrategy
         | 
| 3 | 
            +
                class Base
         | 
| 4 | 
            +
                  attr_accessor :import
         | 
| 5 | 
            +
                  attr_writer :options
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  class << self
         | 
| 8 | 
            +
                    def options(options = nil)
         | 
| 9 | 
            +
                      if options
         | 
| 10 | 
            +
                        @options = options
         | 
| 11 | 
            +
                      else
         | 
| 12 | 
            +
                        @options || {}
         | 
| 13 | 
            +
                      end
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def clear_options
         | 
| 17 | 
            +
                      @options = nil
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def initialize(import, options = {})
         | 
| 22 | 
            +
                    self.import = import
         | 
| 23 | 
            +
                    self.options = options
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  # Combines global and local options
         | 
| 27 | 
            +
                  def options
         | 
| 28 | 
            +
                    self.class.options.merge(@options)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def before_import
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def after_import
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  private
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def customer_country_or_default(country)
         | 
| 42 | 
            +
                    if country.nil? || country.empty?
         | 
| 43 | 
            +
                      Omniorder.default_customer_country
         | 
| 44 | 
            +
                    else
         | 
| 45 | 
            +
                      country
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -0,0 +1,93 @@ | |
| 1 | 
            +
            module Omniorder
         | 
| 2 | 
            +
              module ImportStrategy
         | 
| 3 | 
            +
                # Groupon Import Strategy
         | 
| 4 | 
            +
                # See: https://scm.commerceinterface.com/api-doc/v2/
         | 
| 5 | 
            +
                class Groupon < Base
         | 
| 6 | 
            +
                  API_URL = "https://scm.commerceinterface.com/api/v2/"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  attr_accessor :supplier_id, :access_token
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def initialize(import, options = {})
         | 
| 11 | 
            +
                    super
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    unless self.supplier_id = options[:supplier_id] and !supplier_id.to_s.empty?
         | 
| 14 | 
            +
                      raise "Omniorder::ImportStrategy::Groupon requires a supplier_id"
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    unless self.access_token = options[:access_token] and !access_token.to_s.empty?
         | 
| 18 | 
            +
                      raise "Omniorder::ImportStrategy::Groupon requires an access_token"
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def import_orders
         | 
| 23 | 
            +
                    get_order_info['data'].to_a.each do |order_info|
         | 
| 24 | 
            +
                      success = yield create_order(order_info)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      if success && options[:mark_exported]
         | 
| 27 | 
            +
                        result = Crack::JSON.parse do_request(mark_exported_url(order_info), :post)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                        unless result['success']
         | 
| 30 | 
            +
                          raise "Failed to mark Groupon order ##{order_info['orderid']} as exported"
         | 
| 31 | 
            +
                        end
         | 
| 32 | 
            +
                      end
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def get_orders_url
         | 
| 37 | 
            +
                    URI.join(API_URL, "get_orders?supplier_id=#{supplier_id}&token=#{access_token}")
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def mark_exported_url(order_info)
         | 
| 41 | 
            +
                    lids = order_info['line_items'].map { |li| li["ci_lineitemid"] }
         | 
| 42 | 
            +
                    URI.join(API_URL, "mark_exported?supplier_id=#{supplier_id}&token=#{access_token}&ci_lineitem_ids=[#{lids.join(',')}]")
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  private
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def create_order(order_info)
         | 
| 48 | 
            +
                    order = import.generate_order(
         | 
| 49 | 
            +
                      :order_number => order_info['orderid'],
         | 
| 50 | 
            +
                      :total_price => order_info['amount']['total'].to_f,
         | 
| 51 | 
            +
                      :date => DateTime.strptime(order_info['date'], '%m/%d/%Y %I:%M%p UTC')
         | 
| 52 | 
            +
                    )
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    order.customer = create_customer(order, order_info['customer'])
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    order_info['line_items'].each do |line_item_info|
         | 
| 57 | 
            +
                      order.add_product_by_code(line_item_info['sku'].to_s, line_item_info['quantity'].to_i)
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    order
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def create_customer(order, customer_info)
         | 
| 64 | 
            +
                    # NOTE: Can't find existing customer as no username or email given
         | 
| 65 | 
            +
                    order.generate_customer(
         | 
| 66 | 
            +
                      :name => customer_info['name'],
         | 
| 67 | 
            +
                      :phone => customer_info['phone'],
         | 
| 68 | 
            +
                      :address1 => customer_info['address1'],
         | 
| 69 | 
            +
                      :address2 => customer_info['address2'],
         | 
| 70 | 
            +
                      :address3 => customer_info['city'],
         | 
| 71 | 
            +
                      :address4 => customer_info['state'],
         | 
| 72 | 
            +
                      :postcode => customer_info['zip'].to_s.squeeze(' ').upcase,
         | 
| 73 | 
            +
                      :country => customer_country_or_default(customer_info['country'])
         | 
| 74 | 
            +
                    )
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  # NOTE: We don't appear to get an email address for customers
         | 
| 78 | 
            +
                  def get_order_info
         | 
| 79 | 
            +
                    Crack::JSON.parse do_request(get_orders_url)
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  private
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  def do_request(url, type = :get)
         | 
| 85 | 
            +
                    uri = URI(url)
         | 
| 86 | 
            +
                    http = Net::HTTP.new(uri.host, 443)
         | 
| 87 | 
            +
                    http.use_ssl = true
         | 
| 88 | 
            +
                    http.verify_mode = OpenSSL::SSL::VERIFY_PEER
         | 
| 89 | 
            +
                    http.request((type == :post ? Net::HTTP::Post : Net::HTTP::Get).new(uri.request_uri)).body
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            module Omniorder
         | 
| 2 | 
            +
              # Represents common order behavior
         | 
| 3 | 
            +
              # Include Omniorder::Orderable in your Order class to make it Omniorder compatible.
         | 
| 4 | 
            +
              module Orderable
         | 
| 5 | 
            +
                # Use generate not build so as not to conflict with ActiveRecord
         | 
| 6 | 
            +
                def generate_customer(attributes = {})
         | 
| 7 | 
            +
                  Omniorder.customer_type.new(attributes)
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def add_product(product, quantity = 1)
         | 
| 11 | 
            +
                  order_product = order_products.to_a.find { |op| op.product == product }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  if order_product.nil?
         | 
| 14 | 
            +
                    order_products << Omniorder.order_product_type.new(:product => product, :quantity => quantity)
         | 
| 15 | 
            +
                  else
         | 
| 16 | 
            +
                    order_product.quantity += quantity
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def add_product_by_code(code, quantity = 1)
         | 
| 21 | 
            +
                  Omniorder.product_type.find_by_code(code).tap do |product|
         | 
| 22 | 
            +
                    add_product product, quantity unless product.nil?
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def product_count
         | 
| 27 | 
            +
                  order_products.inject(0) { |sum, op| sum + op.quantity }
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                # Human-readable string representing order products
         | 
| 31 | 
            +
                def product_list
         | 
| 32 | 
            +
                  order_products.sort.map(&:to_s).join('/')
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
    
        data/lib/omniorder.rb
    ADDED
    
    | @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            require "net/http"
         | 
| 2 | 
            +
            require "net/https"
         | 
| 3 | 
            +
            require "crack"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "omniorder/version"
         | 
| 6 | 
            +
            require "omniorder/entity"
         | 
| 7 | 
            +
            require "omniorder/customerable"
         | 
| 8 | 
            +
            require "omniorder/customer"
         | 
| 9 | 
            +
            require "omniorder/purchasable"
         | 
| 10 | 
            +
            require "omniorder/product"
         | 
| 11 | 
            +
            require "omniorder/orderable"
         | 
| 12 | 
            +
            require "omniorder/order"
         | 
| 13 | 
            +
            require "omniorder/order_productable"
         | 
| 14 | 
            +
            require "omniorder/order_product"
         | 
| 15 | 
            +
            require "omniorder/import"
         | 
| 16 | 
            +
            require "omniorder/import_strategy/base"
         | 
| 17 | 
            +
            require "omniorder/import_strategy/groupon"
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            module Omniorder
         | 
| 20 | 
            +
              class << self
         | 
| 21 | 
            +
                attr_writer :order_type
         | 
| 22 | 
            +
                attr_writer :order_product_type
         | 
| 23 | 
            +
                attr_writer :customer_type
         | 
| 24 | 
            +
                attr_writer :product_type
         | 
| 25 | 
            +
                attr_writer :default_customer_country
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def order_type
         | 
| 28 | 
            +
                  @order_type || Order
         | 
| 29 | 
            +
                rescue NameError
         | 
| 30 | 
            +
                  raise "Please set Omniorder#order_type"
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def customer_type
         | 
| 34 | 
            +
                  @customer_type || Customer
         | 
| 35 | 
            +
                rescue NameError
         | 
| 36 | 
            +
                  raise "Please set Omniorder#customer_type"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def product_type
         | 
| 40 | 
            +
                  @product_type || Product
         | 
| 41 | 
            +
                rescue NameError
         | 
| 42 | 
            +
                  raise "Please set Omniorder#product_type"
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def order_product_type
         | 
| 46 | 
            +
                  @order_product_type || OrderProduct
         | 
| 47 | 
            +
                rescue NameError
         | 
| 48 | 
            +
                  raise "Please set Omniorder#order_product_type"
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def default_customer_country
         | 
| 52 | 
            +
                  @default_customer_country || 'United Kingdom'
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
    
        data/omniorder.gemspec
    ADDED
    
    | @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            lib = File.expand_path('../lib', __FILE__)
         | 
| 3 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 4 | 
            +
            require 'omniorder/version'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Gem::Specification.new do |spec|
         | 
| 7 | 
            +
              spec.name          = "omniorder"
         | 
| 8 | 
            +
              spec.version       = Omniorder::VERSION
         | 
| 9 | 
            +
              spec.authors       = ["Howard Wilson"]
         | 
| 10 | 
            +
              spec.email         = ["howard@watsonbox.net"]
         | 
| 11 | 
            +
              spec.summary       = %q{Import online orders from various channels for fulfillment.}
         | 
| 12 | 
            +
              spec.description   = %q{Import online orders from various channels for fulfillment.}
         | 
| 13 | 
            +
              spec.homepage      = ""
         | 
| 14 | 
            +
              spec.license       = "MIT"
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              spec.files         = `git ls-files -z`.split("\x0")
         | 
| 17 | 
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 18 | 
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         | 
| 19 | 
            +
              spec.require_paths = ["lib"]
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              spec.add_dependency "crack", "~> 0.4.2"
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              spec.add_development_dependency "bundler", "~> 1.6"
         | 
| 24 | 
            +
              spec.add_development_dependency "rake"
         | 
| 25 | 
            +
              spec.add_development_dependency "rspec", "~> 3.1.0"
         | 
| 26 | 
            +
              spec.add_development_dependency "webmock", "~> 1.20.4"
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Omniorder::ImportStrategy::Base do
         | 
| 4 | 
            +
              let(:strategy_class) { Class.new(Omniorder::ImportStrategy::Base) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              context 'with a global option' do
         | 
| 7 | 
            +
                around do |example|
         | 
| 8 | 
            +
                  strategy_class.options global_option: true
         | 
| 9 | 
            +
                  example.run
         | 
| 10 | 
            +
                  strategy_class.clear_options
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it 'includes the global options' do
         | 
| 14 | 
            +
                  expect(strategy_class.new(nil, local_option: true).options).to eq(global_option: true, local_option: true)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,82 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
                "meta": {
         | 
| 3 | 
            +
                    "no_of_pages": 1,
         | 
| 4 | 
            +
                    "current_page": 1,
         | 
| 5 | 
            +
                    "max_items_per_page": 250,
         | 
| 6 | 
            +
                    "no_of_items": 2
         | 
| 7 | 
            +
                },
         | 
| 8 | 
            +
                "data": [{
         | 
| 9 | 
            +
                    "orderid": "FFB7A681BE",
         | 
| 10 | 
            +
                    "customer": {
         | 
| 11 | 
            +
                        "city": "BRADFORD",
         | 
| 12 | 
            +
                        "state": "KENT",
         | 
| 13 | 
            +
                        "name": "SOME BODY HERE",
         | 
| 14 | 
            +
                        "zip": "SOME ZIP",
         | 
| 15 | 
            +
                        "country": "UK",
         | 
| 16 | 
            +
                        "address1": "901",
         | 
| 17 | 
            +
                        "address2": "GREENFIELDS LANE",
         | 
| 18 | 
            +
                        "phone": "01234 982103"
         | 
| 19 | 
            +
                    },
         | 
| 20 | 
            +
                    "line_items": [{
         | 
| 21 | 
            +
                        "sku": "03658246",
         | 
| 22 | 
            +
                        "name": "SOME PACK OF 6",
         | 
| 23 | 
            +
                        "weight": 0.0,
         | 
| 24 | 
            +
                        "bom_sku": null,
         | 
| 25 | 
            +
                        "unit_price": 10.99,
         | 
| 26 | 
            +
                        "ci_lineitemid": 54553918,
         | 
| 27 | 
            +
                        "quantity": 3
         | 
| 28 | 
            +
                    }],
         | 
| 29 | 
            +
                    "shipping": {
         | 
| 30 | 
            +
                        "carrier": null,
         | 
| 31 | 
            +
                        "method": "BEST"
         | 
| 32 | 
            +
                    },
         | 
| 33 | 
            +
                    "date": "05/16/2013 08:10AM UTC",
         | 
| 34 | 
            +
                    "amount": {
         | 
| 35 | 
            +
                        "total": 10.99,
         | 
| 36 | 
            +
                        "shipping": 0
         | 
| 37 | 
            +
                    },
         | 
| 38 | 
            +
                    "supplier": "SUPPLIER NAME"
         | 
| 39 | 
            +
                },
         | 
| 40 | 
            +
                {
         | 
| 41 | 
            +
                        "orderid": "FFB7A68990",
         | 
| 42 | 
            +
                        "customer": {
         | 
| 43 | 
            +
                            "city": "BRADFORD",
         | 
| 44 | 
            +
                            "state": "KENT",
         | 
| 45 | 
            +
                            "name": "SOME BODY HERE",
         | 
| 46 | 
            +
                            "zip": "SOME ZIP",
         | 
| 47 | 
            +
                            "country": "UK",
         | 
| 48 | 
            +
                            "address1": "901",
         | 
| 49 | 
            +
                            "address2": "GREENFIELDS LANE",
         | 
| 50 | 
            +
                            "phone": "01234 982103"
         | 
| 51 | 
            +
                        },
         | 
| 52 | 
            +
                        "line_items": [{
         | 
| 53 | 
            +
                            "sku": "03658246",
         | 
| 54 | 
            +
                            "name": "SOME PACK OF 6",
         | 
| 55 | 
            +
                            "weight": 0.0,
         | 
| 56 | 
            +
                            "bom_sku": null,
         | 
| 57 | 
            +
                            "unit_price": 10.99,
         | 
| 58 | 
            +
                            "ci_lineitemid": 54553920,
         | 
| 59 | 
            +
                            "quantity": 3
         | 
| 60 | 
            +
                        },
         | 
| 61 | 
            +
                        {
         | 
| 62 | 
            +
                            "sku": "03658248",
         | 
| 63 | 
            +
                            "name": "SOME PACK OF 6",
         | 
| 64 | 
            +
                            "weight": 0.0,
         | 
| 65 | 
            +
                            "bom_sku": null,
         | 
| 66 | 
            +
                            "unit_price": 10.99,
         | 
| 67 | 
            +
                            "ci_lineitemid": 54553921,
         | 
| 68 | 
            +
                            "quantity": 2
         | 
| 69 | 
            +
                        }],
         | 
| 70 | 
            +
                        "shipping": {
         | 
| 71 | 
            +
                            "carrier": null,
         | 
| 72 | 
            +
                            "method": "BEST"
         | 
| 73 | 
            +
                        },
         | 
| 74 | 
            +
                        "date": "05/16/2013 10:11AM UTC",
         | 
| 75 | 
            +
                        "amount": {
         | 
| 76 | 
            +
                            "total": 10.99,
         | 
| 77 | 
            +
                            "shipping": 0
         | 
| 78 | 
            +
                        },
         | 
| 79 | 
            +
                        "supplier": "SUPPLIER NAME"
         | 
| 80 | 
            +
                    }],
         | 
| 81 | 
            +
                "success": true
         | 
| 82 | 
            +
            }
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Omniorder::Customerable do
         | 
| 4 | 
            +
              let(:customer) { Omniorder::Customer.new }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '#first_name' do
         | 
| 7 | 
            +
                it 'is the first name' do
         | 
| 8 | 
            +
                  customer.name = "Alan Gordon Partridge"
         | 
| 9 | 
            +
                  expect(customer.first_name).to eq("Alan")
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              describe '#first_names' do
         | 
| 14 | 
            +
                it 'is the first names' do
         | 
| 15 | 
            +
                  customer.name = "Alan Gordon Partridge"
         | 
| 16 | 
            +
                  expect(customer.first_names).to eq(["Alan", "Gordon"])
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe '#last_name' do
         | 
| 21 | 
            +
                it 'is the last names' do
         | 
| 22 | 
            +
                  customer.name = "Alan Gordon Partridge"
         | 
| 23 | 
            +
                  expect(customer.last_name).to eq("Partridge")
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              describe '#full_address' do
         | 
| 28 | 
            +
                it 'should ignore blank address components' do
         | 
| 29 | 
            +
                  customer.address1 = "29, Sycamore Lane"
         | 
| 30 | 
            +
                  customer.address3 = "Birmingham"
         | 
| 31 | 
            +
                  customer.postcode = "B13 8JU"
         | 
| 32 | 
            +
                  customer.country = "United Kingdom"
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  expect(customer.full_address).to eq("29, Sycamore Lane\nBirmingham\nB13 8JU\nUnited Kingdom")
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,88 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Omniorder::ImportStrategy::Groupon do
         | 
| 4 | 
            +
              let(:import) { Omniorder::Import.new }
         | 
| 5 | 
            +
              let(:strategy) { Omniorder::ImportStrategy::Groupon.new(import, strategy_options) }
         | 
| 6 | 
            +
              let(:strategy_options) { { supplier_id: '1', access_token: 'xYRPKcoakMoiRzWgKLV5TqPSdNAaZQT' } }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              before do
         | 
| 9 | 
            +
                stub_request(
         | 
| 10 | 
            +
                  :get,
         | 
| 11 | 
            +
                  "https://scm.commerceinterface.com/api/v2/get_orders?supplier_id=1&token=xYRPKcoakMoiRzWgKLV5TqPSdNAaZQT"
         | 
| 12 | 
            +
                ).to_return(
         | 
| 13 | 
            +
                  body: File.new('spec/assets/imports/groupon/get_orders.json'),
         | 
| 14 | 
            +
                  status: 200
         | 
| 15 | 
            +
                )
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              context 'no supplier_id is supplied' do
         | 
| 19 | 
            +
                let(:strategy_options) { { access_token: 'xYRPKcoakMoiRzWgKLV5TqPSdNAaZQT' } }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it 'raises an exception' do
         | 
| 22 | 
            +
                  expect { strategy }.to raise_exception "Omniorder::ImportStrategy::Groupon requires a supplier_id"
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              context 'no access_token is supplied' do
         | 
| 27 | 
            +
                let(:strategy_options) { { supplier_id: '1' } }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                it 'raises an exception' do
         | 
| 30 | 
            +
                  expect { strategy }.to raise_exception "Omniorder::ImportStrategy::Groupon requires an access_token"
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              it 'imports orders with products and a customer' do
         | 
| 35 | 
            +
                orders = []
         | 
| 36 | 
            +
                strategy.import_orders { |o| orders << o }
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                order = orders.first
         | 
| 39 | 
            +
                expect(order.order_number).to eq("FFB7A681BE")
         | 
| 40 | 
            +
                expect(order.total_price).to eq(10.99)
         | 
| 41 | 
            +
                expect(order.date.to_s).to eq("2013-05-16T08:10:00+00:00")
         | 
| 42 | 
            +
                expect(order.order_products.count).to eq(1)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                order_product = order.order_products.first
         | 
| 45 | 
            +
                expect(order_product.quantity).to eq(3)
         | 
| 46 | 
            +
                expect(order_product.product.code).to eq('03658246')
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                customer = order.customer
         | 
| 49 | 
            +
                expect(customer.name).to eq("SOME BODY HERE")
         | 
| 50 | 
            +
                expect(customer.phone).to eq("01234 982103")
         | 
| 51 | 
            +
                expect(customer.address1).to eq("901")
         | 
| 52 | 
            +
                expect(customer.address2).to eq("GREENFIELDS LANE")
         | 
| 53 | 
            +
                expect(customer.address3).to eq("BRADFORD")
         | 
| 54 | 
            +
                expect(customer.address4).to eq("KENT")
         | 
| 55 | 
            +
                expect(customer.postcode).to eq("SOME ZIP")
         | 
| 56 | 
            +
                expect(customer.country).to eq("UK")
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              context 'the mark_exported option is set' do
         | 
| 60 | 
            +
                let(:strategy_options) { { supplier_id: '1', access_token: 'xYRPKcoakMoiRzWgKLV5TqPSdNAaZQT', mark_exported: true } }
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                let(:mark_exported_result) { '{ "success": true }' }
         | 
| 63 | 
            +
                let!(:mark_exported_stub) do
         | 
| 64 | 
            +
                  stub_request(
         | 
| 65 | 
            +
                    :post,
         | 
| 66 | 
            +
                    "https://scm.commerceinterface.com/api/v2/mark_exported?supplier_id=1&token=xYRPKcoakMoiRzWgKLV5TqPSdNAaZQT&ci_lineitem_ids=[54553920,54553921]"
         | 
| 67 | 
            +
                  ).to_return(
         | 
| 68 | 
            +
                    body: mark_exported_result,
         | 
| 69 | 
            +
                    status: 200
         | 
| 70 | 
            +
                  )
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                it 'marks orders as exported when the order handler is truthy' do
         | 
| 74 | 
            +
                  strategy.import_orders { |o| true if o.order_number == "FFB7A68990" }
         | 
| 75 | 
            +
                  expect(mark_exported_stub).to have_been_requested.once
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                context "mark exported API call fails" do
         | 
| 79 | 
            +
                  let(:mark_exported_result) { '{ "success": false }' }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  it 'raises an exception' do
         | 
| 82 | 
            +
                    expect {
         | 
| 83 | 
            +
                      strategy.import_orders { |o| true if o.order_number == "FFB7A68990" }
         | 
| 84 | 
            +
                    }.to raise_exception "Failed to mark Groupon order #FFB7A68990 as exported"
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
            end
         | 
| @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Omniorder::Orderable do
         | 
| 4 | 
            +
              let(:product1) { Omniorder::Product.new(:code => 'CODE1') }
         | 
| 5 | 
            +
              let(:product2) { Omniorder::Product.new(:code => 'CODE2') }
         | 
| 6 | 
            +
              let(:order) { Omniorder::Order.new }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              before do
         | 
| 9 | 
            +
                allow(Omniorder::Product).to receive(:find_by_code)
         | 
| 10 | 
            +
                  .with('CODE1')
         | 
| 11 | 
            +
                  .and_return(product1)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                allow(Omniorder::Product).to receive(:find_by_code)
         | 
| 14 | 
            +
                  .with('CODE2')
         | 
| 15 | 
            +
                  .and_return(product2)
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              describe '#add_product_by_code' do
         | 
| 19 | 
            +
                it 'adds a product to the order when one is found' do
         | 
| 20 | 
            +
                  order.add_product_by_code('CODE1')
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  order_product = order.order_products.first
         | 
| 23 | 
            +
                  expect(order_product.quantity).to eq(1)
         | 
| 24 | 
            +
                  expect(order_product.product).to eq(product1)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it 'does nothing when no matching product is found' do
         | 
| 28 | 
            +
                  expect(Omniorder::Product).to receive(:find_by_code)
         | 
| 29 | 
            +
                    .with('CODE1')
         | 
| 30 | 
            +
                    .and_return(nil)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  order.add_product_by_code('CODE1')
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  expect(order.order_products.count).to eq(0)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              describe '#product_count' do
         | 
| 39 | 
            +
                it 'is the sum of all attached product quantities' do
         | 
| 40 | 
            +
                  order.add_product_by_code('CODE1', 10)
         | 
| 41 | 
            +
                  order.add_product_by_code('CODE2', 6)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  expect(order.product_count).to eq(16)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              describe '#product_list' do
         | 
| 48 | 
            +
                it 'is a human-readable string representing order products' do
         | 
| 49 | 
            +
                  order.add_product_by_code('CODE1', 10)
         | 
| 50 | 
            +
                  order.add_product_by_code('CODE2', 6)
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  expect(order.product_list).to eq('10xCODE1/6xCODE2')
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            require 'webmock/rspec'
         | 
| 2 | 
            +
            require 'omniorder'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            RSpec.configure do |config|
         | 
| 5 | 
            +
              # rspec-expectations config goes here. You can use an alternate
         | 
| 6 | 
            +
              # assertion/expectation library such as wrong or the stdlib/minitest
         | 
| 7 | 
            +
              # assertions if you prefer.
         | 
| 8 | 
            +
              config.expect_with :rspec do |expectations|
         | 
| 9 | 
            +
                # This option will default to `true` in RSpec 4. It makes the `description`
         | 
| 10 | 
            +
                # and `failure_message` of custom matchers include text for helper methods
         | 
| 11 | 
            +
                # defined using `chain`, e.g.:
         | 
| 12 | 
            +
                # be_bigger_than(2).and_smaller_than(4).description
         | 
| 13 | 
            +
                #   # => "be bigger than 2 and smaller than 4"
         | 
| 14 | 
            +
                # ...rather than:
         | 
| 15 | 
            +
                #   # => "be bigger than 2"
         | 
| 16 | 
            +
                expectations.include_chain_clauses_in_custom_matcher_descriptions = true
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              # rspec-mocks config goes here. You can use an alternate test double
         | 
| 20 | 
            +
              # library (such as bogus or mocha) by changing the `mock_with` option here.
         | 
| 21 | 
            +
              config.mock_with :rspec do |mocks|
         | 
| 22 | 
            +
                # Prevents you from mocking or stubbing a method that does not exist on
         | 
| 23 | 
            +
                # a real object. This is generally recommended, and will default to
         | 
| 24 | 
            +
                # `true` in RSpec 4.
         | 
| 25 | 
            +
                mocks.verify_partial_doubles = true
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,148 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: omniorder
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Howard Wilson
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2014-11-19 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: crack
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: 0.4.2
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: 0.4.2
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: bundler
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '1.6'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '1.6'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: rake
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - ">="
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '0'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ">="
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '0'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: rspec
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - "~>"
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: 3.1.0
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - "~>"
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: 3.1.0
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: webmock
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - "~>"
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: 1.20.4
         | 
| 76 | 
            +
              type: :development
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - "~>"
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: 1.20.4
         | 
| 83 | 
            +
            description: Import online orders from various channels for fulfillment.
         | 
| 84 | 
            +
            email:
         | 
| 85 | 
            +
            - howard@watsonbox.net
         | 
| 86 | 
            +
            executables: []
         | 
| 87 | 
            +
            extensions: []
         | 
| 88 | 
            +
            extra_rdoc_files: []
         | 
| 89 | 
            +
            files:
         | 
| 90 | 
            +
            - ".gitignore"
         | 
| 91 | 
            +
            - ".rspec"
         | 
| 92 | 
            +
            - ".travis.yml"
         | 
| 93 | 
            +
            - Gemfile
         | 
| 94 | 
            +
            - LICENSE.txt
         | 
| 95 | 
            +
            - README.md
         | 
| 96 | 
            +
            - Rakefile
         | 
| 97 | 
            +
            - lib/omniorder.rb
         | 
| 98 | 
            +
            - lib/omniorder/customer.rb
         | 
| 99 | 
            +
            - lib/omniorder/customerable.rb
         | 
| 100 | 
            +
            - lib/omniorder/entity.rb
         | 
| 101 | 
            +
            - lib/omniorder/import.rb
         | 
| 102 | 
            +
            - lib/omniorder/import_strategy/base.rb
         | 
| 103 | 
            +
            - lib/omniorder/import_strategy/groupon.rb
         | 
| 104 | 
            +
            - lib/omniorder/order.rb
         | 
| 105 | 
            +
            - lib/omniorder/order_product.rb
         | 
| 106 | 
            +
            - lib/omniorder/order_productable.rb
         | 
| 107 | 
            +
            - lib/omniorder/orderable.rb
         | 
| 108 | 
            +
            - lib/omniorder/product.rb
         | 
| 109 | 
            +
            - lib/omniorder/purchasable.rb
         | 
| 110 | 
            +
            - lib/omniorder/version.rb
         | 
| 111 | 
            +
            - omniorder.gemspec
         | 
| 112 | 
            +
            - spec/assets/imports/groupon/base_spec.rb
         | 
| 113 | 
            +
            - spec/assets/imports/groupon/get_orders.json
         | 
| 114 | 
            +
            - spec/customerable_spec.rb
         | 
| 115 | 
            +
            - spec/import_strategy/groupon_spec.rb
         | 
| 116 | 
            +
            - spec/orderable_spec.rb
         | 
| 117 | 
            +
            - spec/spec_helper.rb
         | 
| 118 | 
            +
            homepage: ''
         | 
| 119 | 
            +
            licenses:
         | 
| 120 | 
            +
            - MIT
         | 
| 121 | 
            +
            metadata: {}
         | 
| 122 | 
            +
            post_install_message: 
         | 
| 123 | 
            +
            rdoc_options: []
         | 
| 124 | 
            +
            require_paths:
         | 
| 125 | 
            +
            - lib
         | 
| 126 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 127 | 
            +
              requirements:
         | 
| 128 | 
            +
              - - ">="
         | 
| 129 | 
            +
                - !ruby/object:Gem::Version
         | 
| 130 | 
            +
                  version: '0'
         | 
| 131 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 132 | 
            +
              requirements:
         | 
| 133 | 
            +
              - - ">="
         | 
| 134 | 
            +
                - !ruby/object:Gem::Version
         | 
| 135 | 
            +
                  version: '0'
         | 
| 136 | 
            +
            requirements: []
         | 
| 137 | 
            +
            rubyforge_project: 
         | 
| 138 | 
            +
            rubygems_version: 2.2.2
         | 
| 139 | 
            +
            signing_key: 
         | 
| 140 | 
            +
            specification_version: 4
         | 
| 141 | 
            +
            summary: Import online orders from various channels for fulfillment.
         | 
| 142 | 
            +
            test_files:
         | 
| 143 | 
            +
            - spec/assets/imports/groupon/base_spec.rb
         | 
| 144 | 
            +
            - spec/assets/imports/groupon/get_orders.json
         | 
| 145 | 
            +
            - spec/customerable_spec.rb
         | 
| 146 | 
            +
            - spec/import_strategy/groupon_spec.rb
         | 
| 147 | 
            +
            - spec/orderable_spec.rb
         | 
| 148 | 
            +
            - spec/spec_helper.rb
         |