Redirect to page stored in table - oracle

I have an application in which a user creates a form, for which several responsible persons are selected in this form and can edit this form.
As soon as the form is submitted, the corresponding page of the process is changed.
The page of the form and the respective responsible persons are saved in a separate table.
The function has to check whether the logged-in user with the user ID is entered in the table as one of the responsibles. The table for example Responsible1 contains a foreign key to the table USERS, in which the ID is located. As soon as it finds the responsible in the table, the function then should redirect the user to the corresponding page.
create or replace function forward_user(p_username in varchar2)
return varchar2
is
l_user varchar2(255);
l_branch_page number;
begin
l_user :=p_username;
/*
Get the target page depending on entry in table
*/
select
page
into l_branch_page
from
FORM_PAGES
where EXISTS (SELECT f.RESP1 from FORM f
left outer join RESPONSIBLE1 s on s.RESP1=f.RESP1
LEFT OUTER JOIN USERS u on u.ID=s.ID where lower(u.USERNAME) =lower(l_user) )
OR (fp.RESP2 in
(SELECT f.RESP2 from FORM f
left outer join RESPONSIBLE2 p on p.RESP2=f.RESP2
left outer join USERS u on u.ID=p.ID where lower(u.USERNAME) =lower(l_user) ))
OR (fp.RESP3 in (select f.RESP from FORM f
left outer join RESPONSIBLE3 e on e.RESP3=f.RESP3
left outer join USERS u on u.ID=e.ID where lower(u.USERNAME) =lower(l_user) ));
return APEX_PAGE.GET_URL(p_page =>l_branch_page);
exception
when no_data_found then
/*Use current page as default page*/
return APEX_PAGE.GET_URL(p_page =>1);
end ;
I then call this function in a pl/sql process when the button NEXT is clicked.
DECLARE
x varchar2(4000);
BEGIN
x:=forward_user(:session_user_name);
END;
I have already checked the sql statements and they work fine, I get the corresponding page.
As well the function compiles successfully.
But when I click the button nothing happens, the user is not forwarded to the stored page in the table.
As well I tried to call this function in a branching process with the behaviour Function Returning a URL(Redirect) but as well nothing happens.
Can someone help me here?

My suggestion would be:
create a hidden page item (as you're on Page 1, let's call it P1_URL)
you already have a process which runs when the Submit button is pressed. Its execution point should be "Processing". Rewrite the process so that it populates P1_URL, e.g.
declare
l_branch_page number;
begin
-- your query goes here; I'll redirect to page 4
l_branch_page := 4;
:P1_URL := APEX_PAGE.GET_URL(p_page => l_branch_page);
end;
create an After Processing branch (why? So that process (see above) first populates P1_URL item). Its behavior's type should be "Page or URL (Redirect)", and its target should be &P1_URL. (literally that - ampersand followed by P1_URL followed by dot).
That's all; when you push the Submit button, process will populate P1_URL item which will be used by the branch and redirect to desired page. Will it work? It worked for me, I've just tested it.
Function:
function forward_user (p_username in varchar2)
return varchar2
is
...
return apex_page.get_url(p_page => l_branch_page);
end;
Process: just one line:
:P1_URL := forward_user(:session_user_name);

Related

Search Form - Execute Query - When detail record found then message

