moy_sklad 1.0.0.beta1

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