Oracle Application Form

  • Uploaded by: Đoàn Hồng Nhật
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Oracle Application Form as PDF for free.

More details

  • Words: 22,062
  • Pages: 119
MỤC LỤC MỤC LỤC................................................................................................................1 Kiến trúc ứng dụng .................................................................................................4 Tổng quan về kiến trúc ứng dụng. .................................................................................. 4 Mô hình phát triển và triển khai Oracle Application. ..................................................... 7

Các chuẩn cho việc Customize ứng dụng .............................................................8 Tổng quan về việc customize Oracle Applications......................................................... 8 Customization theo cách mở rộng. ................................................................................. 9 Customize theo cách mở rộng ......................................................................................... 9 Customize bằng cách chỉnh sửa .................................................................................... 11 Customize cơ sở dữ liệu Oracle Applications............................................................... 12 Nâng cấp và chỉnh sửa Oracle Applications ................................................................. 12 Tích hợp Custom Objects và Schemas ......................................................................... 12 Nâng cấp các form được customize lên Release 11i .................................................... 12

Tổng quan về Coding Standard trong ứng dụng ...............................................13 Theo dõi các thay đổi về dữ liệu với Record History ( WHO ) .................................... 13 Các ràng buộc khai báo ( declarative constraint ) : ....................................................... 15 View : ............................................................................................................................ 16 Sequence : ..................................................................................................................... 16 API đăng kí bảng : ........................................................................................................ 16 Tổng quan về việc sử dụng PL/SQL trong các ứng dụng : ........................................... 17 Thuật ngữ : .................................................................................................................... 17 Các chuẩn chung trong lập trình PL/SQL : ................................................................... 18 Định dạng mã PL/SQL : ............................................................................................... 19 Xử lý lỗi : ...................................................................................................................... 20 Một vài hướng dẫn khi coding SQL : ........................................................................... 21 Các trigger trong form : ................................................................................................ 22 Những sự thay thế cho các built-in trong Oracle Forms ............................................... 22 Lập trình các handler cho item, event và table : ........................................................... 23 Lập trình các handler cho item : ................................................................................... 24 Lập trình các handler cho event : .................................................................................. 25 Lập trình các handler cho table : ................................................................................... 25

Form TEMPLATE ................................................................................................40 Giới thiệu về form TEMPLATE : ................................................................................. 40 Các thư viện trong form TEMPLATE .......................................................................... 40 Các trigger trong form TEMPLATE............................................................................. 42

Thiết lập các thuộc tính của các đối tượng chứa(ContainerObject) ................49 Các đối tượng chứa : ..................................................................................................... 49 Module : ........................................................................................................................ 49 Window :....................................................................................................................... 49 Canvas : ......................................................................................................................... 51 1

Block : ........................................................................................................................... 51 Region : ......................................................................................................................... 54

Thiết lập các thuộc tính của các đối tượng Widget ...........................................55 Text Item : ..................................................................................................................... 55 Display Item : ................................................................................................................ 56 Poplist : ......................................................................................................................... 56 Option Group : .............................................................................................................. 56 Check Box :................................................................................................................... 56 Button ( Nút ) : .............................................................................................................. 56 List of Values ( LOV ) .................................................................................................. 57 Thiết lập các thuộc tính cho item : ................................................................................ 57 Một số lưu ý : ................................................................................................................ 60

Điều khiển hoạt động của Window, Block, và Region .......................................61 Điều khiển hoạt động của Window ............................................................................... 61 Lập trình cho các Tabbed Regions................................................................................ 69 Hành động của tabbed region : ..................................................................................... 70 3 mức khó trong lập trình : ........................................................................................... 70

Cho phép hoạt động truy vấn ..............................................................................73 Query Find : .................................................................................................................. 73 Triển khai Row-LOV .................................................................................................... 73 Triển khai Find Window ............................................................................................... 74

Lập trình các hành động cho item .......................................................................78 Mối quan hệ giữa các Item............................................................................................ 78 Item phụ thuộc có điều kiện .......................................................................................... 81 Các item đa phụ thuộc................................................................................................... 82 2 Master Item và 1 Dependent Item .............................................................................. 83 Kiểu phụ thuộc Cascading ............................................................................................ 85 Các item loại trừ lẫn nhau (Mutually Exclusive Items) ................................................ 86 Các item đồng hành với nhau (Mutually Inclusive Items) ............................................ 88 Mutually Inclusive Item liên hệ với Dependent Item ................................................... 89 Các item bắt buộc điều kiện (Conditionally Mandatory Items) .................................... 91 Các mặc định (Defaults) ............................................................................................... 93 Kiểm tra tính toàn vẹn (Integrity Checking) ................................................................. 94 Đối tượng Calendar ....................................................................................................... 97 Các lựa chọn cấp cao của Calendar .............................................................................. 98

Điều khiển Toolbar và Default Menu ...............................................................100 Pulldown Menu và Toolbar ........................................................................................ 100 Các lựa chọn có trên thanh công cụ ( toolbar ) : ......................................................... 101 Các mục chỉ có trong Menu ........................................................................................ 102 Điều khiển menu động ................................................................................................ 103 Tạo các biểu tượng trên toolbar cho các form bạn customize .................................... 104 Các menu đặc biệt ....................................................................................................... 105 Customize các Right–Mouse Menu (Popup Menus) .................................................. 105

Message Dictionary .............................................................................................108 Tổng quan về Message Dictionary ............................................................................. 108 Các điểm đặc trưng của Message Dictionary ............................................................ 108

2

Các bước cần tiến hành khi xác định Message Dictionary ......................................... 109 Thiết lập Message Dictionary ..................................................................................... 109 Phương pháp đối với Database Server–side Messaging. ............................................ 110

USER PROFILE .................................................................................................112 Các mức của User Profile: .......................................................................................... 112 Định nghĩa mới các tùy chọn của user profile ............................................................ 113 Thiết lập giá trị tùy chọn user profile.......................................................................... 113 Thiết lập user profile riêng của bạn ............................................................................ 113 Xác định trước tùy chọn user profile .......................................................................... 113 Profile Window ........................................................................................................... 114

FOLDER ..............................................................................................................116 Tổng quan về Folder. .................................................................................................. 116 Lập trình với Folder trên form ứng dụng. ................................................................... 116

3

Kiến trúc ứng dụng Tổng quan về kiến trúc ứng dụng. Kiến trúc ứng dụng của hệ thống Oracle Application theo mô hình tập trung 3 lớp, đó là các lớp Desktop Client, Middle Tier (Form Server) và Data Base Server. Mọi thao tác ở Client đều thực hiện dựa trên hệ thống Java nhúng. Dữ liệu nhập liệu được truyền về Application Server, việc xử lí các chức năng được thực hiện ở Application Server. Việc thao tác xử lí dữ liệu thực hiện ở Database Server. Kiến trúc tổng thể được mô tả như hình vẽ dưới đây:



Desktop Client : • Giao diện đồ họa, sử dụng trên các Web browser chuẩn có hỗ trợ Java nhúng chạy Jinitiator. • Oracle JInitiator là phiên bản Oracle của JavaSoft‟s Java Plug-In, cho phép xử lý JVM tại Web client thay vì dựa vào JVM default của browser.

4





Có thể tương thích với mọi PC,network computer hoặc trên bất cứ giao diện nào có Java.

Middle Tier (Form Server): • Xử lý các đáp ứng logic của Form. • Là nơi lưu giữ các dữ liệu cache cục bộ. • Trung gian giữa hai tầng.

5



Database Server: • Sử dụng các lời hàm từ xa (RPC) để giao tiếp với DB khi cần thiết (có thể thực hiện nhiều DB action cùng một lúc – các câu lệnh SQL). • Xử lý thao tác dữ liệu trên ứng dụng. • Lưu các thủ tục trên DB nên giao tiếp giữa các stored procedure và DB xảy ra trong bộ nhớ chứ không phải trên mạng. • Tương thích với DB từ 8i trở lên.

6

Mô hình phát triển và triển khai Oracle Application.

Hiện tại tại trung tâm sử dụng môi trường Window để thiết kế giao diện, dịch Form bằng Form Server trên hệ điều hành Linux. Quá trình phát triển form bao gồm ba bước chính là: • Build • Generate • Run/Test Build Form : Access to Libraries and Referenced Forms Thiết lập FORMS60_PATH. Referenced Objects and the ORACLE_APPLICATIONS V ariable Generating Your Form : (dịch Form trên Forms Server) Moving the File fmb Dịch file : f60gen module=demo.fmb userid=apps/apps Running Your Form for Testing : test trên môi trường Web chứ không phải trên Form developer Sau khi hoàn thành các bước trên chuyển đến Deployment : Nếu đang phát triển và triển khai trên cùng một platform thì chỉ cần copy file .fmx đến đích còn không phải dịch file trên platform đích.

7

Các chuẩn cho việc Customize ứng dụng Để có thể phát triển ứng dụng trên sản phẩm Oracle Applications bạn phải sử dụng Oracle Application Object Library cùng với các công cụ khác như Form và Report. Các chủ đề chính : 

Tổng quan về việc customize Oracle Applications



Customize theo cách mở rộng



Customize theo cách chỉnh sửa



Customize cơ sở dữ liệu Oracle Applications



Nâng cấp và chỉnh sửa Oracle Applications



Nâng cấp Custom Forms lên Release 11i



Upgrade Utility và Standards Compliance Checker: flint60

Tổng quan về việc customize Oracle Applications Các công việc sau bạn có thể làm để phát triển trên ứng dụng : 

Thay đổi các Form trên ứng dụng : – Giao diện (appearance) – Mã kiểm tra (validation logic) – Hành động (behavior)



Thay đổi Report hay chương trình : – Giao diện (appearance) – Mã (logic)



Thay đổi cơ sở dữ liệu của ứng dụng : – Thêm vào các read–only schema – Thêm mã vào các database trigger



Biên dịch lại toàn bộ ứng dụng.

8

Customization theo cách mở rộng. Phát triển các thành phần mới cũng như ứng dụng mới trên nền có sẵn sử dụng Oracle Application Object Library. Điều này có thể đơn giản bằng cách copy một thành phần có sẵn tới một thư mục khác và tiến hành sửa đổi nó. 

Customization theo cách chỉnh sửa Cách này gọi là thay đổi ngay tại chỗ. Tuy nhiên theo khuyến cáo ta nên tránh cách làm này vì có thể gặp sự cố khi nâng cấp hoặc khi sửa đổi.



Các thành phần (Component) Component có thể là module code (như form, report hoặc SQL script) hay các đối tượng Oracle Application Object Library (như menus, responsibilities, messages) hay kể cả đối tượng CSDL(tables, views, packages, or functions). Một ứng dụng phát triển phải được đăng ký với Oracle Application Object Library và phải có thư mục riêng cùng với component của nó.



Các đối tượng cơ sở dữ liệu Một table, index, view, sequence, database trigger, package, grant, hoặc synonym.



Application Short Name Là tên tham chiếu của ứng dụng không có dấu cách.



Application Basepath Là tên của một biến môi trường được chuyển thành top directory của cây thư mục của ứng dụng. Oracle Application Object Library sẽ tìm các đường dẫn tới các thư mục ở mức dưới để thực hiện các file chạy trong ứng dụng kể cả form file.



Cấu trúc thư mục của Application Là sự sắp sếp thứ tự các thư mục trong ứng dụng. Thủ mục của Oracle Applications được tạo ra khi cài đặt ứng dụng hay khi nâng cấp ứng dụng. Với các ứng dụng tự tạo bạn phải tạo riêng các thư mục cho nó.



Các file môi trường (Environment Files) của ứng dụng Xác định biến môi trường khi cài đặt ứng dụng. Biến môi trường bao gồm .env và adovars.env (đối với UNIX platforms).

Customize theo cách mở rộng 

Định nghĩa ứng dụng được customize của bạn

9



Tạo cấu trúc thư mục cho ứng dụng được customize



Thêm ứng dụng được customize vào trong file Environment của ứng dụng



Thêm các thành phần mới vào trong ứng dụng được customize của bạn



Lập tài liệu cho các thành phần mới



Lập tài liệu cho các thành phần mới



Với mỗi thành phần mới, lập tài liệu cho ít nhất là các nội dung sau :



Mục đích



Các tham số đầu vào (cho report và program)



Các đầu ra ví dụ (cho report và program)



Xử lý mã



