orangedata 0.0.4 → 0.0.5
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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +37 -2
- data/lib/orange_data/credentials.rb +12 -10
- data/lib/orange_data/generated_attributes.rb +127 -0
- data/lib/orange_data/receipt.rb +15 -138
- data/lib/orange_data/schema_definitions.yml +8 -1
- data/lib/orange_data/transport.rb +2 -2
- data/lib/orange_data/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f4b1c0d05572781e1ae1550991a896a7d81b9f2
|
4
|
+
data.tar.gz: c3773260bb588960809e57153343ff187bdd90f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fa8f50e4f9326ffca33ef0a5841cacbe2cc32a2573a6f380c47159aa9c8c21a9246a970cbc85dbad0ae6d9a0eb858eef1bb4eadfc2d6c55e551a90a7f41d40b
|
7
|
+
data.tar.gz: 8527fb6abb8a3a7bb0c9eb2aecbc40b239141b0517738091a01ab7d87e193abbd486b8eb2587f9cf52832ed43cd0afeb5530236a377b2d1fcc76b57e3b95922a
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
orangedata (0.0.
|
4
|
+
orangedata (0.0.5)
|
5
5
|
faraday (>= 0.15)
|
6
6
|
faraday_middleware
|
7
7
|
|
@@ -15,7 +15,7 @@ GEM
|
|
15
15
|
safe_yaml (~> 1.0.0)
|
16
16
|
diff-lcs (1.3)
|
17
17
|
docile (1.3.1)
|
18
|
-
faraday (0.15.
|
18
|
+
faraday (0.15.3)
|
19
19
|
multipart-post (>= 1.2, < 3)
|
20
20
|
faraday_middleware (0.12.2)
|
21
21
|
faraday (>= 0.7.4, < 1.0)
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Orangedata Client
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/orangedata)
|
4
|
+

|
4
5
|
[](https://travis-ci.org/Vasfed/orangedata)
|
5
6
|
|
6
7
|
A ruby client for orangedata.ru service.
|
@@ -11,7 +12,7 @@ Note: This is a Work-in-progress. API might change in the future.
|
|
11
12
|
Умеет:
|
12
13
|
- собственно транспорт с подписью запросов
|
13
14
|
- сгенерировать ключ сразу в нужном виде
|
14
|
-
-
|
15
|
+
- маппинг для данных генерируется на базе приведенного в человеческий вид официального json-schema-описания
|
15
16
|
|
16
17
|
## Установка
|
17
18
|
|
@@ -31,7 +32,10 @@ gem 'orangedata'
|
|
31
32
|
|
32
33
|
## Использование
|
33
34
|
|
34
|
-
Для тестового окружения ключики в комплекте - [credentials_test.yml](lib/orange_data/credentials_test.yml), собрано из родного `File_for_test.zip`, доступны как `OrangeData::Credentials.default_test
|
35
|
+
Для тестового окружения ключики в комплекте - [credentials_test.yml](lib/orange_data/credentials_test.yml), собрано из родного `File_for_test.zip`, доступны как `OrangeData::Credentials.default_test`.
|
36
|
+
Получение ключей для продакшна описано ниже.
|
37
|
+
|
38
|
+
### Пробитие чека
|
35
39
|
|
36
40
|
```ruby
|
37
41
|
transport = OrangeData::Transport.new("https://apip.orangedata.ru:2443/api/v2/", OrangeData::Credentials.default_test)
|
@@ -77,6 +81,37 @@ gem 'orangedata'
|
|
77
81
|
# => "t=20181026T2021&s=50.0&fn=9999078900001341&i=3243&fp=301645583&n=1"
|
78
82
|
```
|
79
83
|
|
84
|
+
### Чек коррекции
|
85
|
+
Пока не понятно, почему в API не все значения поля tax соответствуют цифрам в `taxNSum`, поэтому коррекцию, видимо, лучше бить через саппорт или подобным образом.
|
86
|
+
|
87
|
+
Но поддержка в маппинге есть:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
transport = OrangeData::Transport.new("https://apip.orangedata.ru:2443/api/v2/", OrangeData::Credentials.default_test)
|
91
|
+
correction = OrangeData::Correction.income(inn:"123456789012", id:"12345678990"){|c|
|
92
|
+
c.correction_type = :prescribed
|
93
|
+
c.assign_attributes(
|
94
|
+
description: "НЕ ХОЧЕТСЯ НО НАДО",
|
95
|
+
cause_document_date: "2017-08-10T00:00:00", cause_document_number: "ФЗ-54",
|
96
|
+
total_sum: 17.25,
|
97
|
+
sum_cash: 1.23, sum_card: 2.34,
|
98
|
+
sum_prepaid: 5.67, sum_credit: 4.56, sum_counterclaim: 3.45,
|
99
|
+
|
100
|
+
vat_18: 1.34, vat_10: 2.34, vat_0: 3.34,
|
101
|
+
vat_not_charged: 4.34, vat_18_118: 5.34, vat_10_110: 6.34,
|
102
|
+
taxation_system: :simplified,
|
103
|
+
|
104
|
+
automat_number: "123456789",
|
105
|
+
settlement_address: "г.Москва, Красная площадь, д.1",
|
106
|
+
settlement_place: "Палата No6",
|
107
|
+
)
|
108
|
+
}
|
109
|
+
transport.post_correction(correction)
|
110
|
+
# wait some time
|
111
|
+
res = transport.get_correction(correction.inn, correction.id)
|
112
|
+
```
|
113
|
+
|
114
|
+
|
80
115
|
### Получаем сертификаты
|
81
116
|
|
82
117
|
Предполагается, что всякие договоры и прочая фискализация уже успешно пройдена и у вас есть доступ
|
@@ -97,10 +97,10 @@ module OrangeData
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def ==(other)
|
100
|
-
return false unless %i[signature_key_name title].all?{|m|
|
100
|
+
return false unless %i[signature_key_name title].all?{|m| send(m) == other.send(m) }
|
101
101
|
# certificates/keys cannot be compared directly, so dump
|
102
102
|
%i[signature_key certificate certificate_key].all?{|m|
|
103
|
-
c1 =
|
103
|
+
c1 = send(m)
|
104
104
|
c2 = other.send(m)
|
105
105
|
c1 == c2 || (c1 && c2 && c1.to_der == c2.to_der)
|
106
106
|
}
|
@@ -112,7 +112,7 @@ module OrangeData
|
|
112
112
|
signature_key_name: creds[:signature_key_name],
|
113
113
|
signature_key: OpenSSL::PKey::RSA.load_from(creds[:signature_key], creds[:signature_key_pass]),
|
114
114
|
certificate: creds[:certificate] && OpenSSL::X509::Certificate.new(creds[:certificate]),
|
115
|
-
certificate_key: OpenSSL::PKey::RSA.load_from(creds[:certificate_key], creds[:certificate_key_pass])
|
115
|
+
certificate_key: OpenSSL::PKey::RSA.load_from(creds[:certificate_key], creds[:certificate_key_pass])
|
116
116
|
)
|
117
117
|
end
|
118
118
|
|
@@ -127,9 +127,11 @@ module OrangeData
|
|
127
127
|
{
|
128
128
|
title: title,
|
129
129
|
signature_key_name: signature_key_name,
|
130
|
-
signature_key: signature_key &&
|
130
|
+
signature_key: signature_key &&
|
131
|
+
signature_key.to_pem(key_pass && OpenSSL::Cipher.new("aes-128-cbc"), key_pass),
|
131
132
|
certificate: certificate && certificate.to_pem,
|
132
|
-
certificate_key: certificate_key &&
|
133
|
+
certificate_key: certificate_key &&
|
134
|
+
certificate_key.to_pem(key_pass && OpenSSL::Cipher.new("aes-128-cbc"), key_pass),
|
133
135
|
}.tap do |h|
|
134
136
|
h.delete(:title) if !title || title == ''
|
135
137
|
if save_pass
|
@@ -159,7 +161,7 @@ module OrangeData
|
|
159
161
|
}
|
160
162
|
|
161
163
|
if certificate && (subject_name = certificate.subject.to_a.select{|ent| ent.first == 'O' }.first)
|
162
|
-
info_fields[:certificate] = %
|
164
|
+
info_fields[:certificate] = %("#{(subject_name[1] || 'unknown').gsub('"', '\"')}")
|
163
165
|
end
|
164
166
|
|
165
167
|
"#<#{self.class.name}:#{object_id} #{info_fields.map{|(k, v)| "#{k}=#{v}" }.join(' ')}>"
|
@@ -167,7 +169,7 @@ module OrangeData
|
|
167
169
|
|
168
170
|
DEFAULT_KEY_LENGTH = 2048
|
169
171
|
|
170
|
-
#deprecated
|
172
|
+
# deprecated
|
171
173
|
def generate_signature_key!(key_length=DEFAULT_KEY_LENGTH)
|
172
174
|
self.signature_key = self.class.generate_signature_key(key_length)
|
173
175
|
end
|
@@ -179,13 +181,13 @@ module OrangeData
|
|
179
181
|
|
180
182
|
def self.read_certs_from_pack(path, signature_key_name:nil, cert_key_pass:nil, title:nil, signature_key:nil)
|
181
183
|
path = File.expand_path(path)
|
182
|
-
client_cert = Dir.glob(path + '/*.{crt}').select{|f| File.file?(f.sub(/.crt\z/, '.key'))}
|
184
|
+
client_cert = Dir.glob(path + '/*.{crt}').select{|f| File.file?(f.sub(/.crt\z/, '.key')) }
|
183
185
|
raise 'Expect to find exactly one <num>.crt with corresponding <num>.key file' unless client_cert.size == 1
|
184
186
|
client_cert = client_cert.first
|
185
187
|
|
186
188
|
unless signature_key
|
187
189
|
# private_key_test.xml || rsa_\d+_private_key.xml
|
188
|
-
xmls = Dir.glob(path + '/*.{xml}').select{|f| f =~ /private/}
|
190
|
+
xmls = Dir.glob(path + '/*.{xml}').select{|f| f =~ /private/ }
|
189
191
|
signature_key = if xmls.size == 1
|
190
192
|
File.read(xmls.first)
|
191
193
|
else
|
@@ -200,7 +202,7 @@ module OrangeData
|
|
200
202
|
certificate: File.read(client_cert),
|
201
203
|
certificate_key: File.read(client_cert.sub(/.crt\z/, '.key')),
|
202
204
|
certificate_key_pass: cert_key_pass,
|
203
|
-
signature_key: signature_key
|
205
|
+
signature_key: signature_key
|
204
206
|
)
|
205
207
|
end
|
206
208
|
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module OrangeData
|
7
|
+
|
8
|
+
unless "".respond_to?(:underscore)
|
9
|
+
# taken from ActiveSupport
|
10
|
+
module StringExt
|
11
|
+
refine String do
|
12
|
+
def underscore
|
13
|
+
self.gsub(/::/, '/').
|
14
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
15
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
16
|
+
tr("-", "_").
|
17
|
+
downcase
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
using StringExt
|
22
|
+
end
|
23
|
+
|
24
|
+
module GeneratedAttributes
|
25
|
+
def self.from_schema(klass, schema)
|
26
|
+
klass.class_eval{
|
27
|
+
extend GeneratedAttributes
|
28
|
+
generate_accessors_from_schema(schema)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
def generate_accessors_from_schema(schema)
|
34
|
+
plain_types = %w[integer string number]
|
35
|
+
schema["properties"].each_pair do |property, info|
|
36
|
+
property_name = info["x-name"] || property.underscore
|
37
|
+
|
38
|
+
if plain_types.include?(info["type"])
|
39
|
+
if info["x-enum"]
|
40
|
+
inverse_map = info["x-enum"].map{|k, v| [v['val'], k.to_sym] }.to_h
|
41
|
+
define_method(property_name){
|
42
|
+
return nil if @payload[property].nil?
|
43
|
+
inverse_map[@payload[property]] ||
|
44
|
+
raise("unknown value #{@payload[property].inspect} for field #{property}")
|
45
|
+
}
|
46
|
+
define_method(:"#{property_name}="){|val|
|
47
|
+
unless val.nil?
|
48
|
+
val = (info["x-enum"][val.to_s] ||
|
49
|
+
raise(ArgumentError, "unknown value #{val.inspect} for property #{property}")
|
50
|
+
)["val"]
|
51
|
+
end
|
52
|
+
@payload[property] = val
|
53
|
+
}
|
54
|
+
|
55
|
+
elsif info["x-bitfield"]
|
56
|
+
bitmap = info["x-bitfield"].map{|k, v| [k.to_sym, 1 << v['bit']] }.to_h
|
57
|
+
# TODO: return wrapper so that :<< etc will work
|
58
|
+
define_method(property_name){
|
59
|
+
return nil if @payload[property].nil?
|
60
|
+
data = @payload[property].to_i
|
61
|
+
# FIXME: unknown bits will be silently lost
|
62
|
+
bitmap.reject{|_, v| (data & v).zero? }.map(&:first)
|
63
|
+
}
|
64
|
+
define_method(:"#{property_name}="){|val|
|
65
|
+
unless val.nil?
|
66
|
+
val = [val] unless val.is_a?(Array)
|
67
|
+
val = val.map{|v| bitmap[v] || raise(ArgumentError, "unknown value #{v.inspect} for property #{property}") }.reduce(:|)
|
68
|
+
end
|
69
|
+
@payload[property] = val
|
70
|
+
}
|
71
|
+
else
|
72
|
+
# primitive
|
73
|
+
define_method(property_name){ @payload[property] }
|
74
|
+
define_method(:"#{property_name}="){|val| @payload[property] = val }
|
75
|
+
end
|
76
|
+
elsif info["type"] == 'array'
|
77
|
+
if info["items"] && plain_types.include?(info["items"]["type"])
|
78
|
+
define_method(property_name){ @payload[property] }
|
79
|
+
define_method(:"#{property_name}="){|val|
|
80
|
+
val = [val] unless val.is_a?(Array)
|
81
|
+
@payload[property] = val
|
82
|
+
}
|
83
|
+
else
|
84
|
+
# ref?
|
85
|
+
end
|
86
|
+
else
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
if info["x-alias"]
|
91
|
+
alias_method "#{info['x-alias']}", property_name
|
92
|
+
alias_method "#{info['x-alias']}=", "#{property_name}="
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# base class for semi-generated classes
|
99
|
+
class PayloadContent
|
100
|
+
def initialize(payload={})
|
101
|
+
@payload = payload
|
102
|
+
end
|
103
|
+
|
104
|
+
def assign_attributes(options)
|
105
|
+
options.each_pair{|k, v|
|
106
|
+
setter = :"#{k}="
|
107
|
+
send(setter, v)
|
108
|
+
}
|
109
|
+
# for chaining:
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def ==(other)
|
114
|
+
self.class == other.class && to_hash == other.to_hash
|
115
|
+
# @payload == other.instance_variable_get(:@payload)
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_hash
|
119
|
+
@payload
|
120
|
+
end
|
121
|
+
|
122
|
+
def to_json(*args)
|
123
|
+
to_hash.to_json(*args)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
data/lib/orange_data/receipt.rb
CHANGED
@@ -2,25 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'json'
|
5
|
+
require_relative "generated_attributes"
|
5
6
|
|
6
7
|
module OrangeData
|
7
8
|
|
8
9
|
PAYLOAD_SCHEMA = YAML.load_file(File.expand_path('schema_definitions.yml', __dir__)).freeze
|
9
10
|
|
10
|
-
# taken from ActiveSupport
|
11
|
-
module StringExt
|
12
|
-
refine String do
|
13
|
-
def underscore
|
14
|
-
self.gsub(/::/, '/').
|
15
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
16
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
17
|
-
tr("-", "_").
|
18
|
-
downcase
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
using StringExt unless "".respond_to?(:underscore)
|
23
|
-
|
24
11
|
# main class for receipt/correction
|
25
12
|
class Document
|
26
13
|
|
@@ -51,7 +38,7 @@ module OrangeData
|
|
51
38
|
@content = ReceiptContent.new(content || {})
|
52
39
|
super
|
53
40
|
end
|
54
|
-
PAYLOAD_SCHEMA["definitions"]["CheckContent"]["properties"]["type"]["x-enum"].each_pair do |slug,
|
41
|
+
PAYLOAD_SCHEMA["definitions"]["CheckContent"]["properties"]["type"]["x-enum"].each_pair do |slug, _info|
|
55
42
|
define_singleton_method(slug) do |**args, &block|
|
56
43
|
new(**args, &block).tap{|doc|
|
57
44
|
doc.content.type = slug
|
@@ -60,105 +47,8 @@ module OrangeData
|
|
60
47
|
end
|
61
48
|
end
|
62
49
|
|
63
|
-
module GeneratedAttributes
|
64
|
-
def self.from_schema klass, schema
|
65
|
-
klass.class_eval{
|
66
|
-
extend GeneratedAttributes
|
67
|
-
generate_accessors_from_schema(schema)
|
68
|
-
}
|
69
|
-
end
|
70
|
-
|
71
|
-
protected
|
72
|
-
def generate_accessors_from_schema schema
|
73
|
-
plain_types = %w[integer string number]
|
74
|
-
schema["properties"].each_pair do |property, info|
|
75
|
-
if plain_types.include?(info["type"])
|
76
|
-
if info["x-enum"]
|
77
|
-
inverse_map = info["x-enum"].map{|k,v| [v['val'], k.to_sym]}.to_h
|
78
|
-
define_method(property.underscore){
|
79
|
-
return nil if @payload[property].nil?
|
80
|
-
inverse_map[@payload[property]] || "unknown value #{@payload[property].inspect} for field #{property}"
|
81
|
-
}
|
82
|
-
define_method(:"#{property.underscore}="){|val|
|
83
|
-
unless val.nil?
|
84
|
-
val = (info["x-enum"][val.to_s] || raise(ArgumentError, "unknown value #{val.inspect} for property #{property}"))["val"]
|
85
|
-
end
|
86
|
-
@payload[property] = val
|
87
|
-
}
|
88
|
-
|
89
|
-
elsif info["x-bitfield"]
|
90
|
-
bitmap = info["x-bitfield"].map{|k,v| [k.to_sym, 1 << v['bit']]}.to_h
|
91
|
-
# TODO: return wrapper so that :<< etc will work
|
92
|
-
define_method(property.underscore){
|
93
|
-
return nil if @payload[property].nil?
|
94
|
-
data = @payload[property].to_i
|
95
|
-
# FIXME: unknown bits will be silently lost
|
96
|
-
bitmap.reject{|_,v| (data & v).zero? }.map(&:first)
|
97
|
-
}
|
98
|
-
define_method(:"#{property.underscore}="){|val|
|
99
|
-
unless val.nil?
|
100
|
-
val = [val] unless val.is_a?(Array)
|
101
|
-
val = val.map{|v| bitmap[v] || raise(ArgumentError, "unknown value #{v.inspect} for property #{property}") }.reduce(:|)
|
102
|
-
end
|
103
|
-
@payload[property] = val
|
104
|
-
}
|
105
|
-
else
|
106
|
-
# primitive
|
107
|
-
define_method(property.underscore){ @payload[property] }
|
108
|
-
define_method(:"#{property.underscore}="){|val| @payload[property] = val }
|
109
|
-
end
|
110
|
-
elsif info["type"] == 'array'
|
111
|
-
if info["items"] && plain_types.include?(info["items"]["type"])
|
112
|
-
define_method(property.underscore){ @payload[property] }
|
113
|
-
define_method(:"#{property.underscore}="){|val|
|
114
|
-
val = [val] unless val.is_a?(Array)
|
115
|
-
@payload[property] = val
|
116
|
-
}
|
117
|
-
else
|
118
|
-
# ref?
|
119
|
-
end
|
120
|
-
else
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
if info["x-alias"]
|
125
|
-
# alias_method "#{info["x-alias"]}", property.underscore
|
126
|
-
alias_method "#{info["x-alias"]}=", "#{property.underscore}="
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# base class for semi-generated classes
|
133
|
-
class PayloadContent
|
134
|
-
def initialize payload={}
|
135
|
-
@payload = payload
|
136
|
-
end
|
137
|
-
|
138
|
-
def assign_attributes options
|
139
|
-
options.each_pair{|k,v|
|
140
|
-
setter = :"#{k}="
|
141
|
-
send(setter, v) if respond_to?(setter)
|
142
|
-
}
|
143
|
-
# for chaining:
|
144
|
-
self
|
145
|
-
end
|
146
|
-
|
147
|
-
def ==(other)
|
148
|
-
self.class == other.class && @payload == other.instance_variable_get(:@payload)
|
149
|
-
end
|
150
|
-
|
151
|
-
def to_hash
|
152
|
-
@payload
|
153
|
-
end
|
154
|
-
|
155
|
-
def to_json(*args)
|
156
|
-
to_hash.to_json(*args)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
50
|
class ReceiptContent < PayloadContent
|
161
|
-
def initialize
|
51
|
+
def initialize(payload={})
|
162
52
|
@payload = payload || {}
|
163
53
|
# TODO: import...
|
164
54
|
# TODO: taxationSystem default in checkclose
|
@@ -201,14 +91,14 @@ module OrangeData
|
|
201
91
|
self
|
202
92
|
end
|
203
93
|
|
204
|
-
def set_additional_user_attribute
|
94
|
+
def set_additional_user_attribute(**options)
|
205
95
|
@additional_user_attribute = AdditionalUserAttribute.new.assign_attributes(options)
|
206
96
|
end
|
207
97
|
|
208
98
|
|
209
99
|
|
210
100
|
class Position < PayloadContent
|
211
|
-
def initialize
|
101
|
+
def initialize(payload={})
|
212
102
|
@payload = payload
|
213
103
|
@supplier_info = SupplierInfo.new(@payload['supplierInfo']) if @payload['supplierInfo']
|
214
104
|
@agent_info = AgentInfo.new(@payload['agentInfo']) if @payload['agentInfo']
|
@@ -221,12 +111,12 @@ module OrangeData
|
|
221
111
|
}
|
222
112
|
end
|
223
113
|
|
224
|
-
def set_supplier_info
|
114
|
+
def set_supplier_info(**options)
|
225
115
|
@supplier_info = SupplierInfo.new.assign_attributes(options)
|
226
116
|
self
|
227
117
|
end
|
228
118
|
|
229
|
-
def set_agent_info
|
119
|
+
def set_agent_info(**options)
|
230
120
|
@agent_info = AgentInfo.new.assign_attributes(options)
|
231
121
|
self
|
232
122
|
end
|
@@ -237,30 +127,18 @@ module OrangeData
|
|
237
127
|
end
|
238
128
|
|
239
129
|
class AgentInfo < PayloadContent
|
240
|
-
def initialize payload={}
|
241
|
-
@payload = payload
|
242
|
-
end
|
243
|
-
def to_hash
|
244
|
-
@payload
|
245
|
-
end
|
246
130
|
GeneratedAttributes.from_schema(self, PAYLOAD_SCHEMA["definitions"]["AgentInfo"])
|
247
131
|
end
|
248
132
|
|
249
133
|
class SupplierInfo < PayloadContent
|
250
|
-
def initialize payload={}
|
251
|
-
@payload = payload
|
252
|
-
end
|
253
|
-
def to_hash
|
254
|
-
@payload
|
255
|
-
end
|
256
134
|
GeneratedAttributes.from_schema(self, PAYLOAD_SCHEMA["definitions"]["SupplierInfo"])
|
257
135
|
end
|
258
136
|
|
259
137
|
class CheckClose < PayloadContent
|
260
|
-
def initialize
|
138
|
+
def initialize(payload={})
|
261
139
|
payload ||= {}
|
262
140
|
@payload = payload
|
263
|
-
@payments = (payload['payments'] || []).map{|p| Payment.new(p)}
|
141
|
+
@payments = (payload['payments'] || []).map{|p| Payment.new(p) }
|
264
142
|
end
|
265
143
|
|
266
144
|
def to_hash
|
@@ -289,7 +167,7 @@ module OrangeData
|
|
289
167
|
end
|
290
168
|
|
291
169
|
class ReceiptResult < PayloadContent
|
292
|
-
def initialize
|
170
|
+
def initialize(payload)
|
293
171
|
@payload = payload
|
294
172
|
@content = ReceiptContent.new(@payload["content"])
|
295
173
|
end
|
@@ -303,13 +181,12 @@ module OrangeData
|
|
303
181
|
GeneratedAttributes.from_schema(self, PAYLOAD_SCHEMA["definitions"]["CheckStatusViewModel[CheckContent]"])
|
304
182
|
|
305
183
|
def qr_code_content
|
306
|
-
# С живого чека: t=20180518T220500&s=975.88&fn=8710000101125654&i=99456&fp=1250448795&n=1
|
307
184
|
# Пример: t=20150720T1638&s=9999999.00&fn=000110000105&i=12345678&fp=123456&n=2
|
308
185
|
{
|
309
186
|
# - t=<date/time - дата и время осуществления расчета в формате ГГГГММДДТЧЧММ>
|
310
|
-
t:
|
187
|
+
t: processed_at.gsub(/:\d{2}\z/, '').gsub(/[^0-9T]/, ''),
|
311
188
|
# - s=<сумма расчета в рублях и копейках, разделенных точкой>
|
312
|
-
s: content.check_close.payments.inject(0.0){|d, p| d + p.amount},
|
189
|
+
s: content.check_close.payments.inject(0.0){|d, p| d + p.amount },
|
313
190
|
# - fn=<заводской номер фискального накопителя>
|
314
191
|
fn: fs_number,
|
315
192
|
# - i=<порядковый номер фискального документа, нулями не дополняется>
|
@@ -317,7 +194,7 @@ module OrangeData
|
|
317
194
|
# - fp=<фискальный признак документа, нулями не дополняется>
|
318
195
|
fp: fp,
|
319
196
|
# - n=<признак расчета>.
|
320
|
-
n: content.raw_type,
|
197
|
+
n: content.raw_type,
|
321
198
|
}.map{|k, v| "#{k}=#{v}" }.join('&')
|
322
199
|
end
|
323
200
|
end
|
@@ -329,7 +206,7 @@ module OrangeData
|
|
329
206
|
@content = CorrectionContent.new(content || {})
|
330
207
|
super
|
331
208
|
end
|
332
|
-
PAYLOAD_SCHEMA["definitions"]["CorrectionContent"]["properties"]["type"]["x-enum"].each_pair do |slug,
|
209
|
+
PAYLOAD_SCHEMA["definitions"]["CorrectionContent"]["properties"]["type"]["x-enum"].each_pair do |slug, _info|
|
333
210
|
define_singleton_method(slug) do |**args, &block|
|
334
211
|
new(**args, &block).tap{|doc|
|
335
212
|
doc.content.type = slug
|
@@ -343,7 +220,7 @@ module OrangeData
|
|
343
220
|
end
|
344
221
|
|
345
222
|
class CorrectionResult < PayloadContent
|
346
|
-
def initialize
|
223
|
+
def initialize(payload)
|
347
224
|
@payload = payload || {}
|
348
225
|
@content = CorrectionContent.new(@payload["content"] || {})
|
349
226
|
end
|
@@ -605,38 +605,45 @@ definitions:
|
|
605
605
|
type: number
|
606
606
|
automatNumber:
|
607
607
|
description: Номер автомата
|
608
|
+
x-comment: Только для вендинга
|
608
609
|
x-tag-id: 1036
|
609
610
|
type: string
|
610
611
|
settlementAddress:
|
611
612
|
description: Адрес расчетов
|
613
|
+
x-comment: Только для вендинга
|
612
614
|
x-tag-id: 1009
|
613
615
|
type: string
|
614
616
|
settlementPlace:
|
615
617
|
description: Место расчетов
|
618
|
+
x-comment: Только для вендинга
|
616
619
|
x-tag-id: 1187
|
617
620
|
type: string
|
618
621
|
cashSum:
|
622
|
+
x-name: sum_cash
|
619
623
|
format: double
|
620
624
|
description: Сумма по чеку (БСО) наличными
|
621
625
|
x-tag-id: 1031
|
622
626
|
type: number
|
623
627
|
eCashSum:
|
624
|
-
x-
|
628
|
+
x-name: sum_card
|
625
629
|
format: double
|
626
630
|
description: Сумма по чеку (БСО) электронными
|
627
631
|
x-tag-id: 1081
|
628
632
|
type: number
|
629
633
|
prepaymentSum:
|
634
|
+
x-name: sum_prepaid
|
630
635
|
format: double
|
631
636
|
description: Сумма по чеку (БСО) предоплатой (зачетом аванса и (или) предыдущих платежей)
|
632
637
|
x-tag-id: 1215
|
633
638
|
type: number
|
634
639
|
postpaymentSum:
|
640
|
+
x-name: sum_credit
|
635
641
|
format: double
|
636
642
|
description: Сумма по чеку (БСО) постоплатой (в кредит)
|
637
643
|
x-tag-id: 1216
|
638
644
|
type: number
|
639
645
|
otherPaymentTypeSum:
|
646
|
+
x-name: sum_counterclaim
|
640
647
|
format: double
|
641
648
|
description: Сумма по чеку (БСО) встречным предоставлением
|
642
649
|
x-tag-id: 1217
|
@@ -73,7 +73,7 @@ module OrangeData
|
|
73
73
|
when 409
|
74
74
|
raise "Conflict"
|
75
75
|
when 400
|
76
|
-
raise "Invalid doc: #{res.body[
|
76
|
+
raise "Invalid doc: #{res.body['errors'] || res.body}"
|
77
77
|
when 503
|
78
78
|
if res.headers['Retry-After']
|
79
79
|
raise "Document queue full, retry in #{res.headers['Retry-After']}"
|
@@ -89,7 +89,7 @@ module OrangeData
|
|
89
89
|
when 200
|
90
90
|
return res.body
|
91
91
|
when 400
|
92
|
-
raise "Cannot get doc: #{res.body[
|
92
|
+
raise "Cannot get doc: #{res.body['errors'] || res.body}"
|
93
93
|
when 401
|
94
94
|
raise 'Unauthorized'
|
95
95
|
end
|
data/lib/orange_data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orangedata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vasily Fedoseyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- lib/orange_data.rb
|
158
158
|
- lib/orange_data/credentials.rb
|
159
159
|
- lib/orange_data/credentials_test.yml
|
160
|
+
- lib/orange_data/generated_attributes.rb
|
160
161
|
- lib/orange_data/receipt.rb
|
161
162
|
- lib/orange_data/schema_definitions.yml
|
162
163
|
- lib/orange_data/transport.rb
|