moy_sklad 1.0.0.beta1

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +13 -0
  6. data/Rakefile +1 -0
  7. data/bin/gencountry +18 -0
  8. data/doc/xml/Company.xml +165 -0
  9. data/doc/xml/CustomEntity.xml +53 -0
  10. data/doc/xml/CustomerOrder.xml +168 -0
  11. data/doc/xml/Good.xml +127 -0
  12. data/doc/xml/GoodFolder.xml +53 -0
  13. data/doc/xml/MOYsklad.xsd +2450 -0
  14. data/doc/xml/PaymentIn.xml +81 -0
  15. data/doc/xml/README.md +1 -0
  16. data/lib/moy_sklad/client/attribute.rb +119 -0
  17. data/lib/moy_sklad/client/base.rb +112 -0
  18. data/lib/moy_sklad/client/collection.rb +52 -0
  19. data/lib/moy_sklad/client/formatter.rb +37 -0
  20. data/lib/moy_sklad/client/resource.rb +56 -0
  21. data/lib/moy_sklad/client.rb +5 -0
  22. data/lib/moy_sklad/configuration.rb +74 -0
  23. data/lib/moy_sklad/model/company.rb +23 -0
  24. data/lib/moy_sklad/model/country.rb +12 -0
  25. data/lib/moy_sklad/model/custom_entity.rb +4 -0
  26. data/lib/moy_sklad/model/customer_order.rb +21 -0
  27. data/lib/moy_sklad/model/data/country_codes.yml +249 -0
  28. data/lib/moy_sklad/model/demand.rb +20 -0
  29. data/lib/moy_sklad/model/good.rb +32 -0
  30. data/lib/moy_sklad/model/good_folder.rb +4 -0
  31. data/lib/moy_sklad/model/payment_in.rb +9 -0
  32. data/lib/moy_sklad/model/supply.rb +20 -0
  33. data/lib/moy_sklad/model/templates/company.builder +132 -0
  34. data/lib/moy_sklad/model/templates/custom_entity.builder +42 -0
  35. data/lib/moy_sklad/model/templates/customer_order.builder +151 -0
  36. data/lib/moy_sklad/model/templates/demand.builder +147 -0
  37. data/lib/moy_sklad/model/templates/good.builder +83 -0
  38. data/lib/moy_sklad/model/templates/good_folder.builder +41 -0
  39. data/lib/moy_sklad/model/templates/payment_in.builder +72 -0
  40. data/lib/moy_sklad/model/templates/supply.builder +144 -0
  41. data/lib/moy_sklad/model.rb +13 -0
  42. data/lib/moy_sklad/nokogiri/document.rb +28 -0
  43. data/lib/moy_sklad/version.rb +3 -0
  44. data/lib/moy_sklad.rb +4 -0
  45. data/moy_sklad.gemspec +28 -0
  46. data/spec/ms_config.rb +44 -0
  47. data/spec/spec_helper.rb +9 -0
  48. data/spec/unit/company_spec.rb +60 -0
  49. data/spec/unit/country_spec.rb +18 -0
  50. data/spec/unit/custom_entity_spec.rb +64 -0
  51. data/spec/unit/customer_order_spec.rb +131 -0
  52. data/spec/unit/demand_spec.rb +53 -0
  53. data/spec/unit/fail_spec.rb +12 -0
  54. data/spec/unit/good_folder_spec.rb +51 -0
  55. data/spec/unit/good_spec.rb +149 -0
  56. data/spec/unit/payment_in_spec.rb +120 -0
  57. data/spec/unit/supply_spec.rb +51 -0
  58. metadata +211 -0
