Get current user on ABAP CDS 7.40? - abap

I am working on ABAP CDS on ABAP 740 where I don't have access to the $session variables.
The case
USR05.bname = 'XXXXXX' where by the xxxxxx is my user id (Hard coded )
What is the workaround?

Related

Flatten/Unify Table Rows where criteria matches array with ABAP or SQL

I am trying to achieve flattening a table into an array (or structure). My implementation is in SAP ABAP; however, I believe the question is code agnostic. I am wondering if there is an algorithm I'm not aware of or simple solution for what I'm trying to achieve. I will accept any language or pseudocode as an acceptable answer.
I am selecting from a "User Restrictions" (i.e., lt_restrictions) table stored on a database, e.g.:
This is needed for an SAP BSP MVC web app. When the app loads, I am doing user authorization checks to populate a "User Roles" (i.e., mt_user_roles) local table/array (i.e., attribute on an MVC model class).
The authorization checks involve routine ABAP -- using IF statements to conditionally populate the "User Roles" table, e.g.:
AUTHORITY-CHECK OBJECT 'PROGRAM_MANAGER_AUTH' ID 'xxx' FIELD 'yyy'.
IF ( sy-subrc = 0 ).
APPEND VALUE #( low = 'program_manager' ) TO me->mt_user_roles.
ENDIF.
If the user has both e.g., program manager AND entry user authorizations, this "User Roles" table/array would look like this:
With the two tables above, if the user has program manager and entry user roles, the only restriction is convert; therefore, I need to populate a "Restriction List" (i.e., ms_restrictions) like the following:
Otherwise, if the user has e.g., only the entry user role:
...
...there are 2 restrictions (release AND convert), so I would need to populate a "Restriction List" (i.e., ms_restrictions) like this:
I feel like there is a standard algorithm I could use or perhaps this could be done with SQL in a SELECT statement with my database table WHERE restriction = NULL (e.g., WHERE save = ' ') or using a SELECT ... WHERE x IN clause, perhaps, if the "Restrictions List" was a RANGE table?
I should mention, I already have an undesirable, partial solution which involves looping through the database table and having several IF statements for each restriction condition. "Restriction List" is named ms_restrictions, it is a class attribute ABAP STRUCTURE type (for ABAP newbies, this is basically a 1-D sized array):
LOOP AT lt_restrictions INTO DATA(ls_restriction).
LOOP AT mt_user_roles INTO DATA(ls_user_role).
"Check save restriction
IF (
ls_restriction-role = ls_user_role-role AND
ls_user_role = 'save'
).
ms_restrictions-save = 'x'.
ENDIF.
"Check release restriction
IF (
ls_restriction-role = ls_user_role-role AND
ls_user_role = 'release'
).
ms_restrictions-release = 'x'.
ENDIF.
"Check other restrictions
"......
ENDLOOP.
ENDLOOP.
The problem with the solution above is I have to write an IF statement for each restriction. More so, it doesn't take into account whether there are conflicts between 2 or more role restrictions, e.g., program manager has only 1 restriction while entry user has 2. My logic above could be extended to take this into account with -- well -- even more IF statements :-( .. I'm wondering if there's a different approach I can take?
Also, I should mention. The resulting "Restrictions List", i.e., mt_restrictions, is needed in my view for disabling HTML buttons, e.g.:
<button value = 'Save' disabled = '//model/mt_restrictions-save' />
<button value = 'Release' disabled = '//model/mt_restrictions-release' />
<button value = 'Convert' disabled = '//model/mt_restrictions-convert' />
<button ... />
A solution I came up with involves using ABAP <FIELD-SYMBOL>s data-types and an OpenSQL FOR ALL ENTRIES IN SELECT statement addition.
By using <FIELD-SYMBOL>s, you can avoid any hardcoded attribute and/or structure component names. Now, the restriction rules can grow without having to future modify any code.
By using FOR ALL ENTRIES IN, you can sync your Roles table with your Restrictions table. Adding this clause allows you to SELECT from your transparent Role/Restrictions database table INTO a table, only including the roles applicable from the roles found in the AUTH-CHECK (because mt_user_roles populates a new row for each true AUTH-CHECK).
The method is_standard_user( ) is where the AUTH-CHECKs occur. If it equals ABAP_TRUE, then all restrictions are applied -- assuming the ms_restrictions structure components' values all default to ABAP_TRUE.
Dynamically looping through each structure component of ms_restrictions, you can READ the restrictions table for corresponding value. If value equals SPACE, then this means the current row doesn't have a restriction. So mark the structure component value to SPACE (because it may have been marked ABAP_TRUE in a prior iteration) -- this addresses the "conflicting roles issue".
"perform authorization checks
IF ( NOT me->is_standard_user( ) ).
"see if roles found
IF ( lines( me->mt_user_roles ) > 0 ).
"find pertaining restrictions for roles found in auth checks
SELECT
*
FROM
zmm_apr_roles
FOR ALL ENTRIES IN "select only rows applicable to auth-check
#me->mt_user_roles
WHERE
role = #me->mt_user_roles-role
INTO TABLE
#DATA(lt_restrictions).
"dynamically populate restriction list from multi-role restriction table
DATA: lr_descr_struc TYPE REF TO data.
DATA: lo_structdescr TYPE REF TO cl_abap_structdescr.
CREATE DATA lr_descr_struc LIKE ms_restrictions.
lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( p_data_ref = lr_descr_struc ).
LOOP AT lo_structdescr->components ASSIGNING FIELD-SYMBOL(<lv_component>).
ASSIGN COMPONENT <lv_component>-name OF STRUCTURE ms_restrictions TO FIELD-SYMBOL(<lv_field>).
IF ( <lv_field> IS ASSIGNED ).
"non-restricted value overwrites restricted value
READ TABLE lt_restrictions WITH KEY (<lv_component>-name) = space TRANSPORTING NO FIELDS.
IF ( sy-subrc = 0 ).
<lv_field> = space.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
To add a new restriction, all that needs to be done is:
add new roles to zmm_apr_roles and the corresponding data-dictionary components
add new restrictions to corresponding components of ms_restrictions

