rnsap 0.4.0 → 0.4.8

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.
@@ -0,0 +1,14 @@
1
+ # class used to represent a Table Column. Used internally
2
+ # to map SAP's returned working area (WA) into class instances
3
+ class TableColumn
4
+ # @return [String] Name of the table field
5
+ attr_accessor :field_name
6
+ # @return [Integer] Number of characters to offset when looking for the field in the Working Area (WA)
7
+ attr_accessor :offset
8
+ # @return [Integer] Length of the field returned in the Working Area (WA)
9
+ attr_accessor :length
10
+ # @return [String] Data Type (ex: Character, Decimal, Number)
11
+ attr_accessor :type
12
+ # @return [String] Field Description returned by the SAP dictionary
13
+ attr_accessor :description
14
+ end
data/lib/return.rb ADDED
@@ -0,0 +1,21 @@
1
+ # class used to represent RETURN. Used internally
2
+ class Return
3
+ # @return [String] Message code
4
+ attr_accessor :code
5
+ # @return [String] Application log: Internal message serial number
6
+ attr_accessor :log_msg_no
7
+ # @return [String] Application log: log number
8
+ attr_accessor :log_no
9
+ # @return [String] Message Text
10
+ attr_accessor :message
11
+ # @return [String] Message Variable
12
+ attr_accessor :message_v1
13
+ # @return [String] Message Variable
14
+ attr_accessor :message_v2
15
+ # @return [String] Message Variable
16
+ attr_accessor :message_v3
17
+ # @return [String] Message Variable
18
+ attr_accessor :message_v4
19
+ # @return [String] Message type: S Success, E Error, W Warning, I Info, A Abort
20
+ attr_accessor :type
21
+ end
data/lib/rnsap.rb CHANGED
@@ -1,8 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'nwrfc'
4
+ require 'read_table/table_column'
5
+ require 'preq_detail/preq_item'
6
+ require 'preq_detail/preq_acct_assignment'
7
+ require 'preq_detail/preq_text'
8
+ require 'preq_detail/preq_limits'
9
+ require 'preq_detail/preq_contract_limits'
10
+ require 'preq_detail/preq_services'
11
+ require 'preq_detail/preq_services_texts'
12
+ require 'preq_detail/preq_srv_accass_values'
13
+ require 'preq_release_info/preq_gen_release_info'
14
+ require 'preq_release_info/preq_release_prerequisites'
15
+ require 'preq_release_info/preq_release_posted'
16
+ require 'preq_release_info/preq_release_final'
17
+ require 'return'
18
+ require 'helper/rfc_helper'
19
+ require 'helper/util_helper'
4
20
 
5
21
  include NWRFC
22
+ include UtilHelper
6
23
 
7
24
  # Module for SAP helper methods. RnSap allows for a simpler
8
25
  # manner to access SAP servers calling RFC BAPIs.
@@ -18,6 +35,9 @@ module RnSap
18
35
  # keeps the SAP connection alive during the Sap instance lifecycle
19
36
  attr_reader :conn
20
37
 
38
+ INT_TYPES ||= ['b','N']
39
+ FLOAT_TYPES ||= ['P']
40
+ DATE_TYPES ||=['D']
21
41
  # Constructor requires to receive connection parameters,
22
42
  # a hash containint necessary information to logon to SAP
23
43
  # @param conn_parms [Hash] SAP Connection Parameters
@@ -30,6 +50,28 @@ module RnSap
30
50
  conn.disconnect
31
51
  end
32
52
 
