twinfieldrb 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/codeql-analysis.yml +70 -0
  3. data/.github/workflows/rspec.yml +33 -0
  4. data/.gitignore +6 -0
  5. data/.rspec +1 -0
  6. data/CHANGELOG.md +15 -0
  7. data/Gemfile +4 -0
  8. data/README.md +120 -0
  9. data/Rakefile +1 -0
  10. data/lib/twinfield/abstract_model.rb +7 -0
  11. data/lib/twinfield/api/base_api.rb +50 -0
  12. data/lib/twinfield/api/finder.rb +45 -0
  13. data/lib/twinfield/api/o_auth_session.rb +58 -0
  14. data/lib/twinfield/api/process.rb +44 -0
  15. data/lib/twinfield/api/session.rb +170 -0
  16. data/lib/twinfield/browse/transaction/cost_center.rb +145 -0
  17. data/lib/twinfield/browse/transaction/customer.rb +413 -0
  18. data/lib/twinfield/browse/transaction/general_ledger.rb +144 -0
  19. data/lib/twinfield/configuration.rb +49 -0
  20. data/lib/twinfield/create/cost_center.rb +39 -0
  21. data/lib/twinfield/create/creditor.rb +88 -0
  22. data/lib/twinfield/create/debtor.rb +88 -0
  23. data/lib/twinfield/create/error.rb +30 -0
  24. data/lib/twinfield/create/general_ledger.rb +39 -0
  25. data/lib/twinfield/create/transaction.rb +97 -0
  26. data/lib/twinfield/customer.rb +612 -0
  27. data/lib/twinfield/helpers/parsers.rb +23 -0
  28. data/lib/twinfield/helpers/transaction_match.rb +40 -0
  29. data/lib/twinfield/request/find.rb +149 -0
  30. data/lib/twinfield/request/list.rb +66 -0
  31. data/lib/twinfield/request/read.rb +111 -0
  32. data/lib/twinfield/sales_invoice.rb +409 -0
  33. data/lib/twinfield/transaction.rb +112 -0
  34. data/lib/twinfield/version.rb +5 -0
  35. data/lib/twinfield.rb +89 -0
  36. data/script/boot.rb +58 -0
  37. data/script/console +2 -0
  38. data/spec/fixtures/cluster/finder/ivt.xml +1 -0
  39. data/spec/fixtures/cluster/processxml/columns/sales_transactions.xml +312 -0
  40. data/spec/fixtures/cluster/processxml/customer/create_success.xml +100 -0
  41. data/spec/fixtures/cluster/processxml/customer/read_success.xml +93 -0
  42. data/spec/fixtures/cluster/processxml/customer/update_success.xml +1 -0
  43. data/spec/fixtures/cluster/processxml/invoice/create_error.xml +8 -0
  44. data/spec/fixtures/cluster/processxml/invoice/create_final_error.xml +67 -0
  45. data/spec/fixtures/cluster/processxml/invoice/create_success.xml +64 -0
  46. data/spec/fixtures/cluster/processxml/invoice/read_not_found.xml +1 -0
  47. data/spec/fixtures/cluster/processxml/invoice/read_success.xml +106 -0
  48. data/spec/fixtures/cluster/processxml/read/deb.xml +12 -0
  49. data/spec/fixtures/cluster/processxml/response.xml +8 -0
  50. data/spec/fixtures/login/session/wsdl.xml +210 -0
  51. data/spec/spec_helper.rb +17 -0
  52. data/spec/stubs/finder_stubs.rb +19 -0
  53. data/spec/stubs/processxml_stubs.rb +41 -0
  54. data/spec/stubs/session_stubs.rb +28 -0
  55. data/spec/twinfield/api/oauth_session_spec.rb +37 -0
  56. data/spec/twinfield/api/process_spec.rb +7 -0
  57. data/spec/twinfield/browse/transaction/cost_center_spec.rb +60 -0
  58. data/spec/twinfield/browse/transaction/general_ledger_spec.rb +60 -0
  59. data/spec/twinfield/browse/transaction/transaction_spec.rb +72 -0
  60. data/spec/twinfield/config_spec.rb +60 -0
  61. data/spec/twinfield/customer_spec.rb +326 -0
  62. data/spec/twinfield/request/find_spec.rb +24 -0
  63. data/spec/twinfield/request/list_spec.rb +58 -0
  64. data/spec/twinfield/request/read_spec.rb +26 -0
  65. data/spec/twinfield/sales_invoice_spec.rb +253 -0
  66. data/spec/twinfield/session_spec.rb +77 -0
  67. data/spec/twinfield/transaction_spec.rb +149 -0
  68. data/twinfieldrb.gemspec +24 -0
  69. data/wsdls/accounting/finder.wsdl +157 -0
  70. data/wsdls/accounting/process.wsdl +199 -0
  71. data/wsdls/accounting/session.wsdl +452 -0
  72. data/wsdls/accounting2/finder.wsdl +157 -0
  73. data/wsdls/accounting2/process.wsdl +199 -0
  74. data/wsdls/api.accounting/finder.wsdl +157 -0
  75. data/wsdls/api.accounting/process.wsdl +199 -0
  76. data/wsdls/session.wsdl +210 -0
  77. data/wsdls/update +10 -0
  78. metadata +196 -0
