Você está na página 1de 44

HRMS Release 11 Vision Custom Library Examples

The following details work carried out by the Release 11 HRMS Vision team to implement Custom Library examples on the Release 11 vision database. This document is not meant to be an instructor manual for those presenting this feature. It is meant to be a more technically biast description of exactly what was done to achieve the changes to the vision environment. It also gives a brief description of the scenarios implemented. The format of this document is as follows: Objectives Overview of the Custom Library Application Server Architecture Details of scenarios implemented Selling points Appendices Appendix 1 - Guidelines For The Addition Of User Defined Business Rules Within The Oracle Applications White Paper - Andrew McGhee, April 1998 Appendix 2 - Copy of CUSTOM.pll Appendix 3 - Copy of HRCUSTOM.pll Appendix 4 - Copy of HRCUST1.pll Appendix 5 - Copy of HRCUST2.pll Appendix 6 - Copy of Server Side Custom Library Code ( server_cl_code.sql )

Objectives
During the setting up of the Release 11 vision database, it was decided to add Custom Library scenarios to show people what a powerful feature it is when used in conjunction with the Oracle HRMS Application. At the same it was decided to include at least one scenario that made use of the Release 11 Formula PL/Sql function.

Overview Of The Custom Library Application Server Architecture


The Custom Library is a feature that is available from within any of the Oracle Applications, it is not Oracle HRMS specific. This feature first appeared in the Production 13 Smart Client release of the Oracle Applications. Since there is only a single library, one has to give careful consideration to the design of any code they decide to put within the library. As the library is nothing more than a Forms library, all restrictions and limitations that exists in any standard Forms library also apply to the Custom library. The Custom Library is actually a file called CUSTOM.pll and CSUTOM.plx. The .plx extension is a compiled version of the .pll file. These files reside on the Application server in the $AU_TOP/resource directory. Be aware that if both the .pll and .plx versions of the file exist in the same directory then Oracle Forms will use the .pll version of the file. For the purpose of the vision environment set up, a number of additional HRMS specific libraries were created. This was to show how one might go about splitting additional Form Custom Library logic between multiple libraries ( based on Form name ).

CUSTOM Library

HRCUSTOM Library

HRCUST1 Library
PERWSHRG, PERWSEPI, PERWSEMA

HRCUST2 Library
PERWSEPY, PAYWSMEE, PERWSEAD

R11 Vision HRMS Custom Library Architecture

