moysklad 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rspec.yml +29 -0
  3. data/.gitignore +1 -0
  4. data/README.md +14 -3
  5. data/lib/moysklad/client/errors.rb +60 -30
  6. data/lib/moysklad/client.rb +39 -11
  7. data/lib/moysklad/entities/assortment.rb +4 -0
  8. data/lib/moysklad/entities/attribute.rb +111 -37
  9. data/lib/moysklad/entities/attribute_metadata.rb +7 -31
  10. data/lib/moysklad/entities/attribute_value.rb +18 -0
  11. data/lib/moysklad/entities/base.rb +23 -8
  12. data/lib/moysklad/entities/bundle.rb +39 -0
  13. data/lib/moysklad/entities/characteristic.rb +4 -0
  14. data/lib/moysklad/entities/characteristic_metadata.rb +4 -0
  15. data/lib/moysklad/entities/collection.rb +27 -7
  16. data/lib/moysklad/entities/collection_meta.rb +11 -0
  17. data/lib/moysklad/entities/company_settings_metadata.rb +26 -0
  18. data/lib/moysklad/entities/consignment.rb +16 -17
  19. data/lib/moysklad/entities/context.rb +7 -0
  20. data/lib/moysklad/entities/counterparty.rb +20 -0
  21. data/lib/moysklad/entities/country.rb +2 -8
  22. data/lib/moysklad/entities/currency.rb +27 -0
  23. data/lib/moysklad/entities/custom_entity.rb +17 -10
  24. data/lib/moysklad/entities/customer_order.rb +109 -23
  25. data/lib/moysklad/entities/customer_order_position.rb +6 -18
  26. data/lib/moysklad/entities/employee.rb +5 -0
  27. data/lib/moysklad/entities/entity.rb +39 -0
  28. data/lib/moysklad/entities/group.rb +10 -0
  29. data/lib/moysklad/entities/image.rb +16 -0
  30. data/lib/moysklad/entities/meta.rb +12 -0
  31. data/lib/moysklad/entities/organization.rb +17 -0
  32. data/lib/moysklad/entities/owner.rb +4 -0
  33. data/lib/moysklad/entities/price.rb +4 -8
  34. data/lib/moysklad/entities/price_type.rb +0 -8
  35. data/lib/moysklad/entities/product.rb +47 -0
  36. data/lib/moysklad/entities/productfolder.rb +11 -0
  37. data/lib/moysklad/entities/rate.rb +6 -0
  38. data/lib/moysklad/entities/resource_metadata.rb +8 -0
  39. data/lib/moysklad/entities/service.rb +23 -0
  40. data/lib/moysklad/entities/shortcut.rb +9 -0
  41. data/lib/moysklad/entities/store.rb +9 -0
  42. data/lib/moysklad/entities/time.rb +13 -0
  43. data/lib/moysklad/entities/uom.rb +5 -0
  44. data/lib/moysklad/entities/variant.rb +47 -0
  45. data/lib/moysklad/entities.rb +42 -39
  46. data/lib/moysklad/error.rb +1 -0
  47. data/lib/moysklad/resources/assortments.rb +13 -0
  48. data/lib/moysklad/resources/base.rb +35 -46
  49. data/lib/moysklad/resources/custom_entities.rb +29 -0
  50. data/lib/moysklad/resources/custom_entity_metadata.rb +12 -8
  51. data/lib/moysklad/resources/embedded_entity_metadata.rb +2 -3
  52. data/lib/moysklad/resources/indexed.rb +21 -37
  53. data/lib/moysklad/resources/indexed_cache.rb +36 -0
  54. data/lib/moysklad/resources/load_all.rb +21 -0
  55. data/lib/moysklad/resources/positions.rb +15 -0
  56. data/lib/moysklad/resources/products.rb +10 -0
  57. data/lib/moysklad/resources/stock.rb +1 -1
  58. data/lib/moysklad/resources/subresource.rb +0 -1
  59. data/lib/moysklad/resources/where_filter.rb +0 -1
  60. data/lib/moysklad/resources.rb +26 -11
  61. data/lib/moysklad/universe.rb +16 -2
  62. data/lib/moysklad/version.rb +1 -1
  63. data/lib/moysklad.rb +12 -7
  64. data/moysklad.gemspec +5 -3
  65. data/scripts/rest.sh +5 -2
  66. data/spec/lib/moysklad/entities/customer_order_position_spec.rb +4 -17
  67. data/spec/lib/moysklad/entities/customer_order_spec.rb +8 -33
  68. data/spec/lib/moysklad/resources/base_spec.rb +0 -54
  69. data/spec/lib/moysklad/resources_spec.rb +0 -2
  70. data/spec/lib/moysklad/universe_spec.rb +0 -23
  71. data/spec/lib/moysklad_spec.rb +0 -1
  72. data/spec/spec_helper.rb +2 -1
  73. data/spec/support/resource.rb +1 -66
  74. data/test.rb +177 -0
  75. metadata +89 -172
  76. data/.travis.yml +0 -4
  77. data/lib/moysklad/entities/barcode.rb +0 -13
  78. data/lib/moysklad/entities/common.rb +0 -15
  79. data/lib/moysklad/entities/common_object.rb +0 -29
  80. data/lib/moysklad/entities/company.rb +0 -20
  81. data/lib/moysklad/entities/company_concern.rb +0 -20
  82. data/lib/moysklad/entities/contact.rb +0 -15
  83. data/lib/moysklad/entities/custom_entity_metadata.rb +0 -36
  84. data/lib/moysklad/entities/embedded_entity_metadata.rb +0 -18
  85. data/lib/moysklad/entities/error.rb +0 -13
  86. data/lib/moysklad/entities/feature.rb +0 -20
  87. data/lib/moysklad/entities/good.rb +0 -34
  88. data/lib/moysklad/entities/good_folder.rb +0 -9
  89. data/lib/moysklad/entities/good_ref.rb +0 -12
  90. data/lib/moysklad/entities/my_company.rb +0 -12
  91. data/lib/moysklad/entities/sale_price.rb +0 -18
  92. data/lib/moysklad/entities/sale_prices.rb +0 -10
  93. data/lib/moysklad/entities/slot.rb +0 -10
  94. data/lib/moysklad/entities/stock_to.rb +0 -33
  95. data/lib/moysklad/entities/warehouse.rb +0 -15
  96. data/lib/moysklad/entities/xml_fix.rb +0 -15
  97. data/spec/fixtures/302.raw +0 -15
  98. data/spec/fixtures/400.raw +0 -8
  99. data/spec/fixtures/401.html +0 -1
  100. data/spec/fixtures/401_2.html +0 -1
  101. data/spec/fixtures/405.raw +0 -9
  102. data/spec/fixtures/500.raw +0 -8
  103. data/spec/fixtures/502.raw +0 -8
  104. data/spec/fixtures/Consignment_list_0.raw +0 -14
  105. data/spec/fixtures/Consignment_list_1000.raw +0 -14
  106. data/spec/fixtures/Country_list.raw +0 -14
  107. data/spec/fixtures/CustomEntityMetadata_list.raw +0 -14
  108. data/spec/fixtures/CustomEntity_list.raw +0 -14
  109. data/spec/fixtures/CustomEntity_list_bad_chars.raw +0 -17
  110. data/spec/fixtures/EmbeddedEntityMetadata_list.raw +0 -15
  111. data/spec/fixtures/Feature_list.raw +0 -14
  112. data/spec/fixtures/Feature_list_1000.raw +0 -14
  113. data/spec/fixtures/Good_e932ebe1-2e22-11e4-9406-002590a28eca.raw +0 -12
  114. data/spec/fixtures/Good_eb77ad57-2e22-11e4-4030-002590a28eca.raw +0 -12
  115. data/spec/fixtures/Goods_list.raw +0 -14
  116. data/spec/fixtures/Metadata_list.raw +0 -14
  117. data/spec/fixtures/PriceType_list.raw +0 -14
  118. data/spec/fixtures/Stock.raw +0 -11
  119. data/spec/fixtures/Stock_showConsignments.raw +0 -11
  120. data/spec/fixtures/Uom_list.raw +0 -14
  121. data/spec/fixtures/Warehouse_list.raw +0 -14
  122. data/spec/fixtures/attribute_boolean.xml +0 -6
  123. data/spec/fixtures/attribute_dictionary.xml +0 -5
  124. data/spec/fixtures/attribute_double.xml +0 -6
  125. data/spec/fixtures/attribute_file.xml +0 -12
  126. data/spec/fixtures/attribute_long.xml +0 -6
  127. data/spec/fixtures/attribute_text.xml +0 -5
  128. data/spec/fixtures/attribute_time.xml +0 -6
  129. data/spec/fixtures/attribute_url.xml +0 -6
  130. data/spec/fixtures/bad_chars.xml +0 -6
  131. data/spec/fixtures/customer_order.xml +0 -28
  132. data/spec/fixtures/good_with_attributes.raw +0 -12
  133. data/spec/fixtures/resource_forbidden.raw +0 -9
  134. data/spec/fixtures/wrong_password.raw +0 -9
  135. data/spec/fixtures/wrong_type.raw +0 -70
  136. data/spec/fixtures/wrong_user.raw +0 -9
  137. data/spec/lib/moysklad/client/errors_spec.rb +0 -102
  138. data/spec/lib/moysklad/entities/attribute_metadata_spec.rb +0 -30
  139. data/spec/lib/moysklad/entities/attribute_spec.rb +0 -36
  140. data/spec/lib/moysklad/entities/country_spec.rb +0 -25
  141. data/spec/lib/moysklad/entities/custom_entity_metadata_spec.rb +0 -34
  142. data/spec/lib/moysklad/entities/custom_entity_spec.rb +0 -34
  143. data/spec/lib/moysklad/entities/good_spec.rb +0 -46
  144. data/spec/lib/moysklad/resources/countries_spec.rb +0 -22
  145. data/spec/lib/moysklad/resources/custom_entity_metadata_spec.rb +0 -13
  146. data/spec/lib/moysklad/resources/embedded_entity_metadata_indexed_spec.rb +0 -20
  147. data/spec/lib/moysklad/resources/embedded_entity_metadata_spec.rb +0 -11
  148. data/spec/lib/moysklad/resources/good_folders_spec.rb +0 -17
  149. data/spec/lib/moysklad/resources/indexed_spec.rb +0 -61
  150. data/spec/lib/moysklad/resources/stock_spec.rb +0 -63
  151. data/spec/lib/moysklad/resources/warehouses_spec.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0d4466dae399f6e8ec4819ce0c42eb53c9efafb6