How to get session ID in sql in joomla

I'm working with vcharts in Joomla and trying tom implement charts based on who is logged in. Sadly vcharts only allows me to use SQL for queries and not PHP so How will I get the session ID then.
Based on the SO question Variables added to vchart joomla sql query not picked up (that exposes a relevant portion of the vcharts manual which joomla users must ordinarily pay to see...) it seems the placeholder that you can use in your SQL is:
{loggedinuserid}
So, you might write something like
SELECT * FROM #__users WHERE id = {loggedinuserid}
Of course this is just a guess because I've never used vcharts, nor have I seen the actual docs.
If it doesn't like the #__ prefix placeholder, then I guess you'll need to manually replace it like this:
SELECT * FROM lmnop_users WHERE id = {loggedinuserid}
All this said, I have had some experience with the Plotalot extension and it's pretty good with great documentation.
I find this approach: with joomla api
<?php
$link = mysqli_connect("localhost", "joomla_usr", "geheim", "joomla_db");
define('_JEXEC', 1);
define('JPATH_BASE', dirname(__FILE__));
define('DS', DIRECTORY_SEPARATOR);
require_once(JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once(JPATH_BASE . DS . 'includes' . DS . 'framework.php');
require('libraries/joomla/factory.php');
$mainframe = JFactory::getApplication('site');
$mainframe->initialise();
$session = JFactory::getSession();
$query_user = "SELECT name, username, email FROM joomla_users WHERE id=(SELECT userid FROM joomla_session WHERE session_id='" . $session->getId() . "')";
$result_user = mysqli_query($link, $query_user);
$row_user = mysqli_fetch_array($result_user);
?>
Maybe you can use the query direct to access the mysql database from your Platform. Or embed PHP in any way.

SELECT FROM #itab causes syntax error. Why?

I try to use SELECT FROM #itab like explained here in SAP docs.
I have never used this feature, but think this is great. You can query a internal data structure which just exists in the RAM of the interpreter like it would be a real table in the database. I am impressed.
Here is the ABAP code:
data: lt_get_auth_values TYPE STANDARD TABLE OF US335.
CALL FUNCTION 'GET_AUTH_VALUES'
EXPORTING
OBJECT1 = 'Z:FOO'
USER = sy-uname
TABLES
VALUES = lt_get_auth_values.
SELECT highval from #lt_get_auth_values as mytab WHERE field = 'WERKS'
INTO TABLE #DATA(static_perm_filter_fields).
I can't active the function because "from #lt_get_auth_values" is a syntax error according to my system.
What's wrong with this line?
SAP Version: 740 (sorry, it first I thought it was 752)
SELECT ... FROM #itab appeared in 7.52 so it should work.
On my 7.52 system it works but you must indicate a table alias. There's an example in the ABAP documentation (cf first link above).

How to handle Zim Error "The ZIM tree pool has overflowed"

I have the following code:
set output spoole
select * from displays where displayname='dsp020a'
select * from forms where formname in (select formname from displayforms where displayname='dsp020a')
select * from formfields where formname in (select formname from displayforms where displayname='dsp020a')
The third select is crashing ZIM with the following error:
*** ZIM System Error *** The Zim tree pool has overflowed. Type BYE to exit from Zim.
What am I doing wrong and how can I fix it?
When trying to use SQL in ZIM, I also saw problems and unexpected errors. You should always try to use the native ZIM 4GL commands to access data as well as object definitions.
ZIM Data Dictionary contains some predefined internal relations which can help analyse the data model. For example, you could say:
list all Displays DispDispForms DisplayForms where Displays.DisplayName = "dsp020a"
to find out which forms are contained in the given display. Likewise you could do:
list all Forms FormFormFields FormFields where Forms.FormName in ("f020a", "f020b", "f020c")
to list all form fields which belong to the given forms. Unfortunately, there is no relation between DisplayForms and Forms, so you cannot achieve directly what you tried in your example using SQL.
OR (added after your comment):
You can achieve that using a small program. For this example, it would be:
set output output_file
find Displays DispDispForms DisplayForms where Displays.DisplayName = "dsp020a"
while $setcount > 0
let vStr = DisplayForms.FormName
list all Forms FormFormFields FormFields where Forms.FormName = vStr
let $setcount = $setcount - 1
next
endwhile
set output terminal
Now you have all form fields which belong to all forms of the given display listed in the output_file.
There probably already is a relationship between dfs and forms in the db schema but the documentation is poor. However, you can create your own. Note that dfs is a role for displayforms.
add 1 rels let relname = 'dfsforms' relcondition = 'dfs.formname = forms.formname' reltype = 'ZIM' dirname = 'ZIM'
create rel dfsforms
Now you can find forms related to displays using:
find all displays dispdispforms dfs dfsforms forms formformformfields wh displays.displayname = 'dsp020a'

Equivalent BAPI for a MB01 transaction?

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