Skip to content

Actions

An action executes in the database, and is always followed by an automatic commit or rollback. Actions can be connected to an entity, or specified directly in the main section.


action MoveSelectedPart {  
   parameter MoveDirection Text;  
}  

action SetEmuFromDate {  
   ludependencies = CurrencyCode;  
   parameter EmuCurrencyFromDate Date {  
      required = [false];  
   }  
}  

Implementation

The code example below changes the implementation handling of an item (typically attribute or action) to Java, instead of the default which is PL/SQL.

Note! It is recommended to only use this when a custom implementation is necessary, where the default PL/SQL implementation does not suffice.


action DeleteFile {  
   implementation = "Java";  
}  

Ludependencies

A list of model entities that are a part of the returned data.


action MyAction Text {  
   ludependencies = CustomerOrder, SalesPart;  
}  

Parameter

Input parameter to an action or function.

Note: For actions and functions on entities, the entity key is always the first parameter and has no need to be specified, only additional parameters need to be specified.


action LostLine {  
   parameter ReasonId Text;  
   parameter LostTo Text;  
   parameter ReasonNote Text {  
      required = [false];  
   }  
   ludependencies = BusinessOpportunityLine;  
}  

Example 1 (All connected code to an Action called by a command button)

Projection file:


action PromoteObsolete {  
   ludependencies = DocIssue;  
   parameter DocClass Text;  
   parameter DocNo Text;  
   parameter DocSheet Text;  
   parameter DocRev Text;  
   parameter Option Text {  
      required = [false];  
   }  
}  

Plsvc file:


PROCEDURE Promote_Obsolete (  
   docclass_    IN VARCHAR2,  
   doc_no_       IN VARCHAR2,  
   doc_sheet_    IN VARCHAR2,  
   doc_rev_      IN VARCHAR2,  
   option_       IN VARCHAR2 )   
IS  
   objid_      VARCHAR2(2000);  
   objversion_ VARCHAR2(2000);  
   info_       VARCHAR2(2000);  
   attr_       VARCHAR2(32000);  
BEGIN   
   Doc_Issue_API.Get_Id_Version_By_Keys(doc_class_, doc_no_, doc_sheet_, doc_rev_, objid_, objversion_);  
   Doc_Issue_API.Promote_To_Obsolete(info_, objid_, objversion_, attr_, 'DO');  
   IF option_ = 'MOVED' THEN  
   Move_Object_Connections(docclass_, doc_no_, doc_sheet_, doc_rev_, option_);  
   END IF;  
END Promote_Obsolete;  

PROCEDURE Move_Object_Connections (  
   docclass_ IN VARCHAR2,  
   doc_no_    IN VARCHAR2,  
   doc_sheet_ IN VARCHAR2,  
   doc_rev_   IN VARCHAR2,  
   option_    IN VARCHAR2 )   
IS  
BEGIN  
  Doc_Reference_Object_API.Move_From_Obsolete(doc_class_, doc_no_, doc_sheet_, doc_rev_, option_);  
END Move_Object_Connections;  

Client file:


command Obsolete {  
   label = "Obsolete";  
   variable HasMovedObj {  
      type = Text;  
   }  
   variable Option {  
      type = Text;  
   }  
   variable IsStructureDoc;  
   enabled = [(Objstate = "Preliminary" or Objstate = "Approved" or Objstate = "Released") and EdmFileRef.Objstate != "CheckedOut" and EdmFileRef.Objstate != "OperationInProgress" and IsAccessOwner = "TRUE"];  
   execute {  
      if [RedlineFileStatus = "TRUE"] {  
         alert("Cannot set documents to obsolete when comment file is checked out.");  
         exit CANCEL;  
      }  
      call CheckStrucObsolete(DocClass, DocNo) into IsStructureDoc;  
      if [IsStructureDoc = "TRUE"] {  
         confirm("Warning: The document you are trying to set to obsolete is part of a document structure. Do you want to continue with this operation?") {  
            when CANCEL {  
               exit CANCEL;  
            }  
         }  
      }  
      call IsObjConSatisfied(DocClass, DocNo, DocSheet, DocRev) into HasMovedObj;  
      if [HasMovedObj = "TRUE"] {  
         dialog RestoreObjConDlg into(Option) {  
            when OK {  
               if [Option = "Inherited"] {  
                  set Option = "MOVED";  
               }  
            }  
            when CANCEL {  
               exit CANCEL;  
            }  
         }  
      }  
      else {  
         confirm("Do you wish to obsolete the Document?") {  
            when CANCEL {  
               exit CANCEL;  
            }  
         }  
      }  
      call PromoteObsolete(DocClass, DocNo, DocSheet, DocRev, Option);  
   }  
}  

