Skip to content
This repository has been archived by the owner on Nov 10, 2017. It is now read-only.

Add create operation to Windows#Employee and Windows#TimeActivity #92

Merged
merged 3 commits into from
Aug 28, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ Bill | no | no | no | no | no
Bill Payment | no | no | no | no | no
Company Meta Data | no | no | no | no | no | `load`
Customer | yes | yes | yes | no | yes |
Employee | no | no | yes | no | no |
Employee | yes | no | yes | no | no |
Entitlement | n/a | n/a | n/a | n/a | n/a |
Invoice | yes | yes | yes | no | yes |
Item | yes | no | yes | no | yes |
Expand All @@ -404,7 +404,7 @@ Sales Tax | no | no | yes | no | no |
Ship Method | no | no | yes | no | no |
Sync Activity | no | no | no | no | no | `retrieve`
Sync Status | no | no | no | no | no | `retrieve`
Time Activity | no | no | yes | no | no |
Time Activity | yes | no | yes | no | no |
Tracking Class | n/a | n/a | n/a | n/a | n/a |
Vendor | no | no | no | no | no |

Expand Down
126 changes: 70 additions & 56 deletions lib/quickeebooks/windows/model/employee.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,80 @@


module Quickeebooks
module Windows
module Model
class Employee < Quickeebooks::Windows::Model::IntuitType
module Windows
module Model
class Employee < Quickeebooks::Windows::Model::IntuitType
include ActiveModel::Validations

XML_COLLECTION_NODE = 'Employees'
XML_NODE = 'Employee'

# https://services.intuit.com/sb/employee/v2/<realmID>
REST_RESOURCE = "employee"

xml_convention :camelcase
xml_accessor :id, :from => 'Id', :as => Quickeebooks::Windows::Model::Id
xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
xml_accessor :meta_data, :from => 'MetaData', :as => Quickeebooks::Windows::Model::MetaData
xml_accessor :external_key, :from => 'ExternalKey'
xml_accessor :synchronized, :from => 'Synchronized'
xml_accessor :custom_fields, :from => 'CustomField', :as => [Quickeebooks::Windows::Model::CustomField]
xml_accessor :draft
xml_accessor :object_state, :from => 'ObjectState'
xml_accessor :party_reference_id, :from => 'PartyReferenceId'
xml_accessor :type_of, :from => 'TypeOf'
xml_accessor :name, :from => 'Name'
xml_accessor :addresses, :from => 'Address', :as => [Quickeebooks::Windows::Model::Address]
xml_accessor :phone, :from => 'Phone', :as => [Quickeebooks::Windows::Model::Phone]
xml_accessor :web_site, :from => 'WebSite', :as => Quickeebooks::Windows::Model::WebSite
xml_accessor :email, :from => 'Email', :as => Quickeebooks::Windows::Model::Email
xml_accessor :title, :from => 'Title'
xml_accessor :given_name, :from => 'GivenName'
xml_accessor :middle_name, :from => 'MiddleName'
xml_accessor :family_name, :from => 'FamilyName'
xml_accessor :suffix, :from => 'Suffix'
xml_accessor :gender, :from => 'Gender'
xml_accessor :dba_name, :from => 'DBAName'
xml_accessor :tax_identifier, :from => 'TaxIdentifier'
xml_accessor :notes, :from => 'Note', :as => [Quickeebooks::Windows::Model::Note]
xml_accessor :active, :from => 'Active'
xml_accessor :show_as, :from => 'ShowAs'
xml_accessor :employee_type, :from => 'EmployeeType'
xml_accessor :hired_date, :from => 'HiredDate'
xml_accessor :released_date, :from => 'ReleasedDate'
xml_accessor :use_time_entry, :from => 'UseTimeEntry'

def address=(address)
self.addresses ||= []
self.addresses << address
end
XML_COLLECTION_NODE = 'Employees'
XML_NODE = 'Employee'

def billing_address
addresses.detect { |address| address.tag == "Billing" }
end
# https://services.intuit.com/sb/employee/v2/<realmID>
REST_RESOURCE = "employee"

