Skip to content

Commit

Permalink
add settings, pay runs, payslips
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiculescu committed Oct 13, 2013
1 parent de93783 commit cbc529f
Show file tree
Hide file tree
Showing 32 changed files with 494 additions and 180 deletions.
3 changes: 2 additions & 1 deletion lib/xeroizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
['home_address', 'bank_account', 'employee', 'timesheet', 'timesheet_line', 'number_of_unit',
'leave_application', 'leave_period', 'pay_items', 'deduction_type', 'earnings_rate',
'reimbursement_type', 'leave_type', 'payroll_calendar', 'pay_template', 'super_membership',
'leave_line', 'reimbursement_line', 'super_line', 'deduction_line', 'earnings_line', 'opening_balance'].each do |payroll_model|
'leave_line', 'reimbursement_line', 'super_line', 'deduction_line', 'earnings_line', 'opening_balance',
'pay_run', 'settings', 'tracking_categories', 'employee_groups', 'timesheet_categories', 'account'].each do |payroll_model|
require "xeroizer/models/payroll/#{payroll_model}"
end

Expand Down
2 changes: 1 addition & 1 deletion lib/xeroizer/generic_application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class GenericApplication
# @see PrivateApplication
# @see PartnerApplication
def initialize(consumer_key, consumer_secret, options = {})
@xero_url_prefix = options[:xero_url_prefix] || "https://api.xero.com/"
@xero_url_prefix = options[:xero_url_prefix] || "https://api.xero.com"
@xero_url_suffix = options[:xero_url_suffix] || "api.xro/2.0"
@rate_limit_sleep = options[:rate_limit_sleep] || false
@rate_limit_max_attempts = options[:rate_limit_max_attempts] || 5
Expand Down
21 changes: 21 additions & 0 deletions lib/xeroizer/models/payroll/account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Xeroizer
module Record
module Payroll

class AccountModel < PayrollBaseModel

set_permissions :read

end

class Account < PayrollBase

string :type
string :code
string :name
guid :account_id
end

end
end
end
24 changes: 24 additions & 0 deletions lib/xeroizer/models/payroll/employee_groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Xeroizer
module Record
module Payroll

class EmployeeGroupsModel < PayrollBaseModel

set_standalone_model true
set_xml_root_name 'EmployeeGroups'
set_xml_node_name 'EmployeeGroups'
end

# child of TrackingCategories
class EmployeeGroups < PayrollBase

set_primary_key false

guid :tracking_category_id
string :tracking_category_name

end

end
end
end
2 changes: 0 additions & 2 deletions lib/xeroizer/models/payroll/leave_application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ module Payroll
class LeaveApplicationModel < PayrollBaseModel

set_permissions :read, :write, :update

# TODO: calling #get on this requries an employee ID
end

class LeaveApplication < PayrollBase
Expand Down
2 changes: 1 addition & 1 deletion lib/xeroizer/models/payroll/opening_balance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Payroll

class OpeningBalancesModel < PayrollBaseModel

set_all_children_are_subtypes true
set_standalone_model true
set_xml_root_name 'OpeningBalances'
set_xml_node_name 'OpeningBalances'
end
Expand Down
2 changes: 1 addition & 1 deletion lib/xeroizer/models/payroll/pay_items.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class PayItemModel < PayrollBaseModel

set_permissions :read, :write, :update

set_all_children_are_subtypes true
set_standalone_model true
set_xml_root_name 'PayItems'
set_xml_node_name 'PayItems'
end
Expand Down
40 changes: 40 additions & 0 deletions lib/xeroizer/models/payroll/pay_run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Xeroizer
module Record
module Payroll

class PayRunModel < PayrollBaseModel

set_permissions :read, :write, :update

end

# http://developer.xero.com/documentation/payroll-api/payruns/
class PayRun < PayrollBase

set_primary_key :pay_run_id

guid :pay_run_id

guid :payroll_calendar_id

date :pay_run_period_end_date
date :pay_run_period_start_date
date :payment_date

decimal :wages
decimal :deductions
decimal :tax
decimal :super
decimal :reimbursement
decimal :net_pay