4
- data.tar.gz: 6652461f2c0a089662cbe54e608da6f9e500e6a1
2
+ SHA256:
3
+ metadata.gz: 6fad3cc93541b8fa239ed1a6e3e7a900d2206117589163067f85289abb0261b3
4
+ data.tar.gz: bc7c87f9765092342522ffba77d6178c00f670e4e8f5363f77f7055c17a80f9d
5
5
  SHA512:
6
- metadata.gz: 8400a264b733e8eb015d072de499eb6f0896e15a6b1f7d2f095d5c2bc9968c23ce6710db3853b08e1a916b025267c21277dc6a7a16bebf4ff5c4cf57cc29d121
7
- data.tar.gz: 32ba29c475f85b439b3f5239225c854762c93988d80d332112d163b02a7a7103ead308a1458ad964f555db63f394e5223780aad79a7bd798a5d5fefb3b6ad812
6
+ metadata.gz: 2149b17c96a6dcf5a8006f16173739caeb4745f0055921d548d46b9c084a4fc083d6f644e6ff6407cdd7f0563be0fdff43f84e37b3b7a7c77568a16127b09ad6
7
+ data.tar.gz: 5f3ad953ea673c0e69d1fef4405ab5711e8cd603c88a93fa57ac49cda7f2fd8353723da25abcc6b54076416dbc5b5858ed39d1738cb223cde9414a200505126d
@@ -0,0 +1,29 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Rspec
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - name: Checkout repository and submodules
21
+ uses: actions/checkout@v2
22
+ with:
23
+ submodules: recursive
24
+ - name: Set up Ruby
25
+ uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: 3.1.4
28
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
29
+ - run: bundle exec rspec
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.gem
2
+ .byebug_history
2
3
  *.rbc