53
+ def commit(conn)
54
+
55
+ #-- Execute BAPI_TRANSACTION_COMMIT
56
+ fn_commit = conn.get_function('BAPI_TRANSACTION_COMMIT')
57
+ fn_commit = fn_commit.get_function_call
58
+ fn_commit[:WAIT] = 'X'
59
+
60
+ fn_commit.invoke
61
+
62
+ api_return_success({tb_return: fn_commit[:RETURN]})
63
+ end
64
+
65
+ def rollback(conn)
66
+ #-- Execute BAPI_TRANSACTION_ROLLBACK
67
+ fn_rollback = conn.get_function('BAPI_TRANSACTION_ROLLBACK')
68
+ fn_rollback = fn_rollback.get_function_call
69
+
70
+ fn_rollback.invoke
71
+
72
+ api_return_success({tb_return: fn_rollback[:RETURN]})
73
+ end
74
+
33
75
  # Invokes SAP RFC_READ_TABLE function module remotely, passing
34
76
  # the table to be read and receiving back a list of objects of that
35
77
  # table.
@@ -107,13 +149,38 @@ module RnSap
107
149
  end
108
150
 
109
151
  list = []
152
+
110
153
  fc_read_table[:DATA].each do |row|
111
154
  obj = base_obj.class.new
112
- wa = row[:WA]
155
+ wa = row[:WA].split('|')
156
+ pos = -1
113
157
  fields_down.each do |field|
158
+ pos = pos + 1
114
159
  column = columns_hash[field.upcase]
115
- value = wa[column.offset.to_i, column.length.to_i]
116
- eval("obj.#{field} = '#{value}'")
160
+ # value = wa[column.offset.to_i, column.length.to_i]
161
+ if INT_TYPES.include?(column.type)
162
+ value = wa[pos].to_i
163
+ eval("obj.#{field} = #{value}")
164
+ elsif FLOAT_TYPES.include?(column.type)
165
+ value = wa[pos].to_f
166
+ eval("obj.#{field} = #{value}")
167
+ elsif DATE_TYPES.include?(column.type)
168
+ value = wa[pos].strip
169
+ if value == '00000000'
170
+ eval("obj.#{field} = nil")
171
+ else
172
+ value = Date.new(
173
+ value[0..3],
174
+ value[4..5],
175
+ value[6..7]
176
+ )
177
+ eval("obj.#{field} = #{value}")
178
+ end
179
+ else
180
+ value = wa[pos].strip
181
+ eval("obj.#{field} = '#{value}'")
182
+ end
183
+
117
184
  end
118
185
  list << obj
119
186
  end
@@ -133,26 +200,155 @@ module RnSap
133
200
  fc_preq_detail[:SERVICE_TEXTS] = services_texts
134
201
 
135
202
  fc_preq_detail.invoke
203
+
204
+ #-- Execute conversions for returned tables to a designated list (array)
205
+ preq_items = get_object_list(fc_preq_detail[:REQUISITION_ITEMS], PreqItem.to_s)
206
+ preq_acct_assignment = get_object_list(fc_preq_detail[:REQUISITION_ACCOUNT_ASSIGNMENT], PreqAcctAssignment.to_s)
207
+ preq_text = get_object_list(fc_preq_detail[:REQUISITION_TEXT], PreqText.to_s)
208
+ preq_limits = get_object_list(fc_preq_detail[:REQUISITION_LIMITS], PreqLimits.to_s)
209
+ preq_contract_limits = get_object_list(fc_preq_detail[:REQUISITION_CONTRACT_LIMITS], PreqContractLimits.to_s)
210
+ preq_services = get_object_list(fc_preq_detail[:REQUISITION_SERVICES], PreqItem.to_s)
211
+ preq_services_texts = get_object_list(fc_preq_detail[:REQUISITION_SERVICES_TEXTS], PreqServicesText.to_s)
212
+ preq_srv_accass_values = get_object_list(fc_preq_detail[:REQUISITION_SRV_ACCASS_VALUES], PreqServicesAccassValues.to_s)
213
+ tb_return = get_object_list(fc_preq_detail[:RETURN], Return.to_s)
214
+
215
+ retcode = tb_return.detect{|r| r.type == 'E'}
216
+
217
+ if retcode
218
+ api_return_error(retcode)
219
+ else
220
+ api_return_success({
221
+ preq_items: preq_items,
222
+ preq_acct_assignment: preq_acct_assignment,
223
+ preq_text: preq_text,
224
+ preq_limits: preq_limits,
225
+ preq_contract_limits: preq_contract_limits,
226
+ preq_services: preq_services,
227
+ preq_services_texts: preq_services_texts,
228
+ preq_srv_accass_values: preq_srv_accass_values,
229
+ tb_return: tb_return,
230
+ })
231
+ end
136
232
 