I have a search sales_orders/payment_details form ...
I am searching record through enter and execute query but in some cases detail record is not found
For Example: Enter Sales Order and Execute Payment record but there is no payment made yet...
then i would like to give message ('No record found')..
please guide me the trigger and its level of execution
Thanks
Javed
That's a master-detail form. I suggest you create it that way and let Forms worry about default data handling (querying, inserting, deleting) - use Data Block Wizard, it'll do everything right and create number of triggers which will enforce the master-detail relationship.
Once you're done, everything will just work - you don't have to write a single line of code.
As I don't have your tables, I used Scott's dept (master) and emp (detail). If you're familiar with that schema, you know that there are some employees in departments 10, 20 and 30, but nobody works in department 40.
Therefore, you'd want to display some message when you query department 40. On the left hand side is output for executing query on department 10; on the right is what we actually want (department 40, no employees there):
How to do that? Navigate to "Program units" in Object Navigator and edit the QUERY_MASTER_DETAILS trigger - it is one of those objects created by the Data Block Wizard.
Edit its code and add a few lines which will check whether detail rows exist; if not, display a message (see line #20):
PROCEDURE Query_Master_Details(rel_id Relation,detail VARCHAR2) IS
oldmsg VARCHAR2(2); -- Old Message Level Setting
reldef VARCHAR2(5); -- Relation Deferred Setting
BEGIN
--
-- Initialize Local Variable(s)
--
reldef := Get_Relation_Property(rel_id, DEFERRED_COORDINATION);
oldmsg := :System.Message_Level;
--
-- If NOT Deferred, Goto detail and execute the query.
--
IF reldef = 'FALSE' THEN
Go_Block(detail);
Check_Package_Failure;
:System.Message_Level := '10';
Execute_Query;
:System.Message_Level := oldmsg;
-- I added this 4 lines: --> here
if :employees.empno is null then
message('No employees in that department');
message('No employees in that department');
end if;
-- End of lines added by LF
ELSE
--
-- Relation is deferred, mark the detail block as un-coordinated
--
Set_Block_Property(detail, COORDINATION_STATUS, NON_COORDINATED);
END IF;
EXCEPTION
WHEN Form_Trigger_Failure THEN
:System.Message_Level := oldmsg;
RAISE;
END Query_Master_Details;
For simplicity, I used two consecutive message calls which then act as if it were an alert (otherwise, that message would be displayed in the status line at the bottom of the window). If you want, you can use "real" alert; I'll leave it to you.

Oracle APEX -How to combine server side condition of "requet = expression1" and "exisits ( sql query return atleast one row)

I want to call validation when
query return at least one row like ( select 1 from table where id = 1 )
and
when request "add_data" is called
Don't know what to select here:
The value of request can be accessed via the bind variable REQUEST . To tackle your specific problem you could add that to your condition of type 'Rows returned' like this:
SELECT 1
FROM table
WHERE (
id = 1 AND
:REQUEST = 'add_data'
)
If you're more a fan of pl/sql you could take the condition type 'PL/SQL Function Body' with code like this:
DECLARE
l_dummy NUMBER;
BEGIN
-- quit here if request value doesn't match
IF :REQUEST != 'add_data' THEN
RETURN false;
END IF;
-- check if we have rows in table.
BEGIN
SELECT 1
INTO l_dummy
WHERE EXISTS (select 1 from table where id = 1)
EXCEPTION WHEN NO_DATA_FOUND THEN
RETURN false;
END;
RETURN true;
END;
This is more code but you could find it easier to read which can be an advantage for maintenance later on.
The way I understood it, add_data request is related to a button you push. If that's so, then - if you don't do anything, request name equals button name - so let's pretend that button name is ADD_DATA. Therefore:
in "When Button Pressed" property select button's name (ADD_DATA, right?)
in "Condition Type" pick the condition you mentioned ("SQL query returns at least one row")

Authorization to exclude Home Page - Oracle Apex

I have a authorization scheme applied to the properties of the application that returns
RETURN MYFUNCTION(:APP_USER, :APP_PAGE_ID);
The issue is, it does not let the user login when the home page ID doesn't return. How can I apply the scheme to the application excluding home page?
I'm using Apex 19.1
I imagine your function would look something like this, with an added if statement for your problem at hand.
begin
-- exclusions for this page check
if p_page_id in (
101 -- login page
,1 -- home page
) then
return true;
end if;
-- does user have access to the page provided?
select count(*)
into l_exists
from dual
where exists
(select null
from sec_table
where page_id = p_page_id
and username = p_app_user
);
return l_exists = 1;
end;
I'm not sure whether I understood you correctly, but - myfunction should be created so that it accepts exactly two parameters, and their names must be p_username and p_password. It is supposed to return Boolean:
true if credentials are OK and you're allowed to connect
false, if the opposite
It seems that your function returns home page ID; is that correct? If so, well, I just told you what to do. If not, could you, please, explain what you mean by
when the home page ID doesn't return
and
how can I apply the scheme (...) excluding home page

Navigation menu access control through DB - Apex oracle

I have a table with Page and its page numbers stored in it. I want to show only those bars on the navigation menu whose page numbers are assigned to the end user. How can I do it?
I'm using Apex 19.1
Create a function which returns a Boolean, saying whether certain user can (or can not) access certain page, e.g.
create table t_access as
select 1 page_no, 'LITTLE' app_user, 'Y' yn from dual union all --> can access page 1
select 2 page_no, 'LITTLE' app_user, 'N' yn from dual; --> can NOT access page 2
create or replace function f_access(par_page_no in number, par_app_user in varchar2)
return boolean
as
l_yn t_access.yn%type;
begin
select a.yn
into l_yn
from t_access a
where a.page_no = par_page_no
and a.app_user = par_app_user;
return l_yn = 'Y';
exception
when no_data_found then
return false;
end;
Use that function in navigation list entry's conditions property; make it a "PL/SQL function body returning a Boolean" as
return f_access(1, :APP_USER);

Oracle APEX cannot save a value into a session

I have a page item P2_ITEM_TYPE_ID that gets set in Pre-Render, using a process calling PL/SQL:
BEGIN
select ITEM_TYPE_ID INTO :P2_ITEM_TYPE_ID from TABLE1 where ITEM_ID = :P2_ITEM_ID;
exception
when no_data_found then
:P2_ITEM_TYPE_ID := null;
END;
Currently the record for that ITEM_ID does not exist in TABLE1 so the exception NO_DATA_FOUND is thrown and originally the ITEM_TYPE_ID is set to null.
Now I want to set the ITEM_TYPE_ID by clicking on one of the cards on the page, grabbing its ID and setting page item P2_ITEM_TYPE_ID to that ID.
I have a dynamic action that runs the following javascript when card is clicked:
var $item_type_id = this.data;
console.log($item_type_id); //prints out correect ID
apex.item("P2_ITEM_TYPE_ID").setValue($item_type_id);
console.log(apex.item("P2_ITEM_TYPE_ID").getValue()); //prints out correct value
//set session state of P2_ITEM_TYPE_ID
apex.server.process ( "SAVE_HIDDEN_VALUE_IN_SESSION_STATE",
{
x01: $item_type_id,
pageItems: "#P2_ITEM_TYPE_ID"
},
{dataType: 'text'} );
I know the code works, as the correct values get printed to the console, but when I check the session of the page, P2_ITEM_TYPE_ID is blank in session. What could be the problem?
It is almost as if something is preventing th value from changing.
I have identical setup on another page with one small difference - the code in the pre-render does not include the exception part because there is always a record in TABLE1 for that ITEM_ID:
BEGIN
select ITEM_TYPE_ID INTO :P3_ITEM_TYPE_ID from TABLE1 where ITEM_ID = :P3_ITEM_ID;
END;
But the rest of the code is identical and session of P3_ITEM_TYPE_ID changes without an issue
You don't need apex.server.process for this, you can post the value of an item to the server with an Execute PL/SQL Code action that follows the javascript action you already have. Put the item name (e.g. P2_ITEM_TYPE_ID) in the Items to Submit attribute (set PL/SQL Code to just null;).
If everything is the same on those pages, except the EXCEPTION part, well - there's a workaround: use an aggregate function, e.g.
select max(ITEM_TYPE_ID) INTO :P2_ITEM_TYPE_ID from TABLE1 where ITEM_ID = :P2_ITEM_ID;
It will prevent the query from returning NO_DATA_FOUND if there's no value for that :P2_ITEM_ID and will store NULL into the :P2_ITEM_TYPE_ID.

Resources