def shipping_address
addresses.detect { |address| address.tag == "Shipping" }
end
xml_convention :camelcase
xml_accessor :id, :from => 'Id', :as => Quickeebooks::Windows::Model::Id
xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
xml_accessor :meta_data, :from => 'MetaData', :as => Quickeebooks::Windows::Model::MetaData
xml_accessor :external_key, :from => 'ExternalKey'
xml_accessor :synchronized, :from => 'Synchronized'
xml_accessor :custom_fields, :from => 'CustomField', :as => [Quickeebooks::Windows::Model::CustomField]
xml_accessor :draft
xml_accessor :object_state, :from => 'ObjectState'
xml_accessor :party_reference_id, :from => 'PartyReferenceId'
xml_accessor :type_of, :from => 'TypeOf'
xml_accessor :name, :from => 'Name'
xml_accessor :addresses, :from => 'Address', :as => [Quickeebooks::Windows::Model::Address]
xml_accessor :phone, :from => 'Phone', :as => [Quickeebooks::Windows::Model::Phone]
xml_accessor :web_site, :from => 'WebSite', :as => Quickeebooks::Windows::Model::WebSite
xml_accessor :email, :from => 'Email', :as => Quickeebooks::Windows::Model::Email
xml_accessor :title, :from => 'Title'
xml_accessor :given_name, :from => 'GivenName'
xml_accessor :middle_name, :from => 'MiddleName'
xml_accessor :family_name, :from => 'FamilyName'
xml_accessor :suffix, :from => 'Suffix'
xml_accessor :gender, :from => 'Gender'
xml_accessor :dba_name, :from => 'DBAName'
xml_accessor :tax_identifier, :from => 'TaxIdentifier'
xml_accessor :notes, :from => 'Note', :as => [Quickeebooks::Windows::Model::Note]
xml_accessor :active, :from => 'Active'
xml_accessor :show_as, :from => 'ShowAs'
xml_accessor :employee_type, :from => 'EmployeeType'
xml_accessor :hired_date, :from => 'HiredDate'
xml_accessor :released_date, :from => 'ReleasedDate'
xml_accessor :use_time_entry, :from => 'UseTimeEntry'

end
end
end
end
validates_length_of :name, :minimum => 1
validate :name_cannot_contain_invalid_characters

def valid_for_create?
valid?
if type_of.nil?
errors.add(:type_of, "Missing required attribute TypeOf for Create")
end
errors.empty?
end

def name_cannot_contain_invalid_characters
if name.to_s.index(':')
errors.add(:name, "Name cannot contain a colon (:)")
end
end

def address=(address)
self.addresses ||= []
self.addresses << address
end

def billing_address
addresses.detect { |address| address.tag == "Billing" }
end


def shipping_address
addresses.detect { |address| address.tag == "Shipping" }
end

end
end
end
end
109 changes: 61 additions & 48 deletions lib/quickeebooks/windows/model/time_activity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,56 +11,69 @@


module Quickeebooks
module Windows
module Model
class TimeActivity < Quickeebooks::Windows::Model::IntuitType
module Windows
module Model
class TimeActivity < Quickeebooks::Windows::Model::IntuitType
include ActiveModel::Validations

XML_COLLECTION_NODE = 'TimeActivities'
XML_NODE = 'TimeActivity'

# https://services.intuit.com/sb/timeactivity/v2/<realmID>
REST_RESOURCE = "timeactivity"

