bling-ruby-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+