twinfieldrb 0.3.0

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 (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