Các đối tượng CSDL được sử dụng và kiểu truy cập (select, update, insert,delete). Nếu các component tự của bạn là sửa từ bản copy của một component trong ứng dụng bạn phải liệt kê chúng trong file applcust.txt ( nằm ở $APPL_TOP/admin directory Oracle Applications sẽ sử dụng file này trong quá trình patch hay upgrade

 Định nghĩa ứng dụng được customize của bạn Sử dụng Applications window để đăng ký custom application (bao gồm name và short name theo tiêu chuẩn đặt tên thông thường)



Tạo cấu trúc thư mục cho ứng dụng được customize Tự tạo cho ứng dụng của bạn một cấu trúc thư mục hợp lý.



Sửa đổi Applications Environment File Sửa đổi file biến môi trường cho hợp lý sau đó khởi động lại Forms Server và Internal Concurrent Manager rồi chạy file biến môi trường để Oracle Application Object Library tìm thấy các component.



Thêm mới các thành phần Mỗi khi tạo một component mới lưu ý là để chúng ở trong thư mục con hợp lý của ứng dụng.



Thêm một form mới Sử dụng file Template khi bắt đầu tạo một form mới để có thể tương thích

10

với ứng dụng hoặc sửa đổi một form đã có sẵn trên ứng dụng rồi đăng ký lại với ứng dụng.

Các bước tiếp theo là : 

Thêm một Report hoặc một Concurrent Program



Thêm một Report Submission Form



Thêm Online Help



Thêm Menus



Thêm Responsibilities



Thêm các thông báo trong Message Dictionary

Customize bằng cách chỉnh sửa Các bước tiến hành để sửa đổi một form có sẵn trong ứng dụng : Với Release 11i, tất cả các form đêu đặt trong thư mục $AU_TOP/forms/. Copy Oracle Applications form để tiến hành sử đổi ( Lưu ý không sửa đổi trực tiếp lên form). Sử dụng Oracle Forms Developer and Oracle Application Object Library :

1. Xác định một file 2. Copy file vào trong custom application và đổi tên file 3. Bảo toàn file nguyên bản 4. Thực hiện các chỉnh sửa 5. Chú thích cho form 6. Dịch form 7. Đăng kí ứng dụng được customize trong applcust.txt 8. Lập tài liệu cho việc customize



Chú thích cho form Để ghi thông tin về ngày và người sửa của form sử dụng PRE–FORM trigger Oracle Forms. FND_STANDARD.FORM_INFO(‟$Revision: $‟, ‟
‟, ‟<Application Shortname>‟, ‟$Date: $‟, ‟$Author: <developer name> $‟);

11

Lưu ý để có thể sử dụng Help oline thì phải giữ nguyên Application short Name . 

Chỉnh sửa một Report đã có sẵn Các bước tiến hành đối với Oracle Reports .rdf file cũng tương tự như dưới đây : 1. Xác định file 2. Thực hiện chỉnh sửa 3. Chú thích cho report 4. Tạo 1 concurrent program sử dụng file của bạn

Customize cơ sở dữ liệu Oracle Applications Nếu thực hiên việc này phải đặc biệt lưu ý không làm ảnh hưởng tới toàn bộ ứng dụng .

Nâng cấp và chỉnh sửa Oracle Applications 

Kiểm tra các chỉnh sửa đối với CSDL



Xác định các chỉnh sửa cũ



Luân chuyển các chỉnh sửa



Chạy lại Grant và Synonym Scripts



Test tất cả các sự sửa đổi

Tích hợp Custom Objects và Schemas Để thực hiện điều này tốt nhất nên hỏi chuyên gia.

Nâng cấp các form được customize lên Release 11i

12

Tổng quan về Coding Standard trong ứng dụng Theo dõi các thay đổi về dữ liệu với Record History ( WHO ) 

Tính năng Record History ( WHO ) cung cấp thông tin về người đã tạo mới hay cập nhật các hàng trong các bảng Oracle Applications. Nếu bạn thêm các cột WHO đặc biệt vào bảng và các mã WHO vào form và stored procedure, người dùng có thể theo dõi được những thay đổi với dữ liệu của họ. Bạn sử dụng các trường ẩn ( hidden field ) trong mỗi block đại diện cho các cột WHO. Gọi FND_STANDARD.SET_WHO trong các trigger PRE-INSERT, PRE-UPDATE để cung cấp giá trị cho các trường này.



Các cột WHO :

13

14

Các ràng buộc khai báo ( declarative constraint ) : 

NOT NULL



DEFAULT



UNIQUE



CHECK



PRIMARY KEY

Tránh tạo các bảng với kiểu dữ liệu : LONG, LONG RAW, RAW. Sử dụng kiểu VARCHAR2(2000) để thay thế. Với các bảng có tên cột trùng với từ khoá, tạo view đến bảng đó với tên cột được thay bằng tên khác không trùng từ khoá. Có thể thực hiện INSERT, UPDATE, DELETE qua view kiểu này được.

15

View : 

Các block phức tạp thì dựa trên các view, các block đơn giản thì dựa trên các table. Bạn cũng nên tạo các LOV dựa trên view.



Cột đầu tiên trong view nên chọn là cột giả (pseudo-column) ROWID (đặt tên là ROW_ID), rồi đến các cột của bảng ( kể cả các cột WHO ).



Đặt thuộc tính Key Mode của block là Non-Updatable để tắt tham chiếu mặc định đến ROWID của Oracle Forms cho các block dựa trên view. Đặt thuộc tính Primary Key của item là True với item là khoá chính của view.



Lập trình các trigger để thực hiện insert, update, delete và lock : khi tạo 1 block dựa trên view, phải lập trình các trigger ON-INSERT, ON-UPDATE, ON-DELETE và ON-LOCK để insert, update, delete và lock bảng gốc thay vì view.



Với view trên 1 bảng, không cần đến các trigger để insert, update, delete hay lock. Đặt Key Mode của block là Unique. Các view trên 1 bảng không cần đến cột ROW_ID.

Sequence : 

Tạo sequence : để cung cấp các giá trị ID không trùng nhau cho 1 cột của 1 bảng.



Không nên giới hạn phạm vi của sequence ( không sử dụng CYCLE hoặc MAXVALUE ).



Sử dụng kiểu dữ liệu Number để lưu các giá trị của sequence.



Không sử dụng bảng FND_UNIQUE_IDENTIFIER_CONTROL

API đăng kí bảng : 

Bạn đăng kí các bảng ứng dụng tự tạo của mình bằng 1 PL/SQL routine trong package AD_DD.



Các bảng ( và mọi cột của nó ) chỉ phải đăng kí khi chúng sử dụng flexfield hoặc Oracle Alert.



Có thể sử dụng AD_DD API để xoá các đăng kí của bảng và cột



Khi thay đổi cấu trúc bảng, đăng kí lại bằng cách xoá đăng kí cũ ( cột trước rồi đến bảng ), sau đó đăng kí lại.



AD_DD API không kiểm tra sự tồn tại của bảng cần đăng kí. Vì vậy, cần biết chắc bảng cần đăng kí có tồn tại và mô tả đúng các định dạng của nó khi sử dụng AD_DD API.



Không cần phải đăng kí cho view.



Các thủ tục trong package AD_DD : procedure register_table (p_appl_short_name in varchar2, p_tab_name in varchar2,

16

p_tab_type in varchar2, p_next_extent in number default 512, p_pct_free in number default 10, p_pct_used in number default 70); procedure register_column (p_appl_short_name in varchar2, p_tab_name in varchar2, p_col_name in varchar2, p_col_seq in number, p_col_type in varchar2, p_col_width in number, p_nullable in varchar2, p_translate in varchar2, p_precision in number default null, p_scale in number default null); procedure delete_table (p_appl_short_name in varchar2, p_tab_name in varchar2); procedure delete_column (p_appl_short_name in varchar2, p_tab_name in varchar2, p_col_name in varchar2);

Ví dụ về sử dụng package AD_DD để đăng kí 1 bảng flexfield và các cột của nó : EXECUTE ad_dd.register_table(‟FND‟, ‟CUST_FLEX_TEST‟, ‟T‟, 8, 10, 90); EXECUTE ad_dd.register_column(‟FND‟, ‟CUST_FLEX_TEST‟, ‟APPLICATION_ID‟, 1, ‟NUMBER‟, 38, ‟N‟, ‟N‟);

Tổng quan về việc sử dụng PL/SQL trong các ứng dụng : 

Bạn có thể sử dụng các thủ tục PL/SQL như một phần của ứng dụng bạn xây dựng nằm trong Oracle Applications. Bằng cách tuân theo các chuẩn lập trình, bạn có thể tạo ra 1 thủ tục PL/SQL tích hợp hoàn toàn với ứng dụng.



Bạn có thể sử dụng PL/SQL viết các đoạn mã mở rộng có tính thủ tục để custom form và report. PL/SQL cũng giúp module hoá form code của bạn, hoặc phát triển các chương trình chạy đồng thời ( concurrent program ).

Thuật ngữ : 

Server-side : chỉ các thủ tục lưu trên cơ sở dữ liệu Oracle .



Client-side : chỉ các thủ tục chạy trong các chương trình là client của CSDL Oracle.

17

Các chuẩn chung trong lập trình PL/SQL : 

Luôn sử dụng package : định nghĩa các thủ tục PL/SQL trong package



Kích thước package : mã nguồn của 1 đơn vị chương trình ( 1 package ) client-side không được vượt quá 10K, và tổng kích thước source code và compiled code phải nhỏ hơn 64K. Nếu 1 đơn vị chương trình quá lớn, có thể chia ra thành các đơn vị con được liên kết với nhau. Server-side package không bị giới hạn về kích thước.



Thêm các thủ tục mới vào các package đã tồn tại : thêm vào cuối của mỗi package. Nếu thêm vào giữa package ( specification hay body ), phải dịch lại các form có tham chiếu đến package, nếu không sẽ bị lỗi.



Sử dụng tên trường trong các client-side package : luôn dùng tên trường đầy đủ ( BLOCK_NAME.FIELD_NAME ) để khoanh vùng tìm kiếm ( chỉ tìm trong block đó ), và tránh trường hợp xung đột khi có 2 trường trùng tên.



Tên trường trong các tham số của thủ tục : không dùng kiểu tham số OUT hoặc IN OUT vì có thể làm thay đổi các giá trị của trường truyền vào khi kết thúc thủ tục. Với danh sách tham số quá dài, sử dụng “ => “ để truyền đúng tham số.



Sử dụng DEFAULT : sử dụng DEFAULT để khởi tạo giá trị mặc định cho tham số thay vì “:=”, để cho giá trị truyền vào có thể ghi đè lên giá trị mặc định. Ngược lại, với hằng, sử dụng “:=” để giá trị không thể bị ghi đè lên.



Sử dụng ID của object : các đoạn code thay đổi nhiều thuộc tính của 1 đối tượng bằng SET__PROPERTY, nên sử dụng ID của đối tượng. Dùng FIND_ để lấy ID, sau đó truyền ID vào thủ tục được dựng sẵn SET__PROPERTY.



Xử lý giá trị NULL : bất kì biểu thức so sánh nào có chứa phần tử NULL đều trả về giá trị FALSE. Để kiểm tra một phần tử có NULL hay không, sử dụng “IS”.



Các biến global : có 3 loại . Oracle Form global : biến nằm trong pseudo-block ( khối giả ) “global” của form. . PL/SQL package global : biến được định nghĩa trong package specification . Oracle Form Parameter : biến được tạo như một tham số trong Oracle Forms Designer.

18

Định dạng mã PL/SQL : 

Trong 1 package, định nghĩa các biến private trước, sau đó đến các thủ tục private, cuối cùng là các thủ tục public.



Luôn kết thúc thủ tục hoặc package bằng End Procedure_name; hoặc End Package_name; để dễ theo dõi, nhận dạng.



Hàng lệnh dưới lùi vào trong 2 dấu cách để dễ đọc code, ví dụ :



Sử dụng “--“ để thêm dòng chú thích và “/* … */” để bao đoạn chú thích.



Căn lề chú thích và lệnh được chú thích thẳng hàng.

19



Sử dụng chữ hoa ( với các từ khoá ) và chữ thường ( các từ còn lại ) để dễ đọc code ( vì PL/SQL không phân biệt chữ hoa chữ thường ).



Dùng IF-THEN-ELSIF thay cho các cấu trúc IF-THEN-ELSE lồng nhau.



Chỉ tạo các khối PL/SQL lồng nhau trong 1 thủ tục khi phải xử lý những lỗi cụ thể phát sinh.

Xử lý lỗi : 

Lỗi trong thủ tục PL/SQL trong Oracle Form : sử dụng FND_MESSAGE để hiển thị thông báo lỗi, sau đó gọi RAISE FORM_TRIGGER_FAILURE để dừng việc xử lý lại.



Lỗi trong các stored procedure : sử dụng FND_MESSAGE.SET_NAME để hiển thị thông báo lỗi, sau đó gọi APP_EXCEPTION.RAISE_EXCEPTION để dừng xử lý

20



Kiểm tra FORM_SUCCESS, FORM_FAILURE và FORM_FATAL : các giá trị của chúng có thể bị thay đổi bởi một trigger nào đó. Xem ví dụ sau :



Tránh sử dụng RAISE_APPLICATION_ERROR vì nó gây xung đột trong quá trình xử lý lỗi ở phía server.

Một vài hướng dẫn khi coding SQL : 

Sử dụng “select from DUAL” thay vì “select from SYS.DUAL”. Không sử dụng SYSTEM.DUAL.



Tất cả các lệnh SELECT nên sử dụng một cursor (con trỏ) tự định nghĩa từ trước. Một lệnh SELECT bình thường thực hiện 2 xử lý : 1 để lấy dữ liệu và 1 để kiểm tra

21

có bị lỗi TOO_MANY_ROWS không. Ta có thể tránh điều này bằng việc chỉ lấy về 1 bản ghi từ cursor mà ta định nghĩa trước. 

Nếu bạn muốn SELECT vào trong 1 tham số thủ tục, khai báo tham số là IN OUT, cho dù có sử dụng hay không giá trị của tham số ( trừ trường hợp tham số là trường ).



1 single-row SELECT khi không trả về hàng nào sẽ sinh ra lỗi NO_DATA_FOUND. 1 INSERT, UPDATE, hay DELETE khi không tác động lên hàng nào sẽ không báo lỗi. Bạn phải tự kiểm tra giá trị của SQL%NOTFOUND để biết được có bị lỗi không.



Để xử lý NO_DATA_FOUND, viết một đoạn bắt lỗi (exception handler), thay vì dùng COUNT để đếm số hàng hiện thời.



Khi kiểm tra giá trị của một trường hoặc một biến để bắt lỗi sai, kiểm tra trong PL/SQL code, chứ không phải trong mệnh đề WHERE.

Các trigger trong form : 

Kiểu xử lý : Kiểu xử lý cho tất cả các trigger ở mức block hay field nên là Overide (đè lên trigger mức form) hoặc Before (thực hiện trước trigger mức form). Thông thường là sử dụng kiểu Before, vì phiên bản trigger ở mức form cũng cần được thực hiện. Trường hợp ngoại lệ là khi bạn có một lời gọi flexfield trong trigger POST-QUERY mức form, nhưng bạn đặt lại query status của block trong trigger POST-QUERY ở mức block, thì bạn nên đặt kiểu xử lý cho trigger mức block là After.



Trigger WHEN-CREATE-RECORD vẫn kích hoạt khi block không cho phép insert. Vì vậy, nên kiểm tra xem 1 block có cho phép insert không trước khi thực hiện xử lý nào đó trong trigger này :

Những sự thay thế cho các built-in trong Oracle Forms 

Không sử dụng CALL_FORM : vì built-in này không tương thích với OPEN_FORM (được sử dụng bởi các Oracle Application routine). Sử dụng FND_FUNCTION.EXECUTE thay cho CALL_FORM hoặc OPEN_FORM khi muốn mở form bằng lập trình.

22



Những Oracle Forms built-in sau có các APPCORE routine tương đương với chúng : + EXIT_FORM : các form Oracle Applications có xử lý đóng đặc biệt. Không gọi trực tiếp EXIT_FORM, mà luôn gọi do_key(„EXIT_FORM‟). Để đóng toàn bộ Oracle Applications, trước tiên gọi : copy(‘Y’, ’GLOBAL.APPCORE_EXIT_FLAG’); sau đó gọi : do_key(‘EXIT_FORM’); + SET_ITEM_PROPERTY : thay bằng APP_ITEM_PROPERTY.SET_PROPERTY và APP_ITEM_PROPERTY.SET_VISUAL_ATTRIBUTE. Những APPCORE routine này đặt các thuộc tính trong Oracle Applications theo chuẩn.Có một số thuộc tính sử dụng SET_ITEM_PROPERTY. + GET_ITEM_PROPERTY : sử dụng APP_ITEM_PROPERTY.GET_PROPERTY khi lấy các thuộc tính cụ thể của Oracle Applications. Khi đặt hoặc lấy các thuộc tính còn lại, sử dụng các built-in của Oracle Forms. + OPEN_FORM : sử dụng FND_FUNCTION.EXECUTE để thay thế. Cả 2 cách gọi này đều làm cho các trigger POST-RECORD và POST-BLOCK kích hoạt. + CLEAR_FORM : sử dụng do_key(„CLEAR_FORM‟). Routine này sẽ báo lỗi FORM_TRIGGER_FAILURE nếu có 1 bản ghi không hợp lệ. + COMMIT : sử dụng do_key(„COMMIT_FORM‟). Routine này sẽ báo lỗi FORM_TRIGGER_FAILURE nếu có 1 bản ghi không hợp lệ. + EDIT_FIELD / EDIT_TEXTITEM : sử dụng do_key(„edit_field‟). Routine này sẽ gọi calendar khi item hiện tại là date. + VALIDATE : sử dụng APP_STANDARD.APP_VALIDATE để thay thế. Routine này sẽ chuyển focus đến bất kì item nào làm phát sinh lỗi navigation.

Lập trình các handler cho item, event và table : 

Người lập trình có thể gọi các handler (chương trình xử lý) từ trong trigger để xử lý các mã cần thiết để validate một item hoặc đảm bảo cho 1 hành động được thực hiện đúng trong tình huống cụ thể.



1 form điển hình có từng package cho mỗi block, và 1 package cho bản thân form. Lập trình cho các thủ tục trong mỗi package, và gọi thủ tục (hay handler đó) từ các trigger có liên quan. Với handler liên quan đến nhiều block hay đáp ứng cho trigger mức form, đặt nó vào trong package của form.

23



Việc viết các handler ( cho item, event, table ), và gọi chúng trong trigger sẽ giúp cho khối lượng mã trong trigger ở mức tối thiểu.

Lập trình các handler cho item : Các item handler là các thủ tục chứa đựng tất cả các đoạn mã dùng để validate một item cụ thể nào đó. Một item handler package chứa tất cả các thủ tục dùng để validate các item trong 1 block hoặc 1 form. Nên đặt tên package theo tên block ( hoặc tên form ) và đặt tên các thủ tục trong package theo tên các item trong block đó (VD : block EMP, item EMPNO -> package EMP, procedure EMPNO) để dễ xác định code nào đi với item nào. Mỗi item handler luôn có 1 tham số tên là EVENT, kiểu là VARCHAR2, thường để truyền tên của trigger gọi item handler đó. Các EVENT thông dụng và xử lý tương ứng là : 

PRE-RECORD : đặt lại các item attribute cho bản ghi mới. EVENT này thường được sử dụng cho các APPCORE routine (loại enable hoặc disable các trường độc lập). Bạn cũng có thể dùng WHEN-NEW-RECORD-INSTANCE ( thay cho PRERECORD ) trong một vài trường hợp.



INIT : khởi tạo ( initialize ) item. INIT chỉ thị cho item handler kiểm tra các điều kiện hiện tại của form và đặt lại các giá trị mặc định và các thuộc tính động cho item nếu cần thiết. EVENT này được gửi đi bởi các handler khác và là đầu vào cho nhiều APPCORE routine. Trường hợp thông thường nhất là khi 1 item phụ thuộc vào 1 item khác. Khi 1 master item thay đổi, handler của item phụ thuộc sẽ được gọi với sự kiện INIT.



VALIDATE : được sử dụng với nhiều APPCORE routine khi item cần được validate. Sử dụng VALIDATE thay cho WHEN–VALIDATE–ITEM, WHEN– CHECKBOX–CHANGED, WHEN–LIST–CHANGED, hoặc WHEN–RADIO– CHANGED.

24

Lập trình các handler cho event : 

Event handler thực hiện các hành động phức tạp trên nhiều item có liên quan với nhau, trong khi item handler thực hiện các hành động đơn giản trên 1 item. Trong event handler, ta có thể gọi các item handler.



Event handler chỉ xử lý 1 sự kiện ( trên nhiều item ), nên không cần tham số EVENT, và cũng không cần bất kì tham số nào.



Event handler được đặt tên theo trigger, nhưng thay dấu gạch ngang bằng dấu gạch dưới (VD: trigger PRE-QUERY -> handler PRE_QUERY).



Một số event handler thông dụng : . PRE_QUERY : cung cấp các giá trị cần cho các item để lấy được các bản ghi mong muốn. . POST_QUERY : cung cấp giá trị cho các item không liên quan đến bảng dữ liệu. . WHEN_CREATE_RECORD : cung cấp các giá trị mặc định khi tạo bản ghi mới ( khi mà sử dụng thuộc tính default value là chưa đủ ) . WHEN_VALIDATE_RECORD : kiểm tra các quan hệ phức tạp có trong item.

Lập trình các handler cho table : 

Một table handler là 1 server-side package hoặc 1 client-side package cung cấp một API cho 1 bảng. Các table handler được sử dụng để insert, update, delete hoặc lock một bản ghi, hoặc để kiểm tra xem 1 record ở bảng khác có tham chiếu đến record ở trong bảng này ko. Vì hầu hết các form trong Oracle Applications đều dựa trên các view nên cần phải có các table handler này để xử lý những tương tác với các bảng có trong view.

25



Các table handler chứa một vài hoặc tất cả các thủ tục sau : . CHECK_UNIQUE : kiểm tra xem có giá trị lặp trong cột unique hay không . CHECK_REFERENCES : kiểm tra tính toàn vẹn tham chiếu . INSERT_ROW . UPDATE_ROW . DELETE_ROW . LOCK_ROW



INSERT_ROW, UPDATE_ROW, DELETE_ROW và LOCK_ROW thường được sử dụng để thay thế xử lý giao dịch mặc định của Oracle Forms trong các trigger ON-INSERT, ON-UPDATE, ON-DELETE và ON-LOCK.



Trong thủ tục xử lý bảng INSERT_ROW, nếu một cột khoá chính cho phép giá trị NULL, cần thêm “OR (primary_key IS NULL AND X_col IS NULL)” vào mệnh đề WHERE của câu lệnh SELECT ROWID.



Trong thủ tục xử lý bảng LOCK_ROW, nếu 1 cột không được phép NULL, gỡ bỏ điều kiện ”OR (RECINFO.col IS NULL AND X_col IS NULL)” ra khỏi lệnh IF.



Tác động lên 1 bảng thứ hai : để thực hiện 1 hành động trên 1 bảng khác, gọi thủ tục xử lý tương ứng của bảng đó thay cho việc thực hiện hành động trực tiếp. Ví dụ, trong thủ tục DELETE_ROW của bảng master, ta xoá bản ghi master và gọi thủ tục DELETE_ROW của bảng detail để xoá các bản ghi detail tương ứng, chứ không thực hiện lệnh DELETE trực tiếp xoá chúng trong handler của master.



Ví dụ về client-side table handler : handler này cung cấp các thủ tục INSERT_ROW, UPDATE_ROW, DELETE_ROW, and LOCK_ROW cho bảng EMP. Bạn lập trình client–side table handler trực tiếp trong form

Package spec you would code for your EMP block PACKAGE EMP IS PROCEDURE Insert_Row; PROCEDURE Lock_Row; PROCEDURE Update_Row; PROCEDURE Delete_Row; END EMP; Package body you would code for your EMP block PACKAGE BODY EMP IS PROCEDURE Insert_Row IS

26

CURSOR C IS SELECT rowid FROM EMP WHERE empno = :EMP.Empno; BEGIN INSERT INTO EMP( empno, ename, job, mgr, hiredate, sal, comm, deptno ) VALUES ( :EMP.Empno, :EMP.Ename, :EMP.Job, :EMP.Mgr, :EMP.Hiredate, :EMP.Sal, :EMP.Comm, :EMP.Deptno ); OPEN C; FETCH C INTO :EMP.Row_Id; if (C%NOTFOUND) then CLOSE C; Raise NO_DATA_FOUND; end if; CLOSE C; END Insert_Row; PROCEDURE Lock_Row IS

27

Counter NUMBER; CURSOR C IS SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno FROM EMP WHERE rowid = :EMP.Row_Id FOR UPDATE of Empno NOWAIT; Recinfo C%ROWTYPE; BEGIN Counter := 0; LOOP BEGIN Counter := Counter + 1; OPEN C; FETCH C INTO Recinfo; if (C%NOTFOUND) then CLOSE C; FND_MESSAGE.Set_Name(‟FND‟, ‟FORM_RECORD_DELETED‟); FND_MESSAGE.Error; Raise FORM_TRIGGER_FAILURE; end if; CLOSE C; if ( (Recinfo.empno = :EMP.Empno)

28

AND ( (Recinfo.ename = :EMP.Ename) OR ( (Recinfo.ename IS NULL) AND (:EMP.Ename IS NULL))) AND ( (Recinfo.job = :EMP.Job) OR ( (Recinfo.job IS NULL) AND (:EMP.Job IS NULL))) AND ( (Recinfo.mgr = :EMP.Mgr) OR ( (Recinfo.mgr IS NULL) AND (:EMP.Mgr IS NULL))) AND ( (Recinfo.hiredate = :EMP.Hiredate) OR ( (Recinfo.hiredate IS NULL) AND (:EMP.Hiredate IS NULL))) AND ( (Recinfo.sal = :EMP.Sal) OR ( (Recinfo.sal IS NULL) AND (:EMP.Sal IS NULL))) AND ( (Recinfo.comm = :EMP.Comm) OR ( (Recinfo.comm IS NULL) AND (:EMP.Comm IS NULL))) AND (Recinfo.deptno = :EMP.Deptno) ) then return; else FND_MESSAGE.Set_Name(‟FND‟, ‟FORM_RECORD_CHANGED‟); FND_MESSAGE.Error; Raise FORM_TRIGGER_FAILURE; end if; EXCEPTION When APP_EXCEPTIONS.RECORD_LOCK_EXCEPTION then IF (C% ISOPEN) THEN close C;

29

END IF; APP_EXCEPTION.Record_Lock_Error(Counter); END; end LOOP; END Lock_Row; PROCEDURE Update_Row IS BEGIN UPDATE EMP SET empno = :EMP.Empno, ename = :EMP.Ename, job = :EMP.Job, mgr = :EMP.Mgr, hiredate = :EMP.Hiredate, sal = :EMP.Sal, comm = :EMP.Comm, deptno = :EMP.Deptno WHERE rowid = :EMP.Row_Id; if (SQL%NOTFOUND) then Raise NO_DATA_FOUND; end if; END Update_Row; PROCEDURE Delete_Row IS BEGIN DELETE FROM EMP WHERE rowid = :EMP.Row_Id; if (SQL%NOTFOUND) then Raise NO_DATA_FOUND; end if; END Delete_Row; END EMP;

30

- Ví dụ về server-side table handler : handler này cung cấp các thủ tục INSERT_ROW, UPDATE_ROW, DELETE_ROW và LOCK_ROW cho bảng EMP. Handler của bạn sẽ bao gồm 1 package trong form và 1 server–side package trong cơ sở dữ liệu. Package trong form sẽ gọi severside package và truyền tất cả giá trị của các trường như là các đối số.

Package spec you would code in your form for your EMP block PACKAGE EMP IS PROCEDURE Insert_Row; PROCEDURE Update_Row; PROCEDURE Lock_Row; PROCEDURE Delete_Row; END EMP; Package body you would code in your form for your EMP block PACKAGE BODY EMP IS PROCEDURE Insert_Row IS BEGIN EMP_PKG.Insert_Row( X_Rowid => :EMP.Row_Id, X_Empno => :EMP.Empno, X_Ename => :EMP.Ename, X_Job => :EMP.Job, X_Mgr => :EMP.Mgr, X_Hiredate => :EMP.Hiredate, X_Sal => :EMP.Sal, X_Comm => :EMP.Comm, X_Deptno => :EMP.Deptno); END Insert_Row; PROCEDURE Update_Row IS BEGIN 31

EMP_PKG.Update_Row( X_Rowid => :EMP.Row_Id, X_Empno => :EMP.Empno, X_Ename => :EMP.Ename, X_Job => :EMP.Job, X_Mgr => :EMP.Mgr, X_Hiredate => :EMP.Hiredate, X_Sal => :EMP.Sal, X_Comm => :EMP.Comm, X_Deptno => :EMP.Deptno); END Update_Row; PROCEDURE Delete_Row IS BEGIN EMP_PKG.Delete_Row(:EMP.Row_Id); END Delete_Row; PROCEDURE Lock_Row IS Counter Number; BEGIN Counter := 0; LOOP BEGIN Counter := Counter + 1; EMP_PKG.Lock_Row( X_Rowid => :EMP.Row_Id, X_Empno => :EMP.Empno, X_Ename => :EMP.Ename, X_Job => :EMP.Job, X_Mgr => :EMP.Mgr, X_Hiredate => :EMP.Hiredate, X_Sal => :EMP.Sal, X_Comm => :EMP.Comm,

32

X_Deptno => :EMP.Deptno); return; EXCEPTION When APP_EXCEPTIONS.RECORD_LOCK_EXCEPTION then APP_EXCEPTION.Record_Lock_Error(Counter); END; end LOOP; END Lock_Row; END EMP; Package spec for the server–side table handler (SQL script) SET VERIFY OFF DEFINE PACKAGE_NAME=”EMP_PKG” WHENEVER SQLERROR EXIT FAILURE ROLLBACK; CREATE or REPLACE PACKAGE &PACKAGE_NAME as /* Put any header information (such as $Header$) here. It must be written within the package definition so that the header information will be available in the package itself. This makes it easier to identify package versions during upgrades. */ PROCEDURE Insert_Row(X_Rowid IN OUT VARCHAR2, X_Empno NUMBER, X_Ename VARCHAR2, X_Job VARCHAR2, X_Mgr NUMBER, X_Hiredate DATE, X_Sal NUMBER, X_Comm NUMBER, X_Deptno NUMBER ); PROCEDURE Lock_Row(X_Rowid VARCHAR2, X_Empno NUMBER,

33

X_Ename VARCHAR2, X_Job VARCHAR2, X_Mgr NUMBER, X_Hiredate DATE, X_Sal NUMBER, X_Comm NUMBER, X_Deptno NUMBER ); PROCEDURE Update_Row(X_Rowid VARCHAR2, X_Empno NUMBER, X_Ename VARCHAR2, X_Job VARCHAR2, X_Mgr NUMBER, X_Hiredate DATE, X_Sal NUMBER, X_Comm NUMBER, X_Deptno NUMBER ); PROCEDURE Delete_Row(X_Rowid VARCHAR2); END &PACKAGE_NAME; / show errors package &PACKAGE_NAME SELECT to_date(‟SQLERROR‟) FROM user_errors WHERE name = ‟&PACKAGE_NAME‟ AND type = ‟PACKAGE‟ / commit; exit; Package body for the server–side table handler (SQL script) SET VERIFY OFF DEFINE PACKAGE_NAME=”EMP_PKG”

34

WHENEVER SQLERROR EXIT FAILURE ROLLBACK; CREATE or REPLACE PACKAGE BODY &PACKAGE_NAME as /* Put any header information (such as $Header$) here. It must be written within the package definition so the header information is available in the package itself. This makes it easier to identify package versions during upgrades. */ PROCEDURE Insert_Row(X_Rowid IN OUT VARCHAR2, X_Empno NUMBER, X_Ename VARCHAR2, X_Job VARCHAR2, X_Mgr NUMBER, X_Hiredate DATE, X_Sal NUMBER, X_Comm NUMBER, X_Deptno NUMBER ) IS CURSOR C IS SELECT rowid FROM emp WHERE empno = X_Empno; BEGIN INSERT INTO emp( empno, ename, job, mgr, hiredate, sal, comm, deptno ) VALUES ( X_Empno,

35

X_Ename, X_Job, X_Mgr, X_Hiredate, X_Sal, X_Comm, X_Deptno ); OPEN C; FETCH C INTO X_Rowid; if (C%NOTFOUND) then CLOSE C; Raise NO_DATA_FOUND; end if; CLOSE C; END Insert_Row; PROCEDURE Lock_Row(X_Rowid VARCHAR2, X_Empno NUMBER, X_Ename VARCHAR2, X_Job VARCHAR2, X_Mgr NUMBER, X_Hiredate DATE, X_Sal NUMBER, X_Comm NUMBER, X_Deptno NUMBER ) IS CURSOR C IS SELECT * FROM emp WHERE rowid = X_Rowid FOR UPDATE of Empno NOWAIT;

36

Recinfo C%ROWTYPE; BEGIN OPEN C; FETCH C INTO Recinfo; if (C%NOTFOUND) then CLOSE C; FND_MESSAGE.Set_Name(‟FND‟, ‟FORM_RECORD_DELETED‟); APP_EXCEPTION.Raise_Exception; end if; CLOSE C; if ( (Recinfo.empno = X_Empno) AND ( (Recinfo.ename = X_Ename) OR ( (Recinfo.ename IS NULL) AND (X_Ename IS NULL))) AND ( (Recinfo.job = X_Job) OR ( (Recinfo.job IS NULL) AND (X_Job IS NULL))) AND ( (Recinfo.mgr = X_Mgr) OR ( (Recinfo.mgr IS NULL) AND (X_Mgr IS NULL))) AND ( (Recinfo.hiredate = X_Hiredate) OR ( (Recinfo.hiredate IS NULL) AND (X_Hiredate IS NULL))) AND ( (Recinfo.sal = X_Sal) OR ( (Recinfo.sal IS NULL) AND (X_Sal IS NULL))) AND ( (Recinfo.comm = X_Comm) OR ( (Recinfo.comm IS NULL) AND (X_Comm IS NULL))) AND (Recinfo.deptno = X_Deptno)

37

) then return; else FND_MESSAGE.Set_Name(‟FND‟, ‟FORM_RECORD_CHANGED‟); APP_EXCEPTION.Raise_Exception; end if; END Lock_Row; PROCEDURE Update_Row(X_Rowid VARCHAR2, X_Empno NUMBER, X_Ename VARCHAR2, X_Job VARCHAR2, X_Mgr NUMBER, X_Hiredate DATE, X_Sal NUMBER, X_Comm NUMBER, X_Deptno NUMBER ) IS BEGIN UPDATE emp SET empno = X_Empno, ename = X_Ename, job = X_Job, mgr = X_Mgr, hiredate = X_Hiredate, sal = X_Sal, comm = X_Comm, deptno = X_Deptno WHERE rowid = X_Rowid; if (SQL%NOTFOUND) then Raise NO_DATA_FOUND;

38

end if; END Update_Row; PROCEDURE Delete_Row(X_Rowid VARCHAR2) IS BEGIN DELETE FROM emp WHERE rowid = X_Rowid; if (SQL%NOTFOUND) then Raise NO_DATA_FOUND; end if; END Delete_Row; END &PACKAGE_NAME; / show errors package body &PACKAGE_NAME SELECT to_date(‟SQLERROR‟) FROM user_errors WHERE name = ‟&PACKAGE_NAME‟ AND type = ‟PACKAGE BODY‟ / commit; exit;

39

Form TEMPLATE Giới thiệu về form TEMPLATE : 

Form TEMPLATE là điểm khởi đầu cần có đối với mọi sự phát triển form mới. Bắt đầu tạo 1 form mới bằng cách copy form TEMPLATE về 1 thư mục trong máy rồi thay tên nó bằng một tên form mới



Form TEMPLATE bao gồm :  Các tham chiếu tới các nhóm đối tượng trong form APPSTAND (STANDARD_PC_AND_VA,

STANDARD_TOOLBAR,



STANDARD_CALENDAR)  Các kết nối (attachment) đến một số thư viện (FNDSQF, APPCORE, và APPDAYPK)  Một số trigger mức form cần phải thêm code.  Các đơn vị chương trình, trong đó có package APP_CUSTOM (specification và body), chứa các hành động mặc định cho các sự kiện đóng và mở window. Bạn thường phải sửa code trong package này khi phát triển form theo yêu cầu.  Bảng màu của ứng dụng  Rất nhiều đối tượng được tham chiếu ( nằm trong các nhóm đối tượng ), để hỗ trợ cho calendar, toolbar, alternative region và menu. Ví dụ như các LOV, block, parameter, property class.  Một số đối tượng ví dụ đưa ra các item và layout điển hình. Để bỏ chúng đi, xóa các đối tượng sau trong form : Block : BLOCKNAME, DETAILBLOCK Canvas : BLOCKNAME Window : BLOCKNAME

Các thư viện trong form TEMPLATE 

Form TEMPLATE chứa các attachment đến một số thư viện. 3 thư viện được attach trực tiếp là : FNDSQF, APPCORE, APPDAYPK. Các thư viện khác được attach đến 3 thư viện này. Trong Oracle Forms, ta không biệt được thư viện được attach theo kiểu nào.

40



Thư viện APPCORE :  Chứa các thủ tục nằm trong các package mà mọi form đều cần để hỗ trợ menu, toolbar, và các hành động chuẩn theo yêu cầu.  Chứa các package được gọi để lưu các hành động cụ thể khi đang chạy ứng dụng.  Chứa các package cung cấp các thủ tục để xử lý lỗi, thông báo theo các mức…  Các package trong APPCORE thường có tên bắt đầu bằng “APP”.



Thư viện APPDAYPK : chứa các package xử lý tính năng Oracle Applications Calendar.



Thư viện FNDSQF :  Chứa các thủ tục và package cho Message Dictionary, flexfield, profile, xử lý đồng thời (concurrent processing).  Cung cấp các tiện ích cho navigation, multicurrency, WHO  Các package trong FNDSQF thường có tên bắt đầu bằng “FND”.



Thư viện CUSTOM :  Thư viện CUSTOM cho phép mở rộng các form của Oracle Applications mà không phải thay đổi code trong Oracle Applications. Bạn có thể sử dụng thư viện CUSTOM để customize, áp đặt các quy tắc (chẳng hạn tên hãng phải viết hoa), hoặc disable những trường không cần.  Bạn viết code trong thư viện CUSTOM, bên trong những procedure shell được cung cấp. Oracle Applications gửi các sự kiện tới thư viện CUSTOME. Những đoạn code bạn viết có hiệu lực dựa vào những sự kiện này.



Thư viện GLOBE : cho phép người phát triển Oracle Applications tập hợp các tính năng chung hoặc riêng vào trong form Oracle Applications mà không phải thay đổi form Oracle Applications gốc. Oracle Applications gửi các sự kiện tới thư viện GLOBE. Các đoạn code bên trong có hiệu lực dựa vào các sự kiện này. Thư viện GLOBE gọi đến các routine trong các thư viện JA, JE và JL.



Thư viện JA : chứa code đặc trưng cho khu vực Asia/Pacific và được gọi bởi thư viện GLOBE.



Thư viện JE : chứa code đặc trưng cho khu vực EMEA (Europe/Middle East/Africa) và được gọi bởi thư viện GLOBE.



Thư viện JL : chứa code đặc trưng cho khu vực Latin America và được gọi bởi thư viện GLOBE.

41

Các trigger trong form TEMPLATE 

Form TEMPLATE chứa một số trigger mức form. Các trigger này cần phải có để các routine khác hoạt động đúng. Text trong trigger thường được giữ nguyên, người sử dụng sẽ thêm các đoạn text của mình vào trước hoặc sau chúng.



Các trigger chuẩn : KEY–CLRFRM KEY–COMMIT KEY–DUPREC KEY–EDIT KEY–EXIT KEY–HELP KEY–LISTVAL KEY–MENU ON–ERROR POST–FORM PRE–FORM WHEN–FORM–NAVIGATE WHEN–NEW–BLOCK–INSTANCE WHEN–NEW–FORM–INSTANCE WHEN–NEW–ITEM–INSTANCE WHEN–NEW–RECORD–INSTANCE WHEN–WINDOW–CLOSED WHEN–WINDOW–RESIZED



Các trigger do người dùng định nghĩa : ACCEPT CLOSE_THIS_WINDOW CLOSE_WINDOW EXPORT FOLDER_ACTION FOLDER_RETURN_ACTION LASTRECORD MENU_TO_APPCORE QUERY_FIND STANDARD_ATTACHMENTS

42

ZOOM 

Các trigger thường phải chỉnh sửa : 

ACCEPT APP_STANDARD.EVENT(‟ACCEPT‟); Trigger này xử lý chức năng ”Action, Save and Proceed” trên menu hoặc toolbar. Nó lưu những thay đổi và chuyển tới bản ghi tiếp theo của block được xác định là First Navigation Block. Thay thế code trong trigger này, hoặc tạo trigger mức block với kiểu xử lý là „Override‟

 FOLDER_RETURN_ACTION null; Trigger này cho phép customize các folder event xác định. Thay thế text bởi code cần thiết để xử lý các hành động cho folder.

 KEY–DUPREC APP_STANDARD.EVENT(‟KEY–DUPREC‟); Trigger này disable tính năng nhân đôi bản ghi mặc định của Oracle Forms. Để xử lý tính năng ”Edit, Duplicate Record Above” trên menu được đúng, tạo 1 trigger KEY–DUPREC mức block với kiểu xử lý „Override‟. Viết code cho trigger này để nó thực hiện việc nhân đôi bản ghi, sau đó validate hoặc xoá các trường cần thiết.

 KEY–CLRFRM APP_STANDARD.EVENT(‟KEY–CLRFRM‟); Trigger này validate bản ghi trước khi thử xoá form. Thêm code cần thiết bên dưới code có sẵn. Thường thì bạn sẽ thêm các lời gọi GO_BLOCK nếu có các alternative region trong form của bạn, và cung cấp lại các giá trị cho region control poplist của bạn sau hành động Clear Form.  KEY–MENU

43

APP_STANDARD.EVENT(‟KEY–MENU‟); Trigger này disable lệnh Block Menu của Oracle Forms. Để enable hoạt động của Alternative Region bằng bàn phím từ 1 block cụ thể, tạo trigger KEY–MENU mức block với kiểu xử lý là „Override‟. Trigger này nên mở ra 1 LOV với các sự lựa chọn giống như Alternative Region control poplist.

 KEY–LISTVAL APP_STANDARD.EVENT(‟KEY–LISTVAL‟); Trigger này thực hiện các hoạt động của flexfield hoặc gọi LOV. Tạo trigger mức block hoặc item với kiểu xử lý „Override‟ trên các trường sử dụng đối tượng Calendar, hoặc các trường gọi flexfield khi chương trình đang chạy.  ON–ERROR APP_STANDARD.EVENT(‟ON–ERROR‟); Trigger này xử lý tất cả các lỗi, từ server hoặc từ client, sử dụng các lời gọi của Message Dictionary. Để bẫy các lỗi cụ thể, kiểm tra các lỗi cụ thể bạn mắc trước khi gọi APP_STANDARD declare original_mess varchar2(80); begin IF MESSAGE_CODE = THEN original_mess := MESSAGE_TYPE||‟–‟|| to_char(MESSAGE_CODE)||‟: ‟||MESSAGE_TEXT; ––– your code handling the error goes here message(original_mess); ELSE APP_STANDARD.EVENT(‟ON_ERROR‟); END IF end;  POST–FORM APP_STANDARD.EVENT(‟POST–FORM‟); Trigger này được dành cho những sử dụng trong tương lai.

44

Thêm code cần thiết vào trước code có sẵn.

 PRE–FORM FND_STANDARD.FORM_INFO(‟$Revision: $‟, ‟‟, ‟<Application Shortname>‟, ‟$Date: $‟, ‟$Author: <developer name> $‟); APP_STANDARD.EVENT(‟PRE–FORM‟); APP_WINDOW.SET_WINDOW_POSITION(‟BLOCKNAME‟, ‟FIRST_WINDOW‟); Trigger này khởi tạo các giá trị bên trong Oracle Applications và menu. Các giá trị bạn nhập vào sẽ được nhìn thấy khi chọn ”Help, About Oracle Applications” từ menu của Oracle Applications. Bạn phải sửa lại short name của Application. Application Shortname điều khiển file trợ giúp online nào của Application được truy cập khi người dùng chọn nút Help trên toolbar. Form name là tên form của người dùng. Nó chỉ có mục đích để bạn tham khảo, và không được sử dụng ở chỗ nào khác nữa. Oracle sử dụng 1 hệ thống điều khiển mã nguồn cho phép tự động cập nhật các giá trị bắt đầu với “$”. Bạn cũng phải sửa lời gọi APP_WINDOW để đưa tên block của bạn vào.

 QUERY_FIND APP_STANDARD.EVENT(‟QUERY_FIND‟); Trigger này đưa ra 1 thông báo mặc định cho biết Query Find không được dùng. Sửa code trong trigger này, hoặc tạo trigger mức block với kiểu xử lý „Override‟ khi bạn tạo 1 Find Window hoặc 1 Row-LOV trong form của bạn  WHEN–NEW–FORM–INSTANCE

45

FDRCSID(‟$Header: ... $‟); APP_STANDARD.EVENT(‟WHEN–NEW–FORM– INSTANCE‟); –– app_folder.define_folder_block(‟template test‟, ‟folder_block‟, ‟prompt_block‟, ‟stacked_canvas‟, ‟window‟, ‟disabled functions‟); –– app_folder.event(‟VERIFY‟); Lời gọi APP_STANDARD.EVENT trong trigger này hỗ trợ chế độ query-only được gọi bởi FND_FUNCTION.EXECUTE. Lời gọi FDRCSID hỗ trợ hệ thống điều khiển mã nguồn của Oracle Applications. Các lời gọi APP_FOLDER chỉ cho các sử dụng bên trong của Oracle Applications. Các custom form không cần đến FDRCSID hay APP_FOLDER, nhưng giữ lại chúng trong trigger cũng không ảnh hưởng gì. Thêm những code cần thiết trước code đã có.  WHEN–NEW–RECORD–INSTANCE APP_STANDARD.EVENT(‟WHEN–NEW–RECORD– INSTANCE‟); Trigger này quản lý trạng thái của menu và toolbar của Oracle Applications Tạo trigger mức block nếu cần ( kiểu xử lý „Before‟ )  WHEN–NEW–BLOCK–INSTANCE APP_STANDARD.EVENT(‟WHEN–NEW–BLOCK– INSTANCE‟); Trigger này quản lý trạng thái của menu và toolbar của Oracle Applications Tạo trigger mức block nếu cần ( kiểu xử lý „Before‟ )  WHEN–NEW–ITEM–INSTANCE APP_STANDARD.EVENT(‟WHEN–NEW–ITEM–INSTANCE‟); Trigger này quản lý trạng thái của menu và toolbar của Oracle Applications Nếu thêm vào 1 lời gọi đến flexfields routine, thêm nó vào trước lời gọi APP_STANDARD.EVENT. Nói chung không nên thêm các code khác vào trong trigger này, vì sẽ tác động đến mọi item trong form. Nếu cần thì tạo 1 trigger mức block hoặc item với kiểu xử lý là „Before‟.

46



Các trigger không được chỉnh sửa  CLOSE_THIS_WINDOW Trigger này gọi APP_CUSTOM.CLOSE_WINDOW khi chọn “Action –> Close Window” trên menu.  CLOSE_WINDOW APP_CUSTOM.CLOSE_WINDOW(:SYSTEM.EVENT_WINDO W); Trigger này xử lý tất cả các sự kiện đóng window. Các code xử lý nằm trong package APP_CUSTOM.CLOSE_WINDOW

 EXPORT app_standard.event(‟EXPORT‟); Trigger này xử lý lời gọi ”Action, Export” từ menu  FOLDER_ACTION app_folder.event(:global.folder_action); Trigger này xử lý khi gọi các mục trên menu Folder.  KEY–COMMIT APP_STANDARD.EVENT(‟KEY–COMMIT‟); Trigger này xử lý các commit trong các form bình thường hoặc các form được gọi.  KEY–EDIT APP_STANDARD.EVENT(‟KEY–EDIT‟); Trigger này thực hiện các hoạt động của flexfield, hoặc gọi Calendar hay Editor.  KEY–EXIT APP_STANDARD.EVENT(‟KEY–EXIT‟); Trigger này xử lý các sự kiện Close và rời khỏi chế độ enter-query.  KEY–HELP APP_STANDARD.EVENT(‟KEY–HELP‟); Trigger này gọi hệ thống Window Help.  LASTRECORD APP_STANDARD.EVENT(‟LASTRECORD‟);

47

Trigger này xử lý sự kiện menu “Go–>Last Record”.

 MENU_TO_APPCORE APP_STANDARD.EVENT(:global.menu_to_appcore); Trigger này hỗ trợ menu Special

 STANDARD_ATTACHMENTS atchmt_api.invoke; Trigger này xử lý lời gọi của mục menu Attachments hoặc của nút Attachments trên toolbar.

 WHEN–WINDOW–CLOSED execute_trigger(‟CLOSE_WINDOW‟); Trigger này tập trung các sự kiện đóng window từ Oracle Applications hoặc menu Window Manager.

 WHEN–FORM–NAVIGATE Bạn không thể sửa trigger này. Nó enable các hành động tiêu chuẩn chính, như normalize 1 form đang được minimize khi form này được navigate. Để sử dụng sự kiện form này, gán cho biến global có tên là GLOBAL.WHEN_FORM_NAVIGATE giá trị là tên của 1 trigger do người dùng định nghĩa. Thường thì việc gán này được thực hiện ngay trước khi gọi GO_FORM.

 ZOOM appcore_custom.event(‟ZOOM‟); Trigger này xử lý lời gọi của mục menu ”Action, Zoom” hoặc của nút trên toolbar.

48

Thiết lập các thuộc tính của các đối tượng chứa(ContainerObject) Các đối tượng chứa : 

module



window ( modal và non-modal )



canvas ( content và stacked )



block



region



Lớp thuộc tính : form TEMPLATE tự động áp dụng lớp thuộc tính MODULE cho

Module : module. Các thiết lập cho lớp này biến đổi tùy theo nền GUI. 

Tên module : tên module phải giống tên form. VD : tên module là GL01 thì tên form là GL01.fmb



Thuộc tính First Navigation Data Block : đặt cho thuộc tính này tên của block đầu tiên mà người sử dụng tiếp xúc khi form chạy. ( không đặt theo tên của block WORLD hay block CONTROL ). Thuộc tính này cũng quy định điểm đến của con trỏ sau CLEAR_FORM hoặc sau hành động “Action -> Save and Proceed “ mặc định.

Window : 

Window sẽ tự động kế thừa các chuẩn giao diện của nền GUI mà chúng đang chạy trên đó từ form APPSTAND ( như các tính năng của frame, các font trên title bar, các nút quản lý window ).

49



ROOT_WINDOW là một window đặc biệt, không được sử dụng vì sẽ làm ảnh hưởng đến toolbar và các đối tượng chuẩn khác của Oracle Application.



Non-modal Window : cho phép người sử dụng tương tác với các window khác, với thanh công cụ hay menu. Non-modal Window được dùng để thể hiện hầu hết các thành phần trong ứng dụng.  . Lớp thuộc tính : mọi non-modal window đều áp dụng lớp thuộc tính WINDOW.  . Thuộc tính Primary Canvas : nhập vào tên content canvas gắn với window này.  . Xác định tọa độ ( X,Y ) : lập trình định vị tọa độ window trong thủ tục APP_CUSTOM.OPEN_WINDOW.  . Tiêu đề ( Title ) : có thể thiết lập để thay đổi tùy theo nội dung window hiển thị.  . Kích thước : kích thước tối đa của window là 7.8 x 5 ( rộng x cao ) inches.  . Đóng window : Bạn phải lập trình để thực hiện hành động đóng window. Đóng window đầu tiên của một form sẽ đóng lại toàn bộ form và các hành động khác. Lập trình hành động đóng này trong thủ tục APP_CUSTOM.CLOSE_WINDOW.  . Mở window : nếu bạn có đoạn mã nào muốn được thực hiện khi mở window, đặt nó trong thủ tục APP_CUSTOM.OPEN_WINDOW. Bạn phải thêm đoạn mã để điều khiển tọa độ block và định vị window. Khi chuyển đến một khối nào đấy ( bằng GO_BLOCK ), window chứa block đó sẽ tự động mở ra.  . Nếu muốn tắt ( disable ) chức năng nào đó của menu, sử dụng APP_SPECIAL.



Modal Window : buộc người sử dụng chỉ thao tác trong cửa sổ đó (không thể tương tác được với các cửa sổ khác), sau khi chấp nhận hoặc huỷ bỏ những thay đổi đã thực hiện mới thoát được ra khỏi cửa sổ.  . Lớp thuộc tính : sử dụng lớp thuộc tính WINDOW_DIALOG để tạo một modal window.  . Thuộc tính Primary Canvas : nhập vào tên content canvas gắn với window này.  . Vị trí window : modal window khi mở luôn ở chính giữa màn hình

50

 . Đóng window : modal window có thể đóng bằng cơ chế đóng cửa sổ GUI ( kích chuột vào ô có dấu X góc trên bên phải ) hoặc đóng bằng lập trình.

Canvas : 

Content Canvas :  . Lớp thuộc tính : CANVAS  . Kích thước : nên đặt kích thước canvas bằng với kích thước window chứa nó.



Stacked Canvas :  . Lớp thuộc tính : CANVAS_STACKED  . Thuộc tính Raise on Entry luôn đặt là Yes

Block : 

Lớp thuộc tính : BLOCK ( với những block trên non-modal window ), BLOCK_DIALOG ( với những block trên modal window ).



Nếu block dựa trên một bảng hoặc một view đơn ( view trên một bảng ), đặt thuộc tính Key-Mode là Unique. Nếu block dựa trên view liên kết ( view trên nhiều bảng ), đặt Update Allowed là No. Phải có ít nhất một item trong block được đánh dấu là primary key ( đặt thuộc tính Primary Key của nó là Yes ).



Đặt thuộc tính Delete Allowed là No để không cho xoá trong block.



Next and Previous Navigation Data Block : đặt các thuộc tính này của khối bằng tên các khối có thứ tự duyệt sau ( next ) và trước ( previous ) khối đó. Với khối đầu tiên, previous là chính nó, với khối sau cùng, next là chính nó.



Context Block : được thể hiện trong các detail window, cung cấp ngữ cảnh và sao chép các trường được thể hiện trong master window. Để tạo 1 context block, tạo các display item trong cùng block giống như master block và đồng bộ trường context theo trường master.



Dialog Block : được thể hiện trong modal window, đòi hỏi user phải tương tác với chúng trước khi chuyển qua cửa sổ khác.

51



Xử lý các KEY – trigger : mặc dù trong modal window không thể tương tác với menu và toolbar, ta vẫn có thể gọi một số tính năng bằng nhấn một số phím chức năng trên bàn phím. Để tránh điều này, ta disable các Key – trigger cho block bằng cách lập trình một KEY-OTHERS trigger gọi APP_EXCEPTION.DISABLED để tắt mọi chức năng. Sau đó, ta có thể cho phép một vài chức năng có thể được thực hiện bằng việc lập trình lại một số KEY – trigger, như :

( Với block cho phép nhiều bản ghi )

 . Ta cũng có thể để enable cho các KEY - trigger của block, và chỉ disable một số bằng cách gọi APP_EXCEPTION.DISABLED trong những KEY – trigger nào ta muốn disable.  . Navigation ( điều hướng ): ngăn cản việc chuyển focus ra bên ngoài modal window bằng cách : không được đặt Navigation Style là Change Data Block, next và previous của block đặt là chính block đó.

52



Data Block không có bảng cơ sở ( base table ) : sử dụng các trigger giao dịch ( ON-INSERT, ON-LOCK …) nếu các block này phải xử lý commit.



Data Block một bản ghi : cho phép user xem được các bản ghi của một thực thể, nhưng tại mỗi thời điểm chỉ nhìn thấy một bản ghi.



Data Block nhiều bản ghi : cho phép user xem được các bản ghi của một thực thể, nhưng tại mỗi thời điểm có thể thấy nhiều bản ghi.  . Tạo Current Record Indicator : tạo một text item trong block không có detail block ứng với nó. Thiết lập lớp thuộc tính cho nó là CURRENT_RECORD_INDICATOR và tạo trigger WHEN-NEWITEM-INSTANCE

cho

nó,

trong

trigger

đó

gọi

GO_ITEM(tên_block.tên_field). Mỗi lần indicator này được click thì con trỏ sẽ chuyển đến trường đầu tiên của bản ghi tương ứng.  . Tạo Drill-down Indicator : tương tự như Current Record Indicator nhưng là cho block có một hoặc nhiều detail block ứng với nó.



Combination Block : một kiểu định dạng các trường lai giữa kiểu định dạng đơn bản ghi và đa bản ghi, trong đó mỗi kiểu định dạng tồn tại trên window riêng của chúng, nhưng tất cả các trường của cả 2 kiểu định dạng nằm trong cùng một block.



Quan hệ Master – Detail :  . Đặt thuộc tính Coordination là Prevent Masterless Operation để các bản ghi chi tiết luôn luôn tương ứng với bản ghi chính của nó.  . Đặt thuộc tính Master Deletes là Non-Isolated nếu không cho phép xóa các bản ghi ở cả master table và detail table, Isolated nếu chỉ cho xoá ở bảng master, và Cascading nếu cho phép xoá ở cả 2 bảng. Tuy nhiên không nên sử dụng Cascading mà nên dùng Isolated để xóa ở bảng master, sau đó viết một thủ tục cho bảng master thực hiện lệnh xoá các bản ghi detail tương ứng.  . Nếu ( master ) block đầu tiên của form không tự động truy vấn, gọi do_key(„execute_query‟);

trong

trigger

WHEN-NEW-FORM-

INSTANCE.

53



Thiết lập thuộc tính WHERE Clause động : mỗi lần truy vấn đưa vào điều kiện lọc khác nhau.

Region : 

Region là 1 nhóm các trường ( field ). Hầu hết các region chỉ đơn thuần là sự trình bày thẩm mĩ, ví như một frame ( box ) bao lấy nhóm các trường liên quan, hoặc một frame ( line ) kẻ bên trên nhóm các trường có quan hệ với nhau. Khi con trỏ ở trong một region, nó sẽ duyệt theo thứ tự đi qua tất cả các item trong region đó trước khi chuyển qua các field khác ngoài region.  . Tabbed Region : xuất hiện trên tab canvas  . Alternative Region : xuất hiện trên stacked canvas  . Overflow Region

54

Thiết lập các thuộc tính của các đối tượng Widget Text Item : 

Các lớp đối tượng : 

TEXT_ITEM : thường dùng nhất



TEXT_ITEM_DISPLAY_ONLY : dùng cho các trường không cho phép người dùng nhập vào



TEXT_ITEM_MULTILINE



TEXT_ITEM_DATE : dùng cho các trường date



Thuộc tính Query Length : thiết lập độ dài cho xâu truy vấn.



WHEN-VALIDATE-ITEM : trigger này kích hoạt khi giá trị của trường có sự thay đổi.



Các trường date : Các trường date người dùng nhập vào nên sử dụng Calendar. 

Kiểu dữ liệu : DATE ( user không cần nhập giờ phút ) , DATETIME ( user phải nhập cả ngày và giờ phút ), TIME ( user chỉ được nhập giờ ). Đặt giá trị mặc định cho trường bằng ngày hiện tại mà không tính đến giờ bằng $$DBDATE$$, đặt giá trị bằng cả ngày và giờ hiện tại bằng $$DBDATETIME$$, đặt giá trị bằng giờ hiện tại mà bỏ qua ngày bằng $$DBTIME$$.



Độ dài trường : 11 kí tự ( chỉ nhập ngày ) và 20 kí tự ( nhập cả ngày và giờ ). Oracle Forms mặc định kiểu định dạng ( format ) của trường dựa

55

theo biến môi trường NLS_DATE_FORMAT. 

Validation trường date : nên validate trường date ở mức bản ghi thay vì mức item, nó sẽ giúp việc sửa lỗi dễ hơn.

Display Item : Không cho phép người sử dụng tương tác với nó, chỉ đơn thuần hiển thị dữ liệu và không nhận focus. Lớp thuộc tính : DYNAMIC_TITLE, DYNAMIC_PROMPT, DISPLAY_ITEM

Poplist : lưu dữ liệu dưới dạng danh sách ( kích cỡ nhỏ ) các giá trị có thể. 

Lớp thuộc tính : LIST



Giới hạn : độ rộng của một phần tử list tối đa là 30 kí tự.



Có thể tha đổi nội dung phần tử trong list khi chạy

Option Group : Lớp thuộc tính : RADIO_GROUP ( cho nhóm ) và RADIO_BUTTON ( cho các đối tượng trong nhóm )

Check Box : Lớp thuộc tính : CHECKBOX ( thông dụng ), CHECKBOX_COORDINATION ( cho check box tọa độ ).

Button ( Nút ) : 

Nút có thể là nút chữ, hoặc nút hình. Nút nên được đặt cùng block với các đối tượng mà nó tương tác.



Lớp thuộc tính : BUTTON ( nút chữ ) , BUTTON_ICONIC ( nút hình )



Nút hình không thể kích hoạt từ bàn phím.



Hầu hết các nút không thể kích hoạt trong chế độ Enter-Query



Các nút nên gọi APP_STANDARD.APP_VALIDATE và truyền một scope ( vùng validate ) trước khi thực hiện hành động của chúng. Điều này đảm bảo các bản ghi được kiểm tra tính hợp lệ trước khi hành động được thực hiện, và nút thực hiện hành động trên block mà nó mong muốn.

56

List of Values ( LOV ) 

Lớp thuộc tính : LOV



Nên tạo LOV theo view.



Đặt title cho LOV theo tên đối tượng mà nó chứa. Độ rộng cột phải đủ để thể hiện giá trị trường.



Nếu một item có LOV, có thể đặt thuộc tính Validate from List của nó là Yes để chỉ chấp nhận những giá trị nhập vào có trong LOV.



Để LOV luôn tự cập nhật những giá trị mới mỗi khi được gọi, đặt Automatic Refresh là Yes. Nếu LOV có nhiều bản ghi, đặt Filter Before Display là Yes để nhắc user giới hạn phạm vi tìm kiếm mỗi lần gọi LOV.



Để gọi được LOV trong chế độ Enter-Query, tạo 1 trigger KEY-LISTVAL trên đối tượng gọi LOV:

Trong chế độ Enter-Query, giá trị trả về của LOV phải được trả về trường mà từ đó LOV được gọi

Thiết lập các thuộc tính cho item : 

Sử dụng APP_ITEM_PROPERTY.SET_PROPERTY : dùng để thiết lập các thuộc tính : ALTERABLE, ALTERABLE_PLUS, ENTERABLE, DISPLAYED, ENABLED,

REQUIRED.

Các

thuộc

tính

khác

dùng

thủ

tục

gốc

SET_ITEM_PROPERTY của Oracle Form.  Thuộc tính ALTERABLE cho phép ( hoặc không cho phép ) thay đổi một instance ( hàng ) của item mặc cho bản ghi là mới hoặc là bản ghi truy vấn từ CSDL. . Thủ tục : app_item_property.set_property ( itemid, ALTERABLE, PROPERTY_ON); tương đương với set_item_instance_property(itemid,

CURRENT_RECORD,

INSERT_ALLOWED, PROPERTY_ON); set_item_instance_property(itemid, CURRENT_RECORD, UPDATEABLE, PROPERTY_ON); set_item_property(itemid, INSERT_ALLOWED, PROPERTY_ON); set_item_property(itemid, UPDATEABLE, PROPERTY_ON);

57

. Thủ tục : app_item_property.set_property(itemid, ALTERABLE,PROPERTY_OFF); tương đương với set_item_instance_property(itemid,

CURRENT_RECORD,

INSERT_ALLOWED, PROPERTY_OFF); set_item_instance_property(itemid, CURRENT_RECORD, UPDATEABLE, PROPERTY_OFF);



Thuộc tính ALTERABLE_PLUS cho phép hoặc không cho phép thay đổi tất cả các instance ( hàng ) của item, mặc cho bản ghi là mới hoặc được truy vấn từ cơ sở dữ liệu. . Thủ tục : app_item_property.set_property(itemid,

ALTERABLE_PLUS,

PROPERTY_ON); tương đương với : set_item_property(itemid, INSERT_ALLOWED, PROPERTY_ON); set_item_property(itemid, UPDATEABLE, PROPERTY_ON); . Thủ tục : app_item_property.set_property(itemid,

ALTERABLE_PLUS,

PROPERTY_OFF); tương đương với : set_item_property(itemid, INSERT_ALLOWED, PROPERTY_OFF); set_item_property(itemid, UPDATEABLE, PROPERTY_OFF);



Thuộc tính ENTERABLE dùng để enable hoặc disable một instance của item, là sự mở rộng của ALTERABLE bằng việc điều khiển thêm thuộc tính NAVIGALBE. . Thủ tục : app_item_property.set_property(itemid,ENTERABLE, PROPERTY_ON); tương đương với : set_item_instance_property(itemid,CURRENT_RECORD, INSERT_ALLOWED, PROPERTY_ON); set_item_instance_property(itemid,CURRENT_RECORD, UPDATEABLE, PROPERTY_ON);

58

set_item_instance_property(itemid,CURRENT_RECORD, NAVIGABLE, PROPERTY_ON); set_item_property(itemid, INSERT_ALLOWED, PROPERTY_ON); set_item_property(itemid, UPDATEABLE, PROPERTY_ON); set_item_property(itemid, NAVIGABLE, PROPERTY_ON); ( đặt giá trị cho cả item và item-instance để tạo hiệu quả đồng nhất ) . Thủ tục : app_item_property.set_property(itemid,ENTERABLE, PROPERTY_OFF); tương đương với : set_item_instance_property(itemid,CURRENT_RECORD, INSERT_ALLOWED, PROPERTY_OFF); set_item_instance_property(itemid,CURRENT_RECORD, UPDATEABLE, PROPERTY_OFF); set_item_instance_property(itemid,CURRENT_RECORD, NAVIGABLE, PROPERTY_Off);



Thuộc tính DISPLAY điều khiển việc ẩn, hiện item cũng như reset lại các thuộc tính cụ thể mà Oracle Form tự động thiết lập khi ẩn một item nào đó. . Thủ tục sau : app_item_property.set_property(itemid,

DISPLAYED,

PROPERTY_ON); tương đương với : set_item_property(itemid, DISPLAYED, PROPERTY_ON); nếu item không phải là display item thì thiết lập thêm : set_item_property(itemid, ENABLED, PROPERTY_ON); set_item_property(itemid, NAVIGABLE, PROPERTY_ON); nếu item không phải là display item hay nút, thiết lập thêm : set_item_property(itemid, QUERYABLE, PROPERTY_ON); set_item_property(itemid, INSERT_ALLOWED, PROPERTY_ON); set_item_property(itemid, UPDATEABLE, PROPERTY_ON); . Thủ tục sau : app_item_property.set_property(itemid,

DISPLAYED,

PROPERTY_OFF);

59

tương đương với set_item_property(itemid, DISPLAYED, PROPERTY_OFF);

 Thuộc tính ENABLE dùng để enable hay disable một item nào đó, xử lý với APP_ITEM_PROPERTY.SET_PROPERTY khác với xử lý gốc ( native behavior ) của Oracle Forms ở chỗ khi re-enable thì sẽ reset lại các thuộc tính liên quan đã được Oracle Forms đặt tự động khi disable. .

Thủ

tục

:

app_item_property.set_property(itemid,

ENABLED,PROPERTY_ON); tương đương với ( nếu item là text hoặc list ) : set_item_property(itemid, INSERT_ALLOWED, PROPERTY_ON); set_item_property(itemid, UPDATEABLE, PROPERTY_ON); set_item_property(itemid, NAVIGABLE, PROPERTY_ON); tương đương với ( nếu item là button ) : set_item_property(itemid, ENABLED, PROPERTY_ON);



Thuộc tính REQUIRED quyết đinh một item có bắt buộc phải được nhập dữ liệu hay không, là một thuộc tính ở item-level, tức là tác động lên tất cả các instance của item. Nếu chỉ muốn tác động lên một instance cụ thể nào đó của item, ta có thể dùng thủ tục dựng sẵn của Oracle Forms là : SET_ITEM_INSTANCE_PROPERTY. . app_item_property.set_property(itemid, REQUIRED, PROPERTY_ON); . app_item_property.set_property(itemid, REQUIRED, PROPERTY_OFF);

Một số lưu ý : 

Gọi APP_ITEM_PROPERTY.SET_PROPERTY tương đương với một tập các xử lý thuộc tính có liên quan với nhau nếu thiết lập từng bước.



Một số thuộc tính như ALTERABLE hay ENTERABLE chỉ có thể thiết lập khi chạy ( runtime ) vì nó tác động lên từng instance.



Hầu hết các Visual Attribute được triển khai tự động bởi các APPCORE routine, trừ một số visual attribute sau ( mà người phát triển phải tự lập trình để thực hiện ) : DATA_DRILLDOWN, DATA_SPECIAL, DATA_REQUIRED

60

Điều khiển hoạt động của Window, Block, và Region

Điều khiển hoạt động của Window 

Định vị window khi nó được mở :



CASCADE : cửa sổ con chồng lên cửa sổ chính, lệch chéo xuống 0.3‟‟. Thường dùng cho các cửa sổ detail.



RIGHT, BELOW : cửa sổ con mở bên phải, hoặc bên dưới cửa sổ chính, không che cửa sổ chính.



OVERLAP : cửa sổ detail chồng lên cửa sổ chính, lệch xuống dưới 0.3‟‟.



CENTER : cửa sổ mở chính giữa cửa sổ khác, thường dùng cho modal window.



FIRST_WINDOW : định vị cửa sổ ngay dưới toolbar, thường dùng cho cửa sổ chính.

61



Đóng Window : 

Các sự kiện đóng non-modal window ( không phải là modal window ) đều chuyển tới APP_CUSTOME.CLOSE_WINDOW. Code mặc định được viết trong form TEMPLATE thực hiện những việc sau : . Nếu form đang ở chế độ Enter-Query, APP_CUSTOM sẽ gọi : APP_EXCEPTION.DISABLED. . Trường hợp ngược lại, nếu con trỏ đang ở trong window chuẩn bị đóng, APP_CUSTOM thực hiện do_key(„PREVIOUS_BLOCK‟) để đưa con trỏ thoát khỏi window hiện tại. .

Cuối

cùng,

APP_CUSTOM

ẩn

window

bằng

HIDE_WINDOW(„‟) 

Nếu con trỏ vẫn nằm trong window, window sẽ tự động mở lại sau khi được đóng. Để đóng window đầu tiên ( tức là đóng form ), gọi APP_WINDOW.CLOSE_FIRST_WINDOW

Example : In a form with windows ”Header,” ”Lines,” and ”Shipments,” where Lines is a detail of Header, and Shipments is a detail of Lines, the logic to close the windows is as follows:

PROCEDURE close_window (wnd VARCHAR2) IS IF wnd = ‟HEADER‟ THEN –– –– Exit the form –– app_window.close_first_window; ELSIF wnd = ‟LINES‟ THEN –– –– Close detail windows (Shipments) –– app_custom.close_window(‟SHIPMENTS‟); –– –– If cursor is in this window, –– move it to the HEADER block

62

–– IF (wnd = GET_VIEW_PROPERTY(GET_ITEM_PROPERT Y( :SYSTEM.CURSOR_ITEM,ITEM_CANVAS), WINDOW_NAME)) THEN GO_BLOCK(‟HEADER‟); END IF; ELSIF wnd = ‟SHIPMENTS‟ THEN –– –– If cursor is in this window, –– move it to the LINES block –– IF (wnd = GET_VIEW_PROPERTY(GET_ITEM_PROPERT Y( :SYSTEM.CURSOR_ITEM, ITEM_CANVAS), WINDOW_NAME)) THEN GO_BLOCK(‟LINES‟); END IF; END IF; –– –– THIS CODE MUST REMAIN HERE. It ensures –– the cursor is not in the window that will –– be closed by moving it to the previous block. –– IF (wnd = GET_VIEW_PROPERTY(GET_ITEM_PROPERT Y( :SYSTEM.CURSOR_ITEM, ITEM_CANVAS), WINDOW_NAME)) THEN

63

DO_KEY(‟PREVIOUS_BLOCK‟); END IF; –– –– Now actually close the designated window –– HIDE_WINDOW(wnd); END close_window; 

Thiết lập title động cho window :



Nếu

muốn

thay

đổi

base

title

của

SET_WINDOW_PROPERTY(…TITLE…).

một

window,

Bất



lời

gọi

: gọi

APP_WINDOW.SET_TITLE nào trong tương lai sẽ bảo toàn base title mới đó. 

Điều khiển hoạt động của Block 

Lập trình cho các quan hệ Master-Detail : Khi detail block và master block nằm trong 2 cửa sổ khác nhau (đều là non-modal window), detail block phải cung cấp một cơ cấu cho phép user chuyển đổi giữa coordination tức thì và coordination trì hoãn. Khi detail block là visible, chọn coordination tức thì sẽ cho phép các detail record thay đổi khi master record thay đổi. Còn khi detail block là không visible, nên chọn coordination



trì

hoãn.

Sử

dụng

thủ

tục

APP_WINDOW.SET_COORDINATION để coordinate các block. Ví dụ : trong ví dụ sử dụng các đối tượng sau : • Master block ORDERS, trong window ORDERS • Detail Block LINES, trong window LINES • Relation : ORDERS_LINES

64

• Coordination check box : CONTROL.ORDERS_LINES • Nút để navigate tới LINES block : CONTROL.LINES + Bước 1 : tạo 1 nút để navigate tới detail block + Bước 2 : tạo 1 coordination check box ( đặt trong control block ) trong cửa sổ detail cho phép người dùng chọn coordination tức thì hoặc coordination trì hoãn khi cửa sổ được mở. + Bước 3 : tạo 1 thủ tục xử lý item như sau :

PACKAGE BODY control IS PROCEDURE lines(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–BUTTON– PRESSED‟) THEN app_custom.open_window(‟LINES‟); END IF; END lines; PROCEDURE orders_lines(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–CHECKBOX– CHANGED‟) THEN APP_WINDOW.SET_COORDINATION(E VENT, :control.orders_lines, ‟ORDERS_LINES‟); END IF; END orders_lines; END control; 

Bước 4 : sửa package APP_CUSTOM như sau :

65



Bước 5 : Gọi các thủ tục xử lý sự kiện và trường đã viết ở trên trong các trigger :



Triển khai một Combination Block : Mỗi item trong 1 block có thuộc tính Number of Items Display của riêng nó, nên bạn có thể tạo một single block chứa vài item là các single-record ( detail ) và vài item khác là multi-record ( Summary ). Khi triển khai một combination block, hầu hết các item xuất hiện 2 lần, nên coordination của các giá trị trong các item này phải được quản lý. Thuộc tính Synchronize with Item tự động thực hiện điều này. Bạn điều khiển việc navigate tới các phần của block trong các tình huống khác nhau bằng cách sử dụng một trường gọi là Switcher, là trường được navigate đầu tiên trong block. Khi con trỏ chuyển tới Switcher, nó ngay lập tức sẽ được chuyển đến item đầu tiên trong phần Detail hoặc phần Summary của block. Các bước triển khai : 

Bước 1 : Thiết lập Combination Block

Tạo 2 cửa sổ và các canvas để chứa các phần khác nhau của block của bạn. Với phần Summary, sử dụng các non-mirror item. Nhân đôi các item này để tạo phần Detail. Phần Detail của Combination Block nên có thứ tự đầu tiên.

66

Như thế khi user không điền vào 1 required item và thử commit block, Oracle Forms sẽ đặt con trỏ vào item đó trong block Detail. 

Bước 2 : Thiết lập các thuộc tính cho item

. Với các đối tượng ảnh (là bản sao của đối tượng gốc), đổi tên chúng để phán ánh mối quan hệ với đối tượng gốc (ví dụ đối tượng gốc tên là status thì đối tượng ảnh tên là status_mir). Thiết lập thuộc tính Synchronize with Item property và đảm bảo là thuộc tính Database Item được đặt là Yes nếu các đối tượng được đồng bộ ứng với các cột của bảng cơ sở. . Thiết lập thuộc tính Number of Records Displayed ở mức block cho phần Summary. Các item trong block sẽ cùng nhận giá trị này, nếu như không đặt lại thuộc tính đó của chúng. Đặt lại thuộc tính Number of Records Displayed bằng 1 cho các đối tượng trong phần Detail. . Để ngăn người dùng chuyển tab ra khỏi Detail và vào trong Summary, thiết lập thuộc tính Previous Navigation Item cho đối tượng Detail đầu tiên và thuộc tính Next Navigation Item cho đối tượng Detail cuối cùng. . Để chuyển tab đồng thời với chuyển bản ghi trong 1 block nhiều bản ghi, gọi APP_COMBO.KEY_PREV_ITEM trong trigger KEY–PREV–ITEM của đối tượng đầu tiên trong Summary và gọi next_record trong trigger KEY–NEXT– ITEM của đối tượng cuối cùng của phần Summary. . Nếu chuyển đổi 1 block đã có thành combination block, phải thay đổi các tham chiếu trong các trigger đã có, vì bây giờ mỗi trường đều tồn tại 2 phiên bản. 

Bước 3 : Drilldown Record Indicator

Thêm 1 Drilldown Record Indicator thực hiện lệnh : execute_trigger(‟SUMMARY_DETAIL‟);  Bước 4 : Tham số Record Count . Tạo 1 tham số để lưu số bản ghi của phần block (Summary hay Detail) mà bạn đang ở trong. Đặt tên tham số là _RECORD_COUNT, trong đó là tên của combination block. Chuẩn đặt tên này có liên quan đến code trong APPCORE. Kiểu dữ liệu của tham số là number, và giá trị mặc định là 2 (để con trỏ ban đầu đặt trong Summary) hoặc 1 (để con trỏ ban đầu đặt trong Detail). . Tạo trigger mức block WHEN–NEW–ITEM–INSTANCE (Execution Hierarchy: Before) chứa code :

:PARAMETER._RECORD_COUNT :=

67

GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM, RECORDS_DISPLAYED);  Bước 5 : Switcher Tạo 1 text item và gán cho nó lớp thuộc tính SWITCHER. Nó là item được navigate đầu tiên trong block. Đặt nó vào trong toolbar canvas. Tạo 1 trigger WHEN–NEW–ITEM–INSTANCE mức item cho nó (Execution Hierarchy : Override) chứa code :

