bling-ruby-api 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6eb9b91e71c99be3d5190eabfd2f7e095eca9922
4
+ data.tar.gz: 434969bce4d2ceeb8836901ff30f7594c3d52d8a
5
+ SHA512:
6
+ metadata.gz: dcca2d34ba06f39f3700f6f5bc7eba751e54f9085b6501073125ba41a54582227ae22faa6b4581574a41b27f20e8d469c8e20739c6cafc12656668be6a1f1067
7
+ data.tar.gz: da163e6cd8f2fcddf8e63b9ceea721075b9db59bd4de4fa071dbe6b7caf547e906b2454d2e3406c32aa4548de373f387a8876d747b91d02fd68e09264a0cc5eb
data/.gitignore ADDED
@@ -0,0 +1,30 @@
1
+ .DS_Store
2
+
3
+ ## TEXTMATE
4
+ *.tmproj
5
+ tmtags
6
+
7
+ ## EMACS
8
+ *~
9
+ \#*
10
+ .\#*
11
+
12
+ ## VIM
13
+ *.swp
14
+
15
+ ## Rubinius
16
+ *.rbc
17
+ .rbx
18
+
19
+ ## PROJECT::GENERAL
20
+ *.gem
21
+ coverage
22
+ profiling
23
+ turbulence
24
+ rdoc
25
+ pkg
26
+ tmp
27
+ doc
28
+ log
29
+ .yardoc
30
+ measurements
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bling (0.0.1)
5
+ rake
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ codeclimate-test-reporter (0.4.8)
11
+ simplecov (>= 0.7.1, < 1.0.0)
12
+ diff-lcs (1.2.5)
13
+ docile (1.1.5)
14
+ json (1.8.3)
15
+ rake (11.1.2)
16
+ rspec (3.4.0)
17
+ rspec-core (~> 3.4.0)
18
+ rspec-expectations (~> 3.4.0)
19
+ rspec-mocks (~> 3.4.0)
20
+ rspec-core (3.4.4)
21
+ rspec-support (~> 3.4.0)
22
+ rspec-expectations (3.4.0)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.4.0)
25
+ rspec-mocks (3.4.1)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.4.0)
28
+ rspec-support (3.4.1)
29
+ simplecov (0.10.0)
30
+ docile (~> 1.1.0)
31
+ json (~> 1.8)
32
+ simplecov-html (~> 0.10.0)
33
+ simplecov-html (0.10.0)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bling!
40
+ codeclimate-test-reporter
41
+ rspec
42
+
43
+ BUNDLED WITH
44
+ 1.12.5
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2016
2
+ Denis Tierno
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Ruby Bling API
2
+
3
+ Essa gem consiste em uma interface ruby para comunicação com a API do [Bling ERP](https://www.bling.com.br).
4
+
5
+ [![Code Climate](https://codeclimate.com/github/locomotivapro/bling/badges/gpa.svg)](https://codeclimate.com/github/locomotivapro/bling)
6
+ [![Test Coverage](https://codeclimate.com/github/locomotivapro/bling/badges/coverage.svg)](https://codeclimate.com/github/locomotivapro/bling/coverage)
7
+
8
+ ## Configuração
9
+
10
+ Instale a versão mais recente
11
+
12
+ ```
13
+ $ gem install bling
14
+ ```
15
+
16
+ Configure sua chave de integração:
17
+
18
+ ```ruby
19
+ Bling::Config.api_key = '55fxs324dsk3....'
20
+ ```
21
+
22
+ Por padrão a gem é configurada para aceitar os parâmetros em inglês,
23
+ caso deseje é possível configurar a gem para aceitar em português:
24
+
25
+ ```ruby
26
+ Bling::Config.default_language= :pt # :en default
27
+ ```
28
+
29
+ ## Uso
30
+
31
+ A chamada para os possíveis endpoints da API do Bling são todas feitas
32
+ utilizando a class Bling::API ex:
33
+
34
+ ```ruby
35
+ users = Bling::API.users.list
36
+ ```
37
+
38
+ *Cliente*
39
+
40
+ Listagem de todos clientes inseridos no Bling:
41
+
42
+ ```ruby
43
+ user_client = Bling::API.users
44
+ users = user_client.list
45
+ ```
46
+
47
+ Inserir um cliente no Bling:
48
+
49
+ ```ruby
50
+ user = Bling::API.user.create(
51
+ {
52
+ name: 'Jonh Doe',
53
+ company_name: '',
54
+ tax_type: 1,
55
+ document: '35165478662',
56
+ ir_rg: '306153420',
57
+ address: 'My great street',
58
+ number: '33',
59
+ additional_address: 'apt 12',
60
+ zipcode: '03454020',
61
+ city: 'Sao Paulo',
62
+ uf: 'SP',
63
+ phone: '(11) 2233-3322',
64
+ email: jonh@@doe.com'
65
+ }
66
+ )
67
+
68
+ ```
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+
5
+ RSpec::Core::RakeTask.new(:spec) do |task|
6
+ task.pattern = "./spec/**/*_spec.rb"
7
+ task.rspec_opts = ['--color']
8
+ end
9
+
10
+ task :default => %w{spec}
data/bling.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'bling/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.platform = Gem::Platform::RUBY
9
+ s.name = 'bling-ruby-api'
10
+ s.version = Bling::VERSION
11
+ s.summary = 'Gem to access Bling API in ruby'
12
+ s.description = 'Gem to access Bling API in ruby'
13
+ s.required_ruby_version = '>= 2.1'
14
+
15
+ s.author = 'Denis Tierno'
16
+ s.email = 'contato@locomotiva.pro'
17
+ s.homepage = 'http://locomotiva.pro'
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = s.files.grep(%r{^(spec|features)/})
21
+ s.require_path = 'lib'
22
+ s.requirements << 'none'
23
+
24
+ s.add_dependency 'rake'
25
+
26
+ s.add_development_dependency 'rspec'
27
+ end
data/lib/bling.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'bling/base'
2
+ require 'bling/version'
3
+
4
+ require 'bling/api'
5
+ require 'bling/api/client'
6
+ require 'bling/api/translator'
7
+ require 'bling/api/parser'
8
+ require 'bling/api/request'
9
+ require 'bling/api/response'
10
+ require 'bling/api/record'
11
+ require 'bling/api/product'
12
+ require 'bling/api/user'
13
+ require 'bling/api/order'
14
+
15
+
16
+ require 'bling/railtie' if defined?(::Rails) && ::Rails::VERSION::MAJOR >= 3
data/lib/bling/api.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Bling
2
+ module API
3
+ # This module encapsulates all API groups
4
+ # and creates an instance for it. You can make a direct
5
+ # call like Bling::API::Product.new.list but it`s best and
6
+ # less verbose to use this module ex: Bling::API.product.list
7
+ #
8
+ # To see all methods available to each instance, please look
9
+ # in each respectively class
10
+
11
+ extend self
12
+
13
+ def product
14
+ Product.new
15
+ end
16
+
17
+ def user
18
+ User.new
19
+ end
20
+
21
+ def order
22
+ Order.new
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ require 'net/http'
2
+
3
+ module Bling
4
+ module API
5
+ class Client
6
+
7
+ # @param [String, Hash, Symbol] The constructor to build an HTTP request
8
+ # and a response_class used to parse the response
9
+ def initialize(url, params={}, response_class)
10
+ @uri = build_uri(url)
11
+ @params = params
12
+ @response_class = response_class
13
+ end
14
+
15
+ # @return [Response] The accessor to a get request.
16
+ def get
17
+ uri.query = URI.encode_www_form(get_params(params))
18
+ request = Net::HTTP.get_response(uri)
19
+ Response.new(request, response_class)
20
+ end
21
+
22
+ # @return [Response] The accessor to a post request.
23
+ def post
24
+ Response.new(post_request, response_class)
25
+ end
26
+
27
+ # @return [Response] The accessor to a post request.
28
+ def delete
29
+ Response.new(delete_request, response_class)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :uri, :params, :response_class
35
+
36
+ def delete_request
37
+ http = Net::HTTP.new(uri.host, uri.port)
38
+ http.use_ssl = (uri.scheme == 'https')
39
+ request = Net::HTTP::Delete.new(uri.path)
40
+ request.set_form_data({ apikey: api_key })
41
+ http.request(request)
42
+ end
43
+
44
+ def post_request
45
+ post_params = {
46
+ apikey: api_key,
47
+ xml: params
48
+ }
49
+ Net::HTTP.post_form(uri, post_params)
50
+ end
51
+
52
+ def get_params(params)
53
+ { apikey: api_key }.merge!(params)
54
+ end
55
+
56
+ def api_key
57
+ Bling.config.api_key
58
+ end
59
+
60
+ def build_uri(url)
61
+ format_type = Bling.config.response_format.to_s
62
+ URI(Bling.config.api_url + url + '/' + format_type)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,71 @@
1
+ produtos: products
2
+ produto: product
3
+ contato: user
4
+ contatos: users
5
+ pedido: order
6
+ pedidos: orders
7
+
8
+ resultado: result
9
+ retorno: return
10
+ erros: errors
11
+
12
+ codigo: code
13
+ descricao: description
14
+ descricao_complementar: additional_description
15
+ un: unit
16
+ vlr_unit: price
17
+ preco_custo: cost_price
18
+ peso_bruto: raw_weight
19
+ peso_liq: weight
20
+ class_fiscal: tax_category
21
+ origem: origin
22
+ estoque: quantity
23
+ gtin: gtin
24
+ gtin_embalagem: gtin_package
25
+ largura: width
26
+ altura: height
27
+ profundidade: depth
28
+ estoque_minimo: min_quantity
29
+ estoque_maximo: max_quantity
30
+
31
+ nome: name
32
+ fantasia: company_name
33
+ tipo_pessoa: tax_type
34
+ cpf_cnpj: document
35
+ ie_rg: ie_rg
36
+ endereco: address
37
+ numero: number
38
+ complemento: additional_address
39
+ bairro: neighborhood
40
+ cep: zipcode
41
+ cidade: city
42
+ uf: state
43
+ fone: phone
44
+ email: email
45
+
46
+ celular: cellphone
47
+ transportadora: carrier
48
+ tipo_frete: :shipment_type
49
+ servico_correios: correios_service
50
+
51
+ numero_loja: ecommerce_order_number
52
+ loja: store
53
+ nat_operacao: selling_category
54
+ contribuinte: tax_classification
55
+ situacao: status
56
+
57
+ nome_etiqueta_envio: shipment_label_name
58
+ endereco_etiqueta_envio: shipment_label_address
59
+ numero_etiqueta_envio: shipment_label_number
60
+ complemento_etiqueta_envio: shipment_label_additional_address
61
+ municipio_etiqueta_envio: shipment_label_city
62
+ estado_etiqueta_envio: shipment_label_state
63
+ cep_etiqueta_envio: shipment_label_zipcode
64
+ bairro_etiqueta_envio: shipment_label_neighborhood
65
+ qtde: item_quantity
66
+ data: date
67
+ vlr: amount
68
+ obs: additional_info
69
+ vlr_frete: shipment_amount
70
+ vlr_desconto: discount_amount
71
+ obs_internas: private_additional_info
@@ -0,0 +1,224 @@
1
+ module Bling
2
+ module API
3
+ # This class is used to make requests to all available
4
+ # actions related to orders in Bling api. Is strongly recommended
5
+ # to use the Bling::API module wrapper
6
+ #
7
+ class Order < Request
8
+ # Get a list of available orders
9
+ #
10
+ # @example
11
+ # orders = Bling::API::Order.new.list
12
+ #
13
+ # @return [Array] Call orders index and return an array with records
14
+ #
15
+ def list
16
+ get_request(t_url(:orders))
17
+ end
18
+
19
+ # Get a specific object based on order_id
20
+ #
21
+ # @example
22
+ # order = Bling::API::order.new.get
23
+ #
24
+ # @param [String] cpf or cnpj from the order in Bling
25
+ #
26
+ # @return [Array] Call order#show and return an array with one record
27
+ #
28
+ def get(order_id)
29
+ get_request(t_url(:order, order_id))
30
+ end
31
+
32
+ # Insert a order in Bling
33
+ #
34
+ # @example
35
+ # order = Bling::API::Order.new.create(
36
+ # {
37
+ # order_number: '123',
38
+ # ecommerce_order_number: 'R123',
39
+ # store: 'Foo',
40
+ # selling_category: '',
41
+ # user: {
42
+ # name: 'Jonh Doe',
43
+ # company_name: '',
44
+ # tax_type: 1,
45
+ # document: '35165478662',
46
+ # ir_rg: '306153420',
47
+ # tax_classification: 1,
48
+ # address: 'My great street',
49
+ # number: '33',
50
+ # additional_address: 'apt 12',
51
+ # zipcode: '03454020',
52
+ # city: 'Sao Paulo',
53
+ # uf: 'SP',
54
+ # phone: '(11) 2233-3322',
55
+ # cellphone: '(11) 2233-3322',
56
+ # email: jonh@@doe.com'
57
+ # },
58
+ # shipment: {
59
+ # carrier: 'Correios',
60
+ # shipment_type: 'R'
61
+ # shipment_label: {}
62
+ # },
63
+ # items: [
64
+ # { code: '001', description: 'lorem', unit: 'pc', item_quantity: 3, price: 12.30 },
65
+ # { code: '002', description: 'lorem', unit: 'pc', item_quantity: 4, price: 32.30 },
66
+ # ],
67
+ # installments: [
68
+ # { date: '28/06/2016', amount: 140.00, additional_info: '' },
69
+ # { date: '28/07/2016', amount: 140.00, additional_info: '' },
70
+ # ],
71
+ # shipment_amount: 10.0,
72
+ # discount_amount: 0.0,
73
+ # additional_info: '',
74
+ # private_additional_info: ''
75
+ # }
76
+ # )
77
+ #
78
+ # @param [Hash] params A hash with order options
79
+ #
80
+ # @return [Array] Call order#create and return an array with one record
81
+ #
82
+ def create(params)
83
+ post_request(t_url(:order), parsed_xml(params))
84
+ end
85
+
86
+ # Put an order status update based on order_id
87
+ #
88
+ # Available statuses
89
+ #
90
+ # - 0 (Em Aberto)
91
+ # - 1 (Atendido)
92
+ # - 2 (Cancelado)
93
+ # - 3 (Em Andamento)
94
+ # - 4 (Venda Agenciada)
95
+ # - 10 (Em Digitação)
96
+ # - 11 (Verificado)
97
+ #
98
+ # @example
99
+ # order = Bling::API::order.new.update(order_id, status)
100
+ #
101
+ # @param [String] cpf or cnpj from the order in Bling
102
+ # @param [Integer] status number for order in Bling
103
+ #
104
+ # @return [Array] Call order#show and return an array with one record
105
+ #
106
+ def put(order_id, status)
107
+ raise ArgumentError unless [0, 1, 2, 3, 4, 10, 11].include?(status.to_i)
108
+ xml = order_update_template % { status: status.to_i }
109
+ put_request(t_url(:order, order_id), xml)
110
+ end
111
+
112
+ private
113
+
114
+
115
+ def parsed_xml(params)
116
+ @params = params
117
+ @params = translate(@params) unless Bling.config.default_language == :en
118
+
119
+ validate(@params, :name)
120
+
121
+ validate_object(:items, Array)
122
+ @params[:items].each do |item|
123
+ validate(item, :description, :code, :item_quantity, :price)
124
+ end
125
+
126
+ @params[:installments].each do |installment|
127
+ validate(installment, :amount)
128
+ end if @params[:installments]
129
+
130
+ items = @params.delete :items
131
+ installments = @params.delete :installments
132
+
133
+ @params[:items] = parse_items(items)
134
+ @params[:installments] = parse_installments(installments)
135
+
136
+ build_missing_params
137
+ order_template % @params
138
+ end
139
+
140
+ def validate_object(key, klass)
141
+ raise ArgumentError unless @params.has_key?(key) & @params[key].is_a?(klass)
142
+ end
143
+
144
+ def parse_items(items)
145
+ build_item_missing_nodes(items)
146
+ .each_with_object('') { |item, string| string.concat(order_item_template % item) }
147
+ end
148
+
149
+ def parse_installments(installments)
150
+ build_installment_missing_nodes(installments)
151
+ .each_with_object('') { |installment, string| string.concat(order_installment_template % installment) }
152
+ end
153
+
154
+ def build_missing_params
155
+ xml_nodes.each { |node| @params[node] = nil unless @params.has_key?(node) }
156
+ end
157
+
158
+ def build_installment_missing_nodes(installments)
159
+ build_missing_nodes(:installments_xml_nodes, installments)
160
+ end
161
+
162
+ def build_item_missing_nodes(items)
163
+ build_missing_nodes(:item_xml_nodes, items)
164
+ end
165
+
166
+ def build_missing_nodes(node_array, records)
167
+ records.each do |record|
168
+ send(node_array).each { |node| record[node] = nil unless record.has_key?(node) }
169
+ end
170
+ records
171
+ end
172
+
173
+ def installments_xml_nodes
174
+ [:date, :amount, :additional_info]
175
+ end
176
+
177
+ def item_xml_nodes
178
+ [ :code, :description, :unit, :item_quantity, :price ]
179
+ end
180
+
181
+ def xml_nodes
182
+ [
183
+ :date,
184
+ :order_number,
185
+ :ecommerce_order_number,
186
+ :store,
187
+ :selling_category,
188
+ :name,
189
+ :tax_type,
190
+ :address,
191
+ :document,
192
+ :ie_rg,
193
+ :tax_classification,
194
+ :number,
195
+ :additional_address,
196
+ :neighborhood,
197
+ :zipcode,
198
+ :city,
199
+ :state,
200
+ :phone,
201
+ :cellphone,
202
+ :email,
203
+ :carrier,
204
+ :shipment_type,
205
+ :correios_service,
206
+ :shipment_label_name,
207
+ :shipment_label_address,
208
+ :shipment_label_number,
209
+ :shipment_label_additional_address,
210
+ :shipment_label_city,
211
+ :shipment_label_state,
212
+ :shipment_label_zipcode,
213
+ :shipment_label_neighborhood,
214
+ :shipment_amount,
215
+ :discount_amount,
216
+ :additional_info,
217
+ :private_additional_info
218
+ ]
219
+ end
220
+
221
+ end
222
+ end
223
+ end
224
+