Example 2 (All connected code to an Action called by an Assistant)

Projection file:


action ReportQuickTime {  
   ludependencies = JtTaskTransaction, JtExecutionInstance;  
   parameter TaskSeq Number;  
   parameter ExecutionInstanceSeq Number;  
   parameter MaintOrgSite Text;  
   parameter MaintOrg Text;  
   parameter ResourceSeq Number;  
   parameter TransactionDate Timestamp;  
   parameter Hours Number;  
   parameter TimeType Text;  
   parameter Comment Text {  
      required = [false];  
   }  
}  

Client file:


assistant QuickReportAssistant using QuickTimeReportSet  
   {  
   label = "Report Time";  
   setup InitAssignment {  
      variable TaskNo;  
      variable AssignmentNo;  
      variable PlannedHr;  
      variable TimeReportDefault {  
         type = Structure(QuickToolReportStruct);  
      }  

      execute {  
         set TaskSeq = TaskNo;  
         set ExecutionInstanceSeq = AssignmentNo;  
         set Hours = PlannedHr;  
         call GetTimeQuickReport(TaskSeq, ExecutionInstanceSeq) into TimeReportDefault;  
         set TaskSite = TimeReportDefault.TaskSite;  
         set TransactionDate = TimeReportDefault.TodayDate;  
         set TimeType = TimeReportDefault.DefTimeType;  
         set WoNo = TimeReportDefault.WoNo;  
         set Company = TimeReportDefault.Company;  
         set MaintOrgSite = TimeReportDefault.MaintOrgSite;  
         set MaintOrg = TimeReportDefault.MaintOrg;  
         set ResourceId = TimeReportDefault.ResourceId;  
         set ResourceSeq = TimeReportDefault.ResourceSeq;  
      }  
   }  
   steps {  
      step {  
         label = "Report Time";  
         group QuickReportGroup;  
        //list ReportedTimeList(ReportedTimeArray);  
      }  
      final step {  
      }  
      cancelled step {  
      }  
   }  
   finish command {  
      execute {  
         call ReportQuickTime(TaskSeq, ExecutionInstanceSeq, MaintOrgSite, MaintOrg, ResourceSeq, TransactionDate, Hours, TimeType, TimeReportComment);  
         navigate back;  
      }  
   }  
   cancel command {  
      execute {  
         navigate back;  
      }  
   }  
   restart command {  
      visible = [false];  
   }  
}  

Plsvc file:


PROCEDURE Report_Quick_Time (  
   taskseq_               IN NUMBER,  
   execution_instance_seq_ IN NUMBER,  
   maint_org_site_         IN VARCHAR2,  
   maint_org_              IN VARCHAR2,  
   resource_seq_           IN NUMBER,  
   transaction_date_       IN DATE,  
   hours_                  IN NUMBER,  
   time_type_              IN VARCHAR2,  
   comment_                IN VARCHAR2)   
IS  
   transaction_id_ NUMBER;  