The Custom Library can be switched on and off dynamically by the user by selecting the Help.. Tools.. Custom Code.. Off option from the menu bar. You can prevent users from being able to switch off the Custom Library by setting a profile option ( that I cant remember at the time of going to press ). Further details about the Release 11 Custom Library can be found in the Release 11 Applications Documentation Zoom and Customizing Oracle Applications (http://www-apps.us.oracle.com/doclib/11.0/comus/us/index.htm ).

Details Of Scenarios Implemented


All of the scenarios implemented required code to be created in a Forms library and / or a newly created server side procedure. Both the libraries and procedures have been heavily documented and are attached to this document as appendices The following scenarios were implemented:

Scenario 1 - Person & Mega Person Form ( PERWSEPI, PERWSHRG )


When entering the Person form, the user is prompted as to whether they would like a pre-selected list of required fields to be highlighted. The selected fields are: Last Name Employee Number Person Type Social Security Number Gender Date Of Birth

In addition to the above fields, the Ethnic Origin field is one of the selected fields if you are running in a U.S. legislation. The user has to select Yes, No, or Cancel. If they select Yes then the fore mentioned fields are highlighted in blue.

Scenario 2 - Person & Mega Person Form ( PERWSEPI, PERWSHRG )


This scenario is associated with scenario 1. When saving changes in the above forms, and the employee type is Employee, a check is made to see whether the user selected to highlight required fields ( scenario 1 ). If the user chose to highlight the fields then they are only able to save their changes if all of the required fields have been entered. If they havent entered all of the fields then a suitable message is displayed. The message is different depending on the current legislation. If the message is displayed then the record is prevented from being able to commit.

Scenario 3 - Person & Mega Person Form ( PERWSEPI, PERWSHRG )


When entering the Person form, the user is prompted as to whether they would like to hide the Mail To field. The user has to select Yes, No, or Cancel. If they select Yes then the Mail To field is removed from the form. NOTE: When removing the Mail To field, the test Mail To still remains. This is because the text is part of the boiler plate for the form and it isnt currently possible to dynamically remove boiler plate text. Apparently in Forms 5 you will / are able to dynamically remove boiler plate text.

Scenario 4 - Salary Administration Form ( PERWSEPY )


When saving salary proposal details, extra validation is performed to check whether the proposal amount falls within market salary minimum and maximum values associated with the job the person is assigned to. If the amount is outside of the range then a warning message is displayed ( but the user is allowed to commit the changes ). Two segments, market salary minimum and market salary maximum, were created on the Additional Job Details flexfield. These segments are used to compare the entered proposal amount against. A server side procedure was created to retrieve these values from the jobs table.

Scenario 5 - Element Entry Form ( PAYWSMEE )


A new element was created, Earnings Potential with two input values with the following definitions Sequence 1 2 Input Name Current Earnings Earnings Potential User Enterable Yes No

As well as creating the above element, a new formula, CL_EARN_POTENTIAL, was created. This formula basically does the following: Accept an input; current earnings If the person doesnt have a date of birth entered then earnings potential = 0 earnings message = Persons age not recorded. Unable to work out future earnings potential If the persons age is >= 30 then earnings potential = current earnings * 4.5 earnings message = Earnings potential is 4.5 times Current Earnings If the persons age is < 30 then earnings potential = current earnings * 1.5

earnings message = Earnings potential is 1.5 times Current Earnings

Having entered the current earnings input value, the user is prevented from entering the earnings potential segment. On saving the change, a call is made to a server side procedure that execute the CL_EARN_POTENTIAL formula. The formula returns two values; earnings potential and earnings message. The earnings potential returned value us used to update the earnings potential input segment on the element. The earnings message is displayed to the user. This scenario demonstrates a number of things: How the Custom Library can be used to update non-enterable fields How the Custom Library can call a server side procedure that then executes a Formula PL/Sql program How Formulas can be used to store business rules

Having entered the element for a person, it looks really good if you then edit the formula to change the message / calculation logic and then update the saved element to show the new message / calculation being performed !!! On-Line updating of business rules !!! NOTE: The above was set up within the US HRMS Manager. The Earnings Potential element was set up within both the US and UK Vision HRMS business group. This means that when showing this within the UK business group, you have to switch responsibility to the US business group to update the formula.

Scenario 6 - Absence Form ( PERWSEAD )


When entering Family Leave absences for an individual, the FMLA 12 month rolling average hourly and weekly amounts are calculated. Two new segments were created on the Additional Absence Details descriptive flexfield to hold the rolling totals: Accumulated Days Accumulated Weeks The rolling 12 month period is from the ( actual absence end date minus 12 months ) to the actual absence end date. It is assumed that there are 8 hours in a day and 40 hours in a week. The current scenario doesnt do any checks about calendars and weekends etc. A server side procedure was created to do the accumulation.

Scenario 7 - Modulus 11 Check Digit ** NOT IMPLEMENTED IN CUSTOM LIBRARY


In the server side package that was created, vision_cl_code, there is a procedure called check_digit. This routine accepts a number as input and calculates the Modulus 11 check digit value. This routine may be useful to show how it is possible to perform check digit calculations when entering Employee Numbers.

Scenario 8 - Euro Currency Conversion ** NOT IMPLEMENTED IN CUSTOM LIBRARY


In the server side package that was created, vision_cl_code, there is a procedure called euro_conversion. This routine retrieves the EURO exchange rate value from the HR Exchange Rates table. Specific details of pre-requisite setup requirements can be found in the source code for the server side procedure ( appendix 6 ).

Selling Points
The Custom Library is a very strong feature in its own right but when combined it with Formula PL/Sql and API User Hooks, we have a VERY powerful business rule methodology. Appendix 1 contains a copy of an excellent White paper, Guidelines For The Addition Of User Defined Business Rules Within The Oracle Applications; Andrew McGhee, April 1998. This brings together these new technologies and presents a framework of how they can be used together to provide an total business rule solution within the Oracle HRMS Application.

Good luck in your use of this new technology

The Release 11 HRMS Vision Team

Appendix 1 - Guidelines For The Addition Of User Defined Business Rules Within The Oracle Applications White Paper - Andrew McGhee,
April 1998

GUIDELINES FOR THE ADDITION OF USER DEFINED BUSINESS RULES WITHIN THE ORACLE APPLICATIONS Andrew McGhee HRMS Product Support Manager Oracle Corporation, Bracknell, UK Summary It has become evident in recent years that the nature and structure of the Information Technology ( IT ) department within large organizations is changing. This change is being driven from the highest levels of the organization and is fundamentally affecting the organization and its culture. I am referring to the way in which IT is perceived from within the organization and the role it plays to achieve overall corporate success. The IT department may once have been viewed as an independent function within the organization but this is no longer the case. CIOs are realising that their staff need to recognise that the needs of the business must drive technology decisions. Cross functional team projects are becoming common place. This typically involves players from multiple discipline ( business, technology etc ), which enables knowledge to be harnessed to the broader objectives of the project. The business rules and requirements are therefore taking centre stage when reviewing what applications are required to support the overall objectives and goals of the organization. This does not however lessen the importance of choosing the right technology. Wrong decisions in this area could be disastrous. In the past when organizations have looked to create or replace internal business application packages, their options were primarily: 1. Buy an off the shelf built application and hope that it meets all or most of the needs of the organization 2. Custom build the required application from start to finish yourself Both of the above options were considered mutually exclusive and they both have their own relative advantages and disadvantages. Off the shelf applications are ideal if the 100% requirement fit can be satisfied ( but isnt every organization slightly different in some way from another ? ). Custom built applications give you everything that you wanted but the cost of internal ownership of the application ( code, support, maintenance etc ) is high. This paper looks at some well known and some not so well known tools and technologies and new features within the Oracle Applications that make it possible to extend the Oracle Applications to help satisfy your unique business rule requirements within a supportable, manageable and upgradeable framework. In order to review the suitability of the tools and technologies for satisfying business rules, we will examine exactly what is meant by the term business rule and review how these can be implemented using identified tools, technologies and techniques. Scope This paper will look at possible strategies for the addition of business rules to the Oracle Applications in a controlled, supported and upgradeable manner. We will address the following: What is a business rule ? Can business rules be categorised / classified ? If so, how ? Standard business rule coding options ( Forms, Reports, PL/Sql ) New coding options ( Custom Library, APIs ) Coding options post Release 10 ( API User Hooks, Formulas Generating PL/Sql ) Examples of implementing identified business rule categories

To get the best from a packaged solution, the package must be implemented as it was designed to be used with as little alteration to the core package as possible. Following this policy mitigates the risks associated with the ability to upgrade and move forward with the new package, taking advantage of new features and technologies. This in turn reduces the cost of ownership over time. This paper is not intended to be a replication of previous papers on the subject of architecturing your applications environment for the development and preservations of customisations. I may at times refer to good practices outlined in previous articles but hopefully, most of what this paper covers will be new to the reader. The application software baseline used in the examples for this paper was Oracle Applications Production 16.1 Smart Client. Most of what is recommended is applicable to all of the Oracle Application Smart Client modules ( GL, PO, AP, AR etc ). However, there are some sections that are only relevant to the Oracle HRMS suite of application modules. Such unique examples will be highlighted as required. The Human Resources ( HR ) and Payroll application will be used for the highlighting of all examples within this paper. What is a Business Rule ? A business rule, for the purpose of this paper, is any rule of business that is required to be enforced by virtue of performing a specific business function. For example; For each person entered on the system, you must record the gender of the individual or A person can only be promoted if they have held their current position for more than 3 years Oracle Applications, by their very nature and design, are very flexible and extendible. Data definitions e.g. position and grade definitions, are user definable and can be built to suit the individual requirements of your organization. These definitions represent a meta data definition layer of the underlying structures. Such definitions, because they are stored within the application as data in tables, are protected during future upgrades of the application. The applications also enable the definition of user specific attribution within key and descriptive flexfields and special information types ( HRMS specific ). Can Business Rules be Categorised / Classified ? If so, How ? During any standard functional gap analysis exercise ( using the Oracle Applications Implementation Methodology, AIM, for example ), when a new applications is being evaluated / tested for degree of fit suitability, organizational business requirements and rules are tested / mapped on to the new software. A pre-requisite for this is that existing business procedures, rules and requirements have already been identified and recorded. Looking back at the definitions of example business rules ( above ), you will be able to identify that each example could represent a different category of rule. Why, some may ask, is it necessary or good practice to spend time grouping rules into different categories ? The process of categorising rules will facilitate: The identification of duplicate and redundant rules The estimation of effort required to implement all rules based on the numbers in each category The recording and documentation of rules which will help on-going support and understanding of the application by everyone involved in the project. This will also make the process of future upgrades more manageable. When categorising business rules, the interface mechanism ( e.g. OLTP or batch processing ) to interact with the application is not important. What is important is that the rules relate to specific data items or processes that are important to the business. The following is an example of a business rule categorisation chart that I have used. For each rule category, I have attempted to give an example of an appropriate business rule.

1 Static Data Rules 1.1 1.1.1


Single Data Item Attribute Rules Format Data Item Size and Construct Employee phone numbers data items must be able to store country dialing codes as well as the number

1.1.2

Domain

Data Item Allowable Values Organization unique absence types must be available for specified data item values

1.1.3

Required

Data Item Required or Not When entering a person, you must enter their nationality

1.1.4

Logic Attribute Rules

Data Item Specific Validation The start date of an employee cannot fall on a weekend

1.2

Multi Data Item Dependency Rules Item x can only have a value if item y is entered A persons previous last name cannot be the same as the persons current last name

1.3 1.3.1 1.3.2 1.3.3 1.3.4

Entity Rules

Requirement Rules
Entitlement Rules Relationship Rules Access Rules

These rules are hard to classify and could mean different things to different people Each employee must have a home address record Only directors are entitled to company stock options A person must only have one current salary element at any one time The personnel administrator for the finance department is only able to view employees who work within that department

2 Data Operation / Event Rules 2.1 2.2 2.3


Create Rule Update Rule Delete Rule When creating a new employee, notify the employees new manager of joining / starting details Employee salaries can only be increased by amounts as defined by the current organization grading structure Application details made to the organization within the past two years cant be deleted from the system Rules that involve numeric algorithms to compute results e.g. calculate monthly salary from yearly salary value; calculate absence days to date when entering new absence details for an employee When hiring an applicant, the approving manager must forward on the request to his manager to approve the hire. Only when this is complete, can the applicant be formally hired.

3 Calculation Rules

4 Process Flow Rules

Business Rule Categories

Some individuals may be more comfortable with categorising entity type rules in terms of data operation or event e.g. create / update / delete. Be aware that this would require many entity rules to be listed more than once ( as create rules often need to be checked during update as well ). The above groupings are not meant to be a finite definition of categories. As shown with the definition of entity rules, certain individuals may be more comfortable using data operation / event type groupings instead. I have found the above categories in the past to be a good starting point for mapping discussions. Later in this paper we will review these categories and highlight what tools, technologies and techniques are appropriate for implementing each of the categories. Well Known Customization Coding Options One of the advantages of having to customize / extend Oracle Applications is that there are industry leading development tools available to assist you in such a task. Tools include: Oracle Designer 2000 PL/Sql Oracle Developer 2000 SQL*Plus Oracle Discoverer 3.0 Pro*C

Many previous White Papers have been presented on the subject of development tools and their use in conjunction with the Oracle Applications. I will not repeat what has already been said. I would however refer you a White Paper entitled Architecturing Your Applications Environment for the Development and Preservation of Customizations, Paula Kodjou, Oracle Corporation. The paper was presented at the OAUG Spring 1996 conference in Orlando, Florida. This paper builds on the Oracle Application Development standards to present strategies for creating environments that support customizations. All of the above tools are used by the Oracle Applications development teams to actually create the various application system modules. It therefore goes without saying that these tools would be preferred choices when deciding what to use to extend the applications. Not So Well Known Customization Options As everybody well knows, the Oracle Applications are constantly evolving in the areas of both functionality and features and their use of leading edge technology. This means that keeping up to date with new features could be described as an art in itself. From Production 13 of the Oracle Applications Smart Client release, a new feature was introduced to the applications called the Custom Library. The custom library is a facility that enables you to augment and extend the Oracle Applications without modification of Oracle Application code. The custom library can be used for defining zooms ( a mechanism to jump to forms from other forms ) and for enforcing business rules. Some good definitions of the custom library are: A mechanism that allows extension of Oracle Applications without modification of Oracle Application code or An Oracle Forms PL/Sql library that allows you to take full advantage of all of the capabilities of the Developer 2000 suite of products and integrate your code directly with Oracle Applications or A supported, upgradeable, user definable, partitioned code repository for custom code The custom library is a reserved area for user defined extra validation and changes that preserve the base Oracle Application form on upgrade and allow the custom changes to be easily de-coupled when investigating bugs so that the base Oracle Application form can be supported. As you may have already gathered, the custom library is only associated with the application On-Line interface i.e. Forms. It is not suitable for batch type interfaces. The custom library works in the following way; the Oracle Application forms send events to the custom library. User defined custom code can then take effect based on these events. This unique facility is provided for the exclusive use of

Oracle Application customers. The Oracle Application products do not supply any predefined logic in the custom library other than the procedure shells. It is important to be aware that you must not modify any component of an Oracle Applications module ( either directly or through the custom library ) without a thorough understanding of the processing logic and underlying database structure for the component. Appendix 1 details a list of things that I wish that I had known and learnt when using the custom library within a Production 16.1 Smart Client environment. Custom Library Architecture Contains packages and procedures that are required for all forms to support the menu, toolbar and other required standard behaviours APPCORE Library Application Form

CUSTOM Library Custom Library Structure Standard event triggers in the application forms call APPCORE routines that in turn call the custom library. Other libraries exist that are called in the same manner as the custom library but these libraries are for application internal use only and changes to them are NOT supported. Release 10 Custom Library Support Event Points The custom library receives two different kinds of event call; generic and product specific. Generic events are common for all Forms in Oracle Applications. Product specific events are reserved for future use by the applications and are specific to individual applications. Generic custom library events in Release 10 Smart Client include: WHEN-NEW-FORM-INSTANCE WHEN-NEW-RECORD-INSTANCE WHEN-VALIDATE-RECORD WHEN-NEW-BLOCK-INSTANCE WHEN-NEW-ITEM-INSTANCE ZOOM EXPORT

Libraries contain reusable client side code. They enforce coding standards by allowing the same code to be used by all forms to enforce specific validation, navigation and cosmetic behaviours. Libraries allow code to be written once and used by multiple forms. Additionally, because the executables attach at run time, they facilitate the development and maintenance without being invasive to a form. In basic terms, the custom library lets you change properties, functionality and operation of a form as if you were actually changing the source code of the form. Of course you cannot do in a library everything that it is possible to do within a form but you may be surprised by just how much can be done. Some examples of the types of things that Ive been able to do to date with the custom library using the above event points include: Changing form field properties e.g. hiding form fields Adding additional field validation and cross field validation Changing a default LOV or Default Where clause Automatically populate fields based on some form of server side computation Write audit logs directly to file

Call new forms that interact with core forms In addition to the above, the custom library can be used for: Manipulating conditionally required fields Manipulating mutually exclusive fields Setting of default values Setting of inter field calculation between added fields General processing at event points

Release 11 HRMS Custom Library Supported Events This section is only applicable to the Oracle HRMS suite of applications. When working with a very large public sector organization, who had many thousands of so called business rules, it was evident that the standard custom library event points were not sufficient in order to be able to satisfy all of their business rule requirements. As a result, the HRMS application development group identified additional event points that would be useful to both HRMS customers and internal HRMS localization and verticalization teams. The identified event points were: WHEN-CREATE-RECORD PRE-INSERT POST-DELETE WHEN-FORM-NAVIGATE POST-QUERY KEY-DELREC PRE-DELETE POST-UPDATE POST-FORMS-COMMIT SPECIALn WHEN-BUTTON-PRESSED PRE-UPDATE POST-INSERT NAVIGATE

These event points were added to a subset of Release 11 Oracle HRMS Application forms. Forms without these new event points will be updated at some point in the future. The addition of these new event points to all HRMS Application forms will give users of the application much more scope and facilities to extend the functionality of the base application. As we have already seen, these Custom Library changes are very interface dependant i.e. only applicable to the Smart Client ( i.e. Form ) OLTP interface. It would be possible to store all additional business rules within client side packaged procedures but this would prevent such code from being used by other interfaces e.g. Web, batch processes etc. It is therefore recommended that where possible, such rules are stored as package procedure Application Program Interfaces ( APIs ) on the server. APIs APIs are part of the Oracle Applications development methodology for its multi-tiered architecture. Papers have already been presented in the past about exactly what these routines are and why it is important to have code located on the server. Hence, I will not be covering such topics in any depth in this paper. The remainder of this section regarding APIs is Oracle HRMS specific. Oracle Human Resources and Oracle Payroll have implemented APIs using stored package procedures. They are business processes which contain full data validation and manipulation. This development methodology enables integration with client applications such as Web and Forms interfaces. Their flexibility provides an open interface for other uses such as initial data loading and product customization. In Release 10 of the Oracle HRMS Applications Smart Client suite, instead of developing another standalone interface ( as had been done with Release 9 of the Oracle Applications using Oracle Forms 2.3 ), HRMS Development started to changed its development methodology. New standards were created for implementing a set of programs to centralise the validation and processing logic on the server. In the long term avoiding duplication of development and maintenance effort by Oracle Applications across different end user interfaces. These user interfaces would be easier to implement as their database work is carried out by calling the new APIs. At the same time providing a reliable open interface which can be used directly by Oracle consultants and customer implementation teams.

Client-Side Server-Side

Programs APIs Database

Module Structure The API structure is designed around the business processes that we expect customers wish to perform within the application. Each API carries out one complete business operation; instead of providing insert, update and delete procedures for every database table in the application. This approach encapsulates all the database changes which need to be carried out for a single business process. This helps hide the complexity of the database structure and makes the APIs easier to use. For example, when a new employee is entered on to the system, data may be inserted in to 6 database tables. All the individual insert statements are grouped in to one create employee API. Therefore this logic does not have to be duplicated and maintained in both the form and other interface e.g. Web. Using APIs in Forms does not negate the need for client side validation. Forms 4.5.7 contains graphical features such as check boxes and list of values which prevent invalid values from being entered. Oracle HRMS API Layers Within the HRMS application suite, different categories or types of APIs have been identified and are used to enable the modular and structured ( building block ) construction of business process rules. This can best be represented diagramatically: Custom / Alternative Interface Layer E.G. create_gb_employee Business Process Layer E.G. create_employee

Wrapper for create_employee with GB flexfield segment names

Published APIs Oracle Applications internal code layers

Business Support Layer E.G. create_emp_asg

Row Handler Layer E.G. per_people_f Table

Oracle HRMS API Layers This layered architecture and the fact that customer calls to published business process APIs are allowed opens up the ability to write custom business processes that interface with the application in a totally supported and upgradeable manner. The published APIs therefore can be used as building blocks to construct custom APIs. For example, suppose that when a new employee joins your company you always obtain their home address at that time. The address details must be recorded in the HR system because you run reports which expect every employee to have an address. You could write your own business process API to create new employees with an address. This API is like a wrapper that holds together everything that is important to the operation. Such an API could call the standard create_employee API and then immediately afterwards call the standard create_person_address API.

custom_create_company_employee
last_name first_name etc.. person_id etc.. person_id address_line1 etc..

create_employee API (Standard HR API) Wrapper Module Construct

create_person_address API (Standard HR API)

Being able to call standard APIs within a supported framework highlights even more of the unique flexibilitys of the Oracle Applications. But, what if your business rule was associated with a very specific process e.g. creating an employee, and you wanted to able to influence the success or failure of the creation of the employee record(s) depending on whether your custom rule(s) were successful or not. Because of such a requirement, the Oracle HRMS Application development team developed the concept of API User Hooks ( this facility is only available within the HRMS application suite ). Oracle HRMS Application User Hooks In Release 11 of the Oracle HRMS Application suite, a subset of application APIs will support the execution of user defined custom business through a mechanism known as API User Hooks. These hooks let you extend the standard business rules that are executed by the core APIs. Custom specific validation rules or further processing logic can be created and this will be executed automatically whenever the associated API is executed. User hooks are locations in the APIs where extra logic can be executed. When the API processing reaches a user hook, the main processing will stop and any custom logic will be executed. Then, assuming no errors have occurred, the main API processing will continue. All extra custom logic that is needed is implemented as separate server-side package procedures using PL/Sql. Having written additional logic, these procedures need to be associated with the pre-defined user hook points. User hooks are only supported at specific business process and row handler API layers. There are different user hook event points depending on the layer. Business Process Layer E.G. create_employee Before Process Hook Core Logic After Process Hook Row Handler Layer E.G. per_people_f Table After Insert Hook After Update Hook After Delete Hook

HRMS API User Hook Points The linking of the Oracle Application APIs and the hooked custom developed APIs is done through hook package body procedures. These procedure bodies are generated by running an Oracle Application utility. This utility determines what user defined custom package procedures to link to what API user hooks by extracting user hook definitions from definition tables. The utility then generates the hook package body procedure and the custom code is now hooked to the standard API code. For a more detailed description of this process see the Release 11 HRMS API Technical Reference Manual essay. HRMS API user hooks provide you with the ability to transplant your unique business process rules right within the heart of the application to where they are needed without losing Oracle support of the application.

The next logical step would be able to store rules in some sort of dictionary and to be able to automatically generate PL/Sql package procedures that can be hooked in to the core APIs. This was considered important enough that the HRMS Application development group developed a Fast Formula PL/Sql Execution engine that will be part of Release 11 of the applications. This feature is unique to the Oracle HRMS Application suite. Oracle HRMS Fast Formula PL/Sql Execution Engine A core module of the Oracle HRMS Applications suite is the Fast Formula application. Formulas are generic expressions of rules, calculations or comparisons that you may want to perform. They can take input and return values or messages. Formulas were typically used in Release 10 of the Oracle Applications Smart Client application to define computational calculations and input validation for Payroll processes. Formulas are written in their own English like syntax and is therefore positioned to be an end user tool. Being able to generate and execute formulas in PL/Sql now means that nontechnical users can assist in the generation and maintenance of user defined business rules that govern the application. Being able to store rules in a non-technical structure in a formula dictionary greatly reduces the overhead of business rule creation, maintenance and overall cost of ownership. The PL/Sql formula routines are callable from client ( Forms ) and server ( PL/Sql ) interfaces. This feature is a major enhancement to the Oracle HRMS Application. As formulas are part of the core application, they are supported during future software upgrades. There is no need to re-write the business rule because changes have occurred to the database schema. Such changes should be invisible to the end user as they will be handled by the core application. This means that the overall cost of ownership of having such rules is greatly reduced compared to having to custom write PL/Sql code to implement the rules yourself. Business Rule Framework This section is only applicable to the Oracle HRMS suite of applications. So far we have looked at existing and new technologies and tools for the extension and enhancement of the Oracle Applications. One problem in itself is that there are so many tools and techniques to choose from. Deciding which of the tools to use for what purpose is one of the first decisions that will have to be made. As stated earlier in the paper, business rules should ideally be interface independent. The goal is to have one set of code that performs the same rules whether it is being called from a form or some other type of interface ( e.g. batch process ). Because most of the existing Release 10 and Release 11 HRMS application forms call different server side packages to the published user supportable APIs, it is not sufficient to assume that by just using user hooks to define custom rules that all possible system interfaces will be accommodated by the new rules. The custom library thus has an important part to play to link the OLTP forms to the hooked user defined rules. This can best be represented diagramatically showing what I am proposing to be a framework for custom business rules. The arrows represent possible program flows.

Data Model Form Core HRMS APIs Batch Processes Custom Library Custom Business Rules Database

Hooked Code User Defined APIs + PL/Sql Formula APIs

Business Rule Framework The goal is to ensure that where possible, all business rules are created as package procedures stored within the database. Some business rules may be interface dependent and so it may be necessary to have specific rules within the custom library ( e.g. visual attribute rules ).

The custom library should be used to call custom hooked business rules and any OLTP dependent rules ( that may only exist within form libraries ). There is a sizing limitation to the custom library ( as with any Oracle Form library ) and so careful consideration must be given to the design and construct of the custom library and any other attached / associated libraries. If you expect to have a lot of custom library code then it is advisable to partition the code within multiple libraries. For example, create libraries by associating them with forms.

Custom Library If form_name=PERWSEPI then perwsep_custom(event); Else . End if;

PERWSEPI_CUST Custom Library If block_name=PER then . Else . End if;

Custom Library Partitioning Depending on how much custom code is associated with each form, it may be necessary to create further sub-libraries. Note that there will be a trade off between OLTP system performance and ease of maintenance of libraries. The more libraries created, the greater the potential effect on on-line performance. Partitioning libraries in to associated forms will ease the manageability and development of code by enabling related functional modules to be worked on independently of others. When upgrading the application, user defined libraries can easily be identified and check for compatibility with the new release. Of course, the old custom library ( with your calls to your custom libraries ) will have to be backed up during future upgrades to prevent losing some of your own code. Implementation of Business Rule Categories Earlier in this paper a number of business rule categories were presented ( with each category being given an associated number ). The following is a guideline as to what tools, technologies and techniques I would consider using to construct the associated business rule(s). Even though I have listed different tools and techniques for each grouping of rules, this does not imply that you need to use all of the tools and techniques in order to implement the rule. This will depend on the complexity of the individual rule.

Custom Library and/or Hooked APIs and/or User Defined APIs 1.1.1 1.1.2 1.1.3 1.1.4 1.2 1.3.1 1.3.2 1.3.3 2.3

Custom Library and/or Application Security Features 1.3.4 Custom Library and/or Hooked APIs and/or User Defined APIs and/or PL/Sql Formula APIs 2.2 3

Custom Library and/or Hooked APIs and/or User Defined APIs and/or Oracle Workflow and/or Oracle Alert 2.1 4

As can be seen, the majority of the rules require the use of the custom library and API user hooks. The goal is to build on to the core application by extension rather than core application modification i.e. changing the logic of the core forms directly.

Conclusion We have seen that the Oracle Applications continue to advance in terms of development tools, technologies and techniques. The custom library provides a non invasive mechanism that allows customers to extend the application in a manageable and controlled environment whilst preserving support for the core application. The ability to turn custom library code on or off ensures application support when problems are encountered as it enables you to identify whether the problem is custom code related or core application related. The Oracle HRMS application suite, by providing API user hooks and PL/Sql generatable by Oracle Fast Formulas, extends the extensibility of the application within a controlled environment to yet unchartered dimensions. Gone are the days of having to lose support for key features of the application in order to satisfy business requirements because you just had to modify a code module. It is now possible to do what was once impossible. This is due to Oracles recognition of its customers who are all unique in one way or another and therefore want flexible and extendible solutions without jeopardizing the core application. The decision to custom build an application rather than buy something off the shelf is no longer Black and White. Oracle, with its new breed of applications, is demonstrating that it is possible to extend the core application to satisfy that missing 5, 10, 15, 20.. percent business requirement fit in a manner that wont destabalise the underlying application and therefore provides a massive head start compared to custom building an application from scratch.

About the Author: Andrew McGhee ( amcghee@uk.oracle.com ) has been involved with Oracle Applications for more than 6 years and has been responsible for past HRMS beta programs, working closely with customers from all over the world. He also worked along side Motorola in Europe during their pan European Oracle HR roll out. At present Andrew is involved with a U.S. organization in the largest ever Oracle HR implementation in the World ( more than 1.2 million person records ) as well as working with a U.K. organization to implement Oracle Payroll for 120,000 people ( Oracle UKs current largest Payroll implementation ).

APPENDIX 1 Useful Information About the Custom Library in Production 16.1 Custom Library Fundamentals You cannot change the specification of the CUSTOM package You cannot attach the APPCORE library to the CUSTOM library Use FNDSQF library whenever possible for function security, flexfields and message procedures You cannot use SQL in the CUSTOM library ( call server side packages instead ) The CUSTOM library is global to all of the Oracle Applications and has no context associated with it Do not use CALL_FORM or OPEN_FORM within the CUSTOM library, use FND_FUNCTION package instead Function APP_ITEM_PROPERTY is not available within the CUSTOM library, user Oracle Forms SET_ITEM_PROPERTY instead Important bugs I encountered when working with the CUSTOM library 523460: Exceptions raised in custom when-validate-record events are not propagated to the calling code 480675: WHEN-VALIDATE-RECORD event missing from Oracle HRMS Position Form Follow the Oracle Applications Coding standards !! Document EVERYTHING you do !!

Things I wish I had known before using the Custom Library More detailed knowledge about Developer 2000 More detailed knowledge of how to code Packages and Procedures Form processing logic and triggers i.e. what gets fired when How to build basic application compatible forms Detailed processing logic and database objects used by Forms I extended The difference between .plx and .pll library files

Appendix 2 - CUSTOM.pll
Package Header
PACKAGE custom IS function zoom_available return BOOLEAN; function style(event_name varchar2) return integer; procedure event(event_name varchar2); before constant integer := 1; after constant integer := 2; override constant integer := 3; standard constant integer := 4; END custom;

Package Header
package body custom is --- Customize this package to provide specific responses to events -- within Oracle Applications forms. --- Do not change the specification of the CUSTOM package in any way. -- You may, however, add additional packages to this library. --------------------------------------------------------------------function zoom_available return boolean is --- This function allows you to specify if zooms exist for the current -- context. If zooms are available for this block, then return TRUE; -- else return FALSE. --- This routine is called on a per-block basis within every Applications -- form from the WHEN-NEW-BLOCK-INSTANCE trigger. Therefore, any code -- that will enable Zoom must test the current form and block from -- which the call is being made. --- By default this routine must return FALSE. -/* Sample code: form_name varchar2(30) := name_in('system.current_form'); block_name varchar2(30) := name_in('system.cursor_block'); begin if (form_name = 'DEMXXEOR' and block_name = 'ORDERS') then return TRUE; else return FALSE; end if; end zoom_available; */ --- Real code starts here

-begin return FALSE; end zoom_available; -------------------------------------------------------------------function style(event_name varchar2) return integer is --- This function allows you to determine the execution style for some -- product-specific events. You can choose to have your code execute -- before, after, or in place of the code provided in Oracle -- Applications. See the Applications Technical Reference manuals for a -- list of events that are available through this interface. --- Any event that returns a style other than custom.standard must have -- corresponding code in custom.event which will be executed at the -- time specified. --- The following package variables should be used as return values: --- custom.before -- custom.after -- custom.override -- custom.standard --- By default this routine must return custom.standard --- Oracle Corporation reserves the right to change the events -- available through this interface at any time. -/* Sample code: begin if event_name = 'OE_LINES_PRICING' then return custom.override; else return custom.standard; end if; end style; */ --- Real code starts here -begin return custom.standard; end style; -------------------------------------------------------------------procedure event(event_name varchar2) is --- This procedure allows you to execute your code at specific events -- including: --- ZOOM -- WHEN-NEW-FORM-INSTANCE

-- WHEN-NEW-BLOCK-INSTANCE -- WHEN-NEW-RECORD-INSTANCE -- WHEN-NEW-ITEM-INSTANCE -- WHEN-VALIDATE-RECORD --- Additionally, product-specific events will be passed via this -- interface (see the Applications Technical Reference manuals for -- a list of events that are available). --- By default this routine must perform 'null;'. --- Oracle Corporation reserves the right to change the events -- available through this interface at any time. -/* Sample code: form_name varchar2(30) := name_in('system.current_form'); block_name varchar2(30) := name_in('system.cursor_block'); param_to_pass1 varchar2(255); param_to_pass2 varchar2(255); begin -- Zoom event opens a new session of a form and -- passes parameter values to the new session. The parameters -- already exist in the form being opened. if (event_name = 'ZOOM') then if (form_name = 'DEMXXEOR' and block_name = 'ORDERS') then param_to_pass1 := name_in('ORDERS.order_id'); param_to_pass2 := name_in('ORDERS.customer_name'); fnd_function.execute(FUNCTION_NAME=>'DEM_DEMXXEOR', OPEN_FLAG=>'Y', SESSION_FLAG=>'Y', OTHER_PARAMS=>'ORDER_ID="'||param_to_pass1|| '" CUSTOMER_NAME="'||param_to_pass2||'"'); -- all the extra single and double quotes account for -- any spaces that might be in the passed values end if; -- This is an example of a product-specific event. Note that as -- of Prod 15, this event doesn't exist. elsif (event_name = 'OE_LINES_PRICING') then get_custom_pricing('ORDERS.item_id', 'ORDERS.price'); -- This is an example of enforcing a company-specific business -- rule, in this case, that all vendor names must be uppercase. elsif (event_name = 'WHEN-VALIDATE-RECORD') then if (form_name = 'APXVENDR') then if (block_name = 'VENDOR') then copy(upper(name_in('VENDOR.NAME')), 'VENDOR.NAME'); end if; end if; else null; end if;

end event; */ --- Real code starts here -form_name varchar2(30) := name_in('system.current_form'); begin --- The following call to the HRCUSTOM library was put in by the Release 11 HRMS Vision team. -- As the CUSTOM library is shared by ALL applications, it is good practice to call other -- 'user defined' libraries if it is likely that you will be extensively adding user defined -- logic to the custom library. --- Be aware that there will be a marginal performance overhead when you start to introduce -- calls to additional libraries. --

--- If the current form is a HRMS related form then call the user defined HRCUSTOM library. -if substr(form_name,1,2) in ('PE','PY','PA','SS','OT','DT','FF','HR') then hrcustom.event(event_name); end if; end event; end custom;

Appendix 3 - HRCUSTOM.pll
Package Header
PACKAGE hrcustom IS procedure event(event_name varchar2); END hrcustom;

Package Body
/* This 'user defined' library was created by the HRMS Release 11 vision team. Its purpose is to control what sub user defined libraries are called. The sub libraries are called depending on the current form name. The CUSTOM library hiarachy is as follows: CUSTOM | | HRCUSTOM | --------------------------------| | HRCUST1 HRCUST2 perwshrg perwsepi perwsema perwsepy paywsmee perwsead

Other libraries could be added to this hierarchy if required. */ package body hrcustom is procedure event(event_name varchar2) is form_name varchar2(30) := name_in('system.current_form');

begin if form_name in ('PERWSHRG','PERWSEPI','PERWSEMA') then hrcust1.event(event_name); elsif form_name in ('PERWSEPY','PAYWSMEE','PERWSEAD') then hrcust2.event(event_name); else

null; end if; end event; end hrcustom;

Appendix 4 - HRCUST1.pll
Package Header
PACKAGE hrcust1 IS procedure event(event_name varchar2); END hrcust1;

Package Body
/* This library was created by the HRMS Release 11 vision team. The library controls additional business rule validation for the following forms: PERWSEPI PERWSHRG PERWSEMA */ package body hrcust1 is - Person Form - 'Mega' Person Form - Assignment Form

procedure event(event_name varchar2) is form_name block_name l_button_selected l_legislation_code begin varchar2(30) := name_in('system.current_form'); varchar2(30) := name_in('system.current_block'); number default 1; varchar2(5);

--- Perform all additional custom library validation logic for the Person form ( PERWSEPI ) and new -- 'mega' form ( PERWSHRG ). -if form_name in ('PERWSEPI','PERWSHRG') then if block_name = 'PERSON' then --- The following was created to overcome a current synchronization 'feature' with the -- version of NCA being worked on. When going in to the Person form, a value is written to -- the global, MESSAGES_ALREADY_SHOWN, that is checked before the messages are displayed -- in the WHEN-NEW-BLOCK-EVENT. --

if event_name = 'WHEN-NEW-FORM-INSTANCE' then copy ('True','global.messages_already_shown'); end if;

if event_name = 'WHEN-NEW-BLOCK-INSTANCE' then if name_in('global.messages_already_shown') = 'True' then --- SCENARIO 1 --- When entering the person form, prompt the user as to whether they would like all of the -- required fields to be highlighted. For the purpose of this example we have stipulated that -- the following fields are the required; Last Name, Person Type, Gender, Employee Number, -- National Identifier, Ethnic Origin and Date Of Birth. --- Having decided whether the user wants the mandatory fields highlighted or not, a value is -- written to a GLOBAL variable, VISION_HIGHLIGHT_FLDS. This global is used to determine whether -- to warn the user that they have forgotten to enter mandatory fields when saving / updating -- person records. l_legislation_code := name_in('ctl_globals.legislation_code');

fnd_message.set_string('Would you like to highlight all required EMPLOYEE fields ? '); l_button_selected:=fnd_message.question(button1 => 'Cancel', button2 => 'No', button3 => 'Yes', default_btn => 2, cancel_btn => 1, icon => 'question'); fnd_message.show; if l_button_selected = 3 then set_item_property('person.last_name',VISUAL_ATTRIBUTE,'SELECTED_DATA'); set_item_property('person.d_person_type_id',VISUAL_ATTRIBUTE,'SELECTED_DATA'); set_item_property('person.sex',VISUAL_ATTRIBUTE,'SELECTED_DATA'); set_item_property('person.employee_number',VISUAL_ATTRIBUTE,'SELECTED_DATA'); set_item_property('person.national_identifier',VISUAL_ATTRIBUTE,'SELECTED_DATA'); set_item_property('person.date_of_birth',VISUAL_ATTRIBUTE,'SELECTED_DATA'); --- Only highlight the Ethnic Origin field if we are operating in a US business group. -if l_legislation_code = 'US' then set_item_property('person.ethnic_origin_us',VISUAL_ATTRIBUTE,'SELECTED_DATA'); end if; copy('Y','global.vision_highlight_flds'); elsif l_button_selected = 2 then

copy('N','global.vision_highlight_flds'); else copy('N','global.vision_highlight_flds'); end if; --- SCENARIO 3 --- When entering the person form, prompt the user as to whether they would like to hide the Mail To -- field. This example just shows how it is possible to remove fields from the form. --- It is not possible to remove field prompts using the custom library. Field prompts are part of a forms -- boiler plate text. If you wanted to change these prompts then you could either manually modify the form -- to display a different prompt or even remove the prompt all together. If you wanted to change / remove -- a number of boiler plate prompts then you should consider using Oracle Translation Manager ( OTM ) to help -- you make the changes. OTM also acts as a dictionary of changes so that changes can be reapplied to -- existing or new versions of the forms ( which is especially useful when you need to reapply changes -- having upgraded the application ). --

fnd_message.set_string('Would you like to remove the Mail To field ? '); l_button_selected:=fnd_message.question(button1 => 'Cancel', button2 => 'No', button3 => 'Yes', default_btn => 2, cancel_btn => 1, icon => 'question'); fnd_message.show; if l_button_selected = 3 then set_item_property('person.d_home_office',DISPLAYED,PROPERTY_FALSE); elsif l_button_selected = 2 then null; else null; end if; copy ('False','global.messages_already_shown'); end if; end if; if event_name in ('POST-INSERT','POST-UPDATE') then --- SCENARIO 4 --- When creating or updating person information, check whether the Last Name field is in upper case. -- If it isn't then prompt the user to ask whether they would like to convert it to upper case. If they -- answer Yes then automatically convert the field to upper case, otherwise leave the field alone. -if name_in(ctl_globals.legislation_code) = GB then

if name_in('person.last_name') is not null then if upper(name_in('person.last_name')) != name_in('person.last_name') then fnd_message.set_string('Persons Last Name field is not in upper case. Would you like to convert it to upper case ? '); l_button_selected:=fnd_message.question(button1 => 'Cancel', button2 => 'No', button3 => 'Yes', default_btn => 2, cancel_btn => 1, icon => 'question'); fnd_message.show; if l_button_selected = 3 then copy(upper(name_in('person.last_name')),'person.last_name'); elsif l_button_selected = 2 then null; else null; end if; end if; end if; end if; --- SCENARIO 2 --- When creating or updating person information, check whether the user selected to highlight mandatory -- fields. If they did, check whether any of the selected mandatory fields contains a null value. -if name_in('global.vision_highlight_flds') = 'Y' then if name_in('person.last_name') is null or name_in('person.d_person_type_id') is null or name_in('person.sex') is null or name_in('person.national_identifier') is null or name_in('person.date_of_birth') is null or ( name_in('ctl_globals.legislation_code') = 'US' and name_in('person.ethnic_origin_us') is null ) then --- The following logic is only performed if the Employee Type for the entered person is -- "Employee". --- Having determined that at least one of the highlighted mandatory fields is null, prompt the user -- to ensure that values are entered for all of the fields. --- A different message is displayed depending on the the legislation of the business group the user -- is running in. -if name_in('person.d_person_type_id') = 'Employee' then if name_in('ctl_globals.legislation_code') = 'US' then

fnd_message.set_string('You have not entered all required fields: Last Name, Gender, Person Type, Social Security Number, Employee Number, Birth Date and Ethnic Origin); fnd_message.show; elsif name_in('ctl_globals.legislation_code') = 'GB' then fnd_message.set_string('A required person field is null. Required fields are: Last Name, Person Type, Gender, Employee Number,National Insurance Number and Date Of Birth'); fnd_message.show; else fnd_message.set_string('A required person field is null. Required fields are: Last Name, Person Type, Gender, Employee Number,National Identifier Number and Date Of Birth'); fnd_message.show; end if; --- Prevent the form from commiting -raise form_trigger_failure; end if; end if; end if; end if; end if; end if;

--

end event; end hrcust1;

Appendix 5 - HRCUST2.pll
Package Header
PACKAGE hrcust2 IS procedure event(event_name varchar2); END hrcust2;

Package Body
/* This library was created by the HRMS Release 11 vision team. The library controls additional business rule validation for the following forms: PERWSEPY PAYWSMEE PERWSEAD - Salary Administration Form - Element Entry Form - Absence Form

*/

package body hrcust2 is procedure event(event_name varchar2) is form_name block_name l_min_mkt_salary l_max_mkt_salary l_mkt_salary_message l_earn_poten l_earn_mesg l_absence_hours l_hr_total begin varchar2(30) := name_in('system.current_form'); varchar2(30) := name_in('system.current_block'); number; number; varchar2(150); varchar2(60); varchar2(100); varchar2(10); number;

--- Perform all additional custom library validation logic for the Salary Administration form ( PERWSEPY ). -if form_name = 'PERWSEPY' then if block_name = 'REVIEW' then

if event_name in ('POST-INSERT','POST-UPDATE') then --- SCENARIO 4 --- When entering salary proposals for an assignment, check whether the proposed salary falls within -- market salary minimum and maximum values as defined for each job. --- The Additional Job Details decsriptive flexfield needs to be set up as follows: --- First Segment: Market Salary Minimum -Database Field = ATTRIBUTE1 -Validation = < any value set that only allows you to enter numeric values > --- Second Segment: Market Salary Maximum -Database Field = ATTRIBUTE2 -Validation = < any value set that only allows you to enter numeric values > --- This scenario also uses server side procedures that were cerated as part of the VISION_CL_CODE -- package. --- Procesing Login: --- If the assignment that the salary proposal is being made for is associated with a Job then -- retrieve the markey salary minimum and maximum values from the descriptive flexfield ATTRIBUTE1 -- and ATTRIBUTE2 fields. The salary proposal approval date is used to select the correct assignment -- record. --- If the market salary minimum and maximum values are not null then check whether the entered salary -- proposal falls between these figures. If it does then everything is okay. It doesn't then display -- a mesage to the user informing them that the entered amounf does not fall between the minimum and -- maximum market salary values and display the minimum and maximum values. -fnd_message.set_string('Comparing amount against market survey data); fnd_message.show; vision_cl_code.market_salary(p_assignment_id => to_number(name_in('global.g_assignment_id')), p_approval_date => to_date(name_in('review.change_date'),'DD-MON-YYYY'), p_min_mkt_salary => l_min_mkt_salary, p_max_mkt_salary => l_max_mkt_salary ); --- If the l_min_mkt_salary and l_max_mkt_salary variable is 0 then the persons assignment is not -- associated with a Job ( therefore don't display any warnings ). -if ( l_min_mkt_salary is not null or l_max_mkt_salary is not null ) and ( l_min_mkt_salary != 0 or l_max_mkt_salary != 0 ) then if to_number(name_in('review.d_proposed_salary')) between nvl(l_min_mkt_salary,0) and nvl(l_max_mkt_salary,0) then null; else l_mkt_salary_message:='Proposed amount is outside of the market salary range for the job, minimum value = '||to_char(l_min_mkt_salary)||' maximum value = '||to_char(l_max_mkt_salary);

fnd_message.set_string(l_mkt_salary_message ); fnd_message.show; end if; else null; end if; end if; end if; end if;

--- Perform all additional custom library validation logic for the Element Entry form ( PAYWSMEE ). -if form_name = 'PAYWSMEE' then if block_name = 'ENTRY' then if event_name in ('PRE-INSERT','PRE-UPDATE','PRE_UPDATE') then --- SCENARIO 5 --- This example shows how it is possible to call a server side Formula PL/Sql routine to calculate -- a value and then use the returned value to update a user non-enterable element input value. -- The Formula PL/Sql routine also returns a message that is displayed to the user. --- For this scenario you will have to set up the following data on your system: --- Element Entry: "Earnings Potential", non-recurring element with the following input values: --Sequence Input Name User Enterable -1 Current Earnings Yes -2 Earnings Potential No ---- Formula: CL_EARN_POTENTIAL --Review to the definition of this formula within the Vision database --- Having entered a Current Earnings input value for the 'Earnings Potential' element, a server side package -- ( vision_cl_code.call_earn_poten_formula ) is called. This package is a 'wrapper' routine that -- executes an Oracle FastFormula ( from within PL/Sql ). --

if name_in('entry.element_name') = 'Earnings Potential' then if name_in('entry.user_entry1') is not null then -- Call the server side call_earn_poten_formula to... vision_cl_code.call_earn_poten_formula(p_amount => to_number(name_in('entry.user_entry1')), p_session_date => to_date(name_in('ctl_globals.session_date'),'DD-MON-YYYY'),

p_assignment_id => to_number(name_in('entry.assignment_id')), p_earn_poten p_earn_mesg => l_earn_poten, => l_earn_mesg );

copy(replace(to_char(round(nvl(to_number(l_earn_poten),1),2),'999999990.99'),' ',''),'entry.user_entry2'); copy(name_in('entry.user_entry2'),'entry.screen_entry_value2'); fnd_message.set_string(l_earn_mesg); fnd_message.show; else -- The Current Earnings field is empty ( null ) so we need to clear out any values that may be in the Euro -- Equivalent field. copy('','entry.user_entry2'); copy('','entry.screen_entry_value2'); end if; end if;

end if; end if; end if;

--- Perform all additional custom library validation logic for the Absence Form ( PERWSEAD ). -if form_name = 'PERWSEAD' then if block_name = 'ABA' then if event_name in ('WHEN-VALIDATE-RECORD') then -- SCENARIO 6 --- Calculate the FMLS 12 month rolling average for 'Family Leave' absence types. -- The rolling average is between the actual absence end and ( actual absence end date -- minus 365 days ). --- If this check needs to performed for additional absence types then the following statement -- needs to be amended as well as the server side vision_cl_code.rolling_absence_details -- procedure. -if (name_in('aba.date_end') is not null and name_in('aba.c_type_desc') = 'Family Leave' ) then vision_cl_code.rolling_absence_details(p_person_id => to_number(name_in('aba.person_id')),

p_abs_actual_end_date => to_date(name_in('aba.date_end'),'DDMON-YYYY'), p_abs_att_id to_number(name_in('aba.absence_attendance_id')), p_absence_hours => => l_absence_hours );

l_hr_total:=nvl(to_number(name_in('aba.absence_hours')),0)+nvl(to_number(l_absence_hours),0); if name_in('aba.absence_hours') is not null then copy(to_char(round(l_hr_total/8,1)),'aba.attribute6'); copy(to_char(round(l_hr_total/8/5,1)),'aba.attribute7'); end if; end if; end if; end if; end if;

end event; end hrcust2;

Appendix 6 - Server Side Custom Library Code ( server_cl_code.sql )


/* File Header Information ======================= This package has been created to show how it is possible to make the custom library interface with code on the server in order to perform additional business rule validation. It has been created specifically to work with the Oracle Application Vision database, Release 11. In this package I have built in the following procedures and functions:

Check Digit ----------This routine calculates the check digit of a number using the modulus 11 algorithm

Market Salary ------------This routine retrieves the market salary minimum and maximum amounts ( associated with a job ).

Euro Conversion --------------This routine retrieves the Euro currency exchange rate. There is no such currency as EURO within Oracle Applications 11. It is therefore necessary to create such a currency and to assign appropriate exchange rates to / from the currency. This routine relies on the fact that you have already set up the Euro currency ( using the System Asministrator responsibility ) and created exchange rates within your business group against a Payroll called 'Monthly'.

Call Earnings Potential Formula ------------------------------This routine shows how it is possible to call an Oracle Fast Formula PL/Sql formula from the custom library. The formula takes a single input, CURRENT_EARN ( current earnings ), and performs a calculation on the input and returns EARN_POTEN ( earnings potential ) and EARN_MESG ( earnings message ). The calculation set up is very simplistic but it makes use of a database item, PER_AGE. Even though this is a very simple formula, it shows some of the features that are possible that can be accessed via the PL/Sql formula engine. The earnings message is displayed from within the custom library. It is therefore easy to show how you can change the calculation and message from within the formula and then show the user instantly how the changes have taken affect when entering Earnings Potential element entries.

Rolling Absence Details -----------------------

This routine calculates the 12 month rolling total for the Family Leave absence type. The rolling period is taken from the absence 'actual end date'.

Install Instructions ==================== This package must be created in the APPS Oracle schema in your database. This can be done from the Unix prompt of your machine: > sqlplus apps/<apps password> @server_cl_code.sql If you want to make use of this package from with Secure User SQL*Plus accounts then you will need to: 1 - Grant execute on this package to roles HR_SECURE_USER and HR_REPORTING_USER sqlplus apps/<apps password> grant execute on vision_cl_code to hr_secure_user; grant execute on vision_cl_code to hr_reporting_user; 2 - Create a public synonym for this package from within the SYSTEM SQL*Plus account sqlplus system/<system password> create public synonym vision_cl_code for apps.vision_cl_code;

Change List =========== Version Date Author Comments -------+------------+------------------+------------------------------------------------1.0 26-FEB-1998 A.McGhee Created

----------------------------------------------------------------------------------------*/ --- Real code starts here. --- WhenEver SqlError Exit Failure Rollback; create or replace package vision_cl_code as /* $Header:.... some header file details $ */

procedure check_digit (p_cd_number in varchar2 default null ,

p_check_digit out varchar2 );

procedure market_salary (p_assignment_id in number, p_approval_date in date, p_min_mkt_salary out number, p_max_mkt_salary out number );

procedure euro_conversion (p_business_group_id in number, p_session_date in date, p_element_type_id in number, p_euro_conv_rate out number);

procedure call_earn_poten_formula (p_amount in number default 0, p_session_date in date, p_assignment_id in number, p_earn_poten out varchar2, p_earn_mesg out varchar2 );

procedure rolling_absence_details (p_person_id in number, p_abs_actual_end_date in date, p_abs_att_id in number, p_absence_hours out varchar2);

end vision_cl_code; / -------/* File Body Information ===================== This package has been created to show how it is possible to make the custom library interface with code on the server in order to perform additional business rule validation. It has been created specifically to work with the Oracle Application Vision database, Release 11. In this package I have built in the following procedures and functions:

Check Digit

----------This routine calculates the check digit of a number using the modulus 11 algorithm

Market Salary ------------This routine retrieves the market salary minimum and maximum amounts for a particular job.

Euro Conversion --------------This routine retrieves the Euro currency exchange rate. There is no such currency as EURO within Oracle Applications 10.7. It is therefore necessary to create such a currency and to assign appropriate exchange rates to / from the currency. This routine relies on the fact that you have already set up the Euro currency ( using the System Asministrator responsibility ) and created exchange rates within your business group against a Payroll called 'Monthly'.

Call Earnings Potential Formula ------------------------------This routine shows how it is possible to call an Oracle Fast Formula PL/Sql formula from the custom library. The formula takes a single input, CURRENT_EARN ( current earnings ), and performs a calculation on the input and returns EARN_POTEN ( earnings potential ) and EARN_MESG ( earnings message ). The calculation set up is very simplistic but it makes use of a database item, PER_AGE. Even though this is a very simple formula, it shows some of the features that are possible that can be accessed via the PL/Sql formula engine. The earnings message is displayed from within the custom library. It is therefore easy to show how you can change the calculation and message from within the formula and then show the user instantly how the changes have taken affect when entering Earnings Potential element entries.

Rolling Absence Details ----------------------This routine calculates the 12 month rolling total for the Family Leave absence type. The rolling period is taken from the absence 'actual end date'.

Install Instructions ==================== This package must be created in the APPS Oracle schema in your database. This can be done from the Unix prompt of your machine: > sqlplus apps/<apps password> @server_cl_code.sql If you want to make use of this package from with Secure User SQL*Plus accounts then you will need to:

1 - Grant execute on this package to roles HR_SECURE_USER and HR_REPORTING_USER sqlplus apps/<apps password> grant execute on vision_cl_code to hr_secure_user; grant execute on vision_cl_code to hr_reporting_user; 2 - Create a public synonym for this package from within the SYSTEM SQL*Plus account sqlplus system/<system password> create public synonym vision_cl_code for apps.vision_cl_code;

Change List =========== Version Date Author Comments -------+------------+------------------+------------------------------------------------1.0 26-FEB-1998 A.McGhee Created

----------------------------------------------------------------------------------------*/ --- Real code starts here. -WhenEver SqlError Exit Failure Rollback; create or replace package body vision_cl_code as /* $Header:.... Some body file details $ */ -- Package Variables g_package varchar2(33) := 'vision_cl_code.';

-- ******************************** -- *** Procedure CHECK_DIGIT *** -- ******************************** --- Calculate the Modulus 11 check digit. -procedure check_digit (p_cd_number in varchar2 default null , p_check_digit out varchar2 ) is

--

-- Declare cursor and local variables -l_pos1 l_pos2 l_pos3 l_pos4 l_pos5 l_pos6 l_pos7 l_pos8 l_pos9 l_added_total l_remainder l_check_digit begin number default 0; number default 0; number default 0; number default 0; number default 0; number default 0; number default 0; number default 0; number default 0; number default 0; number default 0; number default 0;

--- There are 5 steps to calculate the Modulus check digit. --

--- Step 1: Multiply each of the 9 digits by a weighting factor. -l_pos1:=to_number(substr(p_cd_number,1,1)) * 10; l_pos2:=to_number(substr(p_cd_number,2,1)) * 9; l_pos3:=to_number(substr(p_cd_number,3,1)) * 8; l_pos4:=to_number(substr(p_cd_number,4,1)) * 7; l_pos5:=to_number(substr(p_cd_number,5,1)) * 6; l_pos6:=to_number(substr(p_cd_number,6,1)) * 5; l_pos7:=to_number(substr(p_cd_number,7,1)) * 4; l_pos8:=to_number(substr(p_cd_number,8,1)) * 3; l_pos9:=to_number(substr(p_cd_number,9,1)) * 2; --- Step 2: Add the results of each multiplication together. -l_added_total:=l_pos1 + l_pos2 + l_pos3 + l_pos4 + l_pos5 + l_pos6 + l_pos7 + l_pos8 + l_pos9;

--- Step 3: Divide the total from Step 2 by 11 and establish the remainder. -l_remainder:=mod(l_added_total,11); --- Step 4: Subtract the remainder from 11 to give the check digit. -l_check_digit:=11-l_remainder;

--- Step 5: Validate the check digit. --If the result from step 4 is 11 then a check digit of 0 is used. --If the result from step 4 is 10 then the number is invalid. -In this case I set the check digit value to I ( for Invalid ). This value -gets passed back to the form and the custom library will display an -appropriate message informing the user that the entered Person Number does -not conform using the Modulus 11 algorithm. if l_check_digit=11 then p_check_digit:='0'; elsif l_check_digit=10 then p_check_digit:='I'; else p_check_digit:=to_char(l_check_digit); end if;

end check_digit;

-- ********************************** -- *** Procedure MARKET_SALARY *** -- **********************************

procedure market_salary (p_assignment_id in number, p_approval_date in date, p_min_mkt_salary out number, p_max_mkt_salary out number ) is --- Declare cursor and local variables --

cursor c_get_mkt_values is select to_number(nvl(pj.attribute1,0)), to_number(nvl(pj.attribute2,0)) from per_assignments_f paf, per_jobs pj where paf.assignment_id = p_assignment_id and p_approval_date between paf.effective_start_date and paf.effective_end_date and paf.job_id = pj.job_id;

begin --- Find out whether the person has been associated with a Job on their assignment.

-- If they have, use the job_id value to join to the PER_JOBS table to retrieve the market -- salary minimum and market salary maximum values. These values are stored in ATTRIBUTE1 -- and ATTRIBUTE2 on the Job Descriptive Flexfield. -open c_get_mkt_values; fetch c_get_mkt_values into p_min_mkt_salary, p_max_mkt_salary; close c_get_mkt_values;

end market_salary;

-- ************************************ -- *** Procedure EURO_CONVERSION *** -- ************************************ procedure euro_conversion (p_business_group_id in number, p_session_date in date, p_element_type_id in number, p_euro_conv_rate out number) is --- Declare cursor and local variables --- Using the passed in parameters, retrieve the exchange rate value from the exchange -- rate table where the rate is associated with a payroll called 'Monthly' ( making sure -- that all effective dates are checked using the passed in session date ). --- If there is no entry in the exchange rates table where the 'From Currency' equals 'EUR' -- ( for Euro ) and the 'To Currency' equals the input currency code specified for the -- element type, then this routine returns null for the exchange rate. -cursor c_get_euro_value is select pex.rate from pay_exchange_rates_f pex, pay_element_types_f pet, pay_payrolls_f ppf where ppf.payroll_name = 'Monthly' and ppf.business_group_id = p_business_group_id and p_session_date between ppf.effective_start_date and ppf.effective_end_date and pet.element_type_id = p_element_type_id and pet.business_group_id = p_business_group_id and p_session_date between pet.effective_start_date and pet.effective_end_date and ppf.payroll_id = pex.payroll_id and pex.from_currency_code = 'EUR' and pex.to_currency_code = nvl(pet.input_currency_code,'USD') and p_session_date between pex.effective_start_date and pex.effective_end_date;

begin open c_get_euro_value; fetch c_get_euro_value into p_euro_conv_rate; close c_get_euro_value; end euro_conversion;

-- ******************************************** -- *** Procedure CALL_EARN_POTEN_FORMULA *** -- ******************************************** procedure call_earn_poten_formula (p_amount in number default 0, p_session_date in date, p_assignment_id in number, p_earn_poten out varchar2, p_earn_mesg out varchar2 ) is l_formula_id number; l_effective_date date; l_inputs ff_exec.inputs_t; l_outputs ff_exec.outputs_t; l_loop_cnt number; l_in_cnt number; l_out_cnt number; l_use_dbi_cache boolean default false; begin -- This procedure assumes that you have set up a formula with a single input -- called 'CURRENT_EARN' of data type NUMBER and two outputs, EARN_POTEN and EARN_MESG, -- of type VARCHAR2. -- Set up some of the values we will need to exec formula. If your formula has a -- differnt Id then you need to change the value for l_formula_id. -- The formula created is called CL_EARN_POTENTIAL and has Id 50931. l_formula_id := 50931; l_effective_date := to_date('01-JAN-1997', 'DD-MON-YYYY');

-- Initialise the formula. ff_exec.init_formula(l_formula_id, l_effective_date, l_inputs, l_outputs); -- The input and output table have been initialised. We now have to -- set up the values for the inputs required. This includes both those -- for the 'inputs are' statement and any contexts. --- In our simple example we don't really need a 'for loop' as we know that there

-- is only one input specified for our formula. We could have just used l_inputs..first -- instead. --- Don't try and guess the input value number. It does not always start at '1'. --- Looking at the formula, you would see that there is only a single input, CURRENT_EARN -- but you'll notice that we are setting up inputs for ASSIGNMENT_ID and DATE_EARNED. -- This is because the formula uses database item PER_AGE which has contexts of -- ASSIGNMENT_ID and DATE_EARNED. for l_in_cnt in l_inputs.first..l_inputs.last loop if(l_inputs(l_in_cnt).name = 'CURRENT_EARN') then l_inputs(l_in_cnt).value := p_amount; -- will implicitly convert. elsif(l_inputs(l_in_cnt).name = 'ASSIGNMENT_ID') then l_inputs(l_in_cnt).value := p_assignment_id; -- will implicitly convert. elsif(l_inputs(l_in_cnt).name = 'DATE_EARNED') then l_inputs(l_in_cnt).value := to_char(p_session_date,'DD-MON-YYYY'); end if; end loop; -- Execute the formula. ff_exec.run_formula(l_inputs, l_outputs, l_use_dbi_cache); -- Now we have executed the formula. We are able to retrieve the results. -for l_out_cnt in l_outputs.first..l_outputs.last loop if l_outputs(l_out_cnt).name = 'EARN_POTEN' then p_earn_poten:=l_outputs(l_out_cnt).value; elsif l_outputs(l_out_cnt).name = 'EARN_MESG' then p_earn_mesg:=l_outputs(l_out_cnt).value; end if; end loop;

-- Note: There is no procedure to be called to shut down the execution engine. end call_earn_poten_formula;

-- ******************************************** -- *** Procedure ROLLING_ABSENCE_DETAILS *** -- ******************************************** procedure rolling_absence_details (p_person_id in number, p_abs_actual_end_date in date, p_abs_att_id in number, p_absence_hours out varchar2) is --- If any additional absence types get added that are required to be included in this -- calculation then you need to change (7) with (7,<new absence_attendance_type_id>)

-- e.g. (7,1234) ---- I've added a check to make sure that the absence_attendance_id does not equal the -- absence_attendance_id passed in to the procedure, p_abs_att_id. This is because this -- routine may be called if a persons absence record gets updated on-line. In this case -- we don't want to sum up all absence records for the person because they may have changed the -- absence hours on-line and therefore the on-line value may differ from the value already -- written to the table. -cursor c_cals_abs_total is select sum(nvl(paa.absence_hours,0)) abs_tot_hours from per_absence_attendances paa where paa.absence_attendance_type_id in (7) and paa.person_id = p_person_id and paa.date_end between (p_abs_actual_end_date-365) and p_abs_actual_end_date and paa.absence_attendance_id != nvl(p_abs_att_id,-9999);

begin open c_cals_abs_total; fetch c_cals_abs_total into p_absence_hours; close c_cals_abs_total; end rolling_absence_details; end vision_cl_code; /

Você também pode gostar