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.
- checksums.yaml +4 -4
- data/lib/helper/rfc_helper.rb +21 -0
- data/lib/helper/util_helper.rb +39 -0
- data/lib/preq_detail/preq_acct_assignment.rb +109 -0
- data/lib/preq_detail/preq_contract_limits.rb +27 -0
- data/lib/preq_detail/preq_item.rb +259 -0
- data/lib/preq_detail/preq_limits.rb +59 -0
- data/lib/preq_detail/preq_services.rb +153 -0
- data/lib/preq_detail/preq_services_texts.rb +13 -0
- data/lib/preq_detail/preq_srv_accass_values.rb +23 -0
- data/lib/preq_detail/preq_text.rb +13 -0
- data/lib/preq_release_info/preq_gen_release_info.rb +23 -0
- data/lib/preq_release_info/preq_release_final.rb +55 -0
- data/lib/preq_release_info/preq_release_posted.rb +55 -0
- data/lib/preq_release_info/preq_release_prerequisites.rb +55 -0
- data/lib/read_table/table_column.rb +14 -0
- data/lib/return.rb +21 -0
- data/lib/rnsap.rb +215 -19
- data/lib/rnsap_spec.rb +93 -0
- metadata +18 -1
@@ -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
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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
|
-
|
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.
|
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
|