ヘッダーをスキップ

Oracle E-Business Suite開発者ガイド
リリース12.2
E53035-01
目次へ
目次
前のページへ
前へ
次のページへ
次へ

項目の動作のコーディング

項目関連

複合フォームには、Oracle E-Business Suiteのフィールド・レベル検証モデルに準ずるため、または特定のビジネス・ルールを適用するため、実行時に動的に行う必要のある多くの動作があります。

これらの例にならって、フォームの項目ハンドラおよびイベント・ハンドラをモデリングしてください。

無効な項目とWHEN-VALIDATE-ITEMトリガー

ほとんどの項目関連で、項目は動的に無効化および有効化されます。無効な項目について、Oracle Formsのコーディングに関する次の問題に注意してください。

従属項目

マスター項目が移入されたときにのみ有効となるテキスト項目、チェック・ボックス、またはポップリストを作成するには、プロシージャAPP_FIELD.SET_ DEPENDENT_FIELDを使用します。このルーチンにより次の動作が実行されます。

次の手順に従って項目ハンドラ・プロシージャを作成し、特定のトリガーからプロシージャをコールします。

重要: 表示専用のテキスト項目には、これらのルーチンは適用されません。条件によって表示専用のテキストをグレー表示するには、ルーチンAPP_ITEM_PROPERTY.SET_VISUAL_ ATTRIBUTEを使用します。

関連項目: APP_ITEM_PROPERTY:プロパティ・ユーティリティ

この例では、ブロックorderには項目item_typeitem_nameがあるものとします。Item_nameはitem_typeに従属しているため、item_nameはitem_typeがNULLではない場合にのみ使用可能です。

  1. 項目ハンドラ・プロシージャを次のように作成します。

     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;
    
  2. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    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');
    
  3. マスター項目および従属項目が複数行ブロックにある場合や、マスター・ブロックの詳細である単一行ブロックにある場合は、POST-QUERYイベントにSET_DEPENDENT_FIELDをコールする必要もあります。

    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;
    

    次の場所で項目ハンドラ・プロシージャをコールします。

    Trigger: POST-QUERY
    
    ORDER.ITEM_NAME('POST-QUERY');
    

    重要: マルチ・レコード・ブロックで、従属項目がレコードの最後の項目である場合、マスターからタブ移動すると次のレコードにカーソルがナビゲートします。この動作に対処するために、VALIDATE(Item_scope)を行ってからNEXT_ITEMを実行するKEY-NEXT-ITEMトリガーをコーディングします。

    重要: 従属項目が必須リストまたはオプション・グループの場合は、APP_FIELD.SET_DEPENDENT_FIELDへのコールで、無効なパラメータをTRUEに設定します。このフラグがTRUEに設定されていると、従属項目は消去されずに無効のマークが付けられます。

条件付き従属項目

条件付き従属項目は、マスター項目の特定の値に応じて有効、無効が決まります。この例では、ブロックorderに項目item_typeおよびitem_sizeがあり、Item_sizeはitem_typeが「SHOES」の場合にのみ有効となるものとします。

  1. 項目ハンドラ・プロシージャを次のように作成します。この項目ハンドラ・プロシージャは、マスターおよび従属の場合と非常に似ていますが、マスター項目名ではなく条件を指定する点に注意してください。

    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;
    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 IF;
    END size;
    END order;
    
  2. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    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');
    

複数従属項目

1つのマスター項目に複数の項目が従属していることがあります。たとえば、一定のitem_typesでのみ色やサイズを指定するという場合です。この場合、色のフィールドとサイズのフィールドはマスター・フィールドitem_typeに従属し、item_typeがRAINCOATのときにのみ有効となります。

  1. 項目ハンドラ・プロシージャを次のように作成します。

    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');
    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;
    
  2. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    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つのマスター項目と1つの従属項目

1つの項目が2つのマスター項目に従属しているということもあります。たとえば、サイズの違うセーターが色違いで売られているとします。この場合、item_typeとsizeの両方に値を入力した後で、初めてセーターの色を指定できます。block.dependentの検証はmaster_1とmaster_2の内容によって制御されます。

  1. 項目ハンドラ・プロシージャを次のように作成します。

    PACKAGE BODY order IS
    PROCEDURE item_type(EVENT VARCHAR2) IS
    BEGIN
    IF (EVENT = 'WHEN-VALIDATE-ITEM') THEN
    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;
    
  2. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    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):
    
    order.color('PRE-RECORD');
    