string :pay_run_status
string :payslip_message

#has_many :payslips

end

end
end
end
2 changes: 1 addition & 1 deletion lib/xeroizer/models/payroll/pay_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Payroll

class PayTemplateModel < PayrollBaseModel

set_all_children_are_subtypes true
set_standalone_model true
set_xml_root_name 'PayTemplate'
set_xml_node_name 'PayTemplate'
end
Expand Down
31 changes: 31 additions & 0 deletions lib/xeroizer/models/payroll/payslip.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Xeroizer
module Record
module Payroll

class PayslipModel < PayrollBaseModel

set_permissions :read, :update

end

# http://developer.xero.com/documentation/payroll-api/payslip/
class Payslip < PayrollBase

set_primary_key :payslip_id

guid :payslip_id

guid :employee_id

has_many :earnings_lines
#has_many :timesheet_earnings_lines # TODO
has_many :deduction_lines
#has_many :leave_accrual_lines # TODO
has_many :superannuation_lines, :internal_name_singular => "super_line", :model_name => "SuperLine"
has_many :reimbursement_lines

end

end
end
end
27 changes: 27 additions & 0 deletions lib/xeroizer/models/payroll/settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Xeroizer
module Record
module Payroll

class SettingModel < PayrollBaseModel

set_permissions :read

set_standalone_model true
set_xml_root_name 'Settings'
set_xml_node_name 'Settings'
end

class Setting < PayrollBase

set_primary_key false

has_many :accounts
has_many :timesheet_categories, :model_name => 'TimesheetCategories'
has_many :employee_groups, :model_name => 'EmployeeGroups'
integer :days_in_payroll_year

end

end
end
end
3 changes: 3 additions & 0 deletions lib/xeroizer/models/payroll/super_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ class SuperLine < PayrollBase
string :expense_account_code
string :liability_account_code

date :payment_date_for_this_period

decimal :minimum_monthly_earnings
decimal :percentage
decimal :amount

end

Expand Down
24 changes: 24 additions & 0 deletions lib/xeroizer/models/payroll/timesheet_categories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Xeroizer
module Record
module Payroll

class TimesheetCategoriesModel < PayrollBaseModel

set_standalone_model true
set_xml_root_name 'TimesheetCategories'
set_xml_node_name 'TimesheetCategories'
end

# child of TrackingCategories
class TimesheetCategories < PayrollBase

set_primary_key false

guid :tracking_category_id
string :tracking_category_name

end

end
end
end
26 changes: 26 additions & 0 deletions lib/xeroizer/models/payroll/tracking_categories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Xeroizer
module Record
module Payroll

class TrackingCategoriesModel < PayrollBaseModel

set_permissions :read

set_standalone_model true
set_xml_root_name 'TrackingCategories'
set_xml_node_name 'TrackingCategories'
end

# child of Settings
class TrackingCategories < PayrollBase

set_primary_key false

has_many :employee_groups
has_many :timesheet_categories

end

end
end
end
3 changes: 3 additions & 0 deletions lib/xeroizer/payroll_application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ def self.record(record_type)
record :PayItem
record :PayrollCalendar
record :LeaveApplication
record :PayRun
record :Payslip
record :Setting

def initialize(application)
@application = application
Expand Down
28 changes: 19 additions & 9 deletions lib/xeroizer/record/base_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class InvalidPermissionError < StandardError
class_inheritable_attributes :xml_root_name
class_inheritable_attributes :optional_xml_root_name
class_inheritable_attributes :xml_node_name
class_inheritable_attributes :all_children_are_subtypes
class_inheritable_attributes :standalone_model

include BaseModelHttpProxy

Expand Down Expand Up @@ -71,8 +71,8 @@ def set_optional_xml_root_name(optional_root_name)
# If this is true, the <Class> tag isn't expected. So it would be
# <Classes><Subclasses><Subclass></Subclass></Subclasses></Classes>
# Example: http://developer.xero.com/payroll-api/PayItems/#GET
def set_all_children_are_subtypes(boolean)
self.all_children_are_subtypes = boolean
def set_standalone_model(boolean)
self.standalone_model = boolean
end