xml_convention :camelcase
xml_accessor :id, :from => 'Id', :as => Quickeebooks::Windows::Model::Id
xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
xml_accessor :meta_data, :from => 'MetaData', :as => Quickeebooks::Windows::Model::MetaData
xml_accessor :external_key, :from => 'ExternalKey'
xml_accessor :synchronized, :from => 'Synchronized'
xml_accessor :custom_fields, :from => 'CustomField', :as => [Quickeebooks::Windows::Model::CustomField]
xml_accessor :draft
xml_accessor :object_state, :from => 'ObjectState'
xml_accessor :txn_date, :from => 'TxnDate'
xml_accessor :name_of, :from => 'NameOf'
xml_accessor :employee, :from => 'Employee', :as => Quickeebooks::Windows::Model::TimeActivityEmployee
xml_accessor :vendor, :from => 'Vendor', :as => Quickeebooks::Windows::Model::TimeActivityVendor
xml_accessor :customer_id, :from => 'CustomerId'
xml_accessor :customer_name, :from => 'CustomerName'
xml_accessor :job_id, :from => 'JobId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :job_name, :from => 'JobName'
xml_accessor :item_id, :from => 'ItemId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :item_name, :from => 'ItemName'
xml_accessor :item_type, :from => 'ItemType'
xml_accessor :class_id, :from => 'ClassId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :pay_item_id, :from => 'PayItemId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :pay_item_name, :from => 'PayItemName'
xml_accessor :billable_status, :from => 'BillableStatus'
xml_accessor :taxable, :from => 'Taxable'
xml_accessor :hourly_rate, :from => 'HourlyRate'
xml_accessor :hours, :from => 'Hours'
xml_accessor :minutes, :from => 'Minutes'
xml_accessor :seconds, :from => 'Seconds'
xml_accessor :break_hours, :from => 'BreakHours'
xml_accessor :break_minutes, :from => 'BreakMinutes'
xml_accessor :start_time, :from => 'StartTime'
xml_accessor :end_time, :from => 'EndTime'
xml_accessor :description, :from => 'Description'
XML_COLLECTION_NODE = 'TimeActivities'
XML_NODE = 'TimeActivity'

end
end
end
end
# https://services.intuit.com/sb/timeactivity/v2/<realmID>
REST_RESOURCE = "timeactivity"

xml_convention :camelcase
xml_accessor :id, :from => 'Id', :as => Quickeebooks::Windows::Model::Id
xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
xml_accessor :meta_data, :from => 'MetaData', :as => Quickeebooks::Windows::Model::MetaData
xml_accessor :external_key, :from => 'ExternalKey'
xml_accessor :synchronized, :from => 'Synchronized'
xml_accessor :custom_fields, :from => 'CustomField', :as => [Quickeebooks::Windows::Model::CustomField]
xml_accessor :draft
xml_accessor :object_state, :from => 'ObjectState'
xml_accessor :txn_date, :from => 'TxnDate'
xml_accessor :name_of, :from => 'NameOf'
xml_accessor :employee, :from => 'Employee', :as => Quickeebooks::Windows::Model::TimeActivityEmployee
xml_accessor :vendor, :from => 'Vendor', :as => Quickeebooks::Windows::Model::TimeActivityVendor
xml_accessor :customer_id, :from => 'CustomerId'
xml_accessor :customer_name, :from => 'CustomerName'
xml_accessor :job_id, :from => 'JobId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :job_name, :from => 'JobName'
xml_accessor :item_id, :from => 'ItemId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :item_name, :from => 'ItemName'
xml_accessor :item_type, :from => 'ItemType'
xml_accessor :class_id, :from => 'ClassId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :pay_item_id, :from => 'PayItemId', :as => Quickeebooks::Windows::Model::Id
xml_accessor :pay_item_name, :from => 'PayItemName'
xml_accessor :billable_status, :from => 'BillableStatus'
xml_accessor :taxable, :from => 'Taxable'
xml_accessor :hourly_rate, :from => 'HourlyRate'
xml_accessor :hours, :from => 'Hours'
xml_accessor :minutes, :from => 'Minutes'
xml_accessor :seconds, :from => 'Seconds'
xml_accessor :break_hours, :from => 'BreakHours'
xml_accessor :break_minutes, :from => 'BreakMinutes'
xml_accessor :start_time, :from => 'StartTime'
xml_accessor :end_time, :from => 'EndTime'
xml_accessor :description, :from => 'Description'

validates_inclusion_of :name_of, :in => %w(Employee Vendor)
validates_inclusion_of :billable_status, :in => %w(Billable NotBillable HasBeenBilled),
:allow_blank => true
validate :duration_is_set

def valid_for_create?
valid?
errors.empty?
end


def duration_is_set
unless (self.hours || self.minutes || self.seconds)
errors.add(:base, 'A duration is required')
end
end