IF(:PARAMETER._RECORD_COUNT > 1) THEN GO_ITEM(‟‟); ELSE APP_WINDOW.SET_WINDOW_POSITION(‟‟, ‟OVERLAP‟, ‟<Summary window>‟); GO_ITEM(‟‟); END IF;  Bước 6 : Summary/Detail Menu Item . Tạo 1 trigger SUMMARY_DETAIL mức block (Execution Hierarchy: Override) chứa code :

IF GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM, RECORDS_DISPLAYED) > 1 THEN :PARAMETER._RECORD_COUNT := 1; ELSE :PARAMETER._RECORD_COUNT := 2; END IF; GO_ITEM(‟.Switcher‟); Đoạn code này thay đổi giá trị trong tham số _RECORD_COUNT để Switcher chuyển con trỏ tới phần còn lại trong block. Nó được thực thi khi người dùng chọn “Go -> Summary/Detail”. . Tạo 1 trigger mức block PRE–BLOCK (Execution Hierarchy: Override) chứa code :

68

APP_SPECIAL.ENABLE(‟SUMMARY_DETAIL‟, PROPERTY_ON); . Cuối cùng, tạo 1 trigger mức form PRE–BLOCK (Execution Hierarchy:Override) chứa code :

APP_SPECIAL.ENABLE(‟SUMMARY_DETAIL‟, PROPERTY_OFF); . Nếu tất cả các block đều là combination, bật SUMMARY_DETAIL ở mức form, bỏ qua trigger mức block. Nếu có nhiều block là combination, bật SUMMARY_DETAIL ở mức form, và tắt nó ở mức block với các block không phải combination.  Bước 7 : Định vị window và con trỏ khi mở form Nếu combination block của bạn là block đầu tiên trong form, định vị 2 cửa sổ của nó trong trigger PRE-FORM với những lời gọi sau : APP_WINDOW.SET_WINDOW_POSITION(’<Summary window>’, ’FIRST_WINDOW’); APP_WINDOW.SET_WINDOW_POSITION(’’, ’OVERLAP’, ’<Summary window>’);

