首页 > 开发 > Retek From开发框架

Retek From开发框架

概述:

      Retail 为Form开发提供了一个模板 fm_temp1.fmb ,在/d01/app/retail/rms/app/rms/forms/src目录下,该文件基本上已经将retail form涉及到的底层代码写好(比如实现多语言的调用等),我们在开发一个新的form的时候,只要在该模板的基础上实现自己的业务逻辑就行了。

      另外,还有一个模板fm_date.fmb,用来做和日期相关的操作,最常见的是做LOV。比如,和ebs一样,我们需要选择日期,弹出一个选则日期的LOV,就要用到这个文件。

      Retail的form界面风格和EBS有点不同,给我的总体感觉是布局比较灵活,比较接近我们客户化的风格。它的一个block在界面上显示出来的字段一般比较少,现在还没有发现使用folder的情况。

 

1. 开发一个新的form,需要开发那些文件。

    按Retail的习惯,开发一个新的form,一般需要开发下面三个文件。

1).fm_XXX_find.fmb[可选]

        查找form,在打开“真正”的业务处理form fm_XXX.fmb之前,需要打开这个查找form,该form的作用是选择本次操作的类型,一般有三种类型,查看,编辑,新建。如果是“新建”,则直接打开form_XXX来新建业务;如果是“查看”,则通过该form查到到业务记录,调用fm_XXX查看业务细节,fm_XXX的项都是不可编辑的;如果是“编辑”,则调用fm_XXX查看业务细节,并对业务细节进行编辑。

       使用fm_XXX_find,是因为Retail form中没有EBS的 F11,Ctl+F11等快捷键,也没有EBS中“查找”窗体。我们也可以不使用这个form,只要在打开form fm_XXX.fmb的时候能够确定本次操作是查看,编辑或者新建就好了。比如,同一个form我们需要不同权限的人来打开,有的权限是查看,有的是编辑,有的是新建。这时候,我们只要在菜单上给每个权限挂不同的菜单项,对没个菜单项设置打开form的默认操作即可。

    2).fm_XXX.fmb

        这是实现业务逻辑的主要form。改form由fm_XXX_find.fmb调用open_form打开,open_form会使用一些参数,比如打开新form的状态是view,edit或者是new。

    3).me_XXX.mmb[可选]

        每一个form都对应一个菜单,当然,如果改form上不需要额外的菜单,在设置form对应的菜单的时候,就将该form的菜单设置为公用菜单:rtkform(参考 客户化Form挂到RMS中步骤,Menu中的 Form名和实际的Form名对应关系)

 

2. 开发form的细节

 

   1). 命名规则:

     Block     一般命名为 B_XXX,

     Cavans 一般命名为 C_XXX,

     Window一般命名为 W_XXX这样的形式。

      

   2). 多语言的实现:

       Retail的多语言,和ebs不同。ebs是在不同的语言环境放置不同语言的form程序,retek则只有一个form程序,它将需要显示给用户看的项的label,存放在数据库的特定表里,如果一个项有多种语言,则一个项在表里就有多条记录,当form启动的时候,在Form级WHEN-NEW-FORM-INSTANCE 触发器中,通过P_FORM_STARTUP->P_INITIALIZE 将Form中的每个Item和Item对应Label项取出来(在fm_temp1中已经写好了),我们要做的是将这些项和它们对应的语言手工取出来,放入数据库的特定表中。

       Form的多语言:

       Form的语言是放在表form_elements_langs和form_elements中的。

其获取语言的sql如下:

select fe.block_name,
          fe.item_name,
          fe.sub_item_name,
          fe.item_type,
          nvl(fel.lang_label_prompt, fe.default_label_prompt) label_prompt,
          nvl(fel.lang_access_key,fe.default_access_key) access_key ,fel.lang
     from form_elements_langs fel,
          form_elements fe
    where fe.fm_name = 'FM_ORDHEAD'/*I_form*/--by Form
      and upper(fe.fm_name) = upper(fel.fm_name(+))
      and upper(fe.block_name) = upper(fel.block_name(+))
      and upper(fe.item_name) = upper(fel.item_name(+))
      and upper(fe.sub_item_name) = upper(fel.sub_item_name(+))
      and 8/*L_user_lang*/ = fel.lang(+)--by user Language
      and fe.default_label_prompt is not NULL;