カスケード従属

カスケード従属とは、item_3item_2に従属し、さらにそれがitem_1に従属しているというものです。通常は、すべての項目が同じブロック内にあります。

たとえば、ブロックordervendor、siteおよびcontactの各項目があるとします。

有効なサイト・リストは、ベンダーによって決まります。

有効な連絡先リストは、現行サイトによって決まります。

次の手順に従って、これらの従属項目を正確に動作させるコードを作成します。

  1. 項目ハンドラ・プロシージャを次のように作成します。

    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
    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;
    
  2. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    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');
    

    VENDORフィールドが検証されると、常に次のような一連のイベントが発生することに注意してください。

相互排他項目

プロシージャAPP_FIELD.SET_EXCLUSIVE_FIELDを使用して、同時に1つの項目しか有効になることのできない2つの項目を設定します。

相互排他項目の項目ハンドラ・プロシージャをコーディングする際に重要なのは、2つの相互排他的項目は論理的には1つの項目であるという点です。相互排他項目の一方の項目がある項目に従属しているか、ある項目からの従属を受けているという場合、その関連はもう一方の項目にも適用されます。他の項目との関連は、どちらも常に同一です。したがって、1つの論理項目に対する単一の項目ハンドラ・プロシージャをコーディングします。

相互排他項目が両方ともNULLの場合は、どちらの項目もナビゲート可能です。一方の項目のみに値が入力されている場合、もう一方の項目にはナビゲートされず(ただし、そこでクリックすることは可能)、その項目にある値はすべて消去されます。

どちらかの項目をNULL以外にする必要がある場合は、Oracle Forms Developerで両方の項目のREQUIREDプロパティを「Yes」に設定します。どちらもNULLでよい場合は、両方の項目のREQUIREDプロパティを「No」に設定します。APP_FIELD.SET_ EXCLUSIVE_FIELDは、初期REQUIREDプロパティを読み取り、両方の項目のREQUIREDプロパティを動的に管理します。

さらに、3つの項目で構成される相互排他項目にも、プロシージャAPP_FIELD.SET_EXCLUSIVE_FIELDを使用できます。4つ以上の項目の場合は、独自のカスタム・ロジックを作成する必要があります。

重要: 相互に排他的なチェック・ボックスや必須リストでは、マウス操作が必要となります。

たとえば、ブロックlinesに相互排他項目creditdebitがあるとします。

  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;
    
  2. 項目ハンドラ・プロシージャを次のように作成します。

    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');
    

    WHEN-CREATE-RECORDトリガーは、相互排他フィールドの結果が必須である場合にのみ必要です。初期値では、このトリガーは必須とされているセットのすべての相互排他フィールドに設定されています。必要に応じて、値を入力してフィールドを再設定します。

相互包含項目

NULLではない項目が存在する場合に、すべて必須である項目のセットをコーディングするには、APP_FIELD.SET_INCLUSIVE_FIELDを使用します。

項目値の入力はどの順番でもかまいません。すべての項目がNULLの場合、その項目はオプションとなります。

プロシージャAPP_FIELD.SET_INCLUSIVE_FIELDでは、最大5つの項目を含む相互包含項目を設定できます。セット内の項目を6つ以上にする場合は、独自のカスタム・ロジックをコーディングする必要があります。

次の例では、ブロックpayment_infoに相互包含項目payment_typeamountがあります。

  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
    fnd_message.debug('Invalid event to
    payment_info.payment_type_ amount: ' || EVENT);
    END IF;
    END payment_type_amount;
    END payment_info;
    
  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に相互包含項目payment_typeおよびamountがあります。ブロックには2つのリージョンも含まれており、それぞれ小切手情報用とクレジット・カード情報用です。小切手情報の項目はcheck_numberのみです。クレジット・カード情報にはcredit_type、card_holder、number、expiration_dateおよびapproval_codeの5項目があります。

支払タイプには現金、小切手またはクレジット・カードがあります。

  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',
                                       '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');
          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;
    
  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');
    

条件付き必須項目

