Update Oct, 18th 2006: Functions are now also avaliable as a Web Service. You can download the WSDL and then start developing using the Web Service. Username and Password for HTTP Basic Authentication is SDNCONTEST. piers.harding/blog provided already a Ruby, Ruby on Rails, and SAP Web Services Integration how to do that.
Siteco currently provides its customers access to online price, availability and order information through an ITS Flow Logic application. We currently integrate this application into our corporate website. It is based on the Open Source web content management system Typo3 written in PHP. We write our own extensions for Typo3 to access SAP using SOAP Web Services.
Playing around with Ruby on Rails I thought wouldnt it be better to do it or at least Prototypes for new Features to directly show them our Sales people. We can benefit from Rails advantages: Clear Model View Controller Concept, Dont Repeat Yourself (DRY) and AJAX awareness. Using Piers Hardings saprfc and sap4rails this should be possible.
To start developing the Rails application you can use Craig Cmehils great Scripting in a Box v0.1 Package which already includes Ruby on Rails. To make it work correctly with the Eclipse RadRails Perspective you have to apply the Patches described in URL for the Ruby on Rails example in Scripting in a Box Version 0.1.0.
This is the prize for the best implementation in the Contest a Siteco Vistosa task light:
Login:
Navigation after Login:
Welcome Screen:
Availability check and price information:
Sales Order Status:
Sales Order Details:
PDF of Delivery Note:
Change Password:
To allow everyone to compete to this contest Ive opened an ERP 2004 system to the public with a special User having only authorizations for the needed functionality. You find the login information in the Ruby Unit Test.
This BAPIs are used to achieve the functionality shown in the Business case:
The User Ive created has the Contact Person ID 111 the Type is BUS1006001 which is a Business partner employee. The password is set to test1.
Here is the code of the Ruby Unit Test:
require 'test/unit' require 'test/unit/assertions' require 'rubygems' require_gem 'saprfc' class SAPTest < Test::Unit::TestCase # Login Data @@partneremployeeid = "111" @@password = "test1" @@newpassword = "test2" # Product Data @@material = 'P-100' @@unit = '' # Values set during Test @@customer = '' @@salesorg = '' @@subtotal1 = '' @@subtotal2 = '' def setup SAP::Rfc.useCache = true @rfc = SAP::Rfc.new( :ashost => "lupomania.dyndns.org", :sysnr => 00, :lang => "EN", :client => "800", :user => "SDNCONTEST", :passwd => "SDNCONTEST", :trace => 0 ) end def test_CSC_00005_Login # Check Password pwcheck = @rfc.discover("BAPI_PAR_EMPLOYEE_CHECKPASSWOR") pwcheck.PARTNEREMPLOYEEID.value = @@partneremployeeid pwcheck.PASSWORD.value = @@password @rfc.call(pwcheck) ret = pwcheck.RETURN.value assert(ret['TYPE'] == 'S') # Get Customer Number excheck = @rfc.discover("BAPI_PAR_EMPLOYEE_CHECKEXISTEN") excheck.PARTNEREMPLOYEEID.value = @@partneremployeeid @rfc.call(excheck) @@customer = excheck.CUSTOMER.value assert( @@customer != nil) #puts "
Customer Number: " + @@customer # Get Sales Areas getsalesareas = @rfc.discover("BAPI_CUSTOMER_GETSALESAREAS") getsalesareas.CUSTOMERNO.value = @@customer @rfc.call(getsalesareas) ret = getsalesareas.RETURN.value assert(ret['TYPE'] == 'S') getsalesareas.SALESAREAS.hashRows {|x| @@salesorg = x['SALESORG'] } assert(@@salesorg == '1000') end def test_CSC_00010_CustomerDetail customerdetail = @rfc.discover("BAPI_CUSTOMER_GETDETAIL2") customerdetail.CUSTOMERNO.value = @@customer @rfc.call(customerdetail) ret = customerdetail.RETURN.value assert(ret['TYPE'] != 'E') address = customerdetail.CUSTOMERADDRESS.value puts "
Customer Name: " + address['NAME'] assert( address['NAME'] != nil ) end def test_CSC_00012_ContactDetail contactdetail = @rfc.discover("BAPI_BUSPARTNEREMPLOYE_GETLIST") idrange = contactdetail.IDRANGE.structure idrange.SIGN.value = 'I' idrange.OPTION.value = 'EQ' idrange.LOW.value = @@partneremployeeid contactdetail.IDRANGE.value = [ idrange.value ] @rfc.call(contactdetail) contactdetail.ADDRESSDATA.hashRows { |x| assert( x['LASTNAME'] != nil ) puts "
Contact last name: " + x['LASTNAME'] } end def test_CSC_00015_ChangePassword # Change Password changepassword = @rfc.discover("BAPI_PAR_EMPLOYEE_CHANGEPASSWO") changepassword.PARTNEREMPLOYEEID.value = @@partneremployeeid changepassword.PASSWORD.value = @@password changepassword.NEW_PASSWORD.value = @@newpassword changepassword.VERIFY_PASSWORD.value = @@newpassword @rfc.call(changepassword) ret = changepassword.RETURN.value assert(ret['TYPE'] == 'S') # Back to default changepassword.PASSWORD.value = @@newpassword changepassword.NEW_PASSWORD.value = @@password changepassword.VERIFY_PASSWORD.value = @@password @rfc.call(changepassword) ret = changepassword.RETURN.value assert(ret['TYPE'] == 'S') end def test_CSC_00020_Salesorders # Salesorder List salesorderlist = @rfc.discover("BAPI_SALESORDER_GETLIST") salesorderlist.CUSTOMER_NUMBER.value = @@customer salesorderlist.SALES_ORGANIZATION.value = @@salesorg salesorderlist.TRANSACTION_GROUP.value = 0 @rfc.call(salesorderlist) ret = salesorderlist.RETURN.value assert(ret['TYPE'] != 'E') salesorderlist.SALES_ORDERS.hashRows {|x| @sddoc = x['SD_DOC'] } assert( @sddoc != nil) puts "
Sales Document Number: " + @sddoc # Salesorder salesorder = @rfc.discover("BAPISDORDER_GETDETAILEDLIST") view = salesorder.I_BAPI_VIEW.structure view.HEADER.value = 'X' view.ITEM.value = 'X' salesorder.I_BAPI_VIEW.value = view.value salesdocs = salesorder.SALES_DOCUMENTS.structure salesdocs.VBELN.value = @sddoc salesorder.SALES_DOCUMENTS.value = [ salesdocs.value ] @rfc.call(salesorder) salesorder.ORDER_ITEMS_OUT.hashRows {|x| @doc_number = x['DOC_NUMBER'] } assert( @sddoc == @doc_number ) end def test_CSC_00030_MaterialDetails # Material Detail materialdetail = @rfc.discover("BAPI_MATERIAL_GET_DETAIL") materialdetail.MATERIAL.value = @@material @rfc.call(materialdetail) ret = materialdetail.RETURN.value assert(ret['TYPE'] == 'S') materialgeneral = materialdetail.MATERIAL_GENERAL_DATA.value @@unit = materialgeneral['BASE_UOM'] assert( @@unit != nil) puts "
Material Unit: " + @@unit end def test_CSC_00040_Availability materialavailability = @rfc.discover("BAPI_MATERIAL_AVAILABILITY") materialavailability.MATERIAL.value = @@material materialavailability.UNIT.value = @@unit # Read Plants of Material materialplants = @rfc.discover("MATERIAL_READ_PLANTS") materialplants.MATNR.value = @@material @rfc.call(materialplants) # Check Availability for every Plant totalavailability = 0.0 materialplants.PLANTS.hashRows { |x| @plant = x['WERKS'] materialavailability.PLANT.value = x['WERKS'] @rfc.call(materialavailability) assert( materialavailability.AV_QTY_PLT.value != nil) totalavailability = totalavailability + materialavailability.AV_QTY_PLT.value.to_f } assert( totalavailability >= 0) puts "
Availability total: " + totalavailability.to_s end def test_CSC_00050_Price salesordersimulate = @rfc.discover("BAPI_SALESORDER_SIMULATE") # Order Header orderheader = salesordersimulate.ORDER_HEADER_IN.structure orderheader.DOC_TYPE.value = 'AG' orderheader.SALES_ORG.value = @@salesorg # This is needed because of an error in saprf-0.18 orderheader.REQ_DATE_H.value = '00000000' orderheader.PURCH_DATE.value = '00000000' orderheader.PRICE_DATE.value = '00000000' orderheader.QT_VALID_F.value = '00000000' orderheader.QT_VALID_T.value = '00000000' orderheader.CT_VALID_F.value = '00000000' orderheader.CT_VALID_T.value = '00000000' salesordersimulate.ORDER_HEADER_IN.value = orderheader.value # Order Items orderitems = salesordersimulate.ORDER_ITEMS_IN.structure orderitems.MATERIAL.value = @@material orderitems.REQ_QTY.value = '0000000001000' salesordersimulate.ORDER_ITEMS_IN.value = [ orderitems.value ] # Order Partners orderpartners = salesordersimulate.ORDER_PARTNERS.structure orderpartners.PARTN_ROLE.value = 'AG' orderpartners.PARTN_NUMB.value = @@customer salesordersimulate.ORDER_PARTNERS.value = [ orderpartners.value ] # Call Function @rfc.call(salesordersimulate) ret = salesordersimulate.RETURN.value puts "
Return Message: " + ret['MESSAGE'] salesordersimulate.ORDER_ITEMS_OUT.hashRows { |x| @@subtotal1 = x['SUBTOTAL1'].to_f @@subtotal2 = x['SUBTOTAL2'].to_f assert( 0 < @@subtotal1) assert( 0 < @@subtotal2 ) assert( @@subtotal1 >= @@subtotal2 ) } puts "
List Price: " + @@subtotal1.to_s puts "Net Price: " + @@subtotal2.to_s end def teardown @rfc.close() end end
Publish your Application as a Blog or Article here in SDN. If you dont have a Blogger account its a good reason to become a Blogger now. Deadline is November, 30th 2006, 19 p.m. CET. For discussions please use the Topic SDN Contest: SAP on Rails in a real Business Application in the Scripting Languages Forum.
User | Count |
---|---|
1 | |
1 | |
1 | |
1 |