@@ -0,0 +1,149 @@
1
+ module Twinfield
2
+ module Request
3
+ module Find
4
+ extend self
5
+
6
+ def articles
7
+ options = {}
8
+ options.merge(office: Twinfield.configuration.company)
9
+
10
+ response = Twinfield::Api::Finder.request("ART", options)
11
+
12
+ response.body[:search_response][:data][:items][:array_of_string].values.map do |item|
13
+ {
14
+ code: item[0],
15
+ name: item[1]
16
+ }
17
+ end
18
+ end
19
+
20
+ def asset_methods
21
+ options = {}
22
+ options.merge(office: Twinfield.configuration.company)
23
+
24
+ response = Twinfield::Api::Finder.request("ASM", options)
25
+
26
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
27
+ {
28
+ code: item[:string][0],
29
+ name: item[:string][1]
30
+ }
31
+ end
32
+ end
33
+
34
+ def budgets
35
+ options = {}
36
+ options.merge(office: Twinfield.configuration.company)
37
+
38
+ response = Twinfield::Api::Finder.request("BDS", options)
39
+
40
+ response.body[:search_response][:data][:items][:array_of_string].values.map do |item|
41
+ {
42
+ code: item[0],
43
+ name: item[1]
44
+ }
45
+ end
46
+ end
47
+
48
+ def credit_management_action_codes
49
+ options = {}
50
+ options.merge(office: Twinfield.configuration.company)
51
+
52
+ response = Twinfield::Api::Finder.request("CDA", options)
53
+
54
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
55
+ {
56
+ code: item[:string][0],
57
+ name: item[:string][1]
58
+ }
59
+ end
60
+ end
61
+
62
+ def sales_transactions(options = {})
63
+ options.merge(office: Twinfield.configuration.company)
64
+
65
+ response = Twinfield::Api::Finder.request("IVT", options)
66
+
67
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
68
+ {
69
+ invoice_number: item[:string][0],
70
+ amount: item[:string][1],
71
+ debtor_code: item[:string][2],
72
+ debtor_name: item[:string][3],
73
+ debit_credit: item[:string][4]
74
+ }
75
+ end
76
+ end
77
+
78
+ def creditors
79
+ options = {dimtype: "CRD"}
80
+ options.merge(office: Twinfield.configuration.company)
81
+
82
+ response = Twinfield::Api::Finder.request("DIM", options)
83
+
84
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
85
+ {
86
+ code: item[:string][0],
87
+ name: item[:string][1]
88
+ }
89
+ end
90
+ end
91
+
92
+ def debtors
93
+ options = {dimtype: "DEB"}
94
+ options.merge(office: Twinfield.configuration.company)
95
+
96
+ response = Twinfield::Api::Finder.request("DIM", options)
97
+
98
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
99
+ {
100
+ code: item[:string][0],
101
+ name: item[:string][1]
102
+ }
103
+ end
104
+ end
105
+
106
+ def cost_centers
107
+ options = {dimtype: "KPL"}
108
+ options.merge(office: Twinfield.configuration.company)
109
+
110
+ response = Twinfield::Api::Finder.request("DIM", options)
111
+
112
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
113
+ {
114
+ code: item[:string][0],
115
+ name: item[:string][1]
116
+ }
117
+ end
118
+ end
119
+
120
+ def general_ledgers(options)
121
+ options = options.merge(office: Twinfield.configuration.company)
122
+
123
+ response = Twinfield::Api::Finder.request("DIM", options)
124
+
125
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
126
+ {
127
+ code: item[:string][0],
128
+ name: item[:string][1]
129
+ }
130
+ end
131
+ end
132
+
133
+ # Twinfield::Request::Find.test
134
+ def test
135
+ options = {office: Twinfield.configuration.company, dimtype: "CRD"}
136
+
137
+ response = Twinfield::Api::Finder.request("DIM", options)
138
+
139
+ response.body[:search_response][:data][:items][:array_of_string].map do |item|
140
+ {
141
+
142
+ code: item[:string][0],
143
+ name: item[:string][1]
144
+ }
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,66 @@
1
+ module Twinfield
2
+ module Request
3
+ module List
4
+ extend self
5
+
6
+ def browsefields
7
+ xml_doc = xml_wrap(list(:browsefields))
8
+
9
+ array = []
10
+ xml_doc.css("browsefield").each do |xml|
11
+ array << {
12
+ code: xml.at_css("code").content,
13
+ datatype: xml.at_css("datatype").content,
14
+ finder: xml.at_css("finder").content,
15
+ dropdown: xml.at_css("dropdown").css("option").map { |opt| opt[:name] },
16
+ canorder: xml.at_css("canorder").content
17
+ }
18
+ end
19
+
20
+ array
21
+ end
22
+
23
+ def budgets(options)
24
+ xml_wrap(list(:budgets, options))
25
+ end
26
+
27
+ # Twinfield::Request::List.dimensions({ dimtype: "DEB" })
28
+ def dimensions(options)
29
+ options = options.merge(office: Twinfield.configuration.company)
30
+ xml_wrap(list(:dimensions, options))
31
+ end
32
+
33
+ def offices
34
+ xml_doc = xml_wrap(list(:offices))
35
+
36
+ array = []
37
+ xml_doc.css("office").each do |xml|
38
+ array << {
39
+ name: xml[:name],
40
+ shortname: xml[:shortname],
41
+ code: xml.content
42
+ }
43
+ end
44
+
45
+ array
46
+ end
47
+
48
+ protected
49
+
50
+ def list(element, options = {})
51
+ Twinfield::Api::Process.request(:process_xml_string) do
52
+ %(
53
+ <list>
54
+ <type>#{element}</type>
55
+ #{Twinfield::Api::Process.options_to_xml(options)}
56
+ </list>
57
+ )
58
+ end
59
+ end
60
+
61
+ def xml_wrap(response)
62
+ Nokogiri::XML(response.body[:process_xml_string_response][:process_xml_string_result])
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,111 @@
1
+ module Twinfield
2
+ module Request
3
+ module Read
4
+ extend self
5
+
6
+ def office(options)
7
+ xml_wrap(read(:office, options))
8
+ end
9
+
10
+ def debtor(options)
11
+ xml = xml_wrap(read(:dimensions, options.merge(dimtype: "DEB")))
12
+
13
+ if xml.at_css("dimensions").attributes["result"]&.value == "1"
14
+ []
15
+ elsif xml.at_css("dimension").attributes["result"].value == "1"
16
+ {
17
+ status: 1,
18
+ country: xml.at_css("country").content,
19
+ city: xml.at_css("city").content,
20
+ postcode: xml.at_css("postcode").content,
21
+ address: xml.at_css("field2").content,
22
+ duedays: xml.at_css("duedays").content
23
+ }
24
+ else
25
+ {
26
+ status: 0
27
+ }
28
+ end
29
+ end
30
+
31
+ # Twinfield::Request::Read.sales_invoice({})
32
+ def sales_invoice(invoicenumber, invoicetype: "FACTUUR")
33
+ options = {office: Twinfield.configuration.company, code: "FACTUUR", invoicenumber: invoicenumber}
34
+
35
+ xml = xml_wrap(read(:salesinvoice, options))
36
+
37
+ if xml.at_css("dimension").attributes["result"].value == "1"
38
+ {
39
+ status: 1,
40
+ country: xml.at_css("country").content,
41
+ city: xml.at_css("city").content,
42
+ postcode: xml.at_css("postcode").content,
43
+ address: xml.at_css("field2").content,
44
+ duedays: xml.at_css("duedays").content
45
+ }
46
+ else
47
+ {
48
+ status: 0
49
+ }
50
+ end
51
+ end
52
+
53
+ # Twinfield::Request::Read.browse( options: { code: "000" })
54
+ def browse(options)
55
+ options = options.merge(office: Twinfield.configuration.company)
56
+
57
+ xml_wrap(read(:browse, options))
58
+
59
+ {
60
+ status: 0
61
+ }
62
+ end
63
+
64
+ def xml_to_json(xml)
65
+ rv = {}
66
+ nokogiri = xml.is_a?(String) ? Nokogiri::XML(xml) : xml
67
+
68
+ nokogiri.children.each do |node|
69
+ twig = [xml_to_json(node)]
70
+ twig_keys = twig.map { |a| a.keys }.flatten
71
+ uniq_twig_keys = twig_keys.uniq
72
+ if uniq_twig_keys.count == 1 && "#{uniq_twig_keys.first}s" == node.name
73
+ twig = twig.map { |a| a.values }.flatten
74
+ elsif node.is_a?(Nokogiri::XML::Element) && node.children.count == 1 && node.children.first.is_a?(Nokogiri::XML::Text)
75
+ twig = node.text
76
+ if /\A\d*$/.match?(twig)
77
+ twig = twig.to_i
78
+ end
79
+ elsif node.text.strip == ""
80
+ twig = nil
81
+ end
82
+
83
+ # do not unnecesarily wrap a hash with uniq keys in an array
84
+ if twig.is_a?(Array) && !node.name.end_with?("s") && twig.count == 1
85
+ twig = twig[0]
86
+ end
87
+
88
+ rv[node.name.to_sym] = twig if twig
89
+ end
90
+ rv
91
+ end
92
+
93
+ protected
94
+
95
+ def read(element, options = {})
96
+ Twinfield::Api::Process.request(:process_xml_string) do
97
+ %(
98
+ <read>
99
+ <type>#{element}</type>
100
+ #{Twinfield::Api::Process.options_to_xml(options)}
101
+ </read>
102
+ )
103
+ end
104
+ end
105
+
106
+ def xml_wrap(response)
107
+ Nokogiri::XML(response.body[:process_xml_string_response][:process_xml_string_result])
108
+ end
109
+ end
110
+ end
111
+ end