end
end
end
end
15 changes: 14 additions & 1 deletion lib/quickeebooks/windows/service/employee.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@ class Employee < Quickeebooks::Windows::Service::ServiceBase
def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
fetch_collection(Quickeebooks::Windows::Model::Employee, nil, filters, page, per_page, sort, options)
end

def create(employee)
raise InvalidModelException unless employee.valid_for_create?

# XML is a wrapped 'object' where the type is specified as an attribute
# <Object xsi:type="Invoice">
xml_node = employee.to_xml(:name => 'Object')
xml_node.set_attribute('xsi:type', 'Employee')
xml = Quickeebooks::Shared::Service::OperationNode.new.add do |content|
content << "<ExternalRealmId>#{self.realm_id}</ExternalRealmId>#{xml_node}"
end
perform_write(Quickeebooks::Windows::Model::Employee, xml)
end
end
end
end
end
end
15 changes: 14 additions & 1 deletion lib/quickeebooks/windows/service/time_activity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,20 @@ def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
fetch_collection(Quickeebooks::Windows::Model::TimeActivity, nil, filters, page, per_page, sort, options)
end

def create(time_activity)
raise InvalidModelException unless time_activity.valid_for_create?

# XML is a wrapped 'object' where the type is specified as an attribute
# <Object xsi:type="Invoice">
xml_node = time_activity.to_xml(:name => 'Object')
xml_node.set_attribute('xsi:type', 'TimeActivity')
xml = Quickeebooks::Shared::Service::OperationNode.new.add do |content|
content << "<ExternalRealmId>#{self.realm_id}</ExternalRealmId>#{xml_node}"
end
perform_write(Quickeebooks::Windows::Model::TimeActivity, xml)
end

end
end
end
end
end
72 changes: 71 additions & 1 deletion spec/quickeebooks/windows/services/employee_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,74 @@

end

end
it "cannot create a employee without a name" do
employee = Quickeebooks::Windows::Model::Employee.new
service = Quickeebooks::Windows::Service::Employee.new
service.access_token = @oauth
service.realm_id = @realm_id
lambda do
service.create(employee)
end.should raise_error(InvalidModelException)

employee.valid?.should == false
employee.errors.keys.include?(:name).should == true
end

it "cannot create a employee without a type_of attribute" do
employee = Quickeebooks::Windows::Model::Employee.new
service = Quickeebooks::Windows::Service::Employee.new
service.access_token = @oauth
service.realm_id = @realm_id
lambda do
service.create(employee)
end.should raise_error(InvalidModelException)
employee.errors.keys.include?(:type_of).should == true
end

it "cannot create a employee with invalid name" do
employee = Quickeebooks::Windows::Model::Employee.new
service = Quickeebooks::Windows::Service::Employee.new
service.access_token = @oauth
service.realm_id = @realm_id
employee.name = "Bobs:Plumbing"
lambda do
service.create(employee)
end.should raise_error(InvalidModelException)

employee.valid?.should == false
employee.errors.keys.include?(:name).should == true
end

it "can create a employee" do
xml = windowsFixture("employee_create_success.xml")
service = Quickeebooks::Windows::Service::Employee.new
model = Quickeebooks::Windows::Model::Employee
employee = Quickeebooks::Windows::Model::Employee.new

service.access_token = @oauth
service.realm_id = @realm_id
FakeWeb.register_uri(:post, service.url_for_resource(model::REST_RESOURCE), :status => ["200", "OK"], :body => xml)

employee.type_of = "Person"
employee.name = "Bugs Bunny"
employee.given_name = "Bugs"
employee.family_name = "Bunny"
email = Quickeebooks::Windows::Model::Email.new
email.address = "[email protected]"
email.tag = "Business"
employee.email = email
address = Quickeebooks::Windows::Model::Address.new
address.tag = "Billing"
address.line1 = "123 Main St."
address.city = "San Francisco"
address.country_sub_division_code = "CA"
address.postal_code = "94117"
address.country = "USA"
employee.address = address
create_response = service.create(employee)
create_response.success?.should == true
create_response.success.party_role_ref.id.value.should == "155031"
create_response.success.request_name.should == "EmployeeAdd"
end

end
Loading