Thường thì người dùng vào Summary trước, tuy nhiên nếu muốn vào Detail trước, thiết lập tham số _RECORD_COUNT bằng 1 trong trigger PRE-FORM.

Lập trình cho các Tabbed Regions 

Một số khái niệm : 

Tabbed Region : một nhóm các tab liên quan với nhau, còn gọi là tab canvas.



Tab Page : trang tab trong tabbed region, nơi thể hiện một nhóm các item liên quan.



Topmost tab page : trang tab trên cùng, hay trang tab đang được chọn và đang thể hiện.



Fixed Field : là trường hay item xuất hiện trên nhiều, hoặc trên tất cả, các tab page.



Alternative Region Field : là trường chỉ xuất hiện duy nhất trên môt tab page nào đó và không có mặt trên các tab page khác.

69



Control : là cách gọi khác cho field, item hay widget.

Hành động của tabbed region : Hành động mong muốn là mở ra một tab page và chuyển focus tới một trường thích hợp khi tab đó được click. Hành động này cần được lập trình vì hành động mặc định của Oracle Forms là mở tab và đặt focus trên chính đối tượng tab đó. 

Keyboard-only Operation : người dùng truy cập vào tab qua phím nóng trên keyboard.



Dynamic Tab Layouts : ẩn hay hiện một tab linh động tuỳ theo dữ liệu



