diff --git a/.rubocop.yml b/.rubocop.yml
index adfe750..9059597 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -452,3 +452,6 @@ Style/SymbolProc:
Style/ZeroLengthPredicate:
Enabled: false
+
+Style/MutableConstant:
+ Enabled: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 1e675d5..6c6f6af 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -3,6 +3,7 @@ PATH
specs:
xpm_ruby (0.1.0)
faraday (~> 1)
+ nokogiri
ox (~> 2.13)
GEM
@@ -16,7 +17,10 @@ GEM
multipart-post (>= 1.2, < 3)
jaro_winkler (1.5.4)
method_source (1.0.0)
+ mini_portile2 (2.4.0)
multipart-post (2.1.1)
+ nokogiri (1.10.9)
+ mini_portile2 (~> 2.4.0)
ox (2.13.2)
parallel (1.19.1)
parser (2.7.1.1)
diff --git a/lib/xpm_ruby.rb b/lib/xpm_ruby.rb
index c00a877..5f347b2 100644
--- a/lib/xpm_ruby.rb
+++ b/lib/xpm_ruby.rb
@@ -3,8 +3,12 @@ class Error < StandardError; end
class Unauthorized < Error; end
end
+require "nokogiri"
+
+require "xpm_ruby/version"
require "xpm_ruby/connection"
require "xpm_ruby/job"
require "xpm_ruby/staff"
+require "xpm_ruby/client"
require "xpm_ruby/template"
require "xpm_ruby/version"
diff --git a/lib/xpm_ruby/client.rb b/lib/xpm_ruby/client.rb
new file mode 100644
index 0000000..9e31bbc
--- /dev/null
+++ b/lib/xpm_ruby/client.rb
@@ -0,0 +1,49 @@
+require "faraday"
+require "base64"
+require "ox"
+
+require_relative "client/get"
+require_relative "client/add"
+
+module XpmRuby
+ module Client
+ extend self
+
+ module GstPeriod
+ ONE = "1"
+ TWO = "2"
+ SIX = "6"
+ end
+
+ module GstBasis
+ INVOICE = "Invoice"
+ PAYMENT = "Payment"
+ HYBRID = "Hybrid"
+ end
+
+ module ProvisionalTaxBasis
+ STANDARD_OPTION = "Standard Option"
+ ESTIMATE_OPTION = "Estimate Option"
+ RATIO_OPTION = "Ratio Option"
+ end
+
+ module AgencyStatus
+ WITH_EOT = "With EOT"
+ WITHOUT_EOT = "Without EOT"
+ UNLINKED = "Unlinked"
+ end
+
+ module ReturnType
+ IR3 = "IR3"
+ IR3NR = "IR3NR"
+ IR4 = "IR4"
+ IR6 = "IR6"
+ IR7 = "IR7"
+ IR9 = "IR9"
+ PTS = "PTS"
+ end
+
+ class Error < StandardError; end
+ class Unauthorized < Error; end
+ end
+end
diff --git a/lib/xpm_ruby/client/add.rb b/lib/xpm_ruby/client/add.rb
new file mode 100644
index 0000000..16c9cfc
--- /dev/null
+++ b/lib/xpm_ruby/client/add.rb
@@ -0,0 +1,245 @@
+# client.api/add
+#
+#
+# Bloggs Electrical Ltd
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+# No
+#
+#
+#
+# Jo Bloggs
+# yes
+#
+#
+#
+#
+#
+#
+#
+#
+#
+
+#
+
+#
+#
+#
+#
+
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+
+#
+#
+#
+#
+#
+
+#
+#
+#
+#
+
+module XpmRuby
+ module Client
+ module Add
+ extend self
+
+ def call(api_key:, account_key:, api_url:, client:)
+ builder = ::Nokogiri::XML::Builder.new do |xml|
+ xml.Client do
+ xml.Name do
+ xml.text(client.name)
+ end
+ end
+ end
+
+ response = Connection
+ .new(api_key: api_key, account_key: account_key, api_url: api_url)
+ .post(endpoint: "client.api/add", data: builder.doc.root.to_xml)
+
+ case response.status
+ when 401
+ hash = Ox.load(response.body, mode: :hash_no_attrs, symbolize_keys: false)
+
+ raise Unauthorized.new(hash["html"]["head"]["title"])
+ when 200
+ hash = Ox.load(response.body, mode: :hash_no_attrs, symbolize_keys: false)
+
+ case hash["Response"]["Status"]
+ when "OK"
+ Get::Client.new(
+ uuid: hash["Response"]["Client"]["UUID"],
+ name: hash["Response"]["Client"]["Name"],
+ email: hash["Response"]["Client"]["Email"])
+ when "ERROR"
+ raise Error.new(response["ErrorDescription"])
+ end
+ else
+ raise Error.new(response.status)
+ end
+ end
+
+ class Client
+ attr_accessor :name, :email, :address, :city, :region, :post_code, :country,
+ :postal_address, :postal_city, :postal_region, :postal_post_code, :postal_country,
+ :phone, :fax, :web_site, :referral_source, :export_code, :is_prospect,
+ :account_manager_uuid, :contacts, :billing_client_uuid,
+ :first_name, :last_name, :other_name, :date_of_birth, :job_manager_uuid,
+ :tax_number, :company_number, :business_number, :business_structure, :balance_month,
+ :prepare_gst, :gst_registered, :gst_period, :gst_basis,
+ :provisional_tax_basis, :provisional_tax_ratio,
+ :signed_tax_authority, :tax_agent, :agency_status, :return_type,
+ :prepare_activity_statement, :prepare_tax_return
+
+ # rubocop:disable Metrics/AbcSize
+ def initialize(name:, email: nil,
+ address: nil, city: nil, region: nil, post_code: nil, country: nil,
+ postal_address: nil, postal_city: nil, postal_region: nil,
+ postal_post_code: nil, postal_country: nil,
+ phone: nil, fax: nil, web_site: nil,
+ referral_source: nil, export_code: nil, is_prospect: nil,
+ account_manager_uuid: nil, contacts: nil, billing_client_uuid: nil,
+ first_name: nil, last_name: nil, other_name: nil, date_of_birth: nil,
+ job_manager_uuid: nil, tax_number: nil, company_number: nil,
+ business_number: nil, business_structure: nil, balance_month: nil,
+ prepare_gst: nil, gst_registered: nil, gst_period: nil, gst_basis: nil,
+ provisional_tax_basis: nil, provisional_tax_ratio: nil,
+ signed_tax_authority: nil, tax_agent: nil, agency_status: nil,
+ return_type: nil, prepare_activity_statement: nil, prepare_tax_return: nil)
+ @name = name
+ @email = email
+ @address = address
+ @city = city
+ @region = region
+ @post_code = post_code
+ @country = country
+ @postal_address = postal_address
+ @postal_city = postal_city
+ @postal_region = postal_region
+ @postal_post_code = postal_post_code
+ @postal_country = postal_country
+ @phone = phone
+ @fax = fax
+ @web_site = web_site
+ @referral_source = referral_source
+ @export_code = export_code
+ @is_prospect = is_prospect
+ @account_manager_uuid = account_manager_uuid
+ @contacts = contacts
+ @billing_client_uuid = billing_client_uuid
+ @first_name = first_name
+ @last_name = last_name
+ @other_name = other_name
+ @date_of_birth = date_of_birth
+ @job_manager_uuid = job_manager_uuid
+ @tax_number = tax_number
+ @company_number = company_number
+ @business_number = business_number
+ @business_structure = business_structure
+ @balance_month = balance_month
+ @prepare_gst = prepare_gst
+ @gst_registered = gst_registered
+ @gst_period = gst_period
+ @gst_basis = gst_basis
+ @provisional_tax_basis = provisional_tax_basis
+ @provisional_tax_rate = provisional_tax_ratio
+ @signed_tax_authority = signed_tax_authority
+ @tax_agent = tax_agent
+ @agency_status = agency_status
+ @return_type = return_type
+ @prepare_activity_statement = prepare_activity_statement
+ @prepare_tax_return = prepare_tax_return
+ end
+ # rubocop:enable Metrics/AbcSize
+
+ class AccountManager
+ attr_reader :uuid, :name
+
+ def initialize(uuid: nil, name: nil)
+ @uuid = uuid
+ @name = name
+ end
+
+ def ==(other)
+ uuid == other.uuid
+ end
+
+ def eql?(other)
+ self == other
+ end
+ end
+
+ class Type
+ attr_reader :name, :cost_markup, :payment_term, :payment_day
+
+ def initialize(name: nil, cost_markup: nil, payment_term: nil, payment_day: nil)
+ @name = name
+ @cost_markup = cost_markup
+ @payment_term = payment_term
+ @payment_day = payment_day
+ end
+
+ def ==(other)
+ name == other.name &&
+ cost_markup == other.cost_markup &&
+ payment_term == other.payment_term &&
+ payment_day == other.payment_day
+ end
+
+ def eql?(other)
+ self == other
+ end
+ end
+
+ class Contact
+ def initialize(uuid: nil, is_primary: nil, name: nil, salutation: nil,
+ addressee: nil, mobile: nil, email: nil, phone: nil, position: nil)
+ @uuid = uuid
+ @is_primary = is_primary
+ @name = name
+ @salutation = salutation
+ @addressee = addressee
+ @mobile = mobile
+ @email = email
+ @phone = phone
+ @position = position
+ end
+
+ def ==(other)
+ uuid == other.uuid
+ end
+
+ def eql?(other)
+ self == other
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/xpm_ruby/client/get.rb b/lib/xpm_ruby/client/get.rb
new file mode 100644
index 0000000..18ca2c0
--- /dev/null
+++ b/lib/xpm_ruby/client/get.rb
@@ -0,0 +1,134 @@
+# client.api/get
+
+#
+# OK
+#
+# c257b062-fbc9-4dc7-9132-f18ee956c4f9
+# Acmer Pty Ltd
+# someone@example.com
+# 1970-11-26
+#
+#
+#
+#
+#
+#
+# Level 32, PWC Building
+# 188 Quay Street
+# Auckland Central
+#
+# Auckland
+#
+# 1001
+#
+# (02) 1723 5265
+#
+#
+#
+#
+# No
+#
+# ab3d6db0-f0be-4a3e-bd68-8fad1c6b40bb
+# Jo Blogs
+#
+#
+# 20th of Month
+# 30.00
+# DayOfMonth
+# 20
+#
+#
+#
+# f1ec264f-d269-4232-9615-c167583fa7da
+# yes
+# Wyett E Coyote
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+# note title
+# subject of the note
+#
+# 2008-09-12T13:00:00
+# Jo Bloggs
+#
+#
+#
+# e41ecd7a-ac85-4473-a7b3-052bd670f01e
+# Billing Client
+#
+#
+#
+# ebc0e2ae-3d3e-4546-9787-8c659e445d31
+# John Smith
+#
+#
+#
+#
+#
+# ******123
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+#
+# 9c3abe09-6df2-4f18-8090-36a44e91a1c3
+# Bloggs Family
+#
+#
+#
+#
+# 9c3abe09-6df2-4f18-8090-36a44e91a1c3
+# Shareholder
+#
+# 651ec79a-93cb-458c-b5ca-e123c92192b6
+# Bloggs Ltd
+#
+# 1000
+# 2011-01-01
+# 2013-03-31
+#
+#
+#
+#
+
+module XpmRuby
+ module Client
+ module Get
+ extend self
+
+ class Client
+ attr_accessor :uuid, :name, :email
+
+ def initialize(uuid:, name:, email: nil)
+ @uuid = uuid
+ @name = name
+ @email = email
+ end
+ end
+ end
+ end
+end
diff --git a/spec/vcr_cassettes/xpm_ruby/client/add.yml b/spec/vcr_cassettes/xpm_ruby/client/add.yml
new file mode 100644
index 0000000..94cbdbe
--- /dev/null
+++ b/spec/vcr_cassettes/xpm_ruby/client/add.yml
@@ -0,0 +1,51 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://api.workflowmax.com/v3/client.api/add
+ body:
+ encoding: UTF-8
+ string: |-
+
+ Acmer Pty Ltd
+
+ headers:
+ User-Agent:
+ - Faraday v1.0.1
+ Authorization:
+ - Basic
+ Content-Type:
+ - application/x-www-form-urlencoded
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ access-control-allow-origin:
+ - "*"
+ cache-control:
+ - private
+ content-type:
+ - text/xml; charset=utf-8
+ date:
+ - Tue, 28 Apr 2020 01:52:47 GMT
+ server:
+ - Microsoft-IIS/10.0
+ vary:
+ - Accept-Encoding
+ x-aspnet-version:
+ - 4.0.30319
+ x-aspnetmvc-version:
+ - '4.0'
+ content-length:
+ - '449'
+ connection:
+ - keep-alive
+ body:
+ encoding: ASCII-8BIT
+ string: OK9f868ba7-437c-4574-9a17-8c6f4890545bAcmer
+ Pty LtdNoNoNo
+ http_version: null
+ recorded_at: Tue, 28 Apr 2020 01:52:48 GMT
+recorded_with: VCR 5.1.0
diff --git a/spec/xpm_ruby/client/add_spec.rb b/spec/xpm_ruby/client/add_spec.rb
new file mode 100644
index 0000000..903d579
--- /dev/null
+++ b/spec/xpm_ruby/client/add_spec.rb
@@ -0,0 +1,85 @@
+require "spec_helper"
+
+module XpmRuby
+ module Client
+ RSpec.describe(Add) do
+ around(:each) do |example|
+ VCR.use_cassette("xpm_ruby/client/add") do
+ example.run
+ end
+ end
+
+ describe ".call" do
+ let(:api_key) { "" }
+ let(:account_key) { "" }
+ let(:api_url) { "api.workflowmax.com" }
+
+ let(:client) do
+ Client::Add::Client.new(
+ name: "Acmer Pty Ltd",
+ email: "someone@example.com",
+ address: "1 Address Place",
+ city: "Sydney",
+ region: "NSW",
+ post_code: "2000",
+ country: "Australia",
+ postal_address: "Level 32, PWC Building\n188 Quay Street\nAuckland Central",
+ postal_city: "Auckland",
+ postal_region: "North Island",
+ postal_post_code: "1001",
+ postal_country: "New Zealand",
+ phone: "00 0000 0000",
+ fax: "00 1000 0000",
+ web_site: "http://example.com",
+ referral_source: "referrer",
+ export_code: "EXPORT_CODE",
+ is_prospect: false,
+ account_manager_uuid: nil,
+ contacts: [
+ Client::Add::Client::Contact.new(
+ name: "Someone else",
+ is_primary: true,
+ salutation: "MR",
+ addressee: "Addressee",
+ phone: "02 0000 0000",
+ mobile: "0411 0000 0000",
+ email: "someone.else@example.com",
+ position: "Manager")],
+ billing_client_uuid: nil,
+ first_name: "Someone",
+ last_name: "Person",
+ date_of_birth: Date.parse("1987/05/11"),
+ job_manager_uuid: nil,
+ tax_number: "11 1111 1111",
+ company_number: "02 1000 1000",
+ business_number: "02 1000 2000",
+ business_structure: "Corporate",
+ balance_month: "Jan",
+ prepare_gst: false,
+ gst_registered: true,
+ gst_period: Client::GstPeriod::ONE,
+ gst_basis: Client::GstBasis::INVOICE,
+ provisional_tax_basis: Client::ProvisionalTaxBasis::STANDARD_OPTION,
+ provisional_tax_ratio: "1",
+ signed_tax_authority: true,
+ tax_agent: "Mr Tax Agent",
+ agency_status: Client::AgencyStatus::WITH_EOT,
+ return_type: Client::ReturnType::IR3,
+ prepare_activity_statement: true,
+ prepare_tax_return: true)
+ end
+
+ it "adds client" do
+ created_client = Client::Add.call(
+ api_key: api_key,
+ account_key: account_key,
+ api_url: api_url,
+ client: client)
+
+ expect(created_client.uuid).not_to be_nil
+ expect(created_client.name).to eql(client.name)
+ end
+ end
+ end
+ end
+end
diff --git a/xpm_ruby.gemspec b/xpm_ruby.gemspec
index a8ea1c9..0ccf0e9 100644
--- a/xpm_ruby.gemspec
+++ b/xpm_ruby.gemspec
@@ -35,6 +35,8 @@ Gem::Specification.new do |spec|
spec.add_development_dependency("byebug", "~> 11")
spec.add_development_dependency("pry-byebug", "~> 3")
+ spec.add_runtime_dependency("nokogiri")
+
spec.add_runtime_dependency("faraday", "~> 1")
spec.add_runtime_dependency("ox", "~> 2.13")