jGRUBBS/carousel-ruby-api

View on GitHub
lib/carousel/client.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'net/https'
require 'xmlsimple'

module Carousel
  class Client

    TEST_HOST = "web.carousel.eu"
    TEST_PATH = "carouselwms"
    LIVE_HOST = "web.carousel.eu"
    LIVE_PATH = "carouselwms"
    PORT      = 443
    KEYS_MAP  = { "stockid" => "upc" }

    attr_accessor :username, :password, :options, :response, :type, :request_uri, :path

    def initialize(username, password, options = {})
      raise "Username is required" unless username
      raise "Password is required" unless password

      @username = username
      @password = password
      @options  = default_options.merge!(options)
    end

    def send_order_request(order)
      request  = order_request(order)
      post(request)
    end

    def get_inventory
      request = Inventory.new(self).build_inventory_request
      @path   = build_path(Inventory::PATH)
      inventory_response(request)
    end

    # gets the raw inventory response from the provider
    # then converts provider specific language to match 
    # a uniform API, stored on @response, and returns
    def inventory_response(request)
      response = post(request)
      response.response = map_results(response.response['stock'])
      response
    end

    def order_request(order)
      @path = build_path(Order::PATH)
      Order.new(self).build_order_request(order)
    end

    def build_path(path)
      "/#{env_path}/default.asp#{path}"
    end

    def upcs(inventory)
      inventory.collect { |s| s["upc"] }
    end

    def mapped_inventory(upcs, inventory)
      inventory.collect do |stock| 
        if upcs.include?(stock["upc"])
          { quantity: stock["qty"].to_i }
        end
      end.compact
    end

    def request_uri
      "https://#{host}#{@path}"
    end

    private
    def default_options
      { 
        verbose: true,
        test_mode: false
      }
    end

    def testing?
      @options[:test_mode]
    end

    def verbose?
      @options[:verbose]
    end

    def env_path
      testing? ? TEST_PATH : LIVE_PATH
    end

    def host
      testing? ? TEST_HOST : LIVE_HOST
    end

    def log(message)
      return unless verbose?
      puts message
    end

    def http
      @http ||= Net::HTTP.new(host, PORT)
    end

    def request(xml_request)
      request              = Net::HTTP::Post.new(@path)
      request.body         = xml_request
      request.content_type = 'application/xml'
      http.use_ssl         = true
      http.verify_mode     = OpenSSL::SSL::VERIFY_NONE
      http.request(request)
    end

    def post(xml_request)
      response = request(xml_request)
      parse_response(response.body)
    end

    def parse_response(xml_response)
      log(xml_response)
      @response = Response.new(xml_response, @type)
    end

    def map_results(results)
      results = flatten_results(results)
      results.map do |h|
        h.inject({ }) { |x, (k,v)| x[map_keys(k)] = v; x }
      end
    end

    def flatten_results(results)
      @flattened ||= results.map do |h| 
        h.each { |k,v| h[k] = v[0] }
      end
    end

    def map_keys(key)
      KEYS_MAP[key] || key
    end

  end
end