APEX - Switching to a page through code - oracle

i am currently writing an apolication in ORACLE APEX, i am writing some validation on a login so that when you enter your username and password and click submit it will check to see whether you have changed your password,if yes then it will direct you to the main front page however if not i want it to link to a change password page, i currently have some code which looks like:
BEGIN
FOR c1 IN (SELECT user_name FROM wwv_flow_users) LOOP
IF APEX_UTIL.CHANGE_PASSWORD_ON_FIRST_USE(p_user_name => c1.user_name) THEN
htp.p('User:'||c1.user_name
||' requires password to be changed the first time it is used.');
/*f?p=&APP_ID.:8:&SESSION;*/
END IF;
END LOOP;
END
however i am unsure as to how correct this is, as I am rather new to the topic, this is what i have picked up from looking at oracles API's and from looking round other sources to try and come to a successful conclusion.
Any help would be greatly appreciated
Many thanks
J

You're mixing two different Apex features: validations and branches.
If you want to check for a data entry error, you use a Validation - and generally the same page will be returned to the user so they can correct their error.
If you want to branch to another page, you use a Branch. If you want to branch to different pages depending on a condition, you can create multiple Branches, each with a condition. The first branch that satisfies its condition will be used.
In addition, if you want to do some processing before the branch, you create a Process. Typically a Process is run after the validations are done but before the branches are done.
In your case, you could put your code in a Process, and set a hidden item with a flag that is used by the Branches to work out which page to branch to.

Related

Modifying graphical elements with PL/SQL - Oracle Apex