@@ -0,0 +1,81 @@
1
+ <?xml version="1.0"?>
2
+ <paymentIn readMode="NONE" changeMode="NEIGHBOUR" updated="2013-11-23T15:44:07" updatedBy="string" name="string" stateUuid="string" targetAgentUuid="string" sourceAgentUuid="string" targetStoreUuid="string" sourceStoreUuid="string" applicable="true" projectUuid="string" contractUuid="string" moment="2006-08-19T19:27:14+02:00" targetAccountUuid="string" sourceAccountUuid="string" payerVat="false" retailStoreUuid="string" currencyUuid="string" rate="1.051732E7" vatIncluded="true" created="2017-05-15T08:41:13" createdBy="string" employeeUuid="string" expenseItemUuid="string" incomingDate="2013-12-21T12:32:42+01:00" incomingNumber="string" paymentPurpose="string" vatSum="1.051732E7" commissionReportUuid="string" customerOrderUuid="string" factureOutUuid="string" invoiceOutUuid="string" purchaseReturnUuid="string">
3
+ <!--Optional:-->
4
+ <accountUuid>string</accountUuid>
5
+ <!--Optional:-->
6
+ <accountId>string</accountId>
7
+ <!--Optional:-->
8
+ <uuid>string</uuid>
9
+ <!--Optional:-->
10
+ <groupUuid>string</groupUuid>
11
+ <!--Optional:-->
12
+ <deleted>2016-01-01T20:07:42</deleted>
13
+ <!--Optional:-->
14
+ <code>string</code>
15
+ <!--Optional:-->
16
+ <externalcode>string</externalcode>
17
+ <!--Optional:-->
18
+ <description>string</description>
19
+ <!--Zero or more repetitions:-->
20
+ <attribute readMode="SELF" changeMode="PARENT" updated="2019-08-19T16:35:10" updatedBy="string" metadataUuid="string" valueText="string" valueString="string" doubleValue="1.051732E7" longValue="10" booleanValue="true" timeValue="2013-06-17T19:14:58" entityValueUuid="string" agentValueUuid="string" goodValueUuid="string" placeValueUuid="string" consignmentValueUuid="string" contractValueUuid="string" projectValueUuid="string" employeeValueUuid="string" operationUuid="string">
21
+ <!--Optional:-->
22
+ <accountUuid>string</accountUuid>
23
+ <!--Optional:-->
24
+ <accountId>string</accountId>
25
+ <!--Optional:-->
26
+ <uuid>string</uuid>
27
+ <!--Optional:-->
28
+ <groupUuid>string</groupUuid>
29
+ <!--Optional:-->
30
+ <deleted>2005-09-12T10:55:02+02:00</deleted>
31
+ <!--Optional:-->
32
+ <file readMode="NONE" changeMode="SELF" updated="2015-08-24T01:09:23" updatedBy="string" name="string" created="2015-06-18T00:07:00+02:00" filename="string" miniatureUuid="string">
33
+ <!--Optional:-->
34
+ <accountUuid>string</accountUuid>
35
+ <!--Optional:-->
36
+ <accountId>string</accountId>
37
+ <!--Optional:-->
38
+ <uuid>string</uuid>
39
+ <!--Optional:-->
40
+ <groupUuid>string</groupUuid>
41
+ <!--Optional:-->
42
+ <deleted>2000-04-21T02:36:55+02:00</deleted>
43
+ <!--Optional:-->
44
+ <code>string</code>
45
+ <!--Optional:-->
46
+ <externalcode>string</externalcode>
47
+ <!--Optional:-->
48
+ <description>string</description>
49
+ <!--Optional:-->
50
+ <contents>cXVpc3F1YW0=</contents>
51
+ </file>
52
+ </attribute>
53
+ <!--Zero or more repetitions:-->
54
+ <document readMode="PARENT" changeMode="PARENT" updated="2008-08-06T16:17:00+02:00" updatedBy="string" name="string" created="2011-12-25T03:49:17" filename="string" miniatureUuid="string" emailedDate="2015-10-10T12:07:56+02:00" publicId="string" operationUuid="string">
55
+ <!--Optional:-->
56
+ <accountUuid>string</accountUuid>
57
+ <!--Optional:-->
58
+ <accountId>string</accountId>
59
+ <!--Optional:-->
60
+ <uuid>string</uuid>
61
+ <!--Optional:-->
62
+ <groupUuid>string</groupUuid>
63
+ <!--Optional:-->
64
+ <deleted>2018-07-19T10:02:25+02:00</deleted>
65
+ <!--Optional:-->
66
+ <code>string</code>
67
+ <!--Optional:-->
68
+ <externalcode>string</externalcode>
69
+ <!--Optional:-->
70
+ <description>string</description>
71
+ <!--Optional:-->
72
+ <contents>YmVsbGE=</contents>
73
+ </document>
74
+ <!--Optional:-->
75
+ <sum sum="1.051732E7" sumInCurrency="1.051732E7"/>
76
+ <!--Optional:-->
77
+ <demandsUuid>
78
+ <!--Zero or more repetitions:-->
79
+ <demandRef>string</demandRef>
80
+ </demandsUuid>
81
+ </paymentIn>
data/doc/xml/README.md ADDED
@@ -0,0 +1 @@
1
+ Все xml'ки созданы из MOYSklad.xsd при помощи: http://devutilsonline.com/xsd-xml/generate-xml-from-xsd
@@ -0,0 +1,119 @@
1
+ # Placeholder class used by Nokogiri for create "clean" xml
2
+ # requests.
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+
5
+ module MoySklad::Client
6
+ module Attribute
7
+ class MissingAttr
8
+ def method_missing(meth, *args)
9
+ MissingAttr.new
10
+ end
11
+
12
+ def empty?
13
+ true
14
+ end
15
+ end
16
+ end
17
+
18
+ # Include in baseclass because we need this in ALL subclasses
19
+ # (also in autocreated by AR)
20
+ module MissingAttrHandler
21
+ def method_missing(meth, *args)
22
+ if meth[-1] != '='
23
+ begin
24
+ super
25
+ rescue
26
+ MoySklad::Client::Attribute::MissingAttr.new
27
+ end
28
+ else
29
+ super
30
+ end
31
+ end
32
+ end
33
+
34
+ module CustomAttrBehavior
35
+
36
+ # Attributes array is widely used in all MS data objects. It handle custom attributes
37
+ # for each object. For make life easier we're use get/set_attribute functions.
38
+
39
+ # Get attrubute from the "attributes" array of the object.
40
+ #
41
+ # @attr info [Hash] attribute info hash, should have keys: {:uuid, :value}
42
+ # @attr value [Object] value to set
43
+ #
44
+ def set_attribute(info, value)
45
+
46
+ fail ArgumentError, "Argument should be hash with at least [:uuid, :value] keys" unless info.is_a?(Hash)
47
+
48
+ info = HashWithIndifferentAccess.new(info)
49
+ fail ArgumentError, "You must provide keys: [:uuid, :value]" unless info.has_key?(:uuid) || info.has_key?(:value)
50
+
51
+ v = find_object(:attribute, :metadataUuid, info[:uuid])
52
+ if v.nil?
53
+ data = { metadataUuid: info[:uuid] }
54
+ data[info[:value]] = value
55
+ a = create_and_load_resource('Attribute', data)
56
+ if self.to_a(:attribute).empty?
57
+ self.attribute = [a]
58
+ else
59
+ self.attribute << a
60
+ end
61
+ else
62
+ v.send("#{info[:value]}=".to_sym, value)
63
+ end
64
+
65
+ end
66
+
67
+ # Set attribute in "attributes" array of the object.
68
+ #
69
+ # @attr info [Hash/String] hash with at least [:uuid] key or String with uuid.
70
+ # if hash containts [:value] key then value will be returned
71
+ # instead of plceholder object.
72
+ def get_attribute(info)
73
+
74
+ uuid = info if info.is_a?(String) && (info.length == 36)
75
+
76
+ if info.is_a?(Hash)
77
+ info = HashWithIndifferentAccess.new(info)
78
+ uuid = info[:uuid] if info.is_a?(Hash) && (!info[:uuid].nil? && info[:uuid].length == 36)
79
+ end
80
+
81
+ fail ArgumentError, "Argument should be uuid string or hash with [:uuid] key" if uuid.nil?
82
+
83
+ a = find_object(:attribute, :metadataUuid, uuid)
84
+
85
+ if info.is_a?(Hash) && info.has_key?(:value)
86
+ return a.send(info[:value]) if a.respond_to?(info[:value])
87
+ nil
88
+ else
89
+ a
90
+ end
91
+ end
92
+
93
+ # Get object attribute as array.
94
+ # object.to_a(:some_type) will always return array and of course it can be empty.
95
+ def to_a(type)
96
+
97
+ value = self.send(type)
98
+ return [] if value.nil? || value.is_a?(MoySklad::Client::Attribute::MissingAttr)
99
+
100
+ # Convert
101
+ self.send("#{type}=", [value]) unless value.is_a?(Array)
102
+ self.send(type)
103
+ end
104
+
105
+ # Check is nested resource empty or not
106
+ def empty?
107
+ attributes.empty?
108
+ end
109
+
110
+ # Remove attribute from object
111
+ def remove_attr(attribute)
112
+ attributes.delete(attribute)
113
+ known_attributes.delete(attribute)
114
+ end
115
+ end
116
+
117
+ ActiveResource::Base.send(:include, MissingAttrHandler)
118
+ ActiveResource::Base.send(:include, CustomAttrBehavior)
119
+ end
@@ -0,0 +1,112 @@
1
+ # ActiveResource base class
2
+ # All models shoud extend this class
3
+
4
+ module MoySklad::Client
5
+ class Base < ActiveResource::Base
6
+ self.site = MoySklad.configuration.base_url
7
+ self.format = Formatter.new
8
+ self.user = MoySklad.configuration.user_name
9
+ self.password = MoySklad.configuration.password
10
+ self.auth_type = :basic
11
+
12
+ if ActiveResource::VERSION::STRING >= '4.0.0'
13
+ self.include_format_in_path = false
14
+ self.collection_parser = Collection
15
+ end
16
+
17
+ @@template_path = File.join(File.dirname(__FILE__), '..', 'model', 'templates')
18
+
19
+ class << self
20
+
21
+ def find(*args)
22
+ # Little trick for correct baseclass name
23
+ self.format.element_name = element_name.classify
24
+ super(*args)
25
+ end
26
+
27
+ # Custom path builder
28
+ def element_path(id, prefix_options = {}, query_options = nil)
29
+ check_prefix_options(prefix_options)
30
+
31
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
32
+ "#{prefix(prefix_options)}#{element_name.classify}/" \
33
+ "#{URI.parser.escape id.to_s}#{query_string(query_options)}"
34
+ end
35
+
36
+ def new_element_path(prefix_options = {})
37
+ "#{prefix(prefix_options)}#{element_name.classify}"
38
+ end
39
+
40
+ def collection_name
41
+ @collection_name ||= "#{element_name.classify}/list"
42
+ end
43
+
44
+ if ActiveResource::VERSION::STRING < '4.0.0'
45
+ def collection_path(prefix_options = {}, query_options = nil)
46
+ check_prefix_options(prefix_options)
47
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
48
+ "#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
49
+ end
50
+ end
51
+ end
52
+
53
+ # Override create method, this required because moysklad uses PUT instead of POST
54
+ if ActiveResource::VERSION::STRING < '4.0.0'
55
+ def create
56
+ _create
57
+ end
58
+
59
+ def destroy
60
+ _destroy
61
+ end
62
+ else
63
+ def create
64
+ run_callbacks :create do _create end
65
+ end
66
+
67
+ def destroy
68
+ run_callbacks :destroy do _destroy end
69
+ end
70
+ end
71
+
72
+ def save
73
+ super
74
+ self.error.is_a?(MoySklad::Client::Attribute::MissingAttr)
75
+ end
76
+
77
+ private
78
+
79
+ def _create
80
+ connection.put(new_element_path, encode, self.class.headers).tap do |response|
81
+ self.id = id_from_response(response)
82
+ load_attributes_from_response(response)
83
+ end
84
+ end
85
+
86
+ def _destroy
87
+ connection.delete(self.class.element_path(uuid), self.class.headers)
88
+ end
89
+
90
+ # Custom data encoder
91
+ # Template compiled only ONCE !!!
92
+ def encode
93
+ compile_template unless respond_to?(:create_xml)
94
+ create_xml
95
+ end
96
+
97
+ def compile_template
98
+ file_path = File.join("#{@@template_path}", "#{self.class.element_name}.builder")
99
+ File.open(file_path) do |f|
100
+ template = f.read
101
+
102
+ self.class.module_eval(<<-CODE)
103
+ def create_xml
104
+ builder = ::Nokogiri::XML::Builder.new(encoding: 'utf-8') do |xml|
105
+ #{template}
106
+ end.to_xml()
107
+ end
108
+ CODE
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,52 @@
1
+ # Resources collection handler
2
+
3
+ require 'active_resource'
4
+ require 'active_support/core_ext/hash/conversions'
5
+ require 'active_support/core_ext/hash/indifferent_access'
6
+
7
+ module MoySklad::Client
8
+ if ActiveResource::VERSION::STRING < '4.0.0'
9
+ class Collection
10
+ include Enumerable
11
+
12
+ delegate :collect, :each, :length, :to => :to_a
13
+
14
+ attr_accessor :elements
15
+
16
+ def to_a
17
+ @elements
18
+ end
19
+
20
+ def collect!
21
+ return @elements unless block_given?
22
+ set = []
23
+ each { |o| set << yield(o) }
24
+ @elements = set
25
+ self
26
+ end
27
+
28
+ alias map! collect!
29
+ end
30
+ else
31
+ class Collection < ActiveResource::Collection
32
+ end
33
+ end
34
+
35
+ class Collection
36
+ attr_reader :metadata
37
+
38
+ def initialize(data)
39
+
40
+ @elements = data[:data]['collection'].delete(data[:object])
41
+ @elements = [@elements] if @elements.is_a?(Hash)
42
+ @metadata = HashWithIndifferentAccess.new(data[:data]['collection'])
43
+
44
+ @elements ||= []
45
+
46
+ # Fix keys
47
+ [:total, :start, :count].each do |k|
48
+ @metadata[k] = @metadata[k].to_i if @metadata.has_key?(k)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ # Custom formatter
2
+ # Used only on retrive process. Submission encoder live in base.rb
3
+
4
+ require 'active_resource'
5
+ require 'active_support/core_ext/hash/conversions'
6
+
7
+ module MoySklad::Client
8
+ class Formatter
9
+ include ::ActiveResource::Formats::XmlFormat
10
+
11
+ attr_accessor :element_name
12
+
13
+ def decode(_data)
14
+ data = Hash.from_xml(_data)
15
+
16
+ if data.has_key?('collection')
17
+ collection(data)
18
+ else
19
+ {data.keys.first.underscore => data.values.first}
20
+ end
21
+ end
22
+
23
+ def _data(data)
24
+ { data: data, object: element_name[0].downcase + element_name[1..-1] }
25
+ end
26
+
27
+ if ActiveResource::VERSION::STRING < '4.0.0'
28
+ def collection(data)
29
+ MoySklad::Client::Collection.new(_data(data))
30
+ end
31
+ else
32
+ def collection(data)
33
+ _data(data)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,56 @@
1
+ # Nested resources management
2
+
3
+ module ActiveResource
4
+ class Base
5
+
6
+ # Nested object finder by type uuid + object uuid.
7
+ #
8
+ # MS data model have arrays which contains objects where each object have a special "type"
9
+ # uuid and object uuid. Type + Object uuids are PK for the object.
10
+ #
11
+ # @attr name [Symbol] attribute name
12
+ # @attr type [String] "type" uuid
13
+ # @attr key [String] "object" uuid
14
+ #
15
+ def find_object(name, type, key)
16
+ return nil if self.send(name).is_a?(MoySklad::Client::Attribute::MissingAttr)
17
+
18
+ create_nested_resource(name)
19
+
20
+ # Convert single attr to array
21
+ self.send("#{name}=", [self.send(name)]) unless self.send(name).is_a?(Array)
22
+
23
+ self.send(name).each do |v|
24
+ return v if v.send(type) == key
25
+ end
26
+
27
+ nil
28
+ end
29
+
30
+ private
31
+
32
+ # Construct nested resource class and load with given attributes
33
+ # NB: ALL nested classes should be created through this way.
34
+ def create_and_load_resource(name, attributes = nil)
35
+ res = find_or_create_resource_for(name).new
36
+ res.load(attributes) if !attributes.nil?
37
+ res
38
+ end
39
+
40
+ def create_nested_collection(name)
41
+ create_nested_collection_or_resource(name)
42
+ end
43
+
44
+ def create_nested_resource(name)
45
+ create_nested_collection_or_resource(name, false)
46
+ end
47
+
48
+ def create_nested_collection_or_resource(name, collection = true)
49
+ name = name.to_s
50
+ if !known_attributes.include?(name) || attributes[name].nil?
51
+ known_attributes << name
52
+ attributes[name] = collection ? [] : create_and_load_resource(name)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ require 'moy_sklad/client/formatter'
2
+ require 'moy_sklad/client/collection'
3
+ require 'moy_sklad/client/attribute'
4
+ require 'moy_sklad/client/resource'
5
+ require 'moy_sklad/client/base'
@@ -0,0 +1,74 @@
1
+ module MoySklad
2
+ # Returns the global [Configuration](MoySklad/Configuration) object. While you
3
+ # _can_ use this method to access the configuration, the more common
4
+ # convention is to use [MoySklad.configure](MoySklad#configure-class_method).
5
+ #
6
+ # @example
7
+ # MoySklad.configuration.user_name = 'admin@example'
8
+ # @see MoySklad.configure
9
+ # @see Configuration
10
+ def self.configuration
11
+ @configuration ||= MoySklad::Configuration.new
12
+ end
13
+
14
+ # Yields the global configuration to a block.
15
+ # @yield [Configuration] global configuration
16
+ #
17
+ # @example
18
+ # MoySklad.configure do |config|
19
+ # config.user_name 'admin@example'
20
+ # config.password '1234567890'
21
+ # end
22
+ # @see Configuration
23
+ def self.configure
24
+ yield configuration if block_given?
25
+ end
26
+
27
+ # Stores runtime configuration information.
28
+ #
29
+ # @example
30
+ # MoySklad.configure do |config|
31
+ # config.user_name 'admin@example'
32
+ # config.password '1234567890'
33
+ # end
34
+ #
35
+ # @see MoySklad.configure
36
+ class Configuration
37
+ # User name for authentication.
38
+ # @attr value [String] defaults to `''`
39
+ attr_reader :user_name
40
+
41
+ def user_name=(v)
42
+ MoySklad::Client::Base.user = @user_name = v
43
+ end
44
+
45
+ # Password for authentication.
46
+ # @attr value [String] defaults to `''`
47
+ attr_reader :password
48
+
49
+ def password=(v)
50
+ MoySklad::Client::Base.password = @password = v
51
+ end
52
+
53
+ # Base url.
54
+ # @attr value [String] defaults to
55
+ # `'https://online.moysklad.ru/exchange/rest/ms/xml'`
56
+ attr_reader :base_url
57
+
58
+ def base_url=(v)
59
+ MoySklad::Client::Base.site = @base_url = v
60
+ end
61
+
62
+ # Currency UUID.
63
+ # @attr value [String] defaults to
64
+ # `'131bf5ff-1ee5-11e4-67ed-002590a28eca'`
65
+ attr_accessor :currency
66
+
67
+ def initialize
68
+ @user_name = ''
69
+ @password = ''
70
+ @base_url = 'https://online.moysklad.ru/exchange/rest/ms/xml'
71
+ @currency = '131bf5ff-1ee5-11e4-67ed-002590a28eca'
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,23 @@
1
+ module MoySklad::Model
2
+ class Company < MoySklad::Client::Base
3
+ def initialize(*args)
4
+ super(*args)
5
+
6
+ create_nested_resource(:contact)
7
+ create_nested_resource(:requisite)
8
+ create_nested_resource(:tags)
9
+ create_nested_collection(:contactPerson)
10
+ requisite.create_nested_resource(:bankAccount)
11
+ end
12
+
13
+ def add_contact(options)
14
+
15
+ # We're always have one person
16
+ if to_a(:contactPerson).empty?
17
+ contactPerson << create_and_load_resource('contactPerson', options)
18
+ else
19
+ to_a(:contactPerson)[0].load(options)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ require 'yaml'
2
+
3
+ module MoySklad::Model
4
+ class Country < MoySklad::Client::Base
5
+ class << self
6
+ def uuid_from_code(code)
7
+ @_country_cache ||= YAML.load_file(File.join(File.dirname(__FILE__), 'data', 'country_codes.yml'))
8
+ @_country_cache[code.to_s]
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module MoySklad::Model
2
+ class CustomEntity < MoySklad::Client::Base
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ module MoySklad::Model
2
+ class CustomerOrder < MoySklad::Client::Base
3
+
4
+ def initialize(*args)
5
+ super(*args)
6
+ create_nested_collection(:customerOrderPosition)
7
+ create_nested_collection(:attribute)
8
+ create_nested_resource(:sum)
9
+ end
10
+
11
+ def add_item(id, options = {})
12
+ item = create_and_load_resource("CustomerOrderPosition",
13
+ { goodUuid: id }.merge!(options))
14
+ if to_a(:customerOrderPosition).empty?
15
+ self.customerOrderPosition = [item]
16
+ else
17
+ self.customerOrderPosition << item
18
+ end
19
+ end
20
+ end
21
+ end