diff --git a/Gemfile.lock b/Gemfile.lock
index f3b7ba6..9c5fd3d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,6 +4,7 @@ PATH
xpm_ruby (0.1.0)
activesupport
builder
+ dry-types
faraday
ox (~> 2.13)
@@ -22,6 +23,28 @@ GEM
coderay (1.1.2)
concurrent-ruby (1.1.6)
diff-lcs (1.3)
+ dry-configurable (0.11.5)
+ concurrent-ruby (~> 1.0)
+ dry-core (~> 0.4, >= 0.4.7)
+ dry-equalizer (~> 0.2)
+ dry-container (0.7.2)
+ concurrent-ruby (~> 1.0)
+ dry-configurable (~> 0.1, >= 0.1.3)
+ dry-core (0.4.9)
+ concurrent-ruby (~> 1.0)
+ dry-equalizer (0.3.0)
+ dry-inflector (0.2.0)
+ dry-logic (0.6.1)
+ concurrent-ruby (~> 1.0)
+ dry-core (~> 0.2)
+ dry-equalizer (~> 0.2)
+ dry-types (0.15.0)
+ concurrent-ruby (~> 1.0)
+ dry-container (~> 0.3)
+ dry-core (~> 0.4, >= 0.4.4)
+ dry-equalizer (~> 0.2, >= 0.2.2)
+ dry-inflector (~> 0.1, >= 0.1.2)
+ dry-logic (~> 0.5, >= 0.5)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
i18n (1.8.2)
diff --git a/lib/xpm_ruby.rb b/lib/xpm_ruby.rb
index 491f2b7..bb1b63d 100644
--- a/lib/xpm_ruby.rb
+++ b/lib/xpm_ruby.rb
@@ -10,6 +10,7 @@ class Unauthorized < Error; end
require "xpm_ruby/client"
require "xpm_ruby/connection"
require "xpm_ruby/job"
+require "xpm_ruby/schema/job/add"
require "xpm_ruby/staff"
require "xpm_ruby/template"
require "xpm_ruby/version"
diff --git a/lib/xpm_ruby/job.rb b/lib/xpm_ruby/job.rb
index a29d9de..cc8e3b5 100644
--- a/lib/xpm_ruby/job.rb
+++ b/lib/xpm_ruby/job.rb
@@ -17,5 +17,15 @@ def current(access_token:, xero_tenant_id:)
response["Jobs"]["Job"]
end
+
+ def add(access_token:, xero_tenant_id:, job:)
+ validated_job = XpmRuby::Schema::Job::Add[job]
+
+ response = Connection
+ .new(access_token: access_token, xero_tenant_id: xero_tenant_id)
+ .post(endpoint: "job.api/add", data: validated_job.to_xml(root: "Job"))
+
+ response["Job"]
+ end
end
end
diff --git a/lib/xpm_ruby/schema/job/add.rb b/lib/xpm_ruby/schema/job/add.rb
new file mode 100644
index 0000000..22757ca
--- /dev/null
+++ b/lib/xpm_ruby/schema/job/add.rb
@@ -0,0 +1,21 @@
+require_relative "../../types"
+
+module XpmRuby
+ module Schema
+ module Job
+ Add = Types::Hash.schema(
+ "Name" => Types::String,
+ "Description" => Types::String,
+ "ClientID" => Types::Coercible::String,
+ "ContactID?" => Types::Coercible::String,
+ "StartDate" => Types::Coercible::String,
+ "DueDate" => Types::Coercible::String,
+ "ClientNumber?" => Types::Coercible::String,
+ "ID?" => Types::Coercible::String,
+ "TemplateID?" => Types::Coercible::String,
+ "CategoryID?" => Types::Coercible::String,
+ "Budget?" => Types::Coercible::String
+ )
+ end
+ end
+end
diff --git a/lib/xpm_ruby/types.rb b/lib/xpm_ruby/types.rb
new file mode 100644
index 0000000..8c95b30
--- /dev/null
+++ b/lib/xpm_ruby/types.rb
@@ -0,0 +1,7 @@
+require "dry-types"
+
+module XpmRuby
+ module Types
+ include Dry.Types()
+ end
+end
diff --git a/spec/vcr_cassettes/xpm_ruby/job/add.yml b/spec/vcr_cassettes/xpm_ruby/job/add.yml
new file mode 100644
index 0000000..867a6cc
--- /dev/null
+++ b/spec/vcr_cassettes/xpm_ruby/job/add.yml
@@ -0,0 +1,65 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://api.xero.com/practicemanager/3.0/job.api/add
+ body:
+ encoding: UTF-8
+ string: |
+
+
+ Joe Bloggs
+ New Job
+ 24097642
+ 20091023
+ 20091023
+
+ headers:
+ User-Agent:
+ - Faraday v1.0.1
+ Authorization:
+ - Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjFDQUY4RTY2NzcyRDZEQzAyOEQ2NzI2RkQwMjYxNTgxNTcwRUZDMTkiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJISy1PWm5jdGJjQW8xbkp2MENZVmdWY09fQmsifQ.eyJuYmYiOjE1ODgyMDg3MjksImV4cCI6MTU4ODIxMDUyOSwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS54ZXJvLmNvbSIsImF1ZCI6Imh0dHBzOi8vaWRlbnRpdHkueGVyby5jb20vcmVzb3VyY2VzIiwiY2xpZW50X2lkIjoiNDkyMjZBNjIzMzY0NDVFM0FGQUM5QTQ4MkJGOUUyN0UiLCJzdWIiOiIwY2FmMWU4MWYyZWE1MzdkYWIxYjYzNTY3NTc2ZDk3ZSIsImF1dGhfdGltZSI6MTU4ODIwODU3NSwieGVyb191c2VyaWQiOiJmYzI5MDBjNy0wNjcyLTQzOGItOTNkMS1hOGMyNTBmZDg5MjkiLCJnbG9iYWxfc2Vzc2lvbl9pZCI6IjZmYWRiYTVmYWI3NTQ0NDliNjkwMGE1NzI3OGVlMjc5IiwianRpIjoiZmU2MjUyNzNhNmEwMTI4YjI2N2IxYmI1YWQzMGVkODgiLCJzY29wZSI6WyJlbWFpbCIsInByb2ZpbGUiLCJvcGVuaWQiLCJwcmFjdGljZW1hbmFnZXIiLCJvZmZsaW5lX2FjY2VzcyJdfQ.iL5C3Lcc1KuxTcIMUNUdKfqRoB13flB46dyQ2fUcQesF_lloofR9qWzt1uijc91qQPnkyrgb_Kv2aGvR3YvXXM1naK2Wy87wfAJwonkAGm6IcIIeukgvvJMt3bNZvow-lrk2eb9Wfcz7xt_nJSqL9lr8YV9T5f56IWJzZJzwAiNYz4F1lmqzKMwX5fUU9gYHucgIgQAwDaD3AGPdB-AC71ZNw2Zwsshebv89CbSbpw7rGU9gEhHnI7PjXXYwRn430Zh9k0ruD7IQWNRMh26oS_PR4zIEFDGBn5xBdnm9jLWl9juQUkn0OPQvAwkEuM54AXSWaAgyeasdOtDNjD8JMA
+ xero-tenant-id:
+ - '0791dc22-8611-4c1c-8df7-1c5453d0795b'
+ content_type:
+ - application/xml
+ Content-Type:
+ - application/x-www-form-urlencoded
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ content-type:
+ - text/xml; charset=utf-8
+ server:
+ - Kestrel
+ x-daylimit-remaining:
+ - '4997'
+ x-minlimit-remaining:
+ - '58'
+ xero-correlation-id:
+ - 04e383a3-f80a-4076-b4fa-c5ac40eca5c8
+ content-length:
+ - '412'
+ expires:
+ - Thu, 30 Apr 2020 01:14:38 GMT
+ cache-control:
+ - max-age=0, no-cache, no-store
+ pragma:
+ - no-cache
+ date:
+ - Thu, 30 Apr 2020 01:14:38 GMT
+ connection:
+ - keep-alive
+ x-client-tls-ver:
+ - tls1.3
+ body:
+ encoding: UTF-8
+ string: OKJ000031Joe
+ BloggsNew Job24097642ABC
+ CoPlanned2009-10-23T00:00:002009-10-23T00:00:0044385850
+ http_version: null
+ recorded_at: Thu, 30 Apr 2020 01:14:38 GMT
+recorded_with: VCR 5.1.0
diff --git a/spec/xpm_ruby/job_spec.rb b/spec/xpm_ruby/job_spec.rb
index 553804a..34da5b7 100644
--- a/spec/xpm_ruby/job_spec.rb
+++ b/spec/xpm_ruby/job_spec.rb
@@ -29,5 +29,27 @@ module XpmRuby
expect(first_job["CompletedDate"]).to be_nil
end
end
+
+ describe ".add" do
+ let(:xero_tenant_id) { "0791dc22-8611-4c1c-8df7-1c5453d0795b" }
+ let(:access_token) { "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFDQUY4RTY2NzcyRDZEQzAyOEQ2NzI2RkQwMjYxNTgxNTcwRUZDMTkiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJISy1PWm5jdGJjQW8xbkp2MENZVmdWY09fQmsifQ.eyJuYmYiOjE1ODgyMDg3MjksImV4cCI6MTU4ODIxMDUyOSwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS54ZXJvLmNvbSIsImF1ZCI6Imh0dHBzOi8vaWRlbnRpdHkueGVyby5jb20vcmVzb3VyY2VzIiwiY2xpZW50X2lkIjoiNDkyMjZBNjIzMzY0NDVFM0FGQUM5QTQ4MkJGOUUyN0UiLCJzdWIiOiIwY2FmMWU4MWYyZWE1MzdkYWIxYjYzNTY3NTc2ZDk3ZSIsImF1dGhfdGltZSI6MTU4ODIwODU3NSwieGVyb191c2VyaWQiOiJmYzI5MDBjNy0wNjcyLTQzOGItOTNkMS1hOGMyNTBmZDg5MjkiLCJnbG9iYWxfc2Vzc2lvbl9pZCI6IjZmYWRiYTVmYWI3NTQ0NDliNjkwMGE1NzI3OGVlMjc5IiwianRpIjoiZmU2MjUyNzNhNmEwMTI4YjI2N2IxYmI1YWQzMGVkODgiLCJzY29wZSI6WyJlbWFpbCIsInByb2ZpbGUiLCJvcGVuaWQiLCJwcmFjdGljZW1hbmFnZXIiLCJvZmZsaW5lX2FjY2VzcyJdfQ.iL5C3Lcc1KuxTcIMUNUdKfqRoB13flB46dyQ2fUcQesF_lloofR9qWzt1uijc91qQPnkyrgb_Kv2aGvR3YvXXM1naK2Wy87wfAJwonkAGm6IcIIeukgvvJMt3bNZvow-lrk2eb9Wfcz7xt_nJSqL9lr8YV9T5f56IWJzZJzwAiNYz4F1lmqzKMwX5fUU9gYHucgIgQAwDaD3AGPdB-AC71ZNw2Zwsshebv89CbSbpw7rGU9gEhHnI7PjXXYwRn430Zh9k0ruD7IQWNRMh26oS_PR4zIEFDGBn5xBdnm9jLWl9juQUkn0OPQvAwkEuM54AXSWaAgyeasdOtDNjD8JMA" }
+ let(:job) { { "Name" => "Joe Bloggs", "Description" => "New Job", "ClientID" => "24097642", "StartDate" => "20091023", "DueDate" => "20091023" } }
+
+ around(:each) do |example|
+ VCR.use_cassette("xpm_ruby/job/add") do
+ example.run
+ end
+ end
+
+ it "lists adds a job" do
+ added_job = service.add(access_token: access_token, xero_tenant_id: xero_tenant_id, job: job)
+
+ expect(added_job["Name"]).to eql(job["Name"])
+ expect(added_job["Description"]).to eql(job["Description"])
+ expect(added_job["Client"]["ID"]).to eql(job["ClientID"])
+ expect(added_job["StartDate"]).to eql("2009-10-23T00:00:00")
+ expect(added_job["DueDate"]).to eql("2009-10-23T00:00:00")
+ end
+ end
end
end
diff --git a/spec/xpm_ruby/schema/job/add_spec.rb b/spec/xpm_ruby/schema/job/add_spec.rb
new file mode 100644
index 0000000..33cbff2
--- /dev/null
+++ b/spec/xpm_ruby/schema/job/add_spec.rb
@@ -0,0 +1,27 @@
+require "spec_helper"
+
+module XpmRuby
+ module Schema
+ RSpec.describe(Job) do
+ context "with a valid Add schema" do
+ it "should not raise an error" do
+ hash = { "Name" => "Joe Bloggs", "Description" => "New Job", "ClientID" => 1234, "StartDate" => 20091023, "DueDate" => 20091023 }
+ expect { Job::Add[hash] }.not_to raise_error
+ end
+
+ it "should coerce the types" do
+ hash = { "Name" => "Joe Bloggs", "Description" => "New Job", "ClientID" => 1234, "StartDate" => 20091023, "DueDate" => 20091023 }
+ add = Job::Add[hash]
+ expect(add["ClientID"]).to eql("1234")
+ end
+ end
+
+ context "with an invalid Add schema" do
+ it "should raise an error" do
+ hash = { "Name" => "Joe Bloggs" }
+ expect { Job::Add[hash] }.to raise_error(Dry::Types::ConstraintError, '{"Name"=>"Joe Bloggs"} violates constraints (:Description is missing in Hash input failed)')
+ end
+ end
+ end
+ end
+end
diff --git a/xpm_ruby.gemspec b/xpm_ruby.gemspec
index fad5f02..2e4a862 100644
--- a/xpm_ruby.gemspec
+++ b/xpm_ruby.gemspec
@@ -42,4 +42,6 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency("activesupport")
spec.add_runtime_dependency("builder")
+
+ spec.add_runtime_dependency("dry-types")
end