プロシージャAPP_FIELD.SET_REQUIRED_FIELDを使用して、ある条件を満たした場合にのみ必須となる項目をコーディングします。この項目では、条件がFALSEの場合はその従属項目はオプションとなり、従属項目内の値は消去されません。ある項目が条件付きで必須であり、かつ従属項目である場合には、APP_FIELD.SET_REQUIRED_FIELDをコールする前にAPP_FIELD.SET_DEPENDENT_FIELDをコールします。

次に示すのは、APP_FIELD.SET_REQUIRED_FIELDの使用例です。

ブロックpurchase_orderに、項目totalvp_approvalがあるとします。Vp_approvalは合計金額が10,000ドルを超えた場合に必須となります(注意: quantity * unit_price = total)。

  1. 項目ハンドラ・プロシージャを次のように作成します。

    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;
    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;
    
  2. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    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');
    

デフォルト

新規レコードのデフォルト

新規レコードの作成時にデフォルトの設定値を適用するには、Oracle Forms Designerのデフォルト値プロパティを使用します。より複雑なデフォルト動作を設定するには、次の例に従います。

  1. イベント・ハンドラ・プロシージャを次のように作成します。

    PACKAGE block IS
       
       PROCEDURE WHEN_CREATE_RECORD IS
       BEGIN
          :block.item1 := default_value1;
          :block.item2 := default_value2;
           ...
       END WHEN_CREATE_RECORD;
    
    END block;
    
  2. 次のトリガーを使用して、イベント・ハンドラ・プロシージャをコールします。

    Trigger: WHEN-CREATE-RECORD: 
    
    block.WHEN_CREATE_RECORD;
    

レコードの入力時におけるデフォルト値の適用

有効性が別の項目に依存している項目のデフォルトを設定する場合(マスター値を変更した場合にデフォルトを適用する場合など)は、従属項目のINITイベント内でデフォルト値を設定します。

整合性チェック

この項では、次の項目の処理方法を説明します。

一意性チェック

キーの一意性チェックを行うには、WHEN-VALIDATE-ITEMによってコールされるSELECT文を使用します。

WHEN-VALIDATE-ITEMで実行される一意性チェックでは、コミットされていない行の重複は検出されない点に注意してください(たとえば、詳細ブロックにコミットされていない重複行を入力した場合など)。これは、WHEN-VALIDATE-ITEMが起動してレコードがコミットされるまでの間に別のユーザーが同一のキーをコミットするのと同様、データベース制約によって検出されます。そのため、PRE-UPDATEまたはPRE-INSERTに一意性チェックを書き込む必要はありません。

例:

 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;

項目ハンドラ・プロシージャを次のように作成します。

 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;

参照整合性検査

レコードを削除する場合、そのレコードが他のレコードによって参照されている可能性を考慮する必要があります。たとえば、ある項目がすでに発注上で参照されており、その項目を削除する場合、次の3つの対処方法が考えられます。

ほとんどの項目では、最初の方法が最も実用的かつ合理的です。これを適用するには、参照の有無を検出して例外を呼び出すプロシージャを作成します。

詳細削除前の警告の設定

詳細レコードを削除する前に警告を出すには、詳細レコードが存在する場合はFALSEを返すファンクションとしてCHECK_REFERENCESを作成します。(参照整合性エラーが発生する行を削除する場合でも、CHECK_REFERENCESは例外を呼び出します。)

表にサブタイプが含まれている場合は、CHECK_REFERENCESプロシージャは1つあればよいのか、各サブタイプに1つずつCHECK_REFERENCESプロシージャが必要なのかを判断する必要があります。

サブタイプが、外部キー参照のほとんどをサブタイプ固有の外部キー参照と共有している場合は、最初のパラメータがサイブタイプ弁別子のCHECK_REFERENCESプロシージャを1つ作成します。

サブタイプが直交している場合は、各サブタイプにCHECK_subtype_REFERENCESプロシージャを作成します。

参照整合性検査の例

  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
              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;
    
  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;
    
  3. イベント・ハンドラをコールします。

    Trigger: KEY-DELETE:
    
    block.dey_delete;
    

    ヒント: ON-DELETEトリガーで同じステップを再実行します。これは、削除の要求が出されてから実際にトランザクションが保存されるまでの間に別の場所にレコードが入力されて、参照整合性の問題が発生する可能性があるためです。ユーザーによる削除の開始に呼応してKEY-DELETEが起動しますが、この時点で実際に削除が行われるわけではないことに注意してください。この時点では削除するものとしてレコードにフラグが立てられ、画面から消去されるのみです。実際の削除は、コミット時にON-DELETEトリガーが起動した時点で行われます。