137
- list = []
138
- avoid_list = ['!','__','+', '=','!', '?','~','>', '<']
139
- fc_preq_detail[:REQUISITION_ITEMS].each do |row|
140
- preq = PreqItem.new
141
- preq.class.instance_methods.each do |method_name|
142
- begin
143
- if preq.respond_to?("#{method_name}=")
144
- unless avoid_list.any? { |word| method_name.to_s.include?(word)}
145
- value = row[method_name]
146
- eval("preq.#{method_name} = '#{value}'")
147
- end
148
- end
149
- rescue
150
- end
233
+ end
234
+
235
+ def preq_release_strategy_info(preq = 0, item = "00000", rel_code = "")
236
+ #-- Execute BAPI_REQUISITION_GETRELINFO
237
+ fn_preq_rel_strat_info = @conn.get_function('BAPI_REQUISITION_GETRELINFO')
238
+ fn_preq_rel_strat_info = fn_preq_rel_strat_info.get_function_call
239
+
240
+ fn_preq_rel_strat_info[:NUMBER] = preq
241
+ fn_preq_rel_strat_info[:ITEM] = item
242
+ fn_preq_rel_strat_info[:REL_CODE] = rel_code
243
+
244
+ fn_preq_rel_strat_info.invoke
245
+
246
+ #-- Execute conversions for returned tables to a designated list (array)
247
+ preq_gen_release_info = get_object_list(fn_preq_rel_strat_info[:GENERAL_RELEASE_INFO], PreqGenReleaseInfo.to_s)
248
+ preq_release_prerequisites = get_object_list(fn_preq_rel_strat_info[:RELEASE_PREREQUISITES], PreqReleasePrerequisites.to_s)
249
+ preq_release_posted = get_object_list(fn_preq_rel_strat_info[:RELEASE_ALREADY_POSTED], PreqReleasePosted.to_s)
250
+ preq_release_final = get_object_list(fn_preq_rel_strat_info[:RELEASE_FINAL], PreqReleaseFinal.to_s)
251
+ tb_return = get_object_list(fn_preq_rel_strat_info[:RETURN], Return.to_s)
252
+
253
+ retcode = tb_return.detect{|r| r.type == 'E'}
254
+
255
+ if retcode
256
+ api_return_error(retcode)
257
+ else
258
+ api_return_success({
259
+ preq_gen_release_info: preq_gen_release_info,
260
+ preq_release_prerequisites: preq_release_prerequisites,
261
+ preq_release_posted: preq_release_posted,
262
+ preq_release_final: preq_release_final,
263
+ tb_return: tb_return,
264
+ })
265
+ end
266
+ end
267
+
268
+ def preq_release(preq = 0, rel_code = "", no_commit="", item="00000", use_exceptions="")
269
+ #Validate if will release by item ou general
270
+ if item == "00000" or item == nil or item.empty?
271
+ #-- Execute BAPI_REQUISITION_RELEASE_GEN
272
+ fn_preq_exec_release = @conn.get_function('BAPI_REQUISITION_RELEASE_GEN')
273
+ fn_preq_exec_release = fn_preq_exec_release.get_function_call
274
+ else
275
+ #-- Execute BAPI_REQUISITION_RELEASE
276
+ fn_preq_exec_release = @conn.get_function('BAPI_REQUISITION_RELEASE')
277
+ fn_preq_exec_release = fn_preq_exec_release.get_function_call
278
+ fn_preq_exec_release[:ITEM] = item
279
+ fn_preq_exec_release[:USE_EXCEPTIONS] = use_exceptions
280
+ end
281
+
282
+ fn_preq_exec_release[:NUMBER] = preq
283
+ fn_preq_exec_release[:REL_CODE] = rel_code
284
+ fn_preq_exec_release[:NO_COMMIT_WORK] = no_commit
285
+
286
+ fn_preq_exec_release.invoke
287
+
288
+ tb_return = get_object_list(fn_preq_exec_release[:RETURN], Return.to_s)
289
+
290
+ retcode = tb_return.detect{|r| r.type == 'E'}
291
+
292
+ if retcode
293
+ api_return_error(retcode)
294
+ else
295
+ api_return_success({
296
+ status_new: fn_preq_exec_release[:REL_STATUS_NEW],
297
+ indicator_new: fn_preq_exec_release[:REL_INDICATOR_NEW],
298
+ tb_return: tb_return,
299
+ })
300
+ end
301
+ end
302
+
303
+ def po_detail(po = 0)
304
+ []
305
+ end
306
+
307
+ def po_release_strategy_info(po = 1)
308
+ []
309
+ end
310
+
311
+ # Performs SAP Authority check on a certain authorization
312
+ # object. For more details on SAP authorization,
313
+ # this link will provide good details:
314
+ # * https://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/a92195a9-0b01-0010-909c-f330ea4a585c&overridelayout=true
315
+ # * https://blogs.sap.com/2020/11/14/some-important-information-about-sap-authorization-objects/
316
+ # @param user [String] SAP userid for which authorization will be performed
317
+ # @param auth_object [String] Authorization object to be checked in SAP
318
+ # @param field [String] Authorization field checked within the authorization object
319
+ # @param value [String] Authorization value to be checked. (i.e. 01 for creation, 02 for change, XX for release code)
320
+ def authority_check(user, auth_object, field, value)
321
+ #-- Execute AUTHORITY_CHECK
322
+ function = @conn.get_function('AUTHORITY_CHECK')
323
+ fun_call = function.get_function_call
324
+
325
+ fun_call[:USER] = user
326
+ fun_call[:OBJECT] = auth_object
327
+ fun_call[:FIELD1] = field
328
+ fun_call[:VALUE1] = value
329
+
330
+ begin
331
+ fun_call.invoke
332
+ rescue Exception => ex
333
+ if ex.to_s.include?('USER_IS_AUTHORIZED')
334
+ api_return(0,'Authorized');
335
+ else
336
+ api_return(8,'User is not authorized.')
151
337
  end
