moloni 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +4 -0
- data/.rubocop.yml +76 -0
- data/.travis.yml +6 -0
- data/AGENTS.md +41 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +140 -0
- data/LICENSE.txt +21 -0
- data/MOLONI_API_DOC.md +328 -0
- data/README.md +184 -0
- data/Rakefile +8 -0
- data/bin/auth +16 -0
- data/bin/console +34 -0
- data/bin/setup +8 -0
- data/lib/moloni/auth.rb +105 -0
- data/lib/moloni/base_model.rb +174 -0
- data/lib/moloni/cli/oauth_callback_command.rb +54 -0
- data/lib/moloni/cli/oauth_callback_server.rb +24 -0
- data/lib/moloni/cli/views/variables.erb +80 -0
- data/lib/moloni/configuration.rb +46 -0
- data/lib/moloni/errors.rb +21 -0
- data/lib/moloni/models/company.rb +18 -0
- data/lib/moloni/models/country.rb +13 -0
- data/lib/moloni/models/customer.rb +47 -0
- data/lib/moloni/models/document.rb +18 -0
- data/lib/moloni/models/document_set.rb +9 -0
- data/lib/moloni/models/invoice.rb +9 -0
- data/lib/moloni/models/invoice_receipt.rb +9 -0
- data/lib/moloni/models/language.rb +25 -0
- data/lib/moloni/models/maturity_date.rb +13 -0
- data/lib/moloni/models/payment_method.rb +13 -0
- data/lib/moloni/models/printer.rb +13 -0
- data/lib/moloni/models/product.rb +20 -0
- data/lib/moloni/models/product_category.rb +9 -0
- data/lib/moloni/models/product_stock.rb +9 -0
- data/lib/moloni/models/simplified_invoice.rb +9 -0
- data/lib/moloni/models/subscription.rb +9 -0
- data/lib/moloni/models/supplier.rb +17 -0
- data/lib/moloni/models/tax.rb +33 -0
- data/lib/moloni/models/user.rb +13 -0
- data/lib/moloni/version.rb +5 -0
- data/lib/moloni.rb +55 -0
- data/moloni.gemspec +45 -0
- metadata +271 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Moloni
|
|
4
|
+
class Configuration
|
|
5
|
+
REQUIRED_ATTRIBUTES = %i[
|
|
6
|
+
developer_id
|
|
7
|
+
redirect_uri
|
|
8
|
+
client_secret
|
|
9
|
+
refresh_token
|
|
10
|
+
access_token
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
attr_accessor :developer_id, :redirect_uri, :client_secret, :refresh_token, :access_token,
|
|
14
|
+
:company_id, :access_token_expires_at, :refresh_token_expires_at
|
|
15
|
+
|
|
16
|
+
attr_writer :debug
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@developer_id = ''
|
|
20
|
+
@redirect_uri = ''
|
|
21
|
+
@client_secret = ''
|
|
22
|
+
@refresh_token = ''
|
|
23
|
+
@access_token = ''
|
|
24
|
+
@company_id = 0
|
|
25
|
+
@debug = false
|
|
26
|
+
@access_token_expires_at = nil
|
|
27
|
+
@refresh_token_expires_at = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def debug?
|
|
31
|
+
@debug
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def access_token_expired?(margin_seconds: 300)
|
|
35
|
+
return true if @access_token_expires_at.nil?
|
|
36
|
+
|
|
37
|
+
Time.now >= (@access_token_expires_at - margin_seconds)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def refresh_token_expired?
|
|
41
|
+
return true if @refresh_token_expires_at.nil?
|
|
42
|
+
|
|
43
|
+
Time.now >= @refresh_token_expires_at
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Moloni
|
|
4
|
+
class APIKeyError < StandardError
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class GenericError < StandardError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class APIError < StandardError
|
|
11
|
+
attr_reader :errors
|
|
12
|
+
|
|
13
|
+
def initialize(message, errors = [])
|
|
14
|
+
super(message)
|
|
15
|
+
@errors = errors
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class TokenExpiredError < StandardError
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Company < BaseModel
|
|
7
|
+
@intermediate_path = 'companies/'
|
|
8
|
+
|
|
9
|
+
# Backward-compatible alias (v0.4 accepted a bare id)
|
|
10
|
+
def self.find(id)
|
|
11
|
+
post('getOne/', { company_id: id })
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.check_slug(slug)
|
|
15
|
+
post('freeSlug/', { slug: })[:valid] == 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Customer < BaseModel
|
|
7
|
+
@intermediate_path = 'customers/'
|
|
8
|
+
|
|
9
|
+
def self.find_by_vat(args)
|
|
10
|
+
post('getByVat/', args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.find_by_email(args)
|
|
14
|
+
post('getByEmail/', args)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.find_by_number(args)
|
|
18
|
+
post('getByNumber/', args)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.create(args)
|
|
22
|
+
default_empty_required_params = {
|
|
23
|
+
salesman_id: '',
|
|
24
|
+
payment_day: '',
|
|
25
|
+
discount: '',
|
|
26
|
+
credit_limit: '',
|
|
27
|
+
payment_method_id: '',
|
|
28
|
+
delivery_method_id: ''
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
post('insert/', args.merge(default_empty_required_params))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.update(args)
|
|
35
|
+
default_empty_required_params = {
|
|
36
|
+
salesman_id: '',
|
|
37
|
+
payment_day: '',
|
|
38
|
+
discount: '',
|
|
39
|
+
credit_limit: '',
|
|
40
|
+
payment_method_id: '',
|
|
41
|
+
delivery_method_id: ''
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
post('update/', args.merge(default_empty_required_params))
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Document < BaseModel
|
|
7
|
+
@intermediate_path = 'documents/'
|
|
8
|
+
|
|
9
|
+
# Backward-compatible aliases (v0.4 API names)
|
|
10
|
+
def self.pdf_link(args = {})
|
|
11
|
+
post('getPDFLink/', args)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.all_types(args = {})
|
|
15
|
+
post('getAllDocumentTypes/', args)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Language < BaseModel
|
|
7
|
+
@intermediate_path = 'languages/'
|
|
8
|
+
|
|
9
|
+
def self.pt
|
|
10
|
+
find('pt')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.en
|
|
14
|
+
find('en')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.es
|
|
18
|
+
find('es')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.find(code)
|
|
22
|
+
post('getAll/').select { |el| el[:code].match?(/#{code}/i) }.first
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Product < BaseModel
|
|
7
|
+
@intermediate_path = 'products/'
|
|
8
|
+
|
|
9
|
+
# Backward-compatible alias (v0.4 API name)
|
|
10
|
+
# rubocop:disable Naming/MethodName
|
|
11
|
+
def self.searchByName(args)
|
|
12
|
+
post('getByName/', args)
|
|
13
|
+
end
|
|
14
|
+
# rubocop:enable Naming/MethodName
|
|
15
|
+
|
|
16
|
+
def self.search_by_name(args)
|
|
17
|
+
post('getByName/', args)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Supplier < BaseModel
|
|
7
|
+
@intermediate_path = 'suppliers/'
|
|
8
|
+
|
|
9
|
+
def self.find_by_vat(args)
|
|
10
|
+
post('getByVat/', args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.find_by_email(args)
|
|
14
|
+
post('getByEmail/', args)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'moloni/base_model'
|
|
4
|
+
|
|
5
|
+
module Moloni
|
|
6
|
+
class Tax < BaseModel
|
|
7
|
+
@intermediate_path = 'taxes/'
|
|
8
|
+
|
|
9
|
+
def self.iva_normal
|
|
10
|
+
post('getAll/').select { |el| el[:tax_id] == iva_normal_id }.first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.iva_intermedio
|
|
14
|
+
post('getAll/').select { |el| el[:tax_id] == iva_intermedio_id }.first
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.iva_reduzido
|
|
18
|
+
post('getAll/').select { |el| el[:tax_id] == iva_reduzido_id }.first
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.iva_normal_id
|
|
22
|
+
2_072_734
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.iva_intermedio_id
|
|
26
|
+
2_072_748
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.iva_reduzido_id
|
|
30
|
+
2_072_741
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/moloni.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
|
|
5
|
+
require 'moloni/version'
|
|
6
|
+
require 'moloni/configuration'
|
|
7
|
+
require 'moloni/errors'
|
|
8
|
+
require 'moloni/auth'
|
|
9
|
+
|
|
10
|
+
module Moloni
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
API_PROTOCOL = 'https'
|
|
14
|
+
API_HOST = 'api.moloni.pt'
|
|
15
|
+
API_VERSION = 'v1'
|
|
16
|
+
API_BASE_URL = "#{API_PROTOCOL}://#{API_HOST}/#{API_VERSION}/".freeze
|
|
17
|
+
|
|
18
|
+
def config
|
|
19
|
+
@config ||= Configuration.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def configure
|
|
23
|
+
yield(config)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def connection
|
|
27
|
+
Faraday.new(url: API_BASE_URL) do |conn|
|
|
28
|
+
conn.request :json
|
|
29
|
+
conn.response :logger if config.debug?
|
|
30
|
+
conn.response :json, parser_options: { symbolize_names: true }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Load models
|
|
36
|
+
require 'moloni/base_model'
|
|
37
|
+
require 'moloni/models/company'
|
|
38
|
+
require 'moloni/models/country'
|
|
39
|
+
require 'moloni/models/customer'
|
|
40
|
+
require 'moloni/models/document'
|
|
41
|
+
require 'moloni/models/document_set'
|
|
42
|
+
require 'moloni/models/invoice'
|
|
43
|
+
require 'moloni/models/invoice_receipt'
|
|
44
|
+
require 'moloni/models/language'
|
|
45
|
+
require 'moloni/models/maturity_date'
|
|
46
|
+
require 'moloni/models/payment_method'
|
|
47
|
+
require 'moloni/models/printer'
|
|
48
|
+
require 'moloni/models/product'
|
|
49
|
+
require 'moloni/models/product_category'
|
|
50
|
+
require 'moloni/models/product_stock'
|
|
51
|
+
require 'moloni/models/simplified_invoice'
|
|
52
|
+
require 'moloni/models/subscription'
|
|
53
|
+
require 'moloni/models/supplier'
|
|
54
|
+
require 'moloni/models/tax'
|
|
55
|
+
require 'moloni/models/user'
|
data/moloni.gemspec
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/moloni/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'moloni'
|
|
7
|
+
spec.version = Moloni::VERSION
|
|
8
|
+
spec.authors = ['Tiago Pinto']
|
|
9
|
+
spec.email = ['tp@tiagopinto.pt']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'A RubyGem to consume the Moloni API.'
|
|
12
|
+
spec.description = spec.summary
|
|
13
|
+
# spec.homepage = 'TODO: Put your gem's website or public repo URL here.'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.2.0')
|
|
16
|
+
|
|
17
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
|
18
|
+
# spec.metadata["homepage_uri"] = spec.homepage
|
|
19
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
|
20
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
|
21
|
+
|
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
end
|
|
27
|
+
spec.bindir = 'bin'
|
|
28
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
29
|
+
spec.require_paths = ['lib']
|
|
30
|
+
|
|
31
|
+
spec.add_dependency 'addressable', '~> 2.9'
|
|
32
|
+
spec.add_dependency 'faraday', '~> 2.14'
|
|
33
|
+
spec.add_dependency 'launchy', '~> 3.1'
|
|
34
|
+
spec.add_dependency 'sinatra', '~> 4.2'
|
|
35
|
+
|
|
36
|
+
spec.add_development_dependency 'bundler', '~> 2.4'
|
|
37
|
+
spec.add_development_dependency 'dotenv', '~> 2.8'
|
|
38
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.10'
|
|
39
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
40
|
+
spec.add_development_dependency 'rspec', '~> 3.13'
|
|
41
|
+
spec.add_development_dependency 'rubocop', '~> 1.59'
|
|
42
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.26'
|
|
43
|
+
spec.add_development_dependency 'simplecov', '~> 0.22'
|
|
44
|
+
spec.add_development_dependency 'webmock', '~> 3.26'
|
|
45
|
+
end
|