3
4
  tags
4
5
  gems.tags
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Ruby-клиент для REST XML API Moysklad
2
2
 
3
- [![Build Status](https://travis-ci.org/BrandyMint/moysklad.svg)](https://travis-ci.org/BrandyMint/moysklad)
3
+ [![Build Status](https://travis-ci.org/BrandyMint/moysklad.svg)](https://travis-ci.org/dapi/moysklad)
4
4
  [![Dependency Status](https://www.versioneye.com/user/projects/548225818674a4b5b90004dd/badge.svg?style=flat)](https://www.versioneye.com/user/projects/548225818674a4b5b90004dd)
5
- [![Code Climate](https://codeclimate.com/github/BrandyMint/moysklad/badges/gpa.svg)](https://codeclimate.com/github/BrandyMint/moysklad)
5
+ [![Code Climate](https://codeclimate.com/github/dapi/moysklad/badges/gpa.svg)](https://codeclimate.com/github/dapi/moysklad)
6
6
 
7
7
  * http://www.rubydoc.info/gems/moysklad
8
8
 
@@ -12,8 +12,9 @@
12
12
  * Все используемые сущности описаны и структурированы. Например [Good](lib/moysklad/entities/good.rb)
13
13
  * Любые действия с ресурсами (Create, Read, Update, Delete, List).
14
14
  * Виртуальные действия с ресурсами (`where`, `findWhere`)
15
+ * Автоматическая подгрузка списка если все данные не уместились в один запрос (метод `all`)
15
16
  * _Кеширование и предзагрузка_ ресурса со всеми записями (используем ресурс как локальную базу)
16
- * Работа с нескольмими аккаунтами на склада одновременно (отсуствие глобальных переменных).
17
+ * Работа с нескольмими аккаунтами склада одновременно (отсуствие глобальных переменных).
17
18
  * Удобная работа с подресурсами (например справочником свойств товара)
18
19
  * _Ассоциации_ между сущностями автоматически получают данные по API (`good.features`).
19
20
  * [Client](lib/moysklad/client.rb) для прямого обращения к API в случае крайней необходимости.
@@ -282,10 +283,20 @@ dictionary.entities(universe)
282
283
 
283
284
  > MS_LOGON=логин MS_PASSWORD=пароль ./script/rest.sh Country list > ./spec/fixtures/Country_list.raw
284
285
 
286
+ Если получаете 429 ошибку (too many requests) - лимит обращений по API от одного
287
+ аккаунта - 5 или 10 запросов в секунду (в секунду, Карл). Если не превышать его,
288
+ все будет хорошо - минутных или часовых лимитов нет.
289
+
285
290
  ## Ссылочки
286
291
 
287
292
  * Картапамяти по API http://www.mindmeister.com/246618635/online-moysklad-ru
288
293
  * Документация для разработчииков https://support.moysklad.ru/hc/ru/sections/200561443-Разработчикам
294
+ * Неплохая схема API в json https://gist.github.com/dapi/22a0790db19a4ff51a37
295
+
296
+ ## Другие биллиотеки
297
+
298
+ * PHP https://github.com/Tooyz/moysklad
299
+ * JavaScript/nodejs https://github.com/wmakeev/moysklad-client
289
300
 
290
301
  ## Присылайте пул-реквесты )
291
302
 
@@ -1,23 +1,44 @@
1
1
  class Moysklad::Client
2
2
  class Errors
3
3
  def self.build res
4
- Moysklad.logger.warn "Moyskad::Client: #{res.status}: #{res.env.url.to_s}\n#{res.body}"
4
+ body = res.body.force_encoding('utf-8')
5
+ content_type = res.headers['content-type']
6
+
7
+ if content_type.start_with? 'application/json'
8
+ # ok
9
+ elsif content_type.start_with? 'text/html'
10
+ raise HtmlParsedError, body
11
+ else
12
+ raise UnknownError, body
13
+ end
14
+
15
+ # Encoding::UndefinedConversionError
16
+ # "\xD0" from ASCII-8BIT to UTF-8
17
+ begin
18
+ body = JSON.parse body
19
+ Moysklad.logger.debug "Moysklad::Client: #{res.status}: #{res.headers}, #{res.env.url.to_s}\n#{body}"
20
+ rescue Encoding::UndefinedConversionError => err
21
+ Moysklad.logger.error "#{err}"
22
+ rescue JSON::ParserError => err
23
+ Moysklad.logger.error "#{err}: #{res.headers}, body:#{body}"
24
+ raise ParsingError, body
25
+ end
5
26
 
6
27
  case res.status
7
- when 401
8
- raise UnauthorizedError.new res
28
+ when 401
29
+ raise UnauthorizedError.new body
9
30
  when 403
10
- raise ResourceForbidden.new res
11
- when 404
12
- raise NoResourceFound.new res.body
13
- when 405
14
- raise MethodNotAllowedError.new res
31
+ raise ResourceForbidden.new body
32
+ when 404
33
+ raise NoResourceFound.new body
34
+ when 405, 412
35
+ raise MethodNotAllowedError.new body
15
36
  when 500
16
- raise InternalServerError.new res
37
+ raise InternalServerError.new body
17
38
  when 502
18
- raise BadGatewayError.new res
19
- else
20
- raise ParsedError.new res
39
+ raise BadGatewayError.new body
40
+ else
41
+ raise JsonParsedError.new body
21
42
  end
22
43
  end
23
44
  end
@@ -32,39 +53,48 @@ class Moysklad::Client
32
53
  end
33
54
 
34
55
  def to_s
35
- message
56
+ message.to_s.encode('utf-8')
57
+ # <?xml version="1.0" encoding="UTF-8"?> <error> <uid>kiiiosk@wannabemoscow</uid> <moment>20150609112728449</moment> <message>������������ ���� ���������� �������� ������������.</message> </error>
58
+ rescue Encoding::CompatibilityError
59
+ message.to_s.force_encoding('cp1251').encode('utf-8')
36
60
  end
37
61
  end
62
+ class ParsingError < Error; end
63
+
64
+ class UnknownError < Error; end
38
65
 
39
66
  class NoResourceFound < Error; end
40
67
 
68
+ class JsonParsedError < Error
69
+ def initialize result
70
+ super result.to_json
71
+ end
72
+
73
+ attr_reader :error
74
+ end
75
+
41
76
  class HtmlParsedError < Error
42
- def initialize res
43
- @result = res
44
- @message = "[#{res.status}] #{parse_title res.body}"
77
+ def initialize body
78
+ @message = parse_title body
45
79
  end
46
80
 
47
81
  private
48
82
 
49
83
  def parse_title body
50
- doc = Nokogiri::HTML body
51
- # у ResourceForbidden есть <u>
52
- # у wrong_password <u> несколько
53
- # Можно ошибку разбирать более грамотно по свойствам type, message, description: http://i.gyazo.com/e9d5d08bd610882d87f39d9002cdf25a.png
54
- [doc.css('body').css('h1').text,doc.css('body').css('u').to_a.map(&:text).compact.last].join('; ')
84
+ Nokogiri::HTML(body).css('body').text
55
85
  rescue => err
56
- Moysklad.logger.debug "Moyskad::Client parse error #{err}: #{body}"
86
+ Moysklad.logger.debug "Moysklad::Client parse error #{err}: #{body}"
57
87
  body.force_encoding('utf-8')
58
88
  end
59
89
  end
60
90
 
61
- class MethodNotAllowedError < HtmlParsedError
91
+ class MethodNotAllowedError < JsonParsedError
62
92
  end
63
93
 
64
- class UnauthorizedError < HtmlParsedError
94
+ class UnauthorizedError < JsonParsedError
65
95
  end
66
96
 
67
- class ResourceForbidden < HtmlParsedError
97
+ class ResourceForbidden < JsonParsedError
68
98
  end
69
99
 
70
100
  class ParsedError < Error
@@ -72,24 +102,24 @@ class Moysklad::Client
72
102
  @status = result.status
73
103
  @result = result
74
104
  case result.headers['content-type']
75
-
105
+
76
106
  when /application\/xml/
77
107
  @error = Moysklad::Entities::Error.parse result.body
78
108
  @message = @error.message
79
109
  when /text\/html/
80
- doc = Nokogiri::HTML body
110
+ doc = Nokogiri::HTML result.body
81
111
  @message = doc.css('body').css('h1').text
82
112
  else
83
113
  raise "Unknown content-type #{result.headers['content-type']} to parse error #{result.body}"
84
114
  end
85
115
  rescue => err
86
- @message = "error in init #{err}: #{result.body}"
116
+ @message = "error in init #{err}: #{result}"
87
117
  end
88
118
 
89
119
  attr_reader :error
90
120
  end
91
121
 
92
122
 
93
- class BadGatewayError < HtmlParsedError; end
94
- class InternalServerError < ParsedError; end
123
+ class BadGatewayError < JsonParsedError; end
124
+ class InternalServerError < JsonParsedError; end
95
125
  end
@@ -4,31 +4,55 @@ require_relative 'client/errors'
4
4
 
5
5
  class Moysklad::Client
6
6
 
7
- URL = 'https://online.moysklad.ru'
7
+ # URL = 'https://online.moysklad.ru'
8
+ URL ='https://online.moysklad.ru/api/remap/1.1/'
8
9
 
9
10
  def initialize login: nil, password: nil
10
- @client = Faraday.new URL
11
- @client.basic_auth login, password
11
+ @client = Faraday.new URL do |conn|
12
+ conn.request(:authorization, :basic, login, password)
13
+ end
14
+ end
15
+
16
+ def download(path, filename)
17
+ response = client.get path
18
+ File.open(filename, 'wb') { |fp| fp.write(response.body) }
12
19
  end
13
20
 
14
21
  def get path, params={}
15
22
  logger.debug "Client: GET #{path} #{params}"
16
- validate client.get path, params
23
+ parse_response client.get path, params
24
+ end
25
+
26
+ def post path, data
27
+ logger.debug "Client: POST #{path}"
28
+ result = client.post do |req|
29
+ req.url path
30
+ req.headers['Content-Type'] = 'application/json'
31
+ req.headers['Accept'] = '*/*'
32
+ req.body = data
33
+ end
34
+ parse_response result
17
35
  end
18
36
 
19
37
  def put path, data
20
38
  logger.debug "Client: PUT #{path}"
21
39
  result = client.put do |req|
22
40
  req.url path
23
- req.headers['Content-Type'] = 'application/xml'
41
+ req.headers['Content-Type'] = 'application/json'
24
42
  req.headers['Accept'] = '*/*'
25
43
  req.body = data
26
44
  end
27
- validate result
45
+ parse_response result
28
46
  end
29
47
 
30
48
  def delete path
31
- validate client.delete path
49
+ logger.debug "Client: DELETE #{path}"
50
+ result = client.delete do |req|
51
+ req.url path
52
+ req.headers['Content-Type'] = 'application/json'
53
+ req.headers['Accept'] = '*/*'
54
+ end
55
+ parse_response result
32
56
  end
33
57
 
34
58
  private
@@ -39,10 +63,14 @@ class Moysklad::Client
39
63
  Moysklad.logger
40
64
  end
41
65
 
42
- def validate res
43
- return res.body if res.status == 200
66
+ def parse_response res
67
+ Moysklad.logger.debug "Response [#{res.status}]: #{res.body}"
44
68
 
45
- Moysklad::Client::Errors.build res
69
+ if res.status == 200
70
+ return if res.body.blank?
71
+ JSON.parse res.body
72
+ else
73
+ Moysklad::Client::Errors.build res
74
+ end
46
75
  end
47
-
48
76
  end
@@ -0,0 +1,4 @@
1
+ module Moysklad::Entities
2
+ class Assortment < Entity
3
+ end
4
+ end
@@ -1,47 +1,121 @@
1
+ # Атрибут товара (ссылка на его тип и его значение)
1
2
  module Moysklad::Entities
2
3
  class Attribute < Base
3
- include Moysklad::Entities::Common
4
+ attribute :meta, Meta
5
+ attribute :id, String
6
+ attribute :name, String
7
+ attribute :customEntityMeta, Meta
8
+ attribute :type, String #attributemetadata
9
+ attribute :value, AttributeValue
10
+ attribute :required, Boolean
4
11
 
5
- tag 'attribute'
12
+ def to_s
13
+ "#{name} (#{type}): #{value}"
14
+ end
6
15
 
7
- attribute :metadataUuid, String
8
- attribute :valueString, String
9
- attribute :valueText, String
16
+ def is_dictionary?
17
+ type == 'customentity'
18
+ end
10
19
 
11
- attribute :entityValueUuid, String
20
+ ### Если это свойство типа ID_CUSTOM, то возвращается пользовательский справочник
21
+ ###
22
+ ### @return Moysklad::Entities::CustomEntityMetadata
23
+ ##def dictionatyMetadata universe
24
+ ##raise "Это свойства не типа справочник" unless dictionaryMetadataUuid
25
+ ##universe.custom_entity_metadata.find dictionaryMetadataUuid
26
+ ##end
12
27
 
13
- # Объект описывающий тип атритуба
14
- #
15
- # @return Moysklad::Entities::AttributeMetadata
16
- #
17
- def metadata universe
18
- universe.embedded_entity_metadata.subresource_by_name(:GoodFolder).find metadataUuid
19
- end
28
+ ### Справочник к которому принадлежит это ссвойство
29
+ ###
30
+ ### @return Moysklad::Entities::EmbeddedEntityMetadata
31
+ ##def entityMetadata universe
32
+ ##universe.embedded_entity_metadata.find entityMetadataUuid
33
+ ##end
20
34
 
21
- # Название свойства, полученное из AttributeMetadata
22
- #
23
- # @return String
24
- #
25
- def attributeName universe
26
- metadata(universe).name
27
- end
28
35
 
29
- # Значение свойства согласно его типу
30
- #
31
- # @return [String | Moysklad::Entities::CustomEntity | Integer | Decimal ]
32
- def get_value universe
33
- md = metadata universe
34
- case md.attrType
35
- when 'ID_CUSTOM'
36
- universe.custom_entities.find( entityValueUuid ).name
37
- when 'TEXT'
38
- valueText
39
- when 'STRING'
40
- valueString
41
- # TODO Другие типы
42
- else
43
- raise "Не известный тип мета-аттрибута #{md.uuid}: #{md.attrType}"
44
- end
45
- end
36
+ ### Объект описывающий тип атритуба
37
+ ###
38
+ ### @return Moysklad::Entities::AttributeMetadata
39
+ ###
40
+ ##def metadata universe
41
+ ##universe.embedded_entity_metadata.subresource_by_name(:GoodFolder).find metadataUuid
42
+ ##end
43
+
44
+ ### Название свойства, полученное из AttributeMetadata
45
+ ###
46
+ ### @return String
47
+ ###
48
+ ##def attributeName universe
49
+ ##metadata(universe).name
50
+ ##end
51
+
52
+ ### Значение свойства согласно его типу
53
+ ###
54
+ ### @return [String | Moysklad::Entities::CustomEntity | Integer | Decimal ]
55
+ #def get_value universe
56
+ #md = metadata universe
57
+ #case md.attrType
58
+ #when 'ID_CUSTOM'
59
+ #universe.custom_entities.find( entityValueUuid ).name
60
+ #when 'LINK'
61
+ #valueText
62
+ #when 'TEXT'
63
+ #valueText
64
+ #when 'STRING'
65
+ #valueString
66
+ #when 'DOUBLE'
67
+ #doubleValue
68
+ #when 'LONG'
69
+ #longValue
70
+ #when 'TIME'
71
+ #timeValue
72
+ #when 'FILE'
73
+ #file
74
+ #else
75
+ #raise "Не известный тип мета-аттрибута #{md.uuid}: #{md.attrType}"
76
+ #end
77
+ #end
78
+ ### Объект описывающий тип атритуба
79
+ ###
80
+ ### @return Moysklad::Entities::AttributeMetadata
81
+ ###
82
+ ##def metadata universe
83
+ ##universe.embedded_entity_metadata.subresource_by_name(:GoodFolder).find metadataUuid
84
+ ##end
85
+
86
+ ### Название свойства, полученное из AttributeMetadata
87
+ ###
88
+ ### @return String
89
+ ###
90
+ ##def attributeName universe
91
+ ##metadata(universe).name
92
+ ##end
93
+
94
+ ### Значение свойства согласно его типу
95
+ ###
96
+ ### @return [String | Moysklad::Entities::CustomEntity | Integer | Decimal ]
97
+ ##def get_value universe
98
+ ##md = metadata universe
99
+ ##case md.attrType
100
+ ##when 'ID_CUSTOM'
101
+ ##universe.custom_entities.find( entityValueUuid ).name
102
+ ##when 'LINK'
103
+ ##valueText
104
+ ##when 'TEXT'
105
+ ##valueText
106
+ ##when 'STRING'
107
+ ##valueString
108
+ ##when 'DOUBLE'
109
+ ##doubleValue
110
+ ##when 'LONG'
111
+ ##longValue
112
+ ##when 'TIME'
113
+ ##timeValue
114
+ ##when 'FILE'
115
+ ##file
116
+ ##else
117
+ ##raise "Не известный тип мета-аттрибута #{md.uuid}: #{md.attrType}"
118
+ ##end
119
+ ##end
46
120
  end
47
121
  end
@@ -1,38 +1,14 @@
1
1
  module Moysklad::Entities
2
- # https://online.moysklad.ru/exchange/rest/ms/xml/Metadata/list
3
2
  class AttributeMetadata < Base
4
- include CommonObject
5
-
6
- tag 'attributeMetadata'
7
-
8
- # ID_CUSTOM - элемент из dictionary
9
- # TEXT
10
- # STRING
11
- attribute :attrType, String
12
- attribute :entityMetadataUuid, String
13
- attribute :feature, Boolean
14
- attribute :position, Integer
15
- attribute :required, Boolean
16
- attribute :dictionaryMetadataUuid, String
3
+ attribute :meta, Meta
4
+ attribute :id, String
5
+ attribute :name, String
6
+ attribute :type, String # string, customentity
7
+ attribute :required, Boolean
8
+ attribute :customEntityMeta, Meta
17
9
 
18
10
  def is_dictionary?
19
- attrType == 'ID_CUSTOM'
20
- end
21
-
22
- # Если это свойство типа ID_CUSTOM, то возвращается пользовательский справочник
23
- #
24
- # @return Moysklad::Entities::CustomEntityMetadata
25
- def dictionatyMetadata universe
26
- raise "Это свойства не типа справочник" unless dictionaryMetadataUuid
27
- universe.custom_entity_metadata.find dictionaryMetadataUuid
11
+ type == 'customentity'
28
12
  end
29
-
30
- # Справочник к которому принадлежит это ссвойство
31
- #
32
- # @return Moysklad::Entities::EmbeddedEntityMetadata
33
- def entityMetadata universe
34
- universe.embedded_entity_metadata.find entityMetadataUuid
35
- end
36
-
37
13
  end
38
14
  end
@@ -0,0 +1,18 @@
1
+ module Moysklad::Entities
2
+ class AttributeValue < Virtus::Attribute
3
+ def coerce(value)
4
+ case value
5
+ when String, Float
6
+ value
7
+ when ::Hash
8
+ if value['meta']['type'] == 'customentity'
9
+ CustomEntity.new value
10
+ else
11
+ raise "Unknown meta type: #{value['meta']['type']}"
12
+ end
13
+ else
14
+ raise "Unknown value type (#{value}) #{value.class}"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,16 +1,31 @@
1
1
  module Moysklad::Entities
2
2
  class Base
3
- #include Object
3
+ include Virtus.model
4
+ attr_accessor :universe
5
+ attr_accessor :dump
4
6
 
5
- private
7
+ def self.build(data, universe)
8
+ entity = new data
9
+ entity.universe = universe
10
+ entity
11
+ end
12
+
13
+ def initialize(data = {})
14
+ data['attrs'] = data.delete 'attributes' if data['attributes']
15
+ super (data || {}).merge(dump: data)
16
+ end
6
17
 
7
- def cache ns, key
8
- @cache||={}
9
- @cache[ns]||={}
10
- cc = @cache[ns]
18
+ def to_json(*args)
19
+ presented = {}
20
+ to_h.each_pair do |k, v|
21
+ presented[k] = v unless v.nil?
22
+ end
23
+
24
+ presented.to_json
25
+ end
11
26
 
12
- cc[key] = yield unless cc.has_key? key
13
- cc[key]
27
+ def to_s
28
+ attributes.to_s
14
29
  end
15
30
  end
16
31
  end
@@ -0,0 +1,39 @@
1
+ module Moysklad::Entities
2
+ # Комплект
3
+ # https://online.moysklad.ru/api/remap/1.1/doc/index.html#комплект
4
+ class Bundle < Product
5
+ #meta - Метаданные объекта
6
+ #id - ID Комплекта в формате UUID Только для чтения
7
+ #accountId - ID учетной записи Только для чтения
8
+ #owner - Ссылка на Владельца (Сотрудника) в формате Метаданных
9
+ #shared - Общий доступ
10
+ #group - Отдел сотрудника в формате Метаданных
11
+ #syncId - ID синхронизации Только для чтения
12
+ #version - Версия сущности Только для чтения
13
+ #updated - Момент последнего обновления сущности Только для чтения
14
+ #name - Наименование Комплекта Необходимое
15
+ #description - Описание Комплекта
16
+ #code - Код Комплекта
17
+ #externalCode - Внешний код Комплекта
18
+ #archived - Отметка о том, добавлен ли Комплект в архив
19
+ #pathName - Наименование группы, в которую входит Комплект Только для чтения
20
+ #vat - НДС %
21
+ #effectiveVat - Реальный НДС % Только для чтения
22
+ #productFolder - Ссылка на группу Комплекта
23
+ #uom - Единицы измерения
24
+ #image - Изображение Комплекта Только для чтения
25
+ #minPrice - Минимальная цена
26
+ #salePrices - Цены продажи
27
+ #attributes - Коллекция доп. полей в формате Метаданных
28
+ #country - Ссылка на страну в формате Метаданных
29
+ #article - Артикул
30
+ #weight - Вес
31
+ #volume - Объём
32
+ #barcodes - Массив штрихкодов Комплекта
33
+ #overhead - Дополнительные расходы
34
+ #currency - Валюта доп расходов
35
+ #value - Значение доп расходов
36
+ #components - Компоненты Комплекта
37
+
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ module Moysklad::Entities
2
+ class Characteristic < Attribute
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Moysklad::Entities
2
+ class CharacteristicMetadata < AttributeMetadata
3
+ end
4
+ end