end
Expand Down Expand Up @@ -180,7 +180,7 @@ def parse_response(response_xml, options = {})
if model_name == response_model_name
@response = response
parse_records(response, elements, (options[:base_module] || Xeroizer::Record))
elsif self.class.all_children_are_subtypes && self.class.xml_root_name == elements.first.parent.name
elsif self.class.standalone_model && self.class.xml_root_name == elements.first.parent.name
@response = response
parse_records(response, elements, (options[:base_module] || Xeroizer::Record), true)
end
Expand All @@ -190,21 +190,31 @@ def parse_response(response_xml, options = {})
protected

# Parse the records part of the XML response and builds model instances as necessary.
def parse_records(response, elements, base_module, all_children_are_subtypes = false)
def parse_records(response, elements, base_module, standalone_model = false)
elements.each do | element |
new_record = model_class.build_from_node(element, self, base_module, all_children_are_subtypes)
new_record = model_class.build_from_node(element, self, base_module, standalone_model)
if element.attribute('status').try(:value) == 'ERROR'
new_record.errors = []
element.xpath('.//ValidationError').each do |err|
new_record.errors << err.text.gsub(/^\s+/, '').gsub(/\s+$/, '')
end
end
if all_children_are_subtypes
if standalone_model
if response.response_items.count == 0
response.response_items << new_record
else
field_to_fill = model_class.fields.find {|f| new_record[f[0]].count > 0}
(response.response_items.first[field_to_fill[0]] = new_record[field_to_fill[0]]) unless field_to_fill.nil?
# http://developer.xero.com/documentation/payroll-api/settings/
# tracking categories have subcategories of timesheet categoires and employee groups
# which we group together here as it's much easier to model
fields_to_fill = model_class.fields.find_all do |f|
new_record_field = new_record[f[0]]
if new_record_field.respond_to?(:count)
new_record_field.count > 0
else
!new_record_field.nil?
end
end
fields_to_fill.each {|field| response.response_items.first[field[0]] = new_record[field[0]]}
end
else
response.response_items << new_record
Expand Down
1 change: 1 addition & 0 deletions lib/xeroizer/record/record_association_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def belongs_to(field_name, options = {})

# Create a #build_record_name method to build the record.
define_method "build_#{internal_singular_field_name}" do | *args |

attributes = args.size == 1 ? args.first : {}

# The name of the record model.
Expand Down
10 changes: 5 additions & 5 deletions lib/xeroizer/record/xml_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ def self.included(base)
module ClassMethods

# Build a record instance from the XML node.
def build_from_node(node, parent, base_module, all_children_are_subtypes = false)
def build_from_node(node, parent, base_module, standalone_model = false)
record = new(parent)
node.elements.each do | element |
element_name = all_children_are_subtypes ? element.name.to_s.pluralize : element.name.to_s
element_name = standalone_model ? element.name.to_s.pluralize : element.name.to_s
field = self.fields[element_name.underscore.to_sym]
if field
value = case field[:type]
Expand All @@ -33,9 +33,9 @@ def build_from_node(node, parent, base_module, all_children_are_subtypes = false

when :has_many
if element.element_children.size > 0
sub_field_name = field[:model_name] ? field[:model_name].to_sym : (all_children_are_subtypes ? element.name : element.children.first.name).to_sym
sub_field_name = field[:model_name] ? field[:model_name].to_sym : (standalone_model ? element.name : element.children.first.name).to_sym
sub_parent = record.new_model_class(sub_field_name)
if all_children_are_subtypes
if standalone_model
base_module.const_get(sub_field_name).build_from_node(element, sub_parent, base_module)
else
element.children.inject([]) do | list, element |
Expand All @@ -56,7 +56,7 @@ def build_from_node(node, parent, base_module, all_children_are_subtypes = false
end
if field[:calculated]
record.attributes[field[:internal_name]] = value
elsif all_children_are_subtypes
elsif standalone_model
record.send("add_#{field[:internal_name].to_s.singularize}".to_sym, value)
else
record.send("#{field[:internal_name]}=".to_sym, value)
Expand Down
Loading

0 comments on commit cbc529f

Please sign in to comment.