Other Behavior : các tab nên vận hành được trong chế độ enter-query.

3 mức khó trong lập trình : 

Simple (đơn giản) : không cần scrollbar, không có fixed field. Mỗi tab sẽ tương ứng với 1 block riêng biệt trong form.



Medium (trung bình) : có scrollbar, nhưng không có fixed field. Mỗi tab sẽ có một thanh cuốn ngang để xem các trường và thanh cuốn dọc để xem tất cả các bản ghi. Mỗi tab sẽ tương ứng với một multi-row block riêng biệt.



Difficult ( khó ) : có fixed field ( và có hoặc không có scrollbar ) : một multi-row block có thể dàn trải trên nhiều tab page. Với fixed field, nên đặt các item vào trong stacked-canvas nằm bên trên tab page.



Các bước triển khai tabbed region : 

Bước 1 : Tạo tab canvas. Đặt tên cho tab canvas theo chuẩn TAB_ENTITY_REGIONS (ví dụ với thực thể LINES, đặt tên cho tab canvas là TAB_LINES_REGIONS). Thiết lập lớp thuộc tính là TAB_CANVAS. Thiết lập thuộc tính Window cho tab canvas để đặt nó vào đúng cửa sổ. Nếu đặt sai, bạn sẽ không sử dụng được “View -> Stacked Views” trong Form Builder để hiển thị tab canvas trên content canvas.

 Bước 2 : Điều chỉnh tab canvas. Thiết lập thứ tự của tab canvas sau content canvas và trước bất kì stacked canvas nào sẽ xuất hiện đằng trước nó. Điều chỉnh viewport của tab canvas trong Layout Editor. Hiển thị content canvas cùng lúc để dễ định vị tab canvas.

70



Bước 3 : Tạo các tab page. Với mức trung bình và mức khó, tên của các tab page phải phù hợp với tên của các stacked canvas “alternative region” tương ứng với chúng.

 Bước 4 : Hiệu chỉnh các tab page. Thiết lập lớp thuộc tính là TAB_PAGE. Đặt label cho mỗi tab page. Thiết lập thứ tự cho các tab page trong Object Navigator.  Bước 5 : Riêng với mức khó, tạo fixed field stacked canvas. Đặt tên nó là tab_canvas_FIXED. Thiết lập thứ tự cho nó sau tab canvas nhưng trước bất kì stacked canvas “alternative region” nào mà bạn tạo cho mức khó. Thiết

lập

lớp

thuộc

tính

cho





CANVAS_STACKED_FIXED_FIELD. Chỉnh để viewport của fixed field canvas nằm trong viewport của tab canvas.  Bước 6 : Với mức trung bình và mức khó, tạo các stacked canvas “alternative region”. Tất cả các canvas này phải có cùng vị trí và kích thước viewport. Kiểm tra thuộc tính Visible của các stacked canvas “alternative region”, chỉ để canvas nào xuất hiện đầu tiên có thuộc tính này là Yes. Với mức khó, các canvas “alternative region” này sẽ che khuất một phần (chứ không phải là tất cả) của canvas fixed field. Cần đảm bảo là vị trí và kích thước viewport của alternative region canvas liên hệ phù hợp với fixed field canvas. )  Bước 7 : Đặt các item của bạn vào các tab page hay stacked canvas thích hợp. Đặt các scrollbar của block (nếu có) ở gần cạnh phải canvas. Nếu đang sử dụng stacked canvas, đảm bảo rằng stacked canvas không chồng lên các trường được đặt trực tiếp vào trong tab page. Tương tự, các stacked canvas “alternative region” cũng không được chồng lên các item trong stacked canvas fixed field.  Bước 8 : Hiệu chỉnh layout của bạn. Đặt các tiêu đề tương ứng cho các trường. Khi hiệu chỉnh, lưu ý căn chỉnh các đối tượng hợp lý để đảm bảo tính thẩm mĩ, dễ nhìn.  Bước 9 : Lập trình cho tab handler. Oracle cung cấp 2 file mẫu giúp lập trình cho handler dễ hơn : . FNDTABS.txt cho mức dễ và mức trung bình . FNDTABFF.txt cho trường hợp fixed field (mức khó) Hai file này nằm trong thư mục Resource (trong thư mục FND). Copy text từ file vào trong form rồi sửa lại code cho phù hợp với các đối tượng và các

71

hành động trong form. Tham khảo các comment có trong file để sửa code được dễ hơn. 

Bước 10 : Gọi các tab handler từ trigger. Tạo 1 trigger mức form WHEN–TAB–PAGE–CHANGED, và gọi handler từ trigger này. Trigger nên truyền sự kiện WHEN–TAB–PAGE–CHANGED tới handler, ví dụ :

MY_PACKAGE.TAB_MY_ENTITY_REGIONS(‟WHEN– TAB–PAGE–CHANGED‟); Tạo 1 trigger mức block (Execution Hierarchy Style: Before) WHEN– NEW–ITEM–INSTANCE để gọi tới handler của bạn, ví dụ :

MY_PACKAGE.TAB_MY_ENTITY_REGIONS(‟WHEN– NEW–ITEM–INSTANCE‟);

72

Cho phép hoạt động truy vấn Query Find : 

Có 2 hình thức triển khai cho Query Find. Một sẽ hiển thị một Row-LOV trong đó có các hàng để bạn chọn một. Một sẽ mở ra cửa sổ tìm kiếm ( Find window ), trong đó có các trường mà người sử dụng có thể muốn dùng để chọn dữ liệu. Chỉ sử dụng 1 hình thức triển khai cho mỗi block cụ thể. Tất cả các block có thể truy vấn trong form nên hỗ trợ Query Find.



Gọi Query Find khi mở form : nếu muốn một Row-LOV hoặc Find Window hiện ngay lập tức khi mở form, gọi EXECUTE_TRIGGER( „QUERY_FIND‟ ); ở cuối trigger WHEN-NEW-FORM-INSTANCE.

Triển khai Row-LOV 