所以,我需要向表form_elements_langs和form_elements中插入每个需要显示项的信息。比如,在供应商维护form(SUPVWEDT)中有一个供应商代码(SUPPLIER)字段,查询这两个表

select * from  form_elements where fm_name='FM_SUPVWEDT' and item_name='SUPPLIER'

FM_NAME    BLOCK_NAME    ITEM_NAME    ITEM_TYPE    SUB_ITEM_NAME    DEFAULT_LABEL_PROMPT    DEFAULT_ACCESS_KEY    BASE_IND
FM_SUPVWEDT    B_SUPS    SUPPLIER    Text Item    NONE    Supplier        Y

字段描述:

FM_NAME:          FM_||Form文件的名字

BLOCK_NAME:    该项(SUPPLIER)所在的block名字,如没有,就写"NONE"

ITEM_NAME:       该项(SUPPLIER)名

ITEM_TYPE:        项的类型,这里是 Text Item,还有Push Button,Window,LOV等很多,这里一定要写正确项的类型。

SUB_ITEM_NAME: 子项,目前我写的还没用到

DEFAULT_LABEL_PROMPT: 如果表form_elements_langs中没有设置语言标签,则用这个。

DEFAULT_ACCESS_KEY :   快捷键

BASE_IND:         目前还没搞清是什么意思,表里设置的都是'Y'

 

上面这个表里,是设置form拥有元素,实现多语言,还需要在表form_elements_langs中插入数据。

这个表结构和form_elements差不多,只不过少了字段ITEM_TYPE,多了Lang字段,Lang字段就是语言的种类。目前取值有8(中文)和1(英文)。

 

这样,一个form可视项的多语言就设置成功了。

Retail这样设置多语言,感觉太麻烦,每一个项都这样设置一遍,一个form的工作量很大的。

 

       Menu的多语言:

和form差不多,它的表示menu_elements和menu_elements_langs。

 

   3).Form初始化:

      Form的初始化,写在Form的WHEN-NEW-FORM-INSTANCE触发器中。调用的主要过程有:

      P_FORM_STARTUP->P_INITIALIZE、P_BOILERPLATE,这几个procedure都是fm_temp1中写好的,我们不用改变。我们需要添加的是自己的逻辑。

      A. 初始化List Item

          初始化List Item,要调用P_POPULATE_LIST(p_item_name varchar2,p_para varchar2),这个过程(该过程原型在stand45中),比如:P_POPULATE_LIST('B_apply.LI_cons_rev_freq', 'GCRF')中,'B_apply.LI_cons_rev_freq'指List Item的名(一定要加上block的名),'GCRF'是表code_detail里的code_type字段。基本原理是该过程先定义一个cursor:

