I need to prepare a document which includes all enhancements implemented in the SAP system of the company, what are all steps that I have to go through?
Another more comprehensive way to find all the enhancements is to (re)use the best practices.
A wonderful tool called ABAP Exit Ray Eye was developed yet in 2009 and though it is a bit forgotten now, it is still does the job.
Having different criteria
it can show you currently implemented enhancements in a very nifty and user-friendly way:
The source code of this tool can be grabbed in archive from Github repo and is installable by SAPLink.
Try running SAP Standard program SNIF in se38. It might help. For more information refer to this blog post. https://blogs.sap.com/2012/04/16/lets-find-enhancements/
All the enhancements reside in ENHINCINX table and can be searched by package like this:
PARAMETERS p_pack TYPE devclass.
"Accept wildcards for package
p_pack = COND #( WHEN p_pack IS INITIAL THEN '%' ELSE replace( val = p_pack sub = `*` with = `%` occ = 0 ) ).
SELECT e~*
FROM enhincinx AS e
INNER JOIN tadir AS t
ON 'R3TR' = t~pgmid
AND 'ENHO' = t~object
AND e~enhname = t~obj_name
WHERE t~devclass LIKE #p_pack
INTO TABLE #DATA(lt_enhincinx).
LOOP AT lt_enhincinx ASSIGNING FIELD-SYMBOL(<ls_enhincinx>).
WRITE: / |{ <ls_enhincinx>-programname } / { <ls_enhincinx>-enhname }:|.
ENDLOOP.
Related
Is it possible to determine via code if the current system is R/3 or S/4?
I need it because I have a method that returns the software component of Human Resources related data, but this component should be different to R/3 and S/4 systems.
DATA(lv_software_component) = mo_configuration->get_software_component( ).
SELECT * FROM tadir INTO TABLE #DATA(lt_inftype_tables)
WHERE pgmid = 'R3TR'
AND object = 'TABL'
AND devclass IN ( SELECT devclass FROM tdevc
WHERE dlvunit = #lv_software_component
OR dlvunit = 'SAP_HRGXX'
OR dlvunit = 'SAP_HRRXX' )
On R/3, lv_software_component should be 'SAP_HRCMX', for example, while on S/4 it should be 'S4HCMCMX'. Currently, I have no idea on how to tell the difference between the releases, programmatically speaking.
The best I've come up with is hardcoding SY-SYSID, since I know which systems are S/4 and which aren't, but that shouldn't be ideal.
I appreciate any help, thanks!
You can use below class method for determining it. On the other hand is_s4h method only exists on S4 system. You need to check method exits before calling it.
cl_cos_utilities=>is_s4h( )
Working full example:
REPORT ZMKY_ISS4.
CLASS cl_oo_include_naming DEFINITION LOAD.
DATA oref TYPE REF TO if_oo_class_incl_naming.
DATA: lt_methods TYPE seop_methods_w_include,
lv_clskey TYPE seoclskey,
ls_cpdkey TYPE seocpdkey,
lv_iss4 TYPE abap_bool,
lt_params TYPE abap_parmbind_tab.
lv_clskey = 'CL_COS_UTILITIES'.
oref ?= cl_oo_include_naming=>get_instance_by_cifkey( lv_clskey ).
lt_methods = oref->get_all_method_includes( ).
ls_cpdkey-clsname = lv_clskey.
ls_cpdkey-cpdname = 'IS_S4H'.
READ TABLE lt_methods WITH KEY cpdkey = ls_cpdkey TRANSPORTING NO FIELDS.
IF sy-subrc EQ 0.
lt_params = VALUE #( ( name = 'RV_IS_S4H'
kind = cl_abap_objectdescr=>returning
value = REF #( lv_iss4 ) ) ).
CALL METHOD CL_COS_UTILITIES=>('IS_S4H')
PARAMETER-TABLE
lt_params.
ELSE.
lv_iss4 = abap_false.
ENDIF.
Using the method cl_cos_utilities=>is_s4h is a rather unclean solution, because that method does not exist on older releases.
A cleaner method is to use the function module SFW_IS_BFUNC_SWITCHED_ON. This function module checks if a business function in the switch framework is enabled.
To check for the S4HANA on premise business function:
CALL FUNCTION 'SFW_IS_BFUNC_SWITCHED_ON'
EXPORTING
bfunc_name = 'SIMPLIFY_ON_PREMISE'
IMPORTING
is_switched_on = is_s4.
To check for the S4HANA on cloud business function:
CALL FUNCTION 'SFW_IS_BFUNC_SWITCHED_ON'
EXPORTING
bfunc_name = 'SIMPLIFY_PUBLIC_CLOUD'
IMPORTING
is_switched_on = is_s4.
By the way: The method cl_cos_utilities=>is_s4h actually uses this function module internally.
You might also want to check if it might be more appropriate in your use-case to use that function module to actually detect which HR business functions are active instead of deriving that information indirectly from whether or not the system has S/4 activated.
There's the function module OCS_GET_INSTALLED_COMPS which returns all software components installed. Note that it's not released by SAP. It used to work in old systems and still works in S/4HANA.
You can use function module DELIVERY_CHCK_ACTIVE_COMPONENT to check which of the two components is active.
I am also pretty sure only S/4 systems will have the S4CORE component active if you really need to check if it's S/4 or R/3.
In this other question https://stackoverflow.com/a/36145155/2259571 a code example was posted that defines a Javascript UDF function inline, not in the BigQuery UI UDF Editor, not in a bq command-line --udf_resource option, but loaded directly from the text of the SQL query.
Where in the BigQuery documentation can I find more info about how this is done?
JS(...) looks like a function but I cannot find it in the documentation at https://cloud.google.com/bigquery/query-reference I also cannot find anything about this construct in https://cloud.google.com/bigquery/user-defined-functions Am I just missing it? Or is it undocumented?
Here is a simplified version of the query (this runs in the BigQuery UI and in the bq command line tool):
SELECT outputA
FROM JS(
// input table
(
SELECT text2 as inputA
FROM
(SELECT 'mikhail' AS text2),
(SELECT 'mike' AS text2),
(SELECT 'michael' AS text2),
(SELECT 'javier' AS text2),
(SELECT 'thomas' AS text2)
)
// input columns
, inputA
// output schema
, "[{name: 'outputA', type:'string'}]"
// function
, "function(r, emit) {
emit({
outputA: 'XX ' + r.inputA + ' XX'
});
}"
)
Output:
outputA
XX mikhail XX
XX mike XX
XX michael XX
XX javier XX
XX thomas XX
Update 2022-03-31: BigQuery recommends using standard SQL, which includes the following syntax for inline JS UDFs:
https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions
The inline JS syntax is the "alpha" syntax and is deliberately left undocumented. We currently have no plans to remove or change this functionality, but it's also not an officially supported feature.
We do have plans to provide official support for inline JS UDFs at some point in the future, but with a slightly different syntax.
If you'd like to use this feature despite the caveat above, see Mikhail's answer.
I see now what you are looking for.
Looks like this is not available in google bigquery documentation
But the example you got - pretty much gives you the structure of such use - nothing is missed - everything else is in link you already know - https://cloud.google.com/bigquery/user-defined-functions - and still applicable and the only you need
As of me personally - i've learned about inline js udf relatively long ago from below links (just few of them)
http://www.slideshare.net/BigDataSpain/thomas-park-hands-on-with-big-query-javascript-udfs-bigdataspain-2014
https://www.youtube.com/watch?v=6TYA6hy44Jo
https://www.youtube.com/watch?v=GrD7ymUPt3M (go to 28+ min)
I'm trying to replace some un-reliable sap scripting we have in place to do an MB01 from a custom goods receipt application. I have come across the .NET connector and it looks like it could do a job for me.
Research has churned up the BAPI called BAPI_GOODSMVT_CREATE but can anyone tell me what parameters might be required to perform this transaction?
I have access to a SAP test environment.
BAPI_GOODSMVT_CREATE accepts a table of values called GOODSMVT_ITEM which contains 121 fields. I'm sure that not all of these fields are required.
Ultimately I guess my question is, what how can I work out which ones are required?
Do you have access to a SAP system? I have recently used this BAPI, and it has quite detailed documentation. To view the documentation, use transaction SE37, and enter the BAPI name. Unfortunately I don't currently have access to a system.
You will have to ask one of your MM/Logistics people to tell you what the movement type (BWART) is, and depending on the config you will need details like material number (MATNR), plant (WERKS), storage location etc.
MB01 is a Post GR for PO transaction, it is an equivalent of GM_Code 01 in MIGO or BAPI_GOODSMVT_CREATE. MIGO transaction is a modern successor for obsolete MB01.
So, as per the BAPI_GOODSMVT_CREATE documentation for GM_Code 01 the following fields are mandatory:
Purchase order
Purchase order item
Movement type
Movement indicator
Quantity in unit of entry
ISO code unit of measurement for unit of entry or
quantity proposal
Here is the sample:
gmhead-pstng_date = sy-datum.
gmhead-doc_date = sy-datum.
gmhead-pr_uname = sy-uname.
gmcode-gm_code = '01'.
loop at pcitab.
itab-move_type = pcitab-mvt_type.
itab-mvt_ind = 'B'.
itab-plant = pcitab-plant.
itab-material = pcitab-material.
itab-entry_qnt = pcitab-qty.
itab-move_stloc = pcitab-recv_loc.
itab-stge_loc = pcitab-issue_loc.
itab-po_number = pcitab-pur_doc.
itab-po_item = pcitab-po_item.
concatenate pcitab-del_no pcitab-del_item into itab-item_text.
itab-move_reas = pcitab-scrap_reason.
append itab.
endloop.
call function 'BAPI_GOODSMVT_CREATE'
exporting
goodsmvt_header = gmhead
goodsmvt_code = gmcode
IMPORTING
goodsmvt_headret = mthead
tables
goodsmvt_item = itab
return = errmsg
I'm currently using IBM's UniObjects and I trying to retrieve multiple fields from a UniFile at once to increase efficiency.
UniFile uFile = uSession.CreateUniFile("fileName");
uFile.RecordID = inputID;
string[] fieldNames = {"I_Field_1", "D_Field_1", "I_Field_2", "D_Field_2"};
UniDynArray uFields = uFile.ReadNamedFields(fieldNames);
uFields value:
þvalue1þþvalue2
þ = delimiter for the UniDynArray
The problem is that half of these fields are I-descriptors and half are D-descriptors. The I-descriptors will not output unless only a single one of them is in the array fieldNames like so:
string[] fieldNames = {"I_Field_1"};
UniDynArray uFields = uFile.ReadNamedFields(fieldNames);
So I guess my question is why are the I-descriptor fields not being displayed and if there is a way they can be using this or a similar method.
I'm new to stackoverflow as well as an entry-level developer so thank you for any help you can provide.
It sounds like an defect with UniObject's. Since you say it is IBM's UniObject's, you most likely have an old version (UniData/UniVerse is owned by Rocket Software now).
Assuming you are on an old version, it is possible this works in a newer version. You should look into scheduling an update of your UniData server and hence client software such as UniObjects.
Outside of this, you can probably raise a bug with your VAR/Support Provider or Rocket Software directly.
I have a piece of SQL that I want to translate to OCL. I'm not good at SQL so I want to increase maintainability by this. We are using Interbase 2009, Delphi 2007 with Bold and modeldriven development. Now my hope is that someone here both speaks good SQL and OCL :-)
The original SQL:
Select Bold_Id, MessageId, ScaniaId, MessageType, MessageTime, Cancellation, ChassieNumber, UserFriendlyFormat, ReceivingOwner, Invalidated, InvalidationReason,
(Select Parcel.MCurrentStates From Parcel
Where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) as ParcelState From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and
not Exists (Select * From ScaniaEdiSolMessage EdiSolMsg
Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and EdiSolMsg.MessageType = 'IFTMBF') and
invalidated = 0 Order By MessageTime desc
After a small simplification:
Select Bold_Id, (Select Parcel.MCurrentStates From Parcel
where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and not Exists (Select * From ScaniaEdiSolMessage
EdiSolMsg Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and
EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and
EdiSolMsg.MessageType = 'IFTMBF') and invalidated = 0
NOTE: There are 2 cases for MessageType, 'IFTMBP' and 'IFTMBF'.
So the table to be listed is ScaniaEdiSolMessage.
It has attributes like:
MessageType: String
ChassiNumber: String
ShipFromFinland: Boolean
Invalidated: Boolean
It has also a link to table Parcel named ReceivingOwner with BoldId as key.
So it seems like it list all rows of ScaniaEdiSolMessage and then have a subquery that also list all rows of ScaniaEdiSolMessage and name it EdiSolMsg. Then it exclude almost all rows. In fact the query above give one hit from 28000 records.
In OCL it is easy to list all instances:
ScaniaEdiSolMessage.allinstances
Also easy to filter rows by select for example:
ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
But I do not understand how I should make a OCL to match the SQL above.
Listen to Gabriel and Stephanie, learn more SQL.
You state that you want to make the code more maintainable, yet the number of developers who understand SQL is greater by far than the number of developers who understand OCL.
If you leave the project tomorrow after converting this to OCL, the chances that you'd be able to find someone who could maintain the OCL are very slim. However, the chances that you could find someone to maintain the SQL are very high.
Don't try to fit a square peg in a round hole just because you're good with round hammers :)
There is a project, Dresden OCL, that might help you.
Dresden OCL provides a set of tools to parse and evaluate OCL constraints on various models like UML, EMF and Java. Furthermore Dresden OCL provides tools for Java/AspectJ and SQL code generation. The tools of Dresden OCL can be either used as a library for other project or as a plug-in project that extends Eclipse with OCL support.
I haven't used it, but there is a demo showing how the tool generates SQL from a model and OCL constraints. I realize you're asking for the opposite, but maybe using this you can figure it out. There is also a paper that describes OCL->SQL transformations by the same people.
With MDriven (successor of Bold for Delphi) I would do it like this:
When working with OCL to SQL everything becomes easier if you think about the different set's of information you need to check - and then use ocl operators as ->intersection to find the set you are after.
So in your case you might have a set like this:
ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
but you also have a set like this:
ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP')
And you further more have this criteria:
Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
If all these Sets have the same result type (collection of ScaniaEdiSolMessage) you can simply intersect them to get your desired result
ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
->intersection(ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP'))
->intersection(Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
)
And looking at that we can reduce it a bit to:
ScaniaEdiSolMessage.allinstances
->select(m|m.shipFromFinland and (not m.invalidated) and
(m.ReceivingOwner.MessageType = 'IFTMBP'))
->intersection(Parcel.allinstances->select(p|
p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
)