Để triển khai một Row-LOV, tạo 1 LOV để chọn ra khoá chính của hàng (mà người sử dụng muốn) để đưa vào trong 1 tham số form, sau đó copy giá trị này vào trong trường khoá chính của block chứa kết quả truy vấn ngay trước lúc thực hiện truy vấn.



Xét 1 ví dụ với block DEPT dựa trên bảng DEPT với các cột DEPTNO, DNAME, LOC. Các bước triển khai như sau :  Bước 1 : Tạo 1 tham số cho khoá chính. Tạo 1 tham số form để lưu khoá chính chọn từ LOV. Nếu Row-LOV là dành cho detail block, bạn không cần tạo tham số để lưu khoá ngoại, mà hãy thêm vào mệnh đề WHERE của nhóm bản ghi ( sẽ được tạo ở bước sau ) tên cột kết nối. Thiết lập kiểu dữ liệu và độ dài thích hợp cho tham số. Ví dụ ta tạo tham số DEPTNO_QF tương ứng với block DEPT. 

Bước 2 : Tạo 1 LOV

Tạo 1 LOV chứa các cột cần thiết để người dùng có thể xác định đuợc hàng mình muốn chọn. Nếu Row-LOV là cho detail block, thêm cột kết nối ( khoá ngoại ) vào mệnh đề WHERE của nhóm bản ghi ứng với LOV. Khoá chính ( chọn từ LOV ) sẽ được trả về cho tham số. Ví dụ ta tạo 1 LOV là DEPT_QF chứa 2 cột là DEPTNO và DNAME. Đặt

73

đối tượng nhận giá trị trả về của DEPTNO là DEPTNO_QF. 

Bước 3 : Tạo 1 trigger PRE-QUERY

Tạo 1 trigger PRE-QUERY ở mức block (Execution Hierarchy: Before) chứa đoạn mã sau : IF :parameter.G_query_find = ‟TRUE‟ THEN := :parameter.; :parameter.G_query_find := ‟FALSE‟; END IF; Với khoá chính gồm nhiều thành phần, bạn cần nhiều lệnh gán cho khoá chính. Tham số G_query_find đã có sẵn trong form TEMPLATE. Ví dụ ta tạo trigger PRE-QUERY chứa đoạn mã sau : IF :parameter.G_query_find = ‟TRUE‟ THEN :DEPT.DEPTNO := :parameter.DEPTNO_QF :parameter.G_query_find := ‟FALSE‟; END IF; 

Bước 4 : Tạo 1 trigger QUERY_FIND

Cuối cùng, tạo 1 trigger ( loại trigger tự tạo ) mức block tên là QUERY_FIND (Execution Hierarchy: Override) chứa mã : APP_FIND.QUERY_FIND(‟‟); Ví dụ ta tạo trigger chứa : APP_FIND.QUERY_FIND(‟DEPT_QF‟);

Triển khai Find Window 

Để triển khai 1 Find Window, tạo thêm 1 window chứa các trường mà người dùng thường hay chọn khi bắt đầu thực hiện tìm kiếm và copy tất cả các giá trị của item từ block đó vào trong block chứa kết quả truy vấn ngay trước khi thực hiện truy vấn.



Trong ví dụ mà ta sẽ xem xét, có 1 block dựa trên bảng EMP, là block chứa kết quả truy vấn. Khoá chính của bảng EMP là EMPNO. Block còn chứa một trường kiểu date là HIREDATE. Find Window được thiết kế để xác định các bản ghi bằng EMPNO hoặc HIREDATE.



Các bước triển khai :  Bước 1 : Copy nhóm đối tượng QUERY_FIND từ form APPSTAND . Copy nhóm đối tượng QUERY_FIND từ form APPSTAND vào form của bạn. Nó chứa 1 window, 1 block và 1 canvas mà từ đó xây dựng nên Find Window của bạn.

74

. Sau khi copy, xoá nhóm đối tượng QUERY_FIND đi. Window, canvas và block vẫn còn, và bạn lại có thể copy lại nhóm đối tượng nếu cần thêm Find Window nữa.  Bước 2 : Đổi tên block, canvas và window . Đổi tên block, canvas và window. Đặt thuộc tính queryable của block là No. . Trong ví dụ, đổi tên block, canvas và window thành : EMP_QF, EMP_QF_CANVAS, and EMP_QF_WINDOW.  Bước 3 : Viết code cho trigger của nút NEW . Viết code cho trigger WHEN–BUTTON–PRESSED của nút NEW trong block của Find Window để nó truyền đi tên của block Result như 1 tham số. Thông tin này cho phép Oracle Applications chuyển con trỏ tới block Result và đặt con trỏ tại vị trí bản ghi mới. Sở dĩ có nút NEW là bởi vì khi bạn mở 1 form, Find Window có thể tự động mở ra, và nếu bạn muốn thêm mới ngay 1 bản ghi thì chỉ việc chọn nút NEW. . Trong ví dụ, sửa dòng code app_find.new(‟‟); trong trigger thành app_find.new(‟EMP‟);  Bước 4 : Viết code cho trigger của nút FIND . Viết code cho trigger WHEN–BUTTON–PRESSED của nút FIND để nó truyền đi tên của block Results. Thông tin này cho phép Oracle Applications chuyển focus tới block Results và thực hiện truy vấn. . Trong ví dụ, sửa dòng code app_find.find (‟ ‟); thành app_find.find(‟EMP‟); . Nếu bạn cần phải validate các item trong Find Window, đặt đoạn code của bạn trước lời gọi APP_FIND.FIND. Bạn có thể đưa ra lời nhắc nếu người dùng chưa nhập điều kiện lọc, hoặc điều kiện lọc đó có thể phải mất nhiều thời gian để xử lý.  Bước 5 : Thiết lập thuộc tính Navigation Data Block . Thiết lập thuộc tính Previous Navigation Data Block của block Find là block Results. Điều này cho phép người dùng thoát khỏi Find Window mà không cần thực hiện truy vấn. . Từ block Result, next và previous data block của nó là các đối tượng khác, chứ không bao giờ quay về Find Window.  Bước 6 : Viết code cho trigger KEY–NXTBLK Viết code cho trigger KEY–NXTBLK của block Find để nó có tính năng giống như nút FIND. Khi người dùng chọn “Go–>Next Block”, hành động xảy ra giống như khi nhấn nút FIND.

75

 Bước 7 : Đặt title cho Find Window Đặt title cho Find Window. Trong ví dụ, đặt title là “Find Employees”.  Bước 8 : Tạo các item cần thiết . Tạo các item mà người dùng truy vấn trong block Find Window. Đơn giản nhất là copy các item từ block Result vào block Find Window. . Các thao tác với những item trong Find Window : > Đặt thuộc tính Required là No > Đặt giá trị mặc định là NULL > Nếu bạn copy các item từ block Results, đặt thuộc tính Database Item là No, và loại bỏ các trigger kèm với chúng. Nếu cần giữ lại 1 trigger nào đấy, cần sửa các tham chiếu của nó tới các trường trong block Find Window > Thông thường item trong block Find Window có LOV gắn với nó để người dùng luôn có thể chọn đúng giá trị hợp lệ cho item. Các trường date có thể sử dụng Calendar và trigger KEY-LISTVAL có liên quan. > Các item là check box hay option group trong block Results nên chuyển thành poplist trong block Find Window. Khi chúng NULL, truy vấn không chịu một giới hạn nào.  Bước 9 : Căn chỉnh Find Window trong form Điều chỉnh Find Window của bạn : chỉnh lại kích thước, vị trí, các trường…  Bước 10 : Lập trình trigger PRE-QUERY . Tạo trigger PRE-QUERY cho block Results (Execution Hierarchy : Before) để copy điều kiện lọc truy vấn từ block Find Window sang block Results (là nơi truy vấn thực sự xảy ra). . Bạn có thể sử dụng built-in COPY của Oracle Forms để copy giá trị hoặc có thể gán giá trị trực tiếp bằng “ := ”. IF :parameter.G_query_find = ‟TRUE‟ THEN COPY (,‟‟); :parameter.G_query_find := ‟FALSE‟; END IF; . Một kiểu lọc thường dùng đó là truy vấn trong phạm vi các số (hoặc các ngày,

hoặc

các



tự)

nào

đó.



thể

sử

dụng

thủ

tục

APP_FIND.QUERY_RANGE để thực hiện điều này. Tham số một và hai là giá trị thấp và giá trị cao, tham số ba là tên của trường dữ liệu được truy vấn thực sự. . Trong ví dụ : IF :parameter.G_query_find = ‟TRUE‟ THEN

76

COPY(:EMP_QF.EMPNO, ‟EMP.EMPNO‟); APP_FIND.QUERY_RANGE(:EMP_QF.Hiredate_from, :EMP_QF.Hiredate_to, ‟EMP.Hiredate‟); :parameter.G_query_find := ‟FALSE‟; END IF;  Bước 11 : Tạo trigger QUERY_FIND . Tạo trigger QUERY_FIND (loại trigger tự tạo) cho block Results (Execution Hierarchy: Override) chứa code : APP_FIND.QUERY_FIND(‟‟, ‟‟, ‟‟); . Trong ví dụ : APP_FIND.QUERY_FIND(‟EMP_WINDOW‟,

‟EMP_QF_WINDOW‟,

‟EMP_QF‟);

77

Lập trình các hành động cho item Các chủ đề chính 

Mối quan hệ các Item



Defaults



Kiểm tra tính toàn vẹn



Calendar



CALENDAR: Calendar Package

Mối quan hệ giữa các Item  Các Item phụ thuộc.  Các Item phụ thuộc vào điều kiện.  Các Item đa phụ thuộc.  Hai Master Items & Một Dependent Item  Phụ thuộc tầng.  Các Item loại trừ lẫn nhau.  Các Item bao gồm lẫn nhau.  Mutually Inclusive Items with Dependents  Các Item có tính điều kiện bắt buộc. Các hành động chính đối với các Item như sau: Disabled Items and WHEN–VALIDATE–ITEM Trigger Trong hầu hết mối quan hệ giữa các Item bạn phải tự động enable hoặc disable các Item. WHEN–VALIDATE–ITEM luôn xảy ra tại thời điểm đầu tiên khi một user di chuyển qua mỗi trường của một record mới, thậm chí không thay đổi giá trị gì 

Các item phụ thuộc Để tạo một text item, check box, hoặc poplist mà chỉ enabled khi một master item được tính toán, sử dụng procedure APP_FIELD.SET_

78

DEPENDENT_FIELD. Điều này cho phép : - Các item phụ thuộc hoặc được clear hoặc là invalid khi master thay đổi. - Nếu master item là NULL hoặc điều kiện là FALSE, thì item phụ thuộc disabled.

Trong ví dụ dưới đây ta có hai item là item_type và item_name. Item_name phụ thuộc vào item_type, do đó item_name chỉ enable khi item_type là NOT NULL.

Bước 1 Tạo một thủ tục điều khiển procedures như dưới đây: PACKAGE BODY ORDER IS PROCEDURE ITEM_TYPE(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN -- Any validation logic goes here. ITEM_NAME(‟INIT‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.ITEM_TYPE: ‟ || EVENT); END IF; END ITEM_TYPE; PROCEDURE ITEM_NAME(EVENT VARCHAR2) IS BEGIN IF ((EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟)) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, ‟ORDER.ITEM_TYPE‟, ‟ORDER.ITEM_NAME‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.ITEM_NAME: ‟ || EVENT); END IF; END ITEM_NAME; END ORDER; Bước 2: Gọi thủ tục điều khiển item trong :

79

Trigger: WHEN–VALIDATE–ITEM on item_type: order.item_type(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD on order (Fire in Enter–Query Mode: No): order.item_name(‟PRE–RECORD‟); Bước 3 : Nếu master và dependent item đều trong một multi–row block, hoặc chúng là các items trong một single–row block là detail của một master block, ta phải gọi SET_DEPENDENT_FIELD cho sự kiện POST–QUERY thay vào đó. PROCEDURE ITEM_NAME(EVENT VARCHAR2) IS BEGIN IF ((EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟) OR (EVENT = ‟POST–QUERY‟)) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, ‟ORDER.ITEM_TYPE‟, ‟ORDER.ITEM_NAME‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.ITEM_NAME: ‟ || EVENT); END IF; END ITEM_NAME; Thêm một điều khiển trong: ORDER.ITEM_NAME(’POST–QUERY’);

Chú ý : Trong một multi–record block, nếu item phụ thuộc là Item cuối cùng của record, con trỏ chuột đến record tiếp theo Khi di chuyển từ master. Để làm việc với điều khiển này , thêm vào KEY–NEXT–ITEM trigger mà xảy ra một VALIDATE(Item_scope) tiếp theo là NEXT_ITEM. Chú ý: Nếu item phụ thuộc là một required list hoặc option group, thiết lập ”invalidate” parameter trong lời gọi APP_FIELD.SET_DEPENDENT_FIELD thành TRUE. Khi flag là TRUE, item phụ thuộc được thiết lập như là invalid hơn là cleared.

80

Item phụ thuộc có điều kiện Trong ví dụ này , block orderc có hai là item_type và item_size. Item_size is enabled chỉ khi item_type là ”SHOES.” Bước 1: Tạo một thủ tục điều khiển item dưới đây . Tương tự như trong trường hợp simple master/dependent, nhưng phải thiết lập điều kiện thay vì tên của master item. PACKAGE BODY order IS

PROCEDURE ITEM_TYPE(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN size(‟INIT‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.ITEM_TYPE: ‟ || EVENT); END IF; END item_type; END IF; END size;

PROCEDURE size(EVENT VARCHAR2) IS BEGIN IF ((EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟)) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, (:order.item_type = ‟SHOES‟), ‟ORDER.SIZE‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.SIZE: ‟ || EVENT); END order;

81

Bước 2 Gọi thủ tục điều khiển trong :

Trigger: PRE–RECORD on order (Fire in Enter–Query Mode: No): order.item_size(‟PRE–RECORD‟);

Trigger: WHEN–VALIDATE–ITEM on item_type: order.item_type(‟WHEN–VALIDATE–ITEM‟);

