├── .gitignore ├── .rbenv-gemsets ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── lib ├── myob-api.rb └── myob │ └── api │ ├── client.rb │ ├── helpers.rb │ ├── models │ ├── base.rb │ ├── company.rb │ ├── company_file.rb │ ├── contact.rb │ ├── current_user.rb │ ├── customer.rb │ ├── customer_payment.rb │ ├── employee.rb │ ├── employee_payment_details.rb │ ├── employee_payroll_advice.rb │ ├── employee_payroll_details.rb │ ├── employee_standard_pay.rb │ ├── entitlement.rb │ ├── general_ledger.rb │ ├── invoice.rb │ ├── invoice_item.rb │ ├── payroll_category.rb │ ├── superannuation_category.rb │ ├── superannuation_fund.rb │ ├── tax_table.rb │ ├── timesheet.rb │ └── wage.rb │ └── version.rb └── myob-api.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /.rbenv-gemsets: -------------------------------------------------------------------------------- 1 | myob-api 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in myob-api.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 David Lumley 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MYOB Api 2 | 3 | [MYOB Api](https://github.com/davidlumley/myob-api) is an interface for accessing [MYOB](http://developer.myob.com/api/accountright/v2/)'s AccountRight Live API. 4 | 5 | ## Installation 6 | 7 | Add this line to your application's Gemfile: 8 | 9 | gem 'myob-api' 10 | 11 | And then execute: 12 | 13 | $ bundle 14 | 15 | Or install it yourself as: 16 | 17 | $ gem install myob-api 18 | 19 | ## Usage 20 | 21 | ### OAuth Authentication 22 | 23 | If you've already got an OAuth access token, feel free to skip to API Client Setup. 24 | 25 | The MYOB API uses 3 legged OAuth2. If you don't want to roll your own, or use the [OmniAuth strategy](https://github.com/davidlumley/omniauth-myob) you can authenticate using the `get_access_code_url` and `get_access_token` methods that [ghiculescu](https://github.com/ghiculescu) has provided like so: 26 | 27 | class MYOBSessionController 28 | def new 29 | redirect_to myob_client.get_access_code_url 30 | end 31 | 32 | def create 33 | @token = myob_client.get_access_token(params[:code]) 34 | @company_files = myob_client.company_file.all 35 | # then show the user a view where they can log in to their company file 36 | end 37 | 38 | def myob_client 39 | @myob_client ||= Myob::Api::Client.new({ 40 | :consumer => { 41 | :key => YOUR_CONSUMER_KEY, 42 | :secret => YOUR_CONSUMER_SECRET, 43 | }, 44 | }) 45 | end 46 | end 47 | 48 | ### API Client Setup 49 | 50 | Create an api_client: 51 | 52 | api_client = Myob::Api::Client.new({ 53 | :consumer => { 54 | :key => YOUR_CONSUMER_KEY, 55 | :secret => YOUR_CONSUMER_SECRET, 56 | }, 57 | :access_token => YOUR_OAUTH_ACCESS_TOKEN, 58 | }) 59 | 60 | If you have a refresh token (the Myob API returns one by default) you can use that too: 61 | 62 | api_client = Myob::Api::Client.new({ 63 | :consumer => { 64 | :key => YOUR_CONSUMER_KEY, 65 | :secret => YOUR_CONSUMER_SECRET, 66 | }, 67 | :access_token => YOUR_OAUTH_ACCESS_TOKEN, 68 | :refresh_token => YOUR_OAUTH_REFRESH_TOKEN, 69 | }) 70 | 71 | Or if you know which Company File you want to access too: 72 | 73 | api_client = Myob::Api::Client.new({ 74 | :consumer => { 75 | :key => YOUR_CONSUMER_KEY, 76 | :secret => YOUR_CONSUMER_SECRET, 77 | }, 78 | :access_token => YOUR_OAUTH_ACCESS_TOKEN, 79 | :refresh_token => YOUR_OAUTH_REFRESH_TOKEN, 80 | :company_file => { 81 | :name => COMPANY_FILE_NAME, 82 | :username => COMPANY_FILE_USERNAME, 83 | :password => COMPANY_FILE_PASSWORD, 84 | }, 85 | }) 86 | 87 | If you provide a company file, the gem will attempt to connect to MYOB to get the base API subdomain to use for future requests ([learn more](http://developer.myob.com/api/accountright/best-practice-guides/hypermedia-and-uris/)). 88 | 89 | ### API Methods 90 | 91 | #### Company Files 92 | 93 | Before using the majority of API methods you will need to have selected a Company File. If you've already selected one when creating the client, feel free to ignore this. 94 | 95 | Return a list of company files: 96 | 97 | api_client.company_file.all 98 | 99 | Select a company file to work with 100 | 101 | api_client.select_company_file({ 102 | :id => COMPANY_FILE_ID, 103 | :username => COMPANY_FILE_USERNAME, 104 | :password => COMPANY_FILE_PASSWORD, 105 | }) 106 | 107 | #### Contacts 108 | 109 | Return a list of all contacts 110 | 111 | api_client.contact.all 112 | 113 | #### Customers 114 | 115 | Return a list of all customers (a subset of contacts) 116 | 117 | api_client.customer.all 118 | 119 | #### Employees 120 | 121 | Return a list of all employees 122 | 123 | api_client.employee.all 124 | 125 | #### Invoices 126 | 127 | Return a list of all invoices 128 | 129 | api_client.invoice.all 130 | 131 | #### Pagination 132 | 133 | Basic pagination based on `NextPageLink` parameter returned via [API](http://developer.myob.com/api/accountright/api-overview/retrieving-data/) 134 | 135 | first_page = api_client.contact.all 136 | second_page = api_client.contact.next_page if api_client.contact.next_page? 137 | 138 | You can also get an array of all items (which may make several API calls in the background): 139 | 140 | api_client.contact.all_items # note this returns an array, *not* a hash the way `api_client.contact.all` does - use it if you only need data, without metadata 141 | 142 | #### Filtering 143 | 144 | You can use oData filters: 145 | 146 | api_client.employee.all(filter: "IsActive eq true") 147 | 148 | See http://www.odata.org/documentation/odata-version-2-0/uri-conventions/ and http://developer.myob.com/api/accountright/api-overview/retrieving-data/ for information on oData filtering. 149 | 150 | #### Fetching one entity 151 | 152 | Return an entity with given `UID`: 153 | 154 | contact = api_client.contact.find(contact_uid) 155 | 156 | #### Creating an entity 157 | 158 | To create a new entity, call #save on its model, passing through a hash that represents the entity. Refer to the MYOB API documentation for required fields. 159 | 160 | api_client.employee.save({'FirstName' => 'John', 'LastName' => 'Smith', 'IsIndividual' => true}) 161 | 162 | #### Updating an entity 163 | 164 | To update an existing entity, call #save on its model, passing through a hash you got from the API. This hash should include a `UID` parameter (which is included by default when you get the data). 165 | 166 | user = api_client.employee.all["Items"].last 167 | user['FirstName'] = 'New First Name' 168 | api_client.employee.save(user) 169 | 170 | 171 | ## Todo 172 | 173 | * Expand API methods 174 | * Refactor client factory architecture 175 | * Tests 176 | 177 | 178 | ## Contributing 179 | 180 | 1. Fork it 181 | 2. Create your feature branch (`git checkout -b my-new-feature`) 182 | 3. Commit your changes (`git commit -am 'Add some feature'`) 183 | 4. Push to the branch (`git push origin my-new-feature`) 184 | 5. Create new Pull Request 185 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /lib/myob-api.rb: -------------------------------------------------------------------------------- 1 | require 'myob/api/version' 2 | 3 | require 'myob/api/helpers' 4 | 5 | require 'myob/api/models/base' 6 | require 'myob/api/models/company_file' 7 | require 'myob/api/models/company' 8 | 9 | require 'myob/api/models/current_user' 10 | require 'myob/api/models/superannuation_fund' 11 | 12 | require 'myob/api/models/contact' 13 | require 'myob/api/models/customer' 14 | require 'myob/api/models/employee' 15 | require 'myob/api/models/employee_payment_details' 16 | require 'myob/api/models/employee_payroll_details' 17 | require 'myob/api/models/employee_standard_pay' 18 | 19 | require 'myob/api/models/employee_payroll_advice' 20 | 21 | require 'myob/api/models/customer_payment' 22 | require 'myob/api/models/invoice' 23 | require 'myob/api/models/invoice_item' 24 | 25 | require 'myob/api/models/payroll_category' 26 | require 'myob/api/models/wage' 27 | require 'myob/api/models/entitlement' 28 | require 'myob/api/models/tax_table' 29 | require 'myob/api/models/superannuation_category' 30 | 31 | require 'myob/api/models/timesheet' 32 | 33 | require 'myob/api/models/general_ledger' 34 | 35 | require 'myob/api/models/employee_payroll_advice' 36 | 37 | require 'myob/api/client' 38 | -------------------------------------------------------------------------------- /lib/myob/api/client.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | require 'oauth2' 3 | 4 | module Myob 5 | module Api 6 | class Client 7 | include Myob::Api::Helpers 8 | 9 | attr_reader :current_company_file, :client, :current_company_file_url 10 | 11 | def initialize(options) 12 | Myob::Api::Model::Base.subclasses.each {|c| model(c.name.split("::").last)} 13 | 14 | @redirect_uri = options[:redirect_uri] 15 | @consumer = options[:consumer] 16 | @access_token = options[:access_token] 17 | @refresh_token = options[:refresh_token] 18 | 19 | @client = OAuth2::Client.new(@consumer[:key], @consumer[:secret], { 20 | :site => 'https://secure.myob.com', 21 | :authorize_url => '/oauth2/account/authorize', 22 | :token_url => '/oauth2/v1/authorize', 23 | }) 24 | 25 | # on client init, if we have a company file already, get the appropriate base URL for this company file from MYOB 26 | provided_company_file = options[:selected_company_file] || options[:company_file] 27 | select_company_file(provided_company_file) if provided_company_file 28 | @current_company_file ||= {} 29 | end 30 | 31 | def get_access_code_url(params = {}) 32 | @client.auth_code.authorize_url(params.merge(scope: 'CompanyFile', redirect_uri: @redirect_uri)) 33 | end 34 | 35 | def get_access_token(access_code) 36 | @token = @client.auth_code.get_token(access_code, redirect_uri: @redirect_uri) 37 | @access_token = @token.token 38 | @expires_at = @token.expires_at 39 | @refresh_token = @token.refresh_token 40 | @token 41 | end 42 | 43 | def headers 44 | token = (@current_company_file || {})[:token] 45 | if token.nil? || token == '' 46 | # if token is blank assume we are using federated login - http://myobapi.tumblr.com/post/109848079164/2015-1-release-notes 47 | { 48 | 'x-myobapi-key' => @consumer[:key], 49 | 'x-myobapi-version' => 'v2', 50 | 'Content-Type' => 'application/json' 51 | } 52 | else 53 | { 54 | 'x-myobapi-key' => @consumer[:key], 55 | 'x-myobapi-version' => 'v2', 56 | 'x-myobapi-cftoken' => token, 57 | 'Content-Type' => 'application/json' 58 | } 59 | end 60 | end 61 | 62 | # given some company file credentials, connect to MYOB and get the appropriate company file object. 63 | # store its ID and token for auth'ing requests, and its URL to ensure we talk to the right MYOB server. 64 | # 65 | # `company_file` should be hash. accepted forms: 66 | # 67 | # {name: String, username: String, password: String} 68 | # {id: String, token: String} 69 | def select_company_file(company_file) 70 | # store the provided company file as an ivar so we can use it for subsequent requests 71 | # we need the token from it to make the initial request to get company files 72 | @current_company_file ||= company_file if company_file[:token] 73 | 74 | selected_company_file = company_files.find {|file| 75 | if company_file[:name] 76 | file['Name'] == company_file[:name] 77 | elsif company_file[:id] 78 | file['Id'] == company_file[:id] 79 | end 80 | } 81 | 82 | if selected_company_file 83 | token = company_file[:token] 84 | if (token.nil? || token == '') && !company_file[:username].nil? && company_file[:username] != '' && !company_file[:password].nil? 85 | # if we have been given login details, encode them into a token 86 | token = Base64.encode64("#{company_file[:username]}:#{company_file[:password]}") 87 | end 88 | @current_company_file = { 89 | :id => selected_company_file['Id'], 90 | :token => token 91 | } 92 | @current_company_file_url = selected_company_file['Uri'] 93 | else 94 | @current_company_file = {} 95 | end 96 | end 97 | 98 | def connection 99 | if @refresh_token 100 | @auth_connection ||= OAuth2::AccessToken.new(@client, @access_token, { 101 | :refresh_token => @refresh_token 102 | }).refresh! 103 | else 104 | @auth_connection ||= OAuth2::AccessToken.new(@client, @access_token) 105 | end 106 | end 107 | 108 | private 109 | def company_files 110 | @company_files ||= self.company_file.all.to_a 111 | end 112 | end 113 | end 114 | end 115 | -------------------------------------------------------------------------------- /lib/myob/api/helpers.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | 4 | module RefinedString 5 | refine String do 6 | def underscore 7 | self.gsub(/::/, '/'). 8 | gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 9 | gsub(/([a-z\d])([A-Z])/,'\1_\2'). 10 | tr("-", "_"). 11 | downcase 12 | end 13 | end 14 | end 15 | 16 | module Helpers 17 | using RefinedString 18 | 19 | def model(model_name) 20 | method_name = model_name.to_s.underscore 21 | variable_name = "@#{method_name}_model".to_sym 22 | unless instance_variable_defined?(variable_name) 23 | instance_variable_set(variable_name, Myob::Api::Model.const_get("#{model_name}".to_sym).new(self, model_name.to_s)) 24 | self.define_singleton_method(method_name.to_sym) do 25 | instance_variable_get(variable_name) 26 | end 27 | end 28 | instance_variable_get(variable_name) 29 | end 30 | end 31 | 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/myob/api/models/base.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Base 5 | 6 | API_URL = 'https://api.myob.com/accountright/' # deprecated except for initial requests - should read from API instead - http://myobapi.tumblr.com/post/141169146113/important-update-accountright-live-cloud-api 7 | QUERY_OPTIONS = [:orderby, :top, :skip, :filter] 8 | 9 | def initialize(client, model_name) 10 | @client = client 11 | @model_name = model_name || 'Base' 12 | @next_page_link = nil 13 | end 14 | 15 | def model_route 16 | @model_name.to_s 17 | end 18 | 19 | def all(params = nil) 20 | perform_request(self.url(nil, params)) 21 | end 22 | alias_method :get, :all 23 | 24 | def records(params = nil) 25 | response = all(params) 26 | response.is_a?(Hash) && response.key?('Items') ? response['Items'] : response 27 | end 28 | 29 | def next_page? 30 | !!@next_page_link 31 | end 32 | 33 | def next_page(params = nil) 34 | perform_request(@next_page_link) 35 | end 36 | 37 | def all_items(params = nil) 38 | results = all(params)["Items"] 39 | while next_page? 40 | results += next_page["Items"] || [] 41 | end 42 | results 43 | end 44 | 45 | def find(id) 46 | object = { 'UID' => id } 47 | perform_request(self.url(object)) 48 | end 49 | 50 | def first(params = nil) 51 | all(params).first 52 | end 53 | 54 | def save(object) 55 | new_record?(object) ? create(object) : update(object) 56 | end 57 | 58 | def destroy(object) 59 | @client.connection.delete(self.url(object), :headers => @client.headers) 60 | end 61 | 62 | def url(object = nil, params = nil) 63 | url = if self.model_route == '' 64 | API_URL 65 | else 66 | if @client && @client.current_company_file_url 67 | "#{@client.current_company_file_url}/#{self.model_route}#{"/#{object['UID']}" if object && object['UID']}" 68 | else 69 | "#{API_URL}#{@client.current_company_file[:id]}/#{self.model_route}#{"/#{object['UID']}" if object && object['UID']}" 70 | end 71 | end 72 | 73 | if params.is_a?(Hash) 74 | query = query_string(params) 75 | url += "?#{query}" if !query.nil? && query.length > 0 76 | end 77 | 78 | url 79 | end 80 | 81 | def new_record?(object) 82 | object["UID"].nil? || object["UID"] == "" 83 | end 84 | 85 | private 86 | def create(object) 87 | object = typecast(object) 88 | response = @client.connection.post(self.url, {:headers => @client.headers, :body => object.to_json}) 89 | end 90 | 91 | def update(object) 92 | object = typecast(object) 93 | response = @client.connection.put(self.url(object), {:headers => @client.headers, :body => object.to_json}) 94 | end 95 | 96 | def typecast(object) 97 | returned_object = object.dup # don't change the original object 98 | 99 | returned_object.each do |key, value| 100 | if value.respond_to?(:strftime) 101 | returned_object[key] = value.strftime(date_formatter) 102 | end 103 | end 104 | 105 | returned_object 106 | end 107 | 108 | def date_formatter 109 | "%Y-%m-%dT%H:%M:%S" 110 | end 111 | 112 | def resource_url 113 | if @client && @client.current_company_file_url 114 | "#{@client.current_company_file_url}/#{self.model_route}" 115 | else 116 | "#{API_URL}#{@client.current_company_file[:id]}/#{self.model_route}" 117 | end 118 | end 119 | 120 | def perform_request(url) 121 | model_data = parse_response(@client.connection.get(url, {:headers => @client.headers})) 122 | @next_page_link = model_data['NextPageLink'] if self.model_route != '' 123 | model_data 124 | end 125 | 126 | def query_string(params) 127 | params.map do |key, value| 128 | if QUERY_OPTIONS.include?(key) 129 | value = build_filter(value) if key == :filter 130 | key = "$#{key}" 131 | end 132 | 133 | "#{key}=#{CGI.escape(value.to_s)}" 134 | end.join('&') 135 | end 136 | 137 | def build_filter(value) 138 | return value unless value.is_a?(Hash) 139 | 140 | value.map { |key, value| "#{key} eq '#{value.to_s.gsub("'", %q(\\\'))}'" }.join(' and ') 141 | end 142 | 143 | def parse_response(response) 144 | JSON.parse(response.body) 145 | end 146 | 147 | def process_query(data, query) 148 | query.each do |property, value| 149 | data.select! {|x| x[property] == value} 150 | end 151 | data 152 | end 153 | 154 | end 155 | end 156 | end 157 | end 158 | -------------------------------------------------------------------------------- /lib/myob/api/models/company.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Company < Base 5 | end 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/myob/api/models/company_file.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class CompanyFile < Base 5 | def model_route 6 | '' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/contact.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Contact < Base 5 | end 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/myob/api/models/current_user.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class CurrentUser < Myob::Api::Model::Base 5 | def model_route 6 | 'CurrentUser' 7 | end 8 | end 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/myob/api/models/customer.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Customer < Base 5 | def model_route 6 | 'Contact/Customer' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/customer_payment.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class CustomerPayment < Base 5 | def model_route 6 | 'Sale/CustomerPayment' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/employee.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Employee < Base 5 | def model_route 6 | 'Contact/Employee' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/employee_payment_details.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class EmployeePaymentDetail < Base 5 | def model_route 6 | 'Contact/EmployeePaymentDetails' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/employee_payroll_advice.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class EmployeePayrollAdvice < Base 5 | def model_route 6 | 'Report/Payroll/EmployeePayrollAdvice' 7 | end 8 | end 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/myob/api/models/employee_payroll_details.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class EmployeePayrollDetail < Base 5 | def model_route 6 | 'Contact/EmployeePayrollDetails' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/employee_standard_pay.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class EmployeeStandardPay < Base 5 | def model_route 6 | 'Contact/EmployeeStandardPay' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/entitlement.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Entitlement < Base 5 | def model_route 6 | 'Payroll/PayrollCategory/Entitlement' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/general_ledger.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class GeneralLedger < Base 5 | def model_route 6 | 'GeneralLedger' 7 | end 8 | end 9 | 10 | class Account < Base 11 | def model_route 12 | 'GeneralLedger/Account' 13 | end 14 | end 15 | 16 | class AccountBudget < Base 17 | def model_route 18 | 'GeneralLedger/AccountBudget' 19 | end 20 | end 21 | 22 | class AccountingProperties < Base 23 | def model_route 24 | 'GeneralLedger/AccountingProperties' 25 | end 26 | end 27 | 28 | class AccountRegister < Base 29 | def model_route 30 | 'GeneralLedger/AccountRegister' 31 | end 32 | end 33 | 34 | class Category < Base 35 | def model_route 36 | 'GeneralLedger/Category' 37 | end 38 | end 39 | 40 | class CategoryRegister < Base 41 | def model_route 42 | 'GeneralLedger/CategoryRegister' 43 | end 44 | end 45 | 46 | class GeneralJournal < Base 47 | def model_route 48 | 'GeneralLedger/GeneralJournal' 49 | end 50 | end 51 | 52 | class Job < Base 53 | def model_route 54 | 'GeneralLedger/Job' 55 | end 56 | end 57 | 58 | class JobBudget < Base 59 | def model_route 60 | 'GeneralLedger/JobBudget' 61 | end 62 | end 63 | 64 | class JobRegister < Base 65 | def model_route 66 | 'GeneralLedger/JobRegister' 67 | end 68 | end 69 | 70 | class JournalTransaction < Base 71 | def model_route 72 | 'GeneralLedger/JournalTransaction' 73 | end 74 | end 75 | 76 | class LinkedAccount < Base 77 | def model_route 78 | 'GeneralLedger/LinkedAccount' 79 | end 80 | end 81 | 82 | class TaxCode < Base 83 | def model_route 84 | 'GeneralLedger/TaxCode' 85 | end 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/myob/api/models/invoice.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Invoice < Base 5 | def model_route 6 | 'Sale/Invoice' 7 | end 8 | end 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/myob/api/models/invoice_item.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class InvoiceItem < Base 5 | def model_route 6 | 'Sale/Invoice/Item' 7 | end 8 | end 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/myob/api/models/payroll_category.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class PayrollCategory < Base 5 | def model_route 6 | 'Payroll/PayrollCategory' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/superannuation_category.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class SuperannuationCategory < Base 5 | def model_route 6 | 'Payroll/PayrollCategory/Superannuation' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/superannuation_fund.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class SuperannuationFund < Base 5 | def model_route 6 | '/Payroll/SuperannuationFund' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/tax_table.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class TaxTable < Base 5 | def model_route 6 | 'Payroll/PayrollCategory/TaxTable' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/models/timesheet.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Timesheet < Base 5 | def model_route 6 | 'Payroll/Timesheet' 7 | end 8 | 9 | # http://developer.myob.com/api/accountright/v2/payroll/timesheet/ 10 | # we always want to PUT timesheets, so they are never a "new" record 11 | def new_record?(object) 12 | false 13 | end 14 | 15 | def for(user_id, start_date, end_date) 16 | self.send(:perform_request, url({'Employee' => {'UID' => user_id}, 'StartDate' => start_date, 'EndDate' => end_date})) 17 | end 18 | 19 | # a timesheet is identified based on an employee UID as well as its start and end date 20 | # it does not have a UID of its own 21 | def url(object = nil, params = nil) 22 | if object 23 | "#{super()}/#{object['Employee']['UID']}?StartDate=#{object['StartDate']}&EndDate=#{object['EndDate']}" 24 | else 25 | super 26 | end 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/myob/api/models/wage.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | module Model 4 | class Wage < Base 5 | def model_route 6 | 'Payroll/PayrollCategory/Wage' 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/myob/api/version.rb: -------------------------------------------------------------------------------- 1 | module Myob 2 | module Api 3 | VERSION = "0.10.6" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /myob-api.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'myob/api/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "myob-api" 8 | spec.version = Myob::Api::VERSION 9 | spec.authors = ["David Lumley"] 10 | spec.email = ["david@davidlumley.com.au"] 11 | spec.description = %q{MYOB AccountRight Live API V2} 12 | spec.summary = %q{MYOB AccountRight Live API V2} 13 | spec.homepage = "https://github.com/davidlumley/myob-api" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_dependency "oauth2", "> 0.8" 22 | 23 | spec.add_development_dependency "bundler", "~> 1.3" 24 | spec.add_development_dependency "rake" 25 | end 26 | --------------------------------------------------------------------------------