I am currently trying to migrate Forms' Applications developped ten years ago to Oracle Apex. For some context, the database in which Forms applications are currently running is the Oracle EE 6i, and will be soon upgraded to the 12.2g, hence the need for migration. The data stored within the tables is to big to migrate (like 4To) so we need an alternative to Forms, but we cannot change the DB, and cannot keep Forms (which is let's be honest, outdated a little). I am currently on Oracle XE for my tests and on Apex 20.2.0.00.20 to start my migration (before upgrading).
The thing is, I have some issues with how Apex and Forms are working differently.
I am really blocking on the following issue since my migration:
In Forms, it was really easy to change the color of a button for exemple by calling a Forms method in a certain way depending on a condition (for exemple a SELECT return). Here, in Apex, I am trying to do the same.
I know that there are ten other ways of doing the same, with JS for exemple which I already succeedly do, but when I tried to create my second appplication I realised that compared to Forms, Apex cannot reference/generalise parts of the code(or applications) for different applications (and certainly not for different workspaces). So Javascript is a good solution but not as efficient as PL/SQL which is easier to generalise and will (in my opinion) use less exchange between the db and the client, since stored on the db.
That is why I decided to rely on PL/SQL Stored Procedure which will be specified in the database and called directly in each application where I need the process/computations.But I cannot find the same as in Forms, with my graphical methods helping me do what I need.
I am open to alternative of PL/SQL package/procedure/function if it can keep the same propreties (generalisation and minimum echange between client and db). These are important point since I have around 200 applications to migrate, starting with what we can call 'brick' which will compose the other simpler applications.
Btw: CSS is an option I studied, like HTML with PL/SQL dynamic content but I read that it was either not simple enough to integrate, or that it could be deprecated, so if it is the solution you are using, I could use a really detailled explaination or an exemple.
To give you an instance:
I click on a button triggering a PL/SQL stored procedure
Procedure checks some conditions in the db (like if a process is currently running)
PL/SQL update a table, change a variable in procedure and returns 'green'
The button becomes green, a message is displayed ('You have permission to do this!')
PS: if there are Apex Method modifying the graphical aspect, could I have a documentation ?
Thank you a lot for helping me resolve this issue, I have been stuck for days...
I tried Javascript bu the generalisation was too much a problem. I tried the HTML injecting but didn't work, I tried updating CSS but was not what I expected. I tried different PL/SQL method but couldn't find a way to connect PL/SQL with Apex/CSS/HTML...
It takes a bit of getting used to how APEX works, but everything can be done and once you get up to speed, you'll find there pretty simple ways to get things done. To achieve what you describe, this is what you'd do.
Create a dynamic action on click of button
Add the following actions to the dynamic actions
an action of type "execute pl/sql". This is your "Procedure checks ...". In this pl/sql code you can set page item values (make sure to reference those in "items to return" so the new values is set in the session. There is no reason to have 2 different pl/sql procedures, you can just put them in 1 block. This procedure would return the "green" - but more about this later.
an action to add a class to the button under certain conditions.
Note that the "green" is not something you should decide. In apex, there are a lot of layout modifier classes pre-defined. In your case, it makes sense to use the "success" modifier (which happens to be green).
To check how you want the button to look, there is a tool called the "button builder", you can use that to see what classes you should add/remove to change the look of the button.
Note that 20.2 is not a recent version. It was released in 2020. Since then 4 more releases have been made available: 21.1,21.2,22.1 and 22.2. It is advised to be on the latest version.
Here is a basic example. I have a page with a select list (P117_SELECTLIST), a hidden item to hold the button status (P117_BUTTON_STATE) and a button (MYBUTTON). The select list has 2 static values:
The dynamic action for serverside code is :
Note the items to submit and return values. P117_SELECTLIST is submitted so the pl/sql process picks that up from the client and P117_BUTTON_STATE is returned to the client so it is available for any future use.
Then I have 4 classes to set the button style. One to add success class, one to remove success class, one to add warning class, one to remove warning class. Below is the first one. The only think different in those 4 actions in the class name and the client condition. It can probably done with javascript directly as well with only 1 action.
I'd strongly suggest to update the db version to a version that supports the latest version of apex. It will save you a lot of development worries. Most people of forums only have the latest version available.

Gherkin for CYPRESS - How to format GHERKIN for long test cases with multiple validation points throughout the test

I understand that within this framework users are unable to call scenarios within scenarios.
I am trying to create End to End test cases where there are validation points at multiple stages of the test.
Using 'bad' gherkin syntax the process for the scenario would be something like:
Given Item A exists
When User processes Item
Then Warning is displayed
When User accesses Item
Then Warning is not displayed
When User finalises Item
Then Item status = "CURRENT"
And Record Status = "COMPLETED"
The first thing I considered was breaking the scenario into 3 distinct GWT scenarios.
That is fine.
However suppose I now want to create a new end to end scenario that can re-use one of the 3 scenarios created (as you would re-use a function).
How do I do this without duplication of Gherkin code?
I cannot use Background as the sections that I require to re-use are in the middle of the execution.
Steps prior and after may be different.
IN SUMMARY: I am trying to re-use a GWT scenario that is common for many end to end scenarios where the end to end scenarios are inherently different.
Any feedback or assistance you can provide would be greatly appreciated.
Cheers and thanks,
I think I know what you mean. I have done some "meta" scenario's. For example there are ones that test login, maintaining details and creating an account that are very fine grained. Then I have scenario's that test things further along the way, assuming that the happy path has been taken up to that point. So imagine having a scebnario called:
The user is logged in and has successfully created an account and is at the add product screen
For that, in the step definition, I would just combine function calls with hardcoded values:
#When("^The user is logged in and has successfully created an account and is at the add product screen$")
def addProducts(String val) {
navLibrary.loginAsUser("user", "password")
navLibrary.createAccount("some", "params", "you", "need")
navLibrary.navToProducts("some param")
}
And then start with the finer details in new separate steps. You have to think system design, and cascading. For me it meant a lot of initial rework as the tests started growing, but now it's a breeze. Pick the right level of reusability. It is testing code, so it doesn't have to subscribe perfectly to all the programming precepts. It must work, and it must be low maintenance in the long run.
I didn't use Cypress though. My tests are in Groovy with Selenium and Cucumber.

How to save a record with validation rule in place

I currently have a validation rule that prevents user from making changes to a record when its status is completed. Users are only allowed to make changes if the status is either draft or registered.
AND(
TEXT(Current_Status__c) <> "Draft",
TEXT(Current_Status__c) <> "Registered"
)
There is a new requirement to allow user to update only a specific picklist value field even if the record status is completed. If i remove the validation rule, user will be able to change any fields on the page layout which won't work.
Object setting for the profile is read, create, edit. This object is a child object to Opportunity, OWD is controlled by parent.
Any recommendation on how to solve this issue ?
Thanks in advance.
We can rewrite your rule as ISPICKVAL(Current_Status__c, 'Completed') for example, looks bit cleaner. Your call though, you can keep as is.
So what you'd need is something like ISPICKVAL(Current_Status__c, 'Completed') && !ISCHANGED(Some_Picklist__c). It should let the edit through if you're modifying that picklist.
The problem is it won't check if that's the only change. Usercan cheat, modify 10 fields and they'll "piggyback" and save OK as long as one of them is that picklist.
It's pain to write validation like ISPICKVAL(Current_Status__c, 'Completed') && !ISCHANGED(Some_Picklist__c) && (ISCHANGED(Field1__c) || ISCHANGED(Field2__c) || ISCHANGED(Field3__c)). You'd have to add all editable fields to it, change it every time you make new one. And eventually you'll hit length limits.
I know 3 options for this if it's a concern for you:
Ask a developer to rewrite your logic to Apex trigger, it could then go dynamic through all fields (using "describe" calls to learn field names or stuff like getPopulatedFieldsAsMap.
Another trick is to allow editing completed records only through a quick action, not normal edit page. In that action you could set some hidden checkbox in the field prepopulating step and your validation would let the save through only if that checkbox is set. But then you need to deactivate it somehow anyway or the bypass will get permamently enabled.
If you don't have too many record types on the object a common trick is to change the record type on completion (workflow, process builder etc). And have another page layout with all fields locked down except that special picklist. It works good enough for UI changes but won't protect if you have code and integrations writing to the object too.

how can i add a user to UCM workflows using IDOC script?

I'm trying to implement logic in the oracle UCM workflow, that when a document is rejected, it should add the original author to the workflow step.
I've tried the following idoc script on the entry point of the previous step but it didn't work
<$if wfAction like "REJECT"$>
<$trace(wfGet("originalAuthor") , "#console")$> // this code prints and work
<$trace("#all", "#console")$> // this code prints and work
<$wfAddUser(wfGet("originalAuthor"), "user")$> // this
<$endif$>
the originalAuthor is a variable that i set in the beginning of the workflow , so i can keep track of the original authoer , if other user checked out / checked in other document .
wfAddUser can only be used in a token.
If you haven't worked with workflow tokens before, have a look in the Options menu in Workflow Admin. I don't know what problem you are trying to solve, but by the looks of it, my guess is that tokens are what you are looking for.

Getting a blank data report vb6

I am new to vb6. I am working to create the invoice generation application. I am using data report to show the generated invoice.
The step by step working of process is:
Entering the data in to Invoice and ItemsInvoice tables.
Then getting the maxId using (Adodc) from the data base to show the last generated Invoice.
Then passing the max Id as parameter to the data report which is showing the invoice according to the invoice id.
It is working fine when I first time generate invoice. Now for 2nd invoice without closing application I am getting a blank data report. For data report I am using dataenvironment.
I am guessing the reason the data report is blank is because there was no record for that Id, but actually the record is inserting in the database.
What is going wrong?
I'm not sure how your data set is getting configured, but it sounds like you have a single record in the data and aren't reloading it properly. If your report is manually moving through the recordset and only showing info based on the ID parameter you are passing it and then using the same recordset for the second report, you probably just need to MoveFirst on the recordset to put it back at the beginning.
Load the data environment and refresh the data report.
I am also generating report in the similar fashion. I faced this problem. Here's the solution
Load DataEnvironment1
With DataEnvironment1
'Command1 is the command added to data environment where you fire query or
'set it to point to a table
If .rsCommand1.State <> 0 Then .rsCommand1.Close
.Command1 maxid 'parameter you pass to the recordset
End With
DataReport1.Refresh
DataReport1.Show
Thats it!
You are done. I m sure it will work. Do tell me if it doesn't.
I don't know if the answer will still bother you, but if someone else have the same problem here is a example of how the problem works:
Imagine that there is a gate and a guard looking who is entering, when the first person (the first invoice) comes, the guard registers him, opens the gate (This is the event "Load DataEnvironmet") and then lets the guy pass. The guard believes that no one else would come and lets the door open (the instruction believes that the DataEnvironment ends and the value EOF becomes True), but when the second guy comes (the second invoice) the guard can't ask him who is (has, again, the value and lets it pass without registering him (this is the reason why the second invoice, and subsequent in while invoice would come blank). The solution is to close the gate ("Unload DataEnvironment") after a guy passes (After showing the data report).
The solution is the code given from Sangita above, but just before ending the sub you need to unload the DataEnvironment you were working on.
For me, it works. Sorry if the answer is not what you were looking for (and also if someone else can't understand what I'm writing, my English isn't very good). Just in case I will write the code with the solution
Load DataEnvironment1
With DataEnvironment1
If .rsCommand1.State <> 0 Then
.rsCommand1.Close
End If
.Command1 Value(ID)
End With
DataReport1.Refresh
DataReport1.Show
Unload DataEnvironment1
Try a refresh method like data1.recordset.requery or
Data1.refresh. This should work if you use data controls.

Resources