Các item đa phụ thuộc Đây là trường hợp mà nhiều item phụ thuộc vào một master item. Ví dụ, item_types chắc chắn có thể định rõ color và size. Do đó, trường color và size là phụ thuộc vào the master field item_type, và chỉ enabled khi item_type là ”RAINCOAT.” Bước 1 Tạo các thủ tục xử lý item như sau : PACKAGE BODY order IS PROCEDURE item_type(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN color(‟INIT‟); size(‟INIT‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.ITEM_TYPE: ‟ || EVENT); END IF; END item_type; PROCEDURE color(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, (:order.item_type = ‟RAINCOAT‟), ‟ORDER.COLOR‟);

82

ELSE fnd_message.debug(‟Invalid event passed to ORDER.COLOR: ‟ || EVENT); END IF; END color; PROCEDURE size(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, (:order.item_type = ‟RAINCOAT‟), ‟ORDER.SIZE‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.SIZE: ‟ || EVENT); END IF; END size; END order; Bước 2 Gọi các thủ tục trong :

Trigger: WHEN–VALIDATE–ITEM on order.item_type: order.item_type(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD (Fire in Enter–Query Mode: No): order.color(‟PRE–RECORD‟); order.size(‟PRE–RECORD‟);

2 Master Item và 1 Dependent Item Giả sử các size khác nhau của những chiếc mũ tương ứng với các color khác nhau. Bạn không thể điền vào color của chiếc mũ đến khi nào bạn đã điền vào cả hai item_type và size. Sự hợp lệ của block phụ thuộc được điều khiển bởi nội dung của cả hai master_1 and master_2. Bước 1 Tạo các thủ tục dưới đây : PACKAGE BODY order IS PROCEDURE item_type(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN

83

color(‟INIT‟): ELSE fnd_message.debug(‟Invalid event passed to ORDER.ITEM_TYPE: ‟ || EVENT); END IF; END item_type; PROCEDURE size(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN color(‟INIT‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.SIZE: ‟ || EVENT); END IF; END size; PROCEDURE color(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, ((:order.item_type IS NOT NULL) AND (:order.size IS NOT NULL)), ‟ORDER.COLOR‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.COLOR: ‟ || EVENT); END IF; END color; END order; Bước 2 Gọi các thủ tục điều khiển trong :

Trigger: WHEN–VALIDATE–ITEM on order.item_type: order.item_type(‟WHEN–VALIDATE–ITEM‟);

Trigger: WHEN–VALIDATE–ITEM on order.size: order.size(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD (Fire in Enter–Query Mode: No):

84

order.color(‟PRE–RECORD‟);

Kiểu phụ thuộc Cascading Với kiểu phụ thuộc cascading, item_3 phụ thuộc vào item_2, item_2 phụ thuộc vào item_1. Thông thường tất cả các item trong cùng một block. Ví dụ , block order bao gồm các items vendor, site, và contact. Danh sách list tương ứng của sites phụ thuộc vào vendor hiện tại .

- Khi vendor được thay đổi, site bị cleared. - Bất cứ khi nào vendor là null, site là disabled. Danh sách list của các contacts phụ thuộc vào site hiện tại. - Bất cứ khi nào site thay đổi, contact là cleared. - Bất cứ khi nào site là null, contact là disabled. Bước 1 Tạo thủ tục dưới đây : PACKAGE BODY order IS PROCEDURE vendor(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN SITE(‟INIT‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.VENDOR: ‟ || EVENT); END IF; END VENDOR; PROCEDURE SITE(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN CONTACT(‟INIT‟); ELSIF (EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, ‟ORDER.VENDOR‟, ‟ORDER.SITE‟); CONTACT(EVENT); ELSE fnd_message.debug(‟Invalid event passed to

85

ORDER.SITE: ‟ || EVENT); END IF; END SITE; PROCEDURE CONTACT(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, ‟ORDER.SITE‟, ‟ORDER.CONTACT‟); ELSE fnd_message.debug(‟Invalid event passed to ORDER.CONTACT: ‟ || EVENT); END IF; END CONTACT; END ORDER; Bước 2 Gọi các thủ tục trong :

Trigger: WHEN–VALIDATE–ITEM on vendor: order.vendor(‟WHEN–VALIDATE–ITEM‟);

Trigger: WHEN–VALIDATE–ITEM on site: order.site(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD on order (Fire in Enter–Query Mode: No): order.site(‟PRE–RECORD‟); order.contact(‟PRE–RECORD‟); Trường VENDOR được validate như sau: - VENDOR được validate, gọi SITE (‟INIT‟). - SITE (‟INIT‟) làm trạng thái của SITE thay đổi và gọi CONTACT (‟INIT‟). - CONTACT (‟INIT‟) làm trạng thái của CONTACT thay đổi.

Các item loại trừ lẫn nhau (Mutually Exclusive Items) Sử dụng thủ tục APP_FIELD.SET_EXCLUSIVE_FIELD để viết mã 2 item khi mà chỉ 1 item là hợp lệ tại một thời điểm.

86

Nếu một item không được null, đặt thuộc tính REQUIRED của cả 2 item là Yes trong Oracle Forms Developer. Nếu cả 2 item có thể là null, đặt thuộc tính REQUIRED của cả 2 item là No. APP_FIELD.SET_ EXCLUSIVE_FIELD đọc thuộc tính REQUIRED bên trong và tự động thay đổi thuộc tính REQUIRED của cả 2 item. Bạn cũng có thể sử dụng APP_FIELD.SET_EXCLUSIVE_FIELD với tập hợp của 3 mutually exclusive item. Nếu là nhiều hơn 3 item, bạn phải tự viết mã logic cho chúng.

Chú ý : Các mutually exclusive check box và required list đều yêu cầu được kích hoạt bằng chuột. Ví dụ, một block lines có các mutually exclusive items là credit & debit.

Bước 1 PACKAGE BODY lines IS PROCEDURE credit_debit(EVENT VARCHAR2) IS BEGIN IF ((EVENT = ‟WHEN–VALIDATE–ITEM‟) OR (EVENT = ‟PRE–RECORD‟)) THEN APP_FIELD.SET_EXCLUSIVE_FIELD(EVENT, ‟LINES.CREDIT‟, ‟LINES.DEBIT‟); ELSIF (EVENT = ‟WHEN–CREATE–RECORD‟) THEN SET_ITEM_PROPERTY(‟lines.credit‟, ITEM_IS_VALID, PROPERTY_TRUE); SET_ITEM_PROPERTY(‟lines.debit‟, ITEM_IS_VALID, PROPERTY_TRUE); ELSE fnd_message.debug(‟Invalid event passed to Lines.credit_debit: ‟ || EVENT); END IF; END credit_debit; END lines;

Bước 2

87

Trigger: WHEN–VALIDATE–ITEM on credit: lines.credit_debit(‟WHEN–VALIDATE–ITEM‟);

Trigger: WHEN–VALIDATE–ITEM on debit: lines.credit_debit(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD on lines (Fire in Enter–Query Mode: No): lines.credit_debit(‟PRE–RECORD‟);

Trigger: WHEN–CREATE–RECORD on lines: lines.credit_debit(‟WHEN–CREATE–RECORD‟); Bạn chỉ cần trigger WHEN–CREATE–RECORD nếu kết quả của một trong trường mutually–exclusive được yêu cầu. Trigger này vào lúc đầu thiết lập tất cả các trường mutually–exclusive của tập hợp thành required. Tất cả các trường được reset thích hợp mỗi lần một user nhập giá trị vào một trong các trường đó.

Các item đồng hành với nhau (Mutually Inclusive Items) Sử dụng APP_FIELD.SET_INCLUSIVE_FIELD để viết mã của tập hợp các item trong trường hợp nếu bất cứ item nào là không null, thì tất cả các item là required. Giá trị của các item được nhập vào theo bất cứ thứ tự nào. Nếu tất cả các item là null, thì các item là tùy ý không bất buộc. Bạn có thể dùng APP_FIELD.SET_INCLUSIVE_FIELD đối với không quá 5 mutually inclusive items. Nếu số item là lớn hơn 5 bạn phải tự viết mã logic. Ví dụ dưới gồm 1 block payment_info với các mutually inclusive items là

payment_type và amount. Bước 1: PACKAGE BODY payment_info IS PROCEDURE payment_type_amount(EVENT VARCHAR2) IS BEGIN IF ((EVENT = ‟WHEN–VALIDATE–ITEM‟) OR (EVENT = ‟PRE–RECORD‟)) THEN APP_FIELD.SET_INCLUSIVE_FIELD(EVENT, ‟PAYMENT_INFO.PAYMENT_TYPE‟, ‟PAYMENT_INFO.AMOUNT‟); ELSE

88

fnd_message.debug(‟Invalid event to payment_info.payment_type_ amount: ‟ || EVENT); END IF; END payment_type_amount; END payment_info;

Bước 2: Trigger: WHEN–VALIDATE–ITEM on payment_info.payment_type: payment_info.payment_type_amount(‟WHEN–VALIDATE–ITEM‟);

Trigger: WHEN–VALIDATE–ITEM on payment_info.amount: payment_info.payment_type_amount(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD on payment_info (Fire in Enter–Query Mode: No): payment_info.payment_type_amount(‟PRE–RECORD‟);

Mutually Inclusive Item liên hệ với Dependent Item Đây là trường hợp các items là phụ thuộc vào master items, trong khi master items là mutually inclusive. Ví dụ dưới với block payment_info với các mutually inclusive items là payment_type and amount, như trong ví dụ trước, Block này bao gồm 2 regions, một cái cho check information và 1 cho credit card information. Check Information has a single item, check_number. Credit Card Information gồm 5 item: credit_type, card_holder, number, expiration_date, and approval_code.

Payment Type có thể là Cash, Check, hoặc Credit - Khi Payment Type là Check, thì Check Information region được enabled. - When Payment Type là Credit, the Credit Card Information region được enabled.

Bước 1 : PACKAGE BODY payment_info IS PROCEDURE payment_type_amount(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN APP_FIELD.SET_INCLUSIVE_FIELD(EVENT, ‟PAYMENT_INFO.PAYMENT_TYPE‟,

89

‟PAYMENT_INFO.AMOUNT‟); IF (:SYSTEM.CURSOR_ITEM = ‟payment_info.payment_type‟) THEN check_info(‟INIT‟); credit_info(‟INIT‟); END IF; ELSIF (EVENT = ‟PRE–RECORD‟) THEN APP_FIELD.SET_INCLUSIVE_FIELD(EVENT, ‟PAYMENT_INFO.PAYMENT_TYPE‟, ‟PAYMENT_INFO.AMOUNT‟); ELSE fnd_message.debug(‟Invalid event in payment_info.payment_type_amount: ‟ || EVENT); END IF; END payment_type_amount; PROCEDURE check_info IS BEGIN IF ((EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟)) THEN APP_FIELD.SET_DEPENDENT_FIELD(EVENT, (:payment_info.payment_type = ‟Check‟), ‟PAYMENT_INFO.CHECK_NUMBER‟); ELSE fnd_message.debug(‟Invalid event in payment_info.check_info: ‟ || EVENT); END IF; END check_info; PROCEDURE credit_info IS CONDITION BOOLEAN; BEGIN IF ((EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟)) THEN CONDITION := (:payment_info.payment_type = ‟Credit‟); APP_FIELD.SET_DEPENDENT_FIELD(EVENT, CONDITION, ‟PAYMENT_INFO.CREDIT_TYPE‟);

90

APP_FIELD.SET_DEPENDENT_FIELD(EVENT, CONDITION, ‟PAYMENT_INFO.NUMBER‟); APP_FIELD.SET_DEPENDENT_FIELD(EVENT, CONDITION, ‟PAYMENT_INFO.CARD_HOLDER‟); APP_FIELD.SET_DEPENDENT_FIELD(EVENT, CONDITION, ‟PAYMENT_INFO.EXPIRATION_DATE‟); APP_FIELD.SET_DEPENDENT_FIELD(EVENT, CONDITION, ‟PAYMENT_INFO.APPROVAL_CODE‟); ELSE fnd_message.debug(‟Invalid event in payment_info.credit_info: ‟ || EVENT); END IF; END credit_info; END payment_info;

Bước 2 Trigger: WHEN–VALIDATE–ITEM on payment_info.payment_type: payment_info.payment_type_amount(‟WHEN–VALIDATE–ITEM‟);

Trigger: WHEN–VALIDATE–ITEM on payment_info.amount: payment_info.payment_type_amount(‟WHEN–VALIDATE–ITEM‟);

Trigger: PRE–RECORD on payment_info (Fire in Enter–Query Mode: No): payment_info.payment_type_amount(‟PRE–RECORD‟); payment_info.check_info(‟PRE–RECORD‟); payment_info.credit_info(‟PRE–RECORD‟);

Các item bắt buộc điều kiện (Conditionally Mandatory Items) Sử dụng APP_FIELD.SET_REQUIRED_FIELD nếu 1 item yêu cầu cả 2 điều kiện và Phụ thuộc, thì gọi APP_FIELD.SET_DEPENDENT_FIELD trước APP_FIELD.SET_REQUIRED_FIELD.

91

Trong ví dụ sau một block purchase_order bao gồm 2 item total và vp_approval. Vp_approval được yêu cầu khi total lớn hơn $10,000. (Chú ý : quantity * unit_price = total.)

Bước 1: Viết thủ tục sau : PACKAGE BODY purchase_order IS PROCEDURE vp_approval(EVENT VARCHAR2) IS BEGIN IF ((EVENT = ‟PRE–RECORD‟) OR (EVENT = ‟INIT‟)) THEN APP_FIELD.SET_REQUIRED_FIELD(EVENT, (:purchase_order.total > 10000), ‟PURCHASE_ORDER.VP_APPROVAL‟); ELSE fnd_message.debug(‟Invalid event in purchase_order.vp_approval: ‟ || EVENT); END IF; END vp_approval; PROCEDURE total(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟INIT‟) THEN :purchase_order.total := :purchase_order.quantity * :purchase_order.unit_price; vp_approval(‟INIT‟); ELSE fnd_message.debug(‟Invalid event in purchase_order.total: ‟ || EVENT); END total; PROCEDURE quantity(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN total(‟INIT‟); ELSE fnd_message.debug(‟Invalid event in purchase_order.quantity: ‟ || EVENT); END IF;

92

END quantity; PROCEDURE unit_price(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN total(‟INIT‟); ELSE fnd_message.debug(‟Invalid event in purchase_order.unit_price: ‟ || EVENT); END IF; END unit_price; END purchase_order;

Bước 2: Gọi các thủ tục sau trong : Trigger: PRE–RECORD on purchase_order (Fire in Enter–Query Mode: No): purchase_order.vp_approval(‟PRE–RECORD‟);

Trigger: WHEN–VALIDATE–ITEM on quantity: purchase_order.quantity(‟WHEN–VALIDATE–ITEM‟);

Trigger: WHEN–VALIDATE–ITEM on unit_price: purchase_order.unit_price(‟WHEN–VALIDATE–ITEM‟);

Các mặc định (Defaults) Các mặc định trên 1 bản ghi mới Để thiết lập giá trị mặc định khi user tạo một bản ghi, sử dụng thuộc tính Default values trong the Oracle Forms Designer. Với những Default phức tạp hơn có thể tham khảo tại đây:

Bước 1: Khai báo Package PACKAGE block IS PROCEDURE WHEN_CREATE_RECORD IS BEGIN :block.item1 := default_value1; :block.item2 := default_value2; ... END WHEN_CREATE_RECORD;

93

END block;

Bước 2: Gọi trong trigger sau : Trigger: WHEN–CREATE–RECORD: block.WHEN_CREATE_RECORD;

Áp dụng các Default khi đang truy cập vào bản ghi Khi muốn thiết lập giá trị mặc định cho một item mà phụ thuộc và một item khác thì thiết lập giá trị mặc định trong item phụ thuộc sử dụng sự kiện INIT.

Kiểm tra tính toàn vẹn (Integrity Checking) 

Kiểm tra tính duy nhất (Uniqueness Checks)



Kiểm tra toàn vẹn tham chiếu (Referential Integrity Checks)

Kiểm tra tính duy nhất Trường hợp này có thể thấy khi duplicate một hàng của block dữ liệu. Ta dùng WHEN–VALIDATE–ITEM cho trường đó. PROCEDURE CHECK_UNIQUE(X_ROWID VARCHAR2, pkey1 type1, pkey2 type2, ...) IS DUMMY NUMBER; BEGIN SELECT COUNT(1) INTO DUMMY FROM table WHERE pkeycol1 = pkey1 AND pkeycol2 = pkey2 ... AND ((X_ROWID IS NULL) OR (ROWID != X_ROWID)); IF (DUMMY >= 1) then FND_MESSAGE.SET_NAME(‟prod‟, ‟message_name‟); APP_EXCEPTION.RAISE_EXCEPTION; END IF; END CHECK_UNIQUE;

Tạo thủ tục xử lý item như sau :

94

PACKAGE BODY block IS PROCEDURE item(EVENT VARCHAR2) IS BEGIN IF (EVENT = ‟WHEN–VALIDATE–ITEM‟) THEN table_PKG.CHECK_UNIQUE(:block.row_id, :block.pkey1, :block.pkey2, ...); ELSE message(‟Invalid event in block.item‟); END IF END item; END block;

Kiểm tra toàn vẹn tham chiếu Khi xóa một record, ta phải chú ý đến các record mà có thể tham chiếu đến record đó . Các giải pháp được đưa ra là: - Không cho phép xóa item đó. - Xóa đồng thời item mà nó tham chiếu đến. - Cho phép xóa item , và đặt item tham chiếu đến nó là null.. Thông thường ta sẽ xử ly theo cách đầu.

Đưa ra cảnh báo trước khi xoá các bản ghi detail Để cảnh báo khi xóa một detail record, tạo CHECK_REFERENCES là 1 hàm trả lại giá trị FALSE nếu các bản ghi detail tồn tại (CHECK_REFERENCES cần phải raise 1 exception nếu khi xóa một hàng mà có liên quan đến lỗi tham chiếu). Ví dụ :

Bước 1 : CREATE OR REPLACE PACKAGE BODY table_PKG AS PROCEDURE CHECK_REFERENCES(pkey1 type1, pkey2 type2, ...) IS MESSAGE_NAME VARCHAR2(80); DUMMY

credit;

BEGIN MESSAGE_NAME := ‟message_name1‟; SELECT 1 INTO DUMMY FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM referencing_table1

95

WHERE ref_key1 = pkey1 AND ref_key2 = pkey2 ... ); MESSAGE_NAME := ‟message_name2‟; SELECT 1 INTO DUMMY FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM referencing_table2 WHERE ref_key1 = pkey1 AND ref_key2 = pkey2 ... ); EXCEPTION WHEN NO_DATA_FOUND THEN FND_MESSAGE.SET_NAME(‟prod‟, MESSAGE_NAME); APP_EXCEPTION.RAISE_EXCEPTION; END CHECK_REFERENCES; END table_PKG;

Bước 2 : PACKAGE BODY block IS PROCEDURE key_delete IS BEGIN –– –– First make sure its possible to delete this record. –– An exception will be raised if its not. –– table_PKG.CHECK_REFRENCES(pkey1, pkey2, ...); –– –– Since it is possible to delete the row, ask the –– user if they really want to, –– and delete it if they respond with ‟OK‟. –– app_record.delete_row; END key_delete; END block;

Bước 3 :

96

Trigger: KEY–DELETE: block.dey_delete;

Gợi ý : Bạn cần phải làm các bước tương tự với trigger ON–DELETE. Có thể xảy ra tình huống là trong khoảng thời gian 1 user yêu cầu delete, thậm chí đã saved giao dịch, một record được đưa vào ở đâu đó sẽ gây ra lỗi tham chiếu . Cần phải nhớ rằng KEY–DELETE thực hiện tại thời điểm đầu tiên khi một user thực hiện delete, nhưng không thực sự thực hiện hành động delete; nó chỉ đánh dấu record nào sé xóa và clear nó trên màn hình . Trigger ON–DELETE thực hiện tại thời điểm commit và mới thực sự thực hiện xóa .

Đối tượng Calendar Calender là một đối tượng cho phép lựa chọn ngày tháng một cách trực quan Đối tượng này có sẵn ở trong form template. Để có thể sử dụng đối tượng này ta phải khai báo một số thủ tục trong các trigger tương ứng 

LOV cho các trường Date và Datetime Trường date và datetime phải đặt thuộc tính List lamp. Khi user mở list của trường đó form sẽ mở Calendar window. Trường date phải sử dụng ENABLE_LIST_LAMP LOV, trong TEMPLATE form. Đặt ‟Validate fromList” to No cho trường mà sử dụng LOV. Nếu để ”Validate from List” là Yes, bạn sẽ thấy LOV sẽ không có cột nào.

Các lời gọi cần phải có Mỗi trường date trong form phải sử dụng lời gọi sau :

Trigger: KEY–LISTVAL: calendar.show([first_date]); hoặc calendar.show;

97

Các lựa chọn cấp cao của Calendar Một số thuộc tính của Calendar có thể thực hiện thêm như sau :

Không hiển thị các ngày cuối tuần trong cửa sổ Calendar Để không hiện ngày cuối tuần (Chú ý ở đây là Thứ 7 và CN), gọi calendar.setup(‟WEEKEND‟);

Không hiển thị một chuỗi các ngày nào đó calendar.setup(<30 char identifying name>, , );

Không hiển thị một chuỗi các ngày nào đó lấy từ 1 bảng calendar.setup(<30 char identifying name>, null, null, <SQL>);

Gọi đối tượng Calendar từ các trường non–DATE Có thể gọi Calendar trên các trường không phải là kiểu date-time như kiểu char ,text.Cách gọi vẫn như bình thường. Khi lựa chọn giá trị ngày tháng sẽ trả về trường dưới format dạng ”DD–MON–YYYY.” Tạo một trigger ở mức item và thêm các lệnh để xử lý giá trị đó.

Một số ví dụ về Calendar Ví dụ : Chỉ hiển thị những ngày làm việc trong tuần ( thứ 2 -> thứ 6 ) Trigger: KEY–LISTVAL: calendar.setup(‟WEEKEND‟); calendar.show;

Ví dụ : Chỉ hiển thị những ngày làm việc trong năm ( không tính thứ 7, chủ nhật, các ngày lễ ) Giả sử có trường SHIP_BY_DATE trong một form, bạn muốn dùng Calendar và đặt tùy chọn cho nó : - Không hiển thị tất cả holiday được xác định trong bảng ORG_HOLIDAYS - Không hiển thị 2 ngày nghỉ cuối tuần - Hiện tháng tương ứng với ngày trong trường “LINES.NEED_BY_DATE” khi mở Calendar

Trigger: KEY–LISTVAL: calendar.setup(‟WEEKEND‟); calendar.setup(‟Manufacturing Holidays‟, null, null, ‟select action_date LOW_DATE, action_date HIGH_DATE ‟|| ‟from org_holidays where

98

date_type = ‟‟HOLIDAY‟‟‟); calendar.show(:lines.need_by_date);

Ví dụ : Hiển thị một chuỗi các ngày Trong trường NEED_BY_DATE, bạn muốn Calendar hiện ra tháng tương ứng với ngày trong trong trường LINES.CREATED_DATE + 30 days Bạn đồng thời cũng disable tất cả các ngày trước đó kể cả: LINES.CREATED_DATE.

Trigger: KEY–LISTVAL: calendar.setup(‟After created date‟, null, lines.created_date); calendar.show(:lines.need_by_date + 30);

Ví dụ : Chỉ hiển thị Calendar để xem Trên form có một nút HOLIDAYS chỉ ra tất cả các ngày nghỉ cho phép. Tháng hiện tại được cho trước đó, và calendar tìm những ngày này trong ORG_DATES table.

Trigger: WHEN–BUTTON–PRESSED on HOLIDAYS: calendar.setup(‟TITLE‟, null, null, ‟‟); calendar.setup(‟Manufacturing Holidays‟, null, null, ‟select action_date LOW_DATE, action_date HIGH_DATE ‟|| ‟from org_dates where date_type = ‟‟HOLIDAY‟‟‟); calendar.show;

99

Điều khiển Toolbar và Default Menu Trong chương này sẽ đề cập đến cách custom menu, toolbar, pupup menu trên form. Các thuộc tính này đều có ở form Template. Các mục chính : 

Menu kéo xuống (Pulldown Menu) và Toolbar



Các menu đặc biệt



Customize loại menu xuất hiện khi click chuột phải (Popup Menu, hay Right– Mouse Menu )



APP_POPUP: Điều khiển Right–Mouse Menu



APP_SPECIAL: Điều khiển Menu và Toolbar

Pulldown Menu và Toolbar

Menu bar Tool bar

100

Các lựa chọn có trên thanh công cụ ( toolbar ) :

Các lựa chọn và các trigger tương ứng với nó ( theo thứ tự xuất hiện trên toolbar ) : 

New (Thêm mới bản ghi) (WHEN–NEW–BLOCK–INSTANCE) Có hiệu lực nếu block cho phép insert.



Find... (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực khi block cho phép truy vấn và chưa ở trong chế độ enter–query.



Show Navigator (WHEN–NEW–RECORD–INSTANCE)



Save Luôn có hiệu lực.



Next Step



Print... Luôn có hiệu lực.



Close Form



Cut/Copy/Paste

Các đối tượng menu và toolbar sau được xử lý bởi Oracle Forms 

Clear Record Luôn có hiệu lực.



Delete Record (tương ứng với Edit / Delete trên menu) (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực khi block cho phép xoá.



Edit Field... (WHEN–NEW–ITEM–INSTANCE) Có hiệu lực khi item hiện tại là text item.



Zoom (WHEN–NEW–BLOCK–INSTANCE) Có hiệu lực nếu khách hàng định nghĩa 1 zoom cho block hiện tại



Translations Mặc định là không có hiệu lực. Người phát triển có thể enable/disable nó theo yêu cầu bằng cách sử dụng APP_SPECIAL.ENABLE.



Attachments (WHEN–NEW–RECORD–INSTANCE và WHEN–NEW–BLOCK–INSTANCE)



Folder Tools

101

Có hiệu lực nếu con trỏ ở trong 1 folder block; người phát triển phải viết code trong combination folder block. 

• Window Help Luôn có hiệu lực.

Các mục chỉ có trong Menu • Clear Form Luôn có hiệu lực. • Summary/Detail Mặc định là không có hiệu lực. Người phát triển có thể enable/disable theo yêu cầu bằng cách sử dụng APP_SPECIAL.ENABLE. • Save and Proceed Luôn có hiệu lực. • File / Exit Oracle Applications (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực nếu không ở trong chế độ enter–query. • Edit / Duplicate / Field Above (WHEN–NEW–ITEM–INSTANCE) Có hiệu lực nếu bản ghi hiện tại không phải là bản ghi đầu tiên • Edit / Duplicate / Record Above (WHEN–NEW–RECORD–INSTANCE) hiệu lực nếu bản ghi hiện tại không phải là bản ghi đầu tiên và trạng thái bản ghi là ‟NEW‟. Người phát triển phải customize hành động Duplicate Record trong trigger KEY–DUPREC mức form hoặc mức block. • Edit, Clear, Field (WHEN–NEW–ITEM–INSTANCE) Có hiệu lực khi item hiện tại là text item. • Edit, Clear, Block (WHEN–NEW–ITEM–INSTANCE) Luôn có hiệu lực • Edit, Clear, Form (WHEN–NEW–ITEM–INSTANCE) Luôn có hiệu lực • Edit, Select All • Edit, Deselect All • Edit, Preferences, Change Password • View, Find All (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực nếu block cho phép truy vấn và chưa ở trong chế độ enter– query.

102

• View, Query by Example, Enter (WHEN–NEW–BLOCK–INSTANCE) Có hiệu lực nếu block cho phép truy vấn. • View, Query by Example, Run (WHEN–NEW–BLOCK–INSTANCE) Có hiệu lực nếu block cho phép truy vấn. • View, Query by Example, Cancel (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực nếu ở trong chế độ enter-query • View, Query by Example, Show Last Criteria (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực nếu ở trong chế độ enter-query • View, Query by Example, Count Matching Records (WHEN–NEW–RECORD–INSTANCE) Có hiệu lực nếu block cho phép truy vấn. • View, Record, First Có hiệu lực nếu bản ghi hiện tại không phải là bản ghi đầu tiên • View, Record, Last Có hiệu lực nếu bản ghi hiện tại không phải là bản ghi đầu tiên • View, Requests • Window, Cascade • Window, Tile Horizontally • Window, Tile Vertically • Help, Oracle Applications Library • Help, Keyboard Help • Help, Diagnostics

Điều khiển menu động Để có thể tự điều khiển các menu trong các trường hợp đặc biệt Sử dụng thủ tục sau app_special.enable. Thủ tục này được thêm vào trong các trigger PRE–BLOCK hoặc WHEN–NEW–BLOCK–INSTANCE, WHEN–NEW–RECORD– INSTANCE WHEN–NEW–ITEM–INSTANCE

103

app_standard.event(‟TRIGGER_NAME‟); app_special.enable(‟Menu_item‟, PROPERTY_OFF|ON); Ví dụ : app_special.enable(‟CLEAR.FIELD‟, PROPERTY_OFF);

Ví dụ : Giả sử bạn có một chức năng là ‟Book Order‟mà bạn muốn thêm vào Menu và toolbar. Để thêm ‟Book Order‟là mục đầu tiên tương ứng với 1 icon trên toolbar Mà chỉ có hiệu lực với block Header trên form :

Bước 1 Sửa trong trigger PRE–FORM mức form: PRE–FORM app_special.instantiate(‟SPECIAL1‟, ‟&Book Order‟, ‟bkord‟);

Bước 2 Thêm 1 trigger PRE–BLOCK mức form: PRE–BLOCK app_special.enable(‟SPECIAL1‟,PROPERTY_OFF);

Bước 3 Thêm 1 trigger PRE–BLOCK mức block trong block nào bạn muốn enable các mục menu mới của bạn : PRE–BLOCK trong HEADER block app_special.enable(‟SPECIAL1‟,PROPERTY_ON);

Bước 4 Thêm 1 trigger SPECIAL (loại tự định nghĩa) mức block chứa code thực hiện chức năng ‟Book Order ‟ của bạn. Nó sẽ được thực thi khi người dùng chọn mục menu chức năng này. Các item sẽ được reset lại trong các block khác bởi default menu Mà ta không phải tự reset mỗi khi rời một block, record, item

Tạo các biểu tượng trên toolbar cho các form bạn customize Ta cũng có thể tạo icon riêng cho menu bằng các file .gif đặt tại thư mục Được tạo bởi virtual directory OA_MEDIA

104

Các menu đặc biệt Cut Copy Paste –––––– Folder –––––– Help Disable các menu đặc biệt Để disable tất cả các mục đặc biệt trên menu( như trong trường hợp query–mode) Sử dụng APP_SPECIAL.ENABLE(‟SPECIAL‟,PROPERTY_OFF);

Customize các Right–Mouse Menu (Popup Menus) Thêm các mục vào Right–Mouse Menu Dạng default của menu popup là như sau :

Ta hoàn toàn có thể thay đổi dạng mặc định của menu popup bằng cách thêm

105

Vào các entry mới gồm cả các đường ngăn cách như sau :

Sử dụng thủ tục sau : procedure APP_POPUP.INSTANTIATE( option_name varchar2, --„POPUP1‟=>‟POPUP10‟ txt

varchar2, ---

tên nhãn

initially_enabled boolean default true, ---„TRUE‟/‟FALSE‟ separator

varchar2 default null);

-------

„LINE‟)

Cut Copy Paste –––––––––––– Folder –––––––––––– First Entry Second Entry –––––––––––– Third Entry –––––––––––– Help

Các entry sẽ được thêm vào sau FOLDER và trước HELP.

Ví dụ : Bước 1

106

–––––––––––– Cut Copy Paste –––––––––––– Folder –––––––––––– First Entry –––––––––––– Second Entry Third Entry (disabled, so greyed out) –––––––––––– Help –––––––––––– Sửa trigger PRE–POPUP–MENU mức item trên trường Requisition Number (Execution Hierarchy : After). app_popup.instantiate(‟POPUP1‟, ‟Approve‟);

Bước 2 Thêm 1 trigger POPUP1 mức item (loại tự tạo) chứa code thực hiện chức năng của bạn. Nó thực thi khi user chọn mục menu tương ứng. Ví dụ APP_POPUP.INSTANTIATE(‟POPUP1‟,‟First Entry‟); APP_POPUP.INSTANTIATE(‟POPUP2‟,‟Second Entry‟, TRUE, ‟LINE‟); APP_POPUP.INSTANTIATE(‟POPUP3‟,‟Third Entry‟, FALSE); Kết quả sẽ là như sau :

107

Message Dictionary Tổng quan về Message Dictionary 

Thiết lập về Message Dictionary



Message Dictionary API đối với PL/SQL Procedures



Message Window.

Tổng quan về Message Dictionary Cho phép phân loại các message sẽ được đưa ra của form hay của ứng dụng Với Message Dictionary bạn có thể làm : -

Xác định các message tiêu chuẩn mà form hay ứng dụng sử dụng đến.

-

Cung cấp một cách nhìn và cảm nhận thống nhất đối với các message trong và giữa các ứng dụng.

-

Xác định các messge động có thể bao gồm context–sensitive variable text

-

Giúp dế dàng thay đổi và mà không phải biên dịch lại nội dung message trong ứng dụng.

Các điểm đặc trưng của Message Dictionary 

Có thể sửa đổi nội dung của message:

-

Dễ dang thay đổi thay đổi nội dung message trên một form duy nhất.

-

Các message có thể hiển thị dưới dạng dialog box hoặc dòng.



Dễ dàng biên dịch



Chuẩn hóa message

- Mỗi lần xác định một message trong Message Dictionary bạn có thể quy cho một form, concurrent Program hoặc module trong ứng dụng khác sử dụng tên message mà bạn đã xác định. Bạn có thể gọi Message bao nhiêu lần tùy ý và từ bất cứ nơi nào trong ứng dụng. Nếu bạn cần thay đổi nội dung message Bạn chỉ cần thay đổi ngay tại chỗ. 

Message text động

108

- Message có thể chấp nhận biến text động như trường hoặc tên module

Các bước cần tiến hành khi xác định Message Dictionary 

Tên Message.



Message(<1800 ký tự)



Số Message : Số sẽ xuất hiện cùng với message. Nếu bạn xác định một message number khác không Cho message , Dictionary ẽ thêm vào message tiền tố APP-



Mã thông báo biến : Một từ khóa bạn tạo ra để miêu tả một giá trị khi bạn xác định một message. Bạn chỉ rõ cùng một mã thông báo biến và giá trị của nó, khi gọi Message Dictionary từ một form hay một module chương trình. Message Dictionary sẽ thay thế mỗi mã thông báo biến trong message với giá trị hiện tại bạn đã

Chỉ rõ sau đó là hiện ra thông báo.

Thiết lập Message Dictionary 1.Tạo các thư mục message 2.Xác định message. 3. Tạo các file message Bước1 : Vào Application Developer responsibility vào cửa sổ Submit Requests Bước2: Chọn Generate Messages trong trường Name. Bước3: Trong cửa sổ Parameters, chọn ngôn ngữ cho file cần tạo. Bước4: Chọn tên ứng dụng tương ứng với file cần tạo. Mỗi ứng dụng đều phải có file message riêng của nó. Bước5: Chọn kiểu cho chương trình. Để tạo file message lúc runtime chọn DB_TO_RUNTIME. Bước6: Để trống Filename Parameter, message generator sẽ tạo một file với tên mặc định tiêu chuẩn trong thư mục mesg đối với ứng dụng trên phía server. Bước7: Copy file vừa tạo đến thư mục mesg hợp của ứng dụng trên mỗi máy cần thiết(concurrent processing servers, forms server machines). Tên file phải giữ nguyên tại mọi nơi. 4.Viết mã cài đặt các message.

109

Từ tạo một message và đưa tới người sử dụng gồm hai quá trình : đầu tiên phải cài đặt message( phía client) hoặc gọi nó từ phía server, sau đó trình bày tới người dùng (hoặc viết ra file đối với một concurrent program). Các hàm API phía client cho việc gọi và cài đặt các message: Các hàm này nằm trong package FND_MESSAGE. SET_NAME

Gọi message từ Message Dictionary và đặt nó trong message stack

SET_STRING Lấy một input string và đặt nó trong message stack.. SET_TOKEN Thay thế một message token bằng giá trị bạn đã tạo. RETRIEVE

Gọi một message từ buffer message phía server dịch và thay thế các token và đặt nó vào message stack.

GET(hàm)

Gọi một message từ stack message và trả về giá trị VARCHAR2.

CLEAR

Clear message stack.

Các hàm API phía server: Chỉ có một message được đặt trong bộ đệm phía server. SET_NAME

Đặt một tên message trong khu vực global.

SET_TOKEN Thêm một cặp token/value vào khu vực global. CLEAR

Clear message stack.

5. Viết mã display message. Mỗi lần bạn cài đặt hoặc gọi message và thay thế bất cứ token nào, tiếp theo display tới người dùng (trên form) hoặc viết ra file (database phía server đối với một concurrent program). Các hàm API để trình bày các message ở Form Server. Các hàm sau dùng trong các PL\SQL thủ tục trong form và trong các thư viện để trình bày các message : FND_MESSAGE.SET_NAME, FND_MESSAGE.RETRIEVE. Nếu cần thêm các icon để trình bày dùng các hàm sau : FND_MESSAGE.ERROR, FND_MESSAGE.SHOW, FND_MESSAGE.WARN, FND_MESSAGE.QUESTION

Phương pháp đối với Database Server–side Messaging. Có 3 phương pháp khác nhau không thể thay đổi để trình bày các message được thiết lập phía server: Phương pháp1 : Đặt một message error phía server, sẽ được trình bày phía client form mà gọi thủ tục phía server.

110

Trên phía server, sử dụng FND_MESSAGE.SET_NAME và FND_MESSAGE.SET_TOKEN để thiết lập message. Sau đó gọi APP_EXCEPTION.RAISE_EXCEPTION. Các lỗi này được trả về trigger ON–ERROR phía client. Phương pháp 2 : Đặt một message phía server, được trả về phía client Trên phía server sử dụng FND_MESSAGE.SET_NAME, FND_MESSAGE.SET_TOKEN. Phía client sử dụng FND_MESSAGE.RETRIEVE để lấy message từ phía server, đặt message lên message stack của client. Tiếp đó client gọi FND_MESSAGE.ERROR, FND_MESSAGE.SHOW, FND_MESSAGE.HINT, FND_MESSAGE.WARN để trình bày message hoặc FND_MESSAGE.GET để đặt message vào một buffer. Phương pháp 3 :Lấy một message vào một buffer trên server. Sử dụng FND_MESSAGE.SET_NAME, FND_MESSAGE.SET_TOKEN, FND_MESSAGE.GET để lấy một message vào một buffer hoặc FND_MESSAGE.GET_STRING để lấy một message đơn vào một sâu.

111

USER PROFILE User profile là tập hợp các tùy chọn có thể thay đổi làm ảnh hưởng đến cách thực hiện chương trình. Oracle Application Object Library đưa ra một giá trị cho mỗi tùy chọn trong một profile người dùng khi người dùng log on hoặc khi thay đổi Responsibility. Người dùng có thể thay đổi giá trị của tùy chọn profile bất cứ khi nào. Với tư cách là một nhà phát triển bạn thậm chí có thể xác định thêm các tùy chọn. Bởi vì có thể bạn không muốn người dùng có khả năng ghi đè giá trị lên giá trị bạn đã xác định, do đó bạn có thể xác định tùy chọn tại một trong các mức sau : Site, Application, Responsibility và User.

User

System Administrator

Application User

Responsibility

Application

Site

Các mức của User Profile: User có mức thứ thự cao nhất. Giá trị tùy chọn ở mức cao hơn thì ghi đè lên mức dưới nó. Mỗi tùy chọn user profile thông thường có ở tất cả các mức. Ví dụ Oracle Application Object Library cung cấp tùy chọn mức site cũng như mức Application là Printer. Do đó nếu mức Site Printer có giá trị là “New York” nhưng mức User có giá trị là “Boston” thì báo cáo sẽ được in ở Boston printer.

112

Định nghĩa mới các tùy chọn của user profile Sử dụng Profile Window

Thiết lập giá trị tùy chọn user profile Sử dụng System Administrator responsibility.

Thiết lập user profile riêng của bạn Sử dụng form Update Personal Profile Options

Xác định trước tùy chọn user profile 

Database Profile Options Oracle Application Object Library cung cấp nhiều tùy chọn user profile mà Oracle System Administrator hoặc người dùng có thể nhìn thấy cũng như cập nhật.



Các tùy chọn profile nội tại Bạn có thể thay đổi giá trị của các tùy chọn profile trong Oracle Application Object Library ở form hay chương trình tuy nhiên các ngoại trừ các profile CONC_PRINT_OUTPUT



CONC_PRINT_STYLE

kể

cả

System

administrators. Tên user Oracle Application Objec Library của

USERNAME

user hiện tại. USER_ID

user id

RESP_ID

responsibility ID hiện tại của user.

APPL_SHRT_NAME

short name của ứng dụng liên kết nối tới responsibility.

RESP_APPL_ID

application ID của ứng dụng kệt nối tới responsibility hiện tại.

FORM_NAME

tên của form hiện tại. Không tồn tại đối với concurrent programs.

FORM_APPL_ NAME

application ID của ứng dụng mà form được đăng ký

FORM_APPL_ID. LOGON_DATE. LAST_LOGON_

113

DATE. LOGIN_ID CONC_REQUEST_ID.

equest ID tương ứng với một thể hiện của chương trình hiện tại. Chỉ có thể dùng tùy chọn này trong một concurrent program

CONC_PROGRAM_ID

program ID tương ứng với một chương trình đang chạy. Chỉ có thể dùng tùy chọn này trong một concurrent program.

CONC_ PROGRAM_APPLICATION_ID CONC_LOGIN_ID

giá trị YES hoặc NO trong trường Print Output khi đăng ký một concurrent program.

CONC_PRINT_ STYLE

kiểu in đầu ra của concurrent program khi bạn nhập vào trường Print Style khi đăng ký một concurrent program.

Profile Window

114

115

FOLDER Tổng quan về Folder. Forlder là một chức năng hết sức đặt biệt trên form ứng dụng cho phép người sử dụng thiết lập các thuộc tính riêng. Nó sẽ lưu giữ một profile cụ thể để trình bày tên các promt cho các trường dữ liệu trên form bằng ngôn ngữ bản địa có sử dụng được Unicode. Một chức năng thứ hai là tự động sắp xếp các trường dữ liệu tự động (order by).

Lập trình với Folder trên form ứng dụng. Cụ thể các bước để có thể sử dụng được chức năng này như sau : 

Attach thư viện APPFLDR.



Thêm vào form chuẩn STANDARD_FOLDER Object group.



Tạo _RECORD_COUNT parameter: trong đó BLOCKNAME là tên của Block chứa cột dữ liệu cần thể hiện, Data Type là Number và giá trị default gán bằng 2.



Tạo 2 canvas : một cái là contain(VD đặt tên là FOLDER) một cái là stack(VD đặt tên là STACK). Cả hai canvas này có cùng một Window.



Tạo Block :

Block chính (BLOCKNAME) chứa các cột dữ liệu trong database. Tạo các thủ tục trong các trigger tương ứng với block này như sau : WHEN-NEW-BLOCK-INSTANCE app_folder.event('WHEN-NEW-BLOCK-INSTANCE');

KEY-PREV-ITEM if (:parameter._record_count = 1) then previous_item; else

116

app_folder.event('KEY-PREV-ITEM'); end if;

KEY-NEXT-ITEM if (:parameter._record_count = 1) then next_item; else app_folder.event('KEY-NEXT-ITEM'); end if; PROMPT Block: tạo một block PROMPT ( đặt trên stack là PROMPT_STACK kiểu là stack) chứa các promt cho các cột dữ liệu trong block chính đã tạo ở trên. Trong block này chứa các item có tên trùng với các tên cột trong block trên. Các item này có property class là : Ngoài ra cần phải tạo thêm các item khác là : Item

Name:

FOLDER_OPEN,

Item

Type:

Button,

Canvas:

PROMPT_STACK Item Name: FOLDER_DUMMY, Item Type: Text Item , Canvas: TOOLBAR Item Name: FOLDER_TITLE, Item Type: Display Item, Canvas: PROMPT_STACK Item

Name:

ORDER_BY1,

Item

Type:

Button,

Canvas:

Item

Type:

Button,

Canvas:

Item

Type:

Button,

Canvas:

PROMPT_STACK Item

Name:

ORDER_BY2,

PROMPT_STACK Item

Name:

ORDER_BY3,

PROMPT_STACK. 

Trên trigger mức Form :

FOLDER_ACTION --- Remove the message and uncomment the line after it

117

-- to activate the folder actions --- message('You must modify the FOLDER_ACTION trigger in your form!'); app_folder.event(:global.folder_action); WHEN-NEW-FORM-INSTANCE app_folder.define_folder_block('BLOCKNAME', -- 'Object Name' 'BLOCKNAME', -- 'folder_block', 'PROMPT', -- 'ten prompt_block', ' PROMPT_STACK, --'ten stacked_canvas', „WINDOW1‟, --' ten window', NULL); --'disabled functions'); Tuy nhiên khi sử dụng chức năng này của form thi khi di chuyển ra ngoài View port của BLOCKNAME rồi mới thực hiện chức năng order by thi hệ thống sẽ báo lỗi và ta không làm gì được nữa. (Qua tìm hiểu đây là lỗi của tất cả các Form trên ứng dụng sử dụng chức năng này.

118

ATTACHMENTS Đặc tính của Attachments Attachments cho phép người dùng liên kết những dữ liệu không có cấu trúc như là ảnh, tài liệu word, bảng tính, hoặc dữ liệu text với những dữ liệu của ứng dụng.

119

Related Documents

Application Oracle
November 2019 17
Application Form
June 2020 10
Application Form
April 2020 9
Application Form
October 2019 17
Application Form
June 2020 9

More Documents from ""

Almogaz.pdf
May 2020 10
Modo Uno.docx
June 2020 11
May 2020 11
146569.pdf
May 2020 12
May 2020 10