BEGIN  
   IF(Resource_API.Get_Resource_Type_Db(resource_seq_) != Resource_Types_API.DB_PERSON) THEN   

      Jt_Task_Transaction_API.Create_Time_Tool_Transaction(   
         transaction_id_,  
         'TOOLS',  
         task_seq_,  
         Jt_Execution_Instance_API.Get_Task_Resource_Seq(task_seq_,execution_instance_seq_),  
         execution_instance_seq_,  
         NULL,  
         NULL,  
         resource_seq_,  
         hours_,  
         transaction_date_,  
         maint_org_site_,  
         maint_org_,  
         time_type_,  
         comment_  
      );  
   END IF;  
END Report_Quick_Time_;  

Unbound Actions and Security

Unlike bound actions, unbound actions do not come with its own row level security, and have to be defined by the developer.

Initialcheck for securing Unbound Actions

Due to security reasons, unbound actions require a value set against the initialcheck property. The initialcheck specifies a piece of code that needs to be executed before the actual action takes place, to enforce row level security for the action (provided it is needed).

If an action is bound, initialcheck is normally not needed since the action operates on the data provided by the OData entity. This is where security is enforced by fetching the record, using the row-level security defined on the corresponding View.

For an unbound action it is possible define one more initialcheck as per the requirement. They can be defined in several different ways as follows:

No Security


initialcheck none;  

Typically, this applies to actions without any parameters or with parameters that are not keys. Actions connected to a virtual or structures also normally use this initialcheck definition.

Security implemented in PLSQL Logic


initialcheck implementation;  

Indicates that row level security is implemented by manually written code somewhere within the action implementation (that is the business logic or the PLSVC file).

Security using predefined checks


initialcheck UserAllowedSite(Contract);  
parameter Contract Text;  
parameter PartNo Text;  

This is the use of one (of several) predefined initialcheck definitions that makes use of the "user allowed site function". Using one of the predefined checks results in code generation enforcing the security using the specified function in the PLSVC layer.

Note! When using predefined checks, the argument that is passed in the function needs to be defined as a parameter. In the example above Contract is a parameter.

Security using custom check


initialcheck MyOwnCheck(Contract, PartNo);  

A custom check can also be implemented for enforcing the security. It is necessary to ensure that the function used together with the initialcheck actually exists in the.plsvc file with the exact method signature. In the above example, the PLSVC file must contain a function called My_Own_Check___, with two parameters with the same datatype that is defined in the action definition. The functions used in the custom check must also return a Boolean value where TRUE means the user is allowed to run the action, and FALSE means otherwise.

List of available predefined initialcheck functions

Following initialcheck functions are predefined in Developer Studio:

  • UserAllowedSite(Contract)
  • UserAllowedCompany(Company)
  • UserAllowedHrCompany(Company)
  • UserAllowedHrEmployee(Company, EmpNo)
  • UserAllowedHrEmployee(Company, EmpNo, LogicalUnit)
  • UserAllowedHrEmployee(Company, EmpNo, LogicalUnit, TransactionDate)
  • UserAllowedHrPerson(PersonId)
  • UserAllowedHrPerson(PersonId, LogicalUnit)
  • UserAllowedHrPerson(PersonId, LogicalUnit, TransactionDate)

What this means is that if any of these function names, with the correct number of parameters, are set with the initialcheck, the corresponding PL/SQL code is automatically generated, without having to be defined by the developer.

Each one of the reserved initialcheck functions have a corresponding PL/SQL procedure, which can be used when there is a need to do such checks from within the PLSVC file.

The function and their corresponding PL/SQL Procedures are listed below:

InitialCheck Function Corresponding PL/SQL Procedure
UserAllowedSite User_Allowed_Site_API.Is_Authorized
UserAllowedCompany User_Finance_API.Is_User_Authorized
UserAllowedHrCompany User_Access_API.Is_User_Company_Id
UserAllowedHrEmployee User_Access_API.Is_User_Available_Emp_No
UserAllowedHrPerson User_Access_API. Is_User_Available_Person_Id

Typical usage for these can be when unpacking a string with a selection containing key references (that is KeyRefs) where once unpacked, there is a need to perform the security enforcement for each key reference.