select code,code_desc from code_detail where code_type='GCRF',然后把code和code_desc赋给List Item,所以,List Item的动态值都来源于code_detail,做一个新的List Item之前,需要向这边表里插入数据。

 

   4).Show错误提示:

     显示错误提示,使用函数emessage(p_msg varchar2)如:

     emessage('This_is_a_err_msg');

     raise form_trigger_failure;

     错误提示也是分多语言的。所有的提示信息都放在rtk_errors表中,表里有一个三个重要字段

     rtk_key: 比如这里的'This_is a err_msg'

     rtk_lang: 语言

     rtk_text:  提示信息;

     比如在这个表里存在下面两条记录,则根据不同语言环境提示rtk_text的内容:

     rtk_key                           rtk_lang                        rtk_text  

     This_is_a_err_msg          1                                  This is a err msg

     This_is_a_err_msg          8                                  这个是错误信息

     如果表里没有对于的提示信息,则直接显示emessage('This_is_a_err_msg')中的参数,即'This_is_a_err_msg'

     注:该过程原型:
        PROCEDURE EMESSAGE     (I_key varchar2,
            I_txt_1 varchar2 := null,
            I_txt_2 varchar2 := null,
            I_txt_3 varchar2 := null) IS
            l_ret_val    BOOLEAN;
        BEGIN
           L_ret_val := RMESSAGE.SHOW ('ALT_ERROR', I_key, I_txt_1, I_txt_2, I_txt_3);
        END;

 

   5).Lov:

       Retek的Lov的展现一般不会像ebs中,ebs中,一般是鼠标落在某个text item的项上,弹出某个lov,retek是在这个项的后面有一个按钮,当点击这个按钮的时候,会弹出一个lov,选择lov中的东西,吧选择的东西赋值给该item。

       创建一个Lov的过程:

       Step1. 建立一个Lov,指定其返回给那些项。

       Step2. 在该需要Lov的Text Item的后面加一个按钮项(按钮项的图标:日期按钮的图标名称 calendsm,一般Lov 按钮的图标名称 listval,备注按钮的图标名称 smaltalk)

       Step3. 在按钮下写如下代码:

        Go_Item('B_ordhead.supplier');--先把光标移到Text Item上
        Do_Key('List_Values');--显示Lov

        刚才忘写了,创建弹出日期的Lov过程:

        step1. 打开我们自己写的form的同时,打开fm_date.fmb(这个文件是标准程式)。

        step2. 将fm_date下Object Group下的OG_DATE,拖动到自己的Object Group下,回弹出提示,这时选择“复制”。

        step3. 将calend45.pll添加进来。

        step4. 添加显示日期的text Item的when-new-item-instance事件:

       

        另外,有一种情况也需要注意:

        当需要根据不同的情况,动态显示不同的LOV。比如一个Text Item项里,但参数Para1为'学生'时,调用'学生'Lov(LOV_STUDENT),当Para1为'教师'时候,显示'教师'LOV(LOV_TEACHER)。这种情况,需要在Text Item的KEY-LISTVAL触发器中添加如下代码:

if :P ara1= '学生' then
      if F_SHOW_LOV(LOV_STUDENT') then
         Do_Key('Next_Item');
      end if;
elsif :P ara1= '教师' then
      if F_SHOW_LOV(LOV_TEACHER') then
         Do_Key('Next_Item');
      end if;

............

end if;

         F_SHOW_LOV函数定义在stand45中。

BEGIN
   Validate(Item_Scope);
   if not FORM_SUCCESS then
      raise FORM_TRIGGER_FAILURE;
   end if;
   ---
   if (P_CALENDAR.LP_date_ok is not NULL) then
      if (P_CALENDAR.LP_date_ok = 'Y') then
         :B_MAIN.TI_SETTLEMENT_DATE := P_CALENDAR.LP_current_date;
         P_CALENDAR.LP_date_ok := NULL;
         Do_Key('Next_Item');
      else
         P_CALENDAR.LP_date_ok := NULL;
      end if;
   end if;
EXCEPTION
   when FORM_TRIGGER_FAILURE then
      raise;
   when OTHERS then
      emessage(SQLERRM);
      raise FORM_TRIGGER_FAILURE;
END;

        step5. 添加显示日期的text Item的key-listval事件:

DECLARE
   L_return_to     VARCHAR(256) := 'B_main.TI_settlement_date';
   L_min_date      DATE := NULL;
   L_max_date      DATE := INTERNAL_VARIABLES.GP_vdate;
   L_default_date  DATE := INTERNAL_VARIABLES.GP_vdate;
BEGIN
   Validate(Item_Scope);
   if not FORM_SUCCESS then
      raise FORM_TRIGGER_FAILURE;
   end if;
   ---
   P_CALENDAR.SHOW_CALENDAR(L_return_to    => L_return_to,
                            L_default_date => L_default_date,
                            L_min_date     => L_min_date,
                            L_max_date     => L_max_date);
EXCEPTION
   when FORM_TRIGGER_FAILURE then
      raise;
   when OTHERS then
      emessage(SQLERRM);
      raise FORM_TRIGGER_FAILURE;
END;

 

step4. 在触发按钮下写如下代码:

        Go_Item ('B_main.TI_settlement_date');
        Do_Key ('List_Values');

 

   6).新增菜单

      retail的菜单是通过菜单文件(.mmb)来实现的。其真正的事件是代码是在form中,菜单只调用form中的代码。下面以一个例子来说明:
       这个例子演示的是增加 供应商维护--〉选项 菜单中,增加“联营保底”,其form文件是supvwedt.fmb,菜单文件是supplier.mmb.
      step 1. 新建(修改)Menu
        (我们以supplier.mmb来说明,这个文件已经存在,我们来修改它既可)
        在菜单OPTIONS_MENU下新增一个项:
        name :  GML_CONS_MARGIN
        lable : &Consignment Attributes--其实这里的不准,因为我们后面还会改变它的lable
        Menu Item Type : Plain

      step 2. 在该Menu下写事件

         Execute_Trigger('T_cons_margin');--T_cons_margin是在form中定义的

      step 3. 在Form中写事件
         在 supplier.mmb 中增加form级trigger
         name : T_CONS_MARGIN
         execution Hierarchy : Override
         其他默认
         事件代码:

         declare
         ............
         begin
         ..........
         Open_Form('gmlconsmrgn', --你自己的事件就写到这里就行了。
                ACTIVATE,
                SESSION,
                L_pl_id);
         ...........
         exception ....
         ..
         end;

      step 4. 编译form和Menu
        编译form的步骤以前写的有,编译Menu的脚本和form一样,只是将
        frmcmp.sh userid=$UP module=supvwedt module_type=form /****   编译form    */
        换成
        frmcmp.sh userid=$UP module=supplier module_type=menu /****   编译Menu    */
        编译好后,将生成的.fmx和.mmx放到bin目录下去
注意:如果没有编译菜单文件生成.mmx并放入bin目录下,则菜单虽然会挂上去,但点击所有的菜单都没有任何事件响应。

      step 5. 支持多语言
        首先,执行
        select * from menu_elements where menu_filename='supplier' for update;
         可以看,菜单选项就是放这个表里的。
        字段含义:
        menu_filename            菜单文件名
        menu_name                菜单名
        menu_item_name            菜单选项名--这里我们一般使用英文,随便取一个名字,假设我们取 GML_CONS_MARGIN
        default_lable            默认提示标签--如果语言设置里没有找到对应语言的标签,就会用这个
        base_ind                目前我也不知道是什么含义,把它设为'Y'
        所以,在上面的表里增加一行menu_name 取OPTIONS_MENU(因为我们要挂在“选项”下),menu_item_name 取 GML_CONS_MARGIN,default_lable 取&GML_CONS_MARGIN

        其次,在执行
        select * from form_menu_link where menu_filename='supplier' for update
        可以看到,这个表里存放的是menu和form的关系。因为这form和menu的关系已经存在,我们不去修改它。
        再次,执行
        select * from menu_elements_langs where menu_filename='supplier' for update
        这个表就是存放多语言的关系了。它和menu_elements的字段含义差不多,只不过多了一个语言
        我们增加一行,语言设置成中文(字段值为8)

     最后运行下边的sql检查多语言是否设置成功

     select me.menu_name,
          me.menu_item_name,
          nvl(mel.lang_label, me.default_label) label
     from menu_elements_langs mel,
          menu_elements me,
          form_menu_link fml
    where upper(fml.fm_name) = upper('fm_supvwedt')---form名
      and upper(fml.menu_filename) = upper(me.menu_filename)
      and upper(me.menu_filename) = upper(mel.menu_filename(+))
      and upper(me.menu_name) = upper(mel.menu_name(+))
      and upper(me.menu_item_name) = upper(mel.menu_item_name(+))
      and 8/*L_user_lang*/ = mel.lang(+)--语言
      and mel.menu_item_name = 'GML_CONS_MARGIN'--菜单选项
      and mel.menu_name = 'OPTIONS_MENU';--菜单名

    如果能查到一条数据,就说明多语言设置已经成功了。

注:未完成,有时间再继续.....

 

 

关于作者:

昵称:jeff.huang
档案信息:
联系方式:你可以通过hong.huang@hand-china.com联系作者
点击查看jeff.huang发表过的所有文章...
本文永久链接: http://blog.retailsolution.cn/archives/1882

 

 

对本文的评价:

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading ... Loading ...

 

 

分类: 开发 标签:
  1. 叶德华
    2014年8月26日13:58 | #1

    正在百度中找retek的calend45就发现商老大这一篇文章,正好来系统的了解下retek框架。

  1. 2014年5月5日22:28 | #1
您必须在 登录 后才能发布评论.