152
- list.push(preq)
153
338
  end
154
339
 
155
- list
340
+ end
341
+
342
+ def api_return_success(obj=nil )
343
+ UtilHelper.api_return(0, 'Success!', obj)
344
+ end
345
+
346
+ def api_return_error(obj={}, exception=nil)
347
+ UtilHelper.api_return(8, 'Error.', obj, exception)
348
+ end
349
+
350
+ def api_return(rc=0, message ='', obj=nil, exception=nil )
351
+ UtilHelper.api_return(rc, message, obj, exception)
156
352
  end
157
353
 
158
354
  private
data/lib/rnsap_spec.rb ADDED
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'yaml'
5
+ require_relative '../lib/rnsap'
6
+ require_relative '../lib/preq_detail/preq_item'
7
+
8
+ describe RnSap::Sap do
9
+ let(:params) do
10
+ file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'secrets.yml'))
11
+ YAML.safe_load(File.read(file))
12
+ end
13
+
14
+ let(:logon_info) do
15
+ { 'user' => params['user'],
16
+ 'passwd' => params['password'],
17
+ 'trace' => params['trace'],
18
+ 'client' => params['client'],
19
+ 'ashost' => params['ashost'],
20
+ 'sysnr' => params['sysnr'] }
21
+ end
22
+
23
+ let(:test_data) do
24
+ file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_data.yml'))
25
+ YAML.safe_load(File.read(file))
26
+ end
27
+
28
+ let(:conn) do
29
+ RnSap::Sap.new(logon_info)
30
+ end
31
+
32
+ context 'Based on connection available parameters' do
33
+ it 'connects to SAP' do
34
+ expect(conn).not_to be_nil
35
+ end
36
+ end
37
+
38
+ context 'Reads table information from SAP' do
39
+ it 'gets at least one vendor' do
40
+ list = conn.read_table('lfa1', %w[NAME1 LIFNR LAND1])
41
+ expect(list.count).to be > 0
42
+ end
43
+ it 'gets at least one Raw material' do
44
+ list = conn.read_table('mara', %w[matnr ernam], ["MTART = 'ROH'"])
45
+ expect(list.count).to be > 0
46
+ end
47
+
48
+ it 'gets a two Raw materials skipping the first in the database' do
49
+ list = conn.read_table({ name: 'mara', fields: %w[matnr ernam], clauses: ["MTART = 'ROH'"], row_skip: 1, row_count: 2 })
50
+ expect(list.count).to eq(2)
51
+ end
52
+ end
53
+
54
+ context 'Gets information from a Purchase Requisition' do
55
+ it 'Obtains details from purchase requisition' do
56
+ pr = test_data['preqs']['number']
57
+ puts " -> Pesquisando P.Req: #{pr}"
58
+ details = conn.preq_detail(pr)
59
+
60
+ expect(details).not_to be_nil
61
+ expect(details.class).to be(Hash)
62
+ end
63
+
64
+ it 'gets purchase requisition Release Strategy info' do
65
+ pr = test_data['preqs']['number']
66
+ details = conn.preq_release_strategy_info(pr)
67
+
68
+ expect(details).not_to be_nil
69
+ expect(details.class).to be(Hash)
70
+ end
71
+ end
72
+
73
+ context 'Gets information from a Purchase Order' do
74
+ it 'Obtains details from purchase requisition' do
75
+ po = test_data['po']['number']
76
+ puts " -> Pesquisando P.Order: #{po}"
77
+ details = conn.po_detail(po)
78
+
79
+ expect(details).not_to be_nil
80
+ expect(details.class).to be(Array)
81
+ end
82
+
83
+ it 'gets purchase requisition Release Strategy info' do
84
+ po = test_data['po']['number']
85
+ details = conn.po_release_strategy_info(po)
86
+
87
+ expect(details).not_to be_nil
88
+ expect(details.class).to be(Array)
89
+ end
90
+ end
91
+
92
+
93
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rnsap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rogerio Nascimento
@@ -45,7 +45,24 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - lib/helper/rfc_helper.rb
49
+ - lib/helper/util_helper.rb
50
+ - lib/preq_detail/preq_acct_assignment.rb
51
+ - lib/preq_detail/preq_contract_limits.rb
52
+ - lib/preq_detail/preq_item.rb
53
+ - lib/preq_detail/preq_limits.rb
54
+ - lib/preq_detail/preq_services.rb
55
+ - lib/preq_detail/preq_services_texts.rb
56
+ - lib/preq_detail/preq_srv_accass_values.rb
57
+ - lib/preq_detail/preq_text.rb
58
+ - lib/preq_release_info/preq_gen_release_info.rb
59
+ - lib/preq_release_info/preq_release_final.rb
60
+ - lib/preq_release_info/preq_release_posted.rb
61
+ - lib/preq_release_info/preq_release_prerequisites.rb
62
+ - lib/read_table/table_column.rb
63
+ - lib/return.rb
48
64
  - lib/rnsap.rb
65
+ - lib/rnsap_spec.rb
49
66
  homepage: https://github.com/rnasc/rnsap
50
67
  licenses:
51
68
  - MIT