Is there a standard way to get previous login date of SAP user? - abap

I've got a requirement to check whether some objects were modified since last logon of current user. There is a table USR02 that contains last logon date, but it is updated at moment of logon and here "last" means "current".
For example, I logged in 2014.11.21 and then 2014.11.26, so dates range I want to get is 21…26, but when I enter the system, date 2014.11.21 in USR02 will be overwritten with 2014.11.26.
Of course, I could follow Z-way and create my own table containing user name and previous login date, but maybe there is there a standard way to achieve this?

I noticed that you can see the current as well as the last logon date and time in the dialog you can open with System --> Status. I went through the code of the function pool SHSY that contains this dialog and found the following implementation:
DATA: BEGIN OF last_logon,
date LIKE sy-datum,
time LIKE sy-uzeit,
date_now LIKE sy-datum,
time_now LIKE sy-uzeit,
END OF last_logon.
* ...
* Datum und Zeit der aktuellen und letzten Anmeldung
GET PARAMETER ID 'US2' FIELD last_logon.
Certainly not the standard API one would expect, but apparently it's all there is...

Related

How can I fetch a dynamic file from FTP server-generated every day?

There are transactional input CSV files coming on a daily basis on an FTP location. I need to read these input files and process them on daily batch execution. The name of the files remains the same every day, but the date gets appended at the end of the filenames every day,
Ex:
Day1
General_Ledger1_2020-07-01,
General_Ledger2_2020-07-01,
General_Ledger3_2020-07-01,
General_Ledger4_2020-07-01,
General_Ledger5_2020-07-01
Day2
General_Ledger1_2020-07-02,
General_Ledger2_2020-07-02,
General_Ledger3_2020-07-02,
General_Ledger4_2020-07-02,
General_Ledger5_2020-07-02
How can I append this Date information to the input file name every time the job runs?
I have faced similar problem earlier and this can be solved using calculated parameter in the file path. Here, you can create expressions that will retrieve the file dynamically.
Example,
CONCAT( UPPER(lit('$(Prefix)')), ADD_DAYS( TODATE(lit('$(currentTime)'), 'yyyy-mm-dd'), 'yyyy-mm-dd' ,-1),'.csv')
Breaking of the expression :
$(currentTime) : this system parameter will get the current date (this will also include timestamp).
(TODATE(lit('$(currentTime)'), 'yyyy-mm-dd') : TODATE will get only date from the whole timestamp with format as ‘yyyy-mm-dd’.
ADD_DAYS(TODATE(lit('$(currentTime)'), 'yyyy-mm-dd'), 'yyyy-mm-dd' ,-1) : ADD_DAYS here will add -1 to the date retrieved from. TODATE(). Hence (2020-04-24) + (-1) would give us 2020-04-23
$(Prefix) : $(Prefix) will be an user defined input parameter of type String which user will be providing at runtime – Since the
prefix will be always dynamic.
CONCAT() : Finally to combine all the results and form the exact file path CONCAT() can be used. Also in between some static
string is added as it will always be fixed for every file to be read.

AUTHORITY-CHECK for complex selection field (like SELECT-OPTIONS)

I have a custom report with the following selection screen. It allows the user to input value ranges when executing the report.
I want to carryout an authorization check to the inputs that the user has entered.
For this I use AUTHORITY-CHECK OBJECT with the user and the selection field;
AUTHORITY-CHECK OBJECT 'P_PYEVDOC'
FOR USER sy-uname
ID 'BUKRS' FIELD pnpbukrs-low
.
Where pnpbukrs is the selection field that the user has entered.
How do I do this check properly for all possible combinations that the user might give?
When I provide the direct pnpbukrs field, the Options in the selection field is considered in the auth. check giving errors.
When I user pnpbukrs-low, only a single value is used in the auth. check making a check bypass.
In case the selection table contains generic entries, intervals, excluded entries or excluded intervals, you should first get the list of companies corresponding to the selection table (with WHERE ... IN selectiontable ; IN will deal with all these kinds of filters), then do an authority-check on each of the real companies.
For instance, I assume that the companies are to be taken from the table T001 :
SELECT bukrs FROM t001 WHERE bukrs IN pnpbukrs INTO TABLE #DATA(companies).
LOOP AT companies ASSIGNING FIELD-SYMBOL(<company>).
AUTHORITY-CHECK OBJECT 'P_PYEVDOC'
ID 'BUKRS' FIELD <company>.
IF sy-subrc <> 0.
" this company is not authorized, do something
ENDIF.
ENDLOOP.
PS #1: If the goal is only to select the authorized data from a given table, you may use the class CL_AUTH_OBJECTS_TO_SQL (>= 7.50)
PS #2: for AUTHORITY-CHECK, it's useless to mention FOR USER sy-uname as it's the default setting.
For range with any data
Go for #Sandra Rossi answer
For range filled with LOW component only:
Try looping over the select-options field and make an authority check for each iteration:
LOOP AT pnpbukrs ASSIGNING FIELD-SYMBOL(<line>).
AUTHORITY-CHECK OBJECT 'P_PYEVDOC'
FOR USER sy-uname
ID 'BUKRS'
FIELD <line>-low.
ENDLOOP.

MS Access 2010: Automatically Filters all the records depending on the user logged in

I am creating a database in Microsoft Access 2010 where when a user logged in the database, the user will only see records that is related to him or her. I've put a criteria in the record's query specifically in IssuingManager field which is [Forms]![frm_Home]![txtUser] but I always get enter parameter value when I run it. txtUser is an invisible text box in my main form so the records will have a reference on which records to filter. My main goal is to limit the user's data to their own records and hide or block them to others. I am new to access and still learning it. Any help or other ways I can filter the data or limit it to the records that is only related to the current user logged in is a big help.
This is my SQL code:
SELECT AdditionalFields.Status, tbl_NTE.CaseIDNo, tbl_NTE.EmployeeName,
tbl_PAH.DPosition, tbl_NTE.Function, tbl_NTE.IssuingManager,
tbl_NTE.ApprovingManager, tbl_NTE.ObjectOfViolation, tbl_NTE.Offense,
tbl_NTE.ClassPenalty, tbl_NTE.CorrectiveActionPenalty,
tbl_NTE.ObjectOfViolation2, tbl_NTE.Offense2, tbl_NTE.ClassPenalty2,
tbl_NTE.ObjectOfViolation3, tbl_NTE.CorrectiveActionPenalty2,
tbl_NTE.Offense3, tbl_NTE.ClassPenalty3, tbl_NTE.ObjectOfViolation4,
tbl_NTE.CorrectiveActionPenalty3, tbl_NTE.Offense4, tbl_NTE.ClassPenalty4,
tbl_NTE.CorrectiveActionPenalty4, tbl_NTE.DatesWhenActsWasWereCommited,
tbl_NTE.DatesWhenActsWasWereDiscovered, tbl_NTE.NTEDate,
tbl_NTE.NTELastDateModified, tbl_NTE.NTELastTimeModified,
tbl_NTE.NTELastUser, tbl_PAH.PAHDate, tbl_PAH.PAHLastDateModified,
tbl_PAH.PAHLastTimeModified, tbl_PAH.PAHLastUser, tbl_NCA.NCADate,
tbl_NCA.NCALastDateModified, tbl_NCA.NCALastTimeModified,
tbl_NCA.NCALastUser, tbl_NTE.EndorsedNTENoticeToHR,
tbl_NTE.EndorsementOfNTEToIS, tbl_NTE.DateReceivedNTEByTheEmployee,
tbl_NTE.SubmissionOfWEtoIS, tbl_NTE.SubmissionOfWEtoHRER,
tbl_NTE.InitialDecision, tbl_PAH.ScheduleForPAH, tbl_PAH.Recommendation,
tbl_PAH.EndorsementOfDecisionNoticeFromPAHCommitteeChairToHR,
tbl_PAH.EndorsementOfFinalizedPAHRecommendationToIS,
tbl_NCA.EndorsementOfDA2ToHRForReview, tbl_NCA.EndorsementOfReviewedDA2ToIS,
tbl_NCA.EmployeeAcceptanceOfDecision,
AdditionalFields.DescriptionOfPenaltyFinalDecision,
AdditionalFields.ApplicableDatesofEffectivity, AdditionalFields.Remarks,
AdditionalFields.RunningTAT, AdditionalFields.TAT, tbl_NTE.EHRID,
tbl_NTE.IssuingManagerEmailAddress, tbl_NTE.WrittenExplanationDueDate,
tbl_NTE.OffenseNo5, tbl_NTE.Offense5, tbl_NTE.ObjectOfViolation5,
tbl_NTE.ClassPenalty5, tbl_NTE.CorrectiveActionPenalty5, tbl_NTE.OffenseNo6,
tbl_NTE.Offense6, tbl_NTE.ObjectOfViolation6, tbl_NTE.ClassPenalty6,
tbl_NTE.CorrectiveActionPenalty6, tbl_NTE.OffenseNo7, tbl_NTE.Offense7,
tbl_NTE.ObjectOfViolation7, tbl_NTE.ClassPenalty7,
tbl_NTE.CorrectiveActionPenalty7
FROM (tbl_Worker INNER JOIN ((tbl_PAH INNER JOIN tbl_NCA ON tbl_PAH.
[CaseIDNo] = tbl_NCA.[CaseIDNo]) INNER JOIN AdditionalFields ON
tbl_NCA.CaseIDNo = AdditionalFields.CaseIDNo) ON tbl_Worker.WorkerID =
tbl_NCA.NameOfIssuingManager) INNER JOIN tbl_NTE ON (tbl_NTE.CaseIDNo =
tbl_PAH.CaseIDNo) AND (tbl_Worker.WorkerName = tbl_NTE.IssuingManager)
WHERE (((tbl_NTE.IssuingManager)=[Forms]![frm_Home]![txtUser]));
I would recommend to avoid using form's field references in queries at all. If form closed, the query will request parameter, like most likely in your case.
Replace the reference by global function created in standard module. This function can store the name, for instance, in static/global variable or retrieve it from table. Main or login form can set this variable/table record once, then the form can be closed without affecting queries functionality
Add another column and put the username. So when selecting the records, there's a condition where user='username'. They look all the data base on what the username has.
your method is fine & correct; you just have some sort of cockpit implementation error
the criteria in the query should be: Forms!frm_Home.txtUser
you could have a spelling error in your form name or text box name
make the textbox visible and enter a valid entry and run the query manually
what you are getting appears to be a parameter prompt that means it cannot find the object i.e. form named frm_Home

How can I show the most recent events per user with Keen IO?

Suppose you have a Keen IO collection called "survey-completed" that contains events matching the following pattern:
keen.id: <unique autogenerated id>
keen.timestamp: <autogenerated overridable timestamp>
userId: <hex string for user>
surveyScore: <integer from 1 to 10>
...
How would you create a report of only the most up-to-date satisfaction score for each user that responded to one or more surveys within a given amount of time (such as one week)?
There isn't a really elegant way to make it happen, but for a given userId you could successfully return your the most up-to-date event create a count query with a group_by on [surveyScore, keen.timestamp] and an order_by on the keen.timestamp property. You will want to set limit=1 to select only the most recent surveyScore.
If you'd like to use an extraction, the most straight forward way would be to run an extraction with property_names set to ["userId","keen.timestamp","surveyScore"]. Once you receive the results you can then do some client-side post processing. This is probably the best way if you want to take a look at all of your userIds.
If you're interested in a given userId and want to use an extraction, you can run an extraction with a filter on the userId eq X, define the optional parameter latest set to latest=1. The latest property is an integer containing the number of most recent events to extract. Note: The use of latest will call upon the keen.created_at timestamp instead of keen.timestamp (https://keen.io/docs/api/#the-keen-object).

tzs for Jawbone Moves

I would like some clarification on tzs for the Jawbone Moves endpoint: https://jawbone.com/up/developer/endpoints/moves. Is this key going to be present on all response items? If not, what types of records will have it vs those that don't. Additionally, the docs indicate it will be an array of arrays with the following format:
"tzs": [
[1384963500, "America/Phoenix"],
[1385055720, "America/Los_Angeles"]
]
However, I am getting response that look like the following:
"tzs": [[1468410383, -14400]]
Is the second an offset I presume in seconds?
The tzs key will appear in responses from the moves endpoint that provide data for a given day's move. It will always be present, but it will only contain more than one entry if the user changes timezones during the given time period (e.g., the user is travelling).
Here's the explanation from the documentation:
Each entry in the list contains a unix timestamp and a timezone. In most instances the timezone entry is a string containing the Olson timezone.
When the timezone entry is just a number, then you are correct it's the GMT offset in seconds, so -14400 corresponds to US/Eastern