カレンダ

カレンダ・オブジェクトは、カレンダから日付および時間の値を選択するための標準オブジェクトです。さらに、開発者は有効な日付のみを選択可能にする検証規則を指定することもできます。どの日付フィールドでも、リスト機能や編集機能でカレンダを起動できます。

フォーム内の各日付フィールドに、ユーザーがカレンダ機能をコールするのに必要なコードを作成します。ただし、カレンダはフィールド内にあるデータの検証の代替機能にはなりません。

カレンダは、自動的にTEMPLATEフォームに含められます。

カレンダのユーザー・インタフェース標準の詳細は、Oracle E-Business Suiteフォーム・ベース製品のユーザー・インタフェース標準を参照してください。

日付フィールドおよび日時フィールドのLOV

日付および日時フィールドでは、「リスト」ランプが有効になっています。これらのフィールド上でリストを実行すると、フォームに「カレンダ」ウィンドウが開きます。

日付フィールドには、ENABLE_LIST_LAMP LOVを使用する必要があります。これはTEMPLATEフォーム内にあります。この設定によって、日付フィールドのメニューと「ツールバー値リスト」エントリが使用可能になります。このLOVを使用するフィールドでは、「リストで妥当性チェック」を「No」に設定します。「リストで妥当性チェック」を「Yes」のままにしておくと、LOVに列が表示されません。

必須コール

フォーム内のすべての日付フィールドに、次のコーディングを行う必要があります。

Trigger: KEY-LISTVAL:
calendar.show([first_date]);

デフォルトでは、カレンダを最初に開くと日付フィールドの値(値がある場合)の月が表示されます。フィールドに日付がない場合は、現在の月のカレンダが表示されます。

フィールドの有効性検査が強制されてしまうので、現行フィールドをパラメータとしてCALENDAR.SHOWに渡さないでください。現行フィールドは、デフォルトとして使用されます。通常、KEY-LISTVALのコードは次のとおりです。

calendar.show;

重要: カレントの日付フィールドを、引数としてCALENDAR.SHOWに渡さないでください。カレンダは実際にはすべてのOracle Forms有効性検査を一時的に使用不可にするため、無効な日付を入力すると即時にカレンダが起動し、PL/SQLエラーが発生します。引数が渡されていない場合は、このような状況はSHOWによって自動的に処理されます。

KEY-LISTVALトリガーの実行階層は「オーバーライド」とし、問合せ入力モードでは起動しないようにします。

関連項目: CALENDAR: カレンダ・パッケージ

表示専用モード

カレンダは、表示専用モードでも起動できます。その場合、特定の日付を選択するというより、選択済の複数の日付を表示するために使用されます。たとえば、ある従業員が休暇を取った日をすべて表示できます。

このモードでは、カーソルがあるフィールドの特性は無視されます。すべてのユーザーができる操作は、表示する月や年を変更することと、「OK」を押してウィンドウを閉じることのみです(値がフォームに書き込まれることはありません)。

このモードを起動するには、前述のものに加えて次のコールが必要です。

Trigger: KEY-LISTVAL:
calendar.setup('DISPLAY');
calendar.setup('TITLE', null, null,
               '<translated text for window title>');

日付を選択されたものとして表示するには、これらの2つに加えてCALENDAR.SETUPコールが必要です。

拡張カレンダ・オプション

カレンダのコールにオプション機能を組み込むこともできます。オプション・コールを使用する場合は、必ずcalendar.showの必須コールの前に配置します。

次の例では、カレンダをカスタマイズして特定の日付を表示または使用不可にします。

「カレンダ」ウィンドウ内で週末を使用不可にする方法

週末(ここでは土曜日と日曜日として定義)を使用不可にするには、次のようにコーディングします。

calendar.setup('WEEKEND');

特定の日付範囲を使用不可にする方法

ハードコードされているか、フォームの他のフィールドで参照されている特定の日付範囲を使用不可にするには、次のようにコーディングします。

calendar.setup(<30 char identifying name>, <low_date>,
  <high_date>);

このコールは必要な回数繰り返すことができます。NULL値のLOW_DATEは期間の開始として、NULL値のHIGH_DATEが期間の終了として処理されます。

表中の特定の日付範囲を使用不可にする方法

表にある特定の日付範囲を使用不可にするには、次のようにコーディングします。

calendar.setup(<30 char identifying name>, null, null, <SQL>);

このコールをフィールドに対し1回実行した場合でも、複数の行が返される場合があります。NULL値のLOW_DATEは期間の開始として、NULL値のHIGH_DATEは期間の終了として処理されます。この動作を行わないようにする場合は、SQL文でNVLを使用します。

UNION SQL文を使用すると、複数の表からの制約を実行できます。選択した列に、LOW_DATEおよびHIGH_DATEという別名を付ける必要があります。

ヒント: LOW_DATE列の順序付けを行うと、パフォーマンスが向上する場合があります。同様に、予想される選択値を含む狭い範囲を返すように日付を制限することも、パフォーマンスの向上に繋がります。

非DATEフィールドからのカレンダのコール

DATEまたはDATETIMEとして明示的に宣言されていないフィールドからカレンダを有効化できる必要がある場合(たとえば、文脈によって様々な目的に使用されるCHARテキスト項目など)でも、通常どおりカレンダのコールを記述します。カレンダはDATEフィールドから起動したときと同様に機能し、ユーザーが値を選択すると、日付は「DD-MON-YYYY」の書式でフィールドに書き込まれます。

その後、ユーザー命名トリガーCALENDAR_WROTE_DATEが起動します。トリガーを項目レベルで作成し、値処理に必要なコードを追加します(通常は、マスクを適用する必要があります)。

カレンダの例

例: 平日のみ

この例では、現在DATE項目に表示されている日付か、日付が表示されていない場合は現在月を表示するカレンダを開きます。さらに、週末(土曜日と日曜日)を使用不可にします。

トリガー: KEY-LISTVAL:

calendar.setup('WEEKEND');
calendar.show;

例: 操業日のみを含める

フィールドSHIP_BY_DATEのフォームでカレンダを開き、次のようにカスタマイズします。

これを実装するコードは次のとおりです。

トリガー: KEY-LISTVAL:

calendar.setup('WEEKEND');
calendar.setup('Manufacturing Holidays', null, null, 
                 'select action_date LOW_DATE,
                 action_date HIGH_DATE '||
                 'from org_holidays where 
                 date_type = ''HOLIDAY''');
calendar.show(:lines.need_by_date);

例: 一定の日付範囲を使用可能にする

フィールドNEED_BY_DATEのフォームで、フォールドLINES.CREATED_DATEの日付から30日後の日付に対応する月のカレンダを表示するとします。さらに、LINES.CREATED_DATEの日付とそれ以前のすべての日付を使用不可にします。

これを実装するコードは次のとおりです。

トリガー: KEY-LISTVAL:

calendar.setup('After created date', null,
                 lines.created_date);
calendar.show(:lines.need_by_date + 30);

例: 表示専用のカレンダ

フォームで「休日」というボタンを使用して、すべての製造休業日を表示します。最初に現在の月が表示され、次にORG_DATES表で選択された日付が検索されます。

これを実装するコードは次のとおりです。

トリガー: HOLIDAYS上のWHEN-BUTTON-PRESSED:

calendar.setup('TITLE', null, null,
          '<translated text for "Manufacturing Holidays">');
calendar.setup('Manufacturing Holidays', null, null, 
     'select action_date LOW_DATE, action_date HIGH_DATE '||
     'from  org_dates where date_type = ''HOLIDAY''');
calendar.show;

CALENDAR: カレンダ・パッケージ

フォームへカレンダ情報をコーディングする標準的な方法とコーディング例は、「カレンダ」を参照してください。

CALENDAR.SHOW

要約

PROCEDURE show (first_date date default null);

説明

このコールによりカレンダが表示されます。現行フィールドの値をshowに渡さないでください。この値はデフォルト値として使用されます。

CALENDAR.SETUP

要約

PROCEDURE setup (new_type varchar2,
                 low_date date DEFAULT null,
                 high_date date DEFAULT null,
                 sql_string varchar2 DEFAULT null);

重要: WEEKEND引数は土曜日と日曜日としてハードコードされています。そのため、週末を金曜日と土曜日としている国などでは適用できません。

CALENDAR.EVENT

要約

PROCEDURE event (event varchar2);