首页 >> 大全

Oracle Mobile Web Application (MWA) 学习小结

2023-12-04 大全 21 作者:考证青年

MWA个性化说明

Chain (MSCA) 是供应链管理解决方案的一部分,让用户能够移动操作。使用手持式射频(RF)设备和叉车安装射频扫描仪,保证 数据的准确性和增加流动性,同时便利而又简化操作,减少人为错误。

知识前提:了解并熟悉MWA开发

业务场景:在实际开发中,我们经常会遇到客户提出如字段默认,自动enter,扫描批次转物料等PDA常用个性化需求,这些需求虽小,但确实可以减少客户的工作量和提高客户操作的效率;

实现方式:

客户化开发,修改对应客户化开发适应个性化需求,标准界面修改源码风险较大;需要反复修改源码,重启端口,较繁琐(不推荐);MWA个性化配置界面,个性化配置界面配置字段默认,字段扫描转换,字段自动enter等相关个性化,方便,快捷,无需重启端口,顾问都可以设置简单个性化(推荐);修改标准.class文件增加个性化,MWA配置界面还是有一些限制性,比如说:界面增加字段,替换LOV,清除标准字段默认值等,这时,我们就需要修改专门为MWA开发设计的个性化文件实现需求; MWA个性化配置界面使用说明 配置界面安装

安装列表:

安装方式:perl脚本安装,将code文件夹上传服务器,perl .pl安装,这里不做详细说明;安装完后检查无效对象并运行on.sql。

注意:其中cux,inv,mwa文件要对应安装到服务器的$//apps/路径下去,其中会替换几项标准文件,安装前请备份(备份文件有:inv文件中和mwa文件夹中文件);

安装结束后配置配置文件:

将图上两个配置文件在地点层设置为:是,启用个性化,其中 MWA:预处理扫描的输入 是开启字段预扫描的个性化设置,如:字段的装换及防呆都是需要开启这个配置文件。

安装和配置结束后,重启端口,以生效个性化配置界面。

个性化配置界面如下:

配置界面使用说明

配置界面是针对功能去实现个性化的,所以头上是功能选择项;针对功能个性化配置共分三个TAB页面,分别是字段,属性,验证。

字段

字段TAB页是我们维护需要对功能界面需要实现个性化功能的所需字段,以前字段相关属性的设置;字段设置的属性有:隐藏,必输,只读及启用值来源,其中启用值来源是配置后面字段分割需要,将在属性TAB结合实际案例说明。

说明:其中字段名需要我们从PDA各功能登录界面获取。

登录功能界面,如上图,按Ctrl+X进入页面信息界面,可看到当前页面的功能名及各个字段名,如下图所示:

如界面字段显示不全,可通过键盘向下按键显示更多字段名称,字段TAB页的字段名称和此界面获取的字段名称一致就好,然后我们就可以在配置界面字段TAB页设置这些字段的相应属性,如只读,必输,隐藏等,非常方便。

属性

属性TAB页我们可以设置字段的一些处理(字段名称必须在字段TAB页维护才能选到),值来源类型分:值字段,字段,表达式,字符,转换及无,下面对各个类型进行详细说明:

a. 值字段

值字段需要和字段属性TAB启用值来源和值分割符使用,如下图

图中,我们对确认子库字段启用值来源,值分割符为英文逗号,然后我们再属性页面配置值来源类型为值字段,设置如下图所示:

我们设置确认子库和输入字段确认子库按值分割符分割的第一部分给值,分割的第二部分给确认货位;

效果,确认子库输入如下图所示:

按回车,效果如下:

_Oracle Mobile Web Application (MWA) 学习小结_Oracle Mobile Web Application (MWA) 学习小结

以上就可以达到我们的值分割效果,此功能主要设计为二维码截取字段所需。

说明:如果值分割符有多个,我们用@@隔开各个分割符就好,如分割符为逗号和上尖号,应维护:,@@^

b.字段

值来源类型为字段其实很好理解,就是值来源于哪个字段,若维护如下:

则进入页面效果如下:

其中,属性页面右边有两个复选框设置是否自动enter和是否启用当前个性化,默认勾选,若勾选自动enter,则当进入页面,字段会自动获取来源字段值并触发自动回车,否则需要自己手动按enter,这也是为减少用户操作而设计。

c.表达式/字符

表达式和字符类型都是光标进入该字段就触发,表达式可以是,也可以是sql,字符即设置字段默认值,这里只对表达式做说明;

sql设置如下:

效果如下:

设置如下:

内容如下:

/*==================================================Procedure/Function Name :get_subinvDescription:     Argument:   p_organization_id          :organization_idReturn:     History: 1.00 2018-10-11 Fang  Creation 
==================================================*/ 
FUNCTION get_subinv(p_organization_id IN NUMBER) RETURN VARCHAR2 ISl_result VARCHAR2(40); 
BEGINSELECT msi.secondary_inventory_nameINTO l_resultFROM mtl_secondary_inventories msiWHERE msi.organization_id = p_organization_idAND msi.secondary_inventory_name = '0013';RETURN l_result; 
EXCEPTIONWHEN OTHERS THENRETURN NULL;
END;

效果如下:

说明,中参数如需要界面字段的值,可以用英文逗号分隔,‘:’+字段名称 获取对应字段值(例如,: MAIN.),如果是中的值可以直接通过‘:’获取(例如,:ORGID);

d.转换

转换触发的时间点是字段按enter后触发,但是先于字段的所有验证逻辑,是扫描时预输入的处理(需要开启配置文件:MWA:预处理扫描的输入),主要用于字段的装换,属性界面设置如下:

进入PDA功能界面如下:

子库确认字段没有值,当我们输入其他值时,如0015,敲回车,子库确认字段会自动修改为0013;

转换函数:

/*==================================================Procedure/Function Name :get_subinvDescription:     Argument:       p_organization_id          : organization_idp_subinventory_code        : subinventory_codeReturn:       History: 1.00 2018-10-11 Fang  Creation==================================================*/FUNCTION get_subinv(p_organization_id IN NUMBER, p_subinventory_code IN VARCHAR2)    RETURN VARCHAR2 ISl_result VARCHAR2(40); 
BEGINSELECT msi.secondary_inventory_nameINTO l_resultFROM mtl_secondary_inventories msi  WHERE msi.organization_id = p_organization_idAND msi.secondary_inventory_name = '0013';RETURN l_result; 
EXCEPTIONWHEN OTHERS THENRETURN p_subinventory_code;END;

验证

验证界面主要是为了增加页面的字段验证控制,减少不必要的代码修改;

说明:程序包名和过程名按实际情况填写,参数文本如图上说明,参数必须用逗号分隔,且程序包必须包含三个固定输出参数(,, );

验证函数如下:

/*==================================================Procedure/Function Name :validate_locatorDescription:验证挑库货位Argument: Return: History:1.00 2018-10-11 Fang Creation 
==================================================*/PROCEDURE validate_locator(x_return_status   OUT NOCOPY VARCHAR2,x_msg_count       OUT NOCOPY NUMBER,x_msg_data        OUT NOCOPY VARCHAR2,p_locator         IN VARCHAR2,p_locator_confirm IN VARCHAR2) ISl_api_name       CONSTANT VARCHAR2(30) := 'validate_locator';l_savepoint_name CONSTANT VARCHAR2(30) := NULL;l_count NUMBER; 
BEGIN-- start activity to create savepoint,check compatibility-- and initialize message list, include debug message hint to enter apix_return_status := cux_api.start_activity(p_pkg_name       => g_pkg_name,                                            p_api_name       => l_api_name,                                             p_savepoint_name => l_savepoint_name,                                             p_init_msg_list  => fnd_api.g_true);raise_exception(x_return_status);-- API bodyIF p_locator <> p_locator_confirm THENcux_api.set_message('CUX','CUX_WMS_LOCATOR_NOT_CORRECT'); --货位不正确RAISE fnd_api.g_exc_error;END IF;-- API end body-- end activity, include debug message hint to exit apix_return_status :=cux_api.end_activity(p_pkg_name  => g_pkg_name,                                           p_api_name  => l_api_name,                                           p_commit    => fnd_api.g_false,                                           x_msg_count => x_msg_count,                                           x_msg_data  => x_msg_data);EXCEPTIONWHEN fnd_api.g_exc_error THENx_return_status := cux_api.handle_exceptions(p_pkg_name       => g_pkg_name, p_api_name       => l_api_name,                                                              p_savepoint_name => l_savepoint_name,p_exc_name       => cux_api.g_exc_name_error,x_msg_count      => x_msg_count,x_msg_data       => x_msg_data);WHEN fnd_api.g_exc_unexpected_error THENx_return_status := cux_api.handle_exceptions(p_pkg_name       => g_pkg_name, p_api_name       => l_api_name,                                                              p_savepoint_name => l_savepoint_name,p_exc_name       => cux_api.g_exc_name_unexp,x_msg_count      => x_msg_count,x_msg_data       => x_msg_data);WHEN OTHERS THENx_return_status := cux_api.handle_exceptions(p_pkg_name       => g_pkg_name, p_api_name       => l_api_name,                                                              p_savepoint_name => l_savepoint_name,p_exc_name       => cux_api.g_exc_name_others,x_msg_count      => x_msg_count,x_msg_data       => x_msg_data);    END;

执行层次说明:

之前:在触发标准验证逻辑之前触发

之后:在触发标准验证逻辑之后触发

Oracle Mobile Web Application (MWA) 学习小结__Oracle Mobile Web Application (MWA) 学习小结

终止说明:若勾上,则客户化程序报错会停止PDA操作,若不够,PDA还是能正常操作;

如程序中写明,若货位和确认货位不同,则报错,标准的逻辑若不走例外替换货位是有校验的,如果我们执行层次选之前,则会报出客户化消息,如下:

小结

经过以上介绍,是不是觉得这个配置界面很强大?

实现界面的字段属性控制:隐藏,必输,只读

实现界面字段的控制:值来源,字段,表达式,字符,装换,无(自动enter)

增强界面字段的验证:之前/之后的验证层次更好的满足验证需求;

亮点:无需重启端口,即时生效,不影响业务操作;

但是……

配置界面也有一些局限性,也有一些功能是不能做到,这些就是我后面需要讲的,通过修改文件去做一些特殊的个性化。

MWA 个性化 个性化实现说明

个性化实现其实标准支持的实现方式是在$ //apps/mwa/beans中的.class来实现相关的个性化,但是我们修改了该文件,继承出来一套独立实现个性化并支持了MWA配置界面;其中预扫描的输入实现是通过修改$ //apps/inv/lov/中的.class文件,继承出来单独实现。

修改的文件

所以我们一些修改都是在客户化的继承的.java文件就好,修改如下:

package oracle.apps.cux.wms.fnd;
import java.sql.SQLException;
import java.util.Hashtable;
import oracle.apps.cux.wms.fnd.im.CuxWmsFieldBeanUtil;
import oracle.apps.cux.wms.fnd.im.CuxWmsImManager;
import oracle.apps.inv.invinq.server.ItemOnhandQueryPage;
import oracle.apps.inv.lov.server.ItemLOV;
import oracle.apps.inv.lov.server.LPNLOV;
import oracle.apps.inv.lov.server.LotLOV;
import oracle.apps.inv.utilities.server.InvOrganizationPageBean;
import oracle.apps.inv.utilities.server.NumberFieldBean;
import oracle.apps.inv.utilities.server.UtilFns;
import oracle.apps.mwa.beans.ButtonFieldBean;
import oracle.apps.mwa.beans.CustomListener;
import oracle.apps.mwa.beans.FieldBean;
import oracle.apps.mwa.beans.InputableFieldBean;
import oracle.apps.mwa.beans.LOVFieldBean;
import oracle.apps.mwa.beans.PageBean;
import oracle.apps.mwa.beans.TextFieldBean;
import oracle.apps.mwa.container.Session;
import oracle.apps.mwa.eventmodel.AbortHandlerException;
import oracle.apps.mwa.eventmodel.DefaultOnlyHandlerException;
import oracle.apps.mwa.eventmodel.InterruptedHandlerException;
import oracle.apps.mwa.eventmodel.MWAEvent;
import oracle.apps.mwa.eventmodel.MWAFieldListener;
import oracle.apps.wms.td.server.PickDropPage;
import oracle.apps.wms.td.server.PutawayPage;
import oracle.apps.wip.wma.page.MovePage;public class CuxWmsCusListener implements MWAFieldListener {private Session session;private PageBean currentPage;private PageBean previousPage;private FieldBean fieldBean;private String action; private Long organizationId;private CustomListener customListener =null;public CuxWmsCusListener() {} public CuxWmsCusListener(CustomListener customListener) {this.customListener = customListener;} @Overridepublic void fieldEntered(MWAEvent paramMWAEvent) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException {this.session = paramMWAEvent.getSession();this.currentPage = this.session.getCurrentPage();this.previousPage = this.session.getPreviousPage();this.fieldBean = this.currentPage.getCurrentFieldBean();if (!(paramMWAEvent.getAction().equals("MWA_NEXTFIELD") || paramMWAEvent.getAction().equals("MWA_SUBMIT"))) {return;}// replace lov all parameters for cux extends standard pageif (this.currentPage.getName().contains("CuxWms") && !this.currentPage.getClass().getSuperclass().getName().equals("oracle.apps.mwa.beans.PageBean")) {if (this.fieldBean instanceofLOVFieldBean) {CuxWmsUtil.replaceLovParameter((LOVFieldBean) this.fieldBean,this.currentPage.getClass().getSuperclass().getName(),this.currentPage.getName());}}if (this.customListener != null && this.fieldBean.getListeners().lastElement().equals(this.customListener)) {CuxWmsUtil.clearFieldCusListener(fieldBean);}//addded by Fang@2018-06-12:转移并完工界面数量字段清空if (this.currentPage.getName().equals("oracle.apps.wip.wma.page.MovePage") && ((String)  this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_WMA_MOVE_EZ_COMPLETE") && this.fieldBean.getName().equals("quantity")) {((InputableFieldBean) this.fieldBean).setValue("");}//added end by Fang@2018-06-12//added by Fang@2018-07-03:卸货去除自动带出的卸载LPNif (this.currentPage.getName().equals("oracle.apps.wms.td.server.PickDropPage") || this.currentPage.getName().equals("oracle.apps.wms.td.server.PutawayPage")) {if (((String) this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_IN_WMS_DROP_LOADED_LPNS_MO") || ((String) this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_OUT_WMS_DROP_LOADED_LPNS_M") || ((String) this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_WMS_MOVE_ANY_LPN_MOB")) {if (this.fieldBean.getName().equals("PKD.CONFIRM_ZONE")) {((PickDropPage) this.currentPage).getDropLPN().setValue("");}(new CuxWmsCusUtil()).addItemInfoField(this.session,this.currentPage);  //added by Fang@2018-07-23:增加显示LPN物料信息}}//added end by Fang@2018-07-03//added by @2018-06-11:增加MWA配置界面逻辑if ((this.fieldBean instanceofInputableFieldBean) || (this.fieldBean instanceof ButtonFieldBean)) {CuxWmsImManager.fieldValueIm(this.session,this.fieldBean);}//added end by @2018-06-11
}@Overridepublic void fieldExited(MWAEvent paramMWAEvent) throws AbortHandlerException, InterruptedHandlerException,DefaultOnlyHandlerException {this.session = paramMWAEvent.getSession();this.currentPage = this.session.getCurrentPage();this.previousPage = this.session.getPreviousPage();this.fieldBean = (FieldBean) paramMWAEvent.getSource();this.action = paramMWAEvent.getAction();this.organizationId = Long.parseLong(this.session.getObject("ORGID").toString());if (this.action.equals("MWA_SUBMIT") || this.action.equals("MWA_NEXTFIELD")) {//modified by Fang@2018-06-21:增加对客户化挑库功能的限制//快速挑库,替换批次状态必须一致if ((this.currentPage.getName().equals("oracle.apps.wms.td.server.MainPickPage") || 
this.currentPage.getName().equals("oracle.apps.wms.td.server.CuxWmsMainPickPage")) && this.fieldBean.getName().equals("MAIN.LPN") && (((String)
this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_WMS_TASKS_OUT_NOLPN_MOB") || ((String)  this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_WMS_TASKS_OUT_NOLPN_MOB_N"))) {		CuxWmsCusUtil.validLpnLotStatus(this.session,this.currentPage);}//modified end by Fang@2018-06-21 // for buttonsif (action == "MWA_SUBMIT") {;}}//added by Fang@2018-08-06:增加限制字段跳转if (this.currentPage.getName().equals("oracle.apps.wip.wma.page.MovePage") && ((String) this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_WMA_MOVE_EZ_COMPLETE") && this.fieldBean.getName().equals("INV.LOT_QTY")) {UtilFns.trace("CUX remain qty :" + ((MovePage) currentPage).getRemainingQtyFld().getValue());if (((MovePage) currentPage).getRemainingQtyFld().getValue().equals("0")) {UtilFns.trace("CUX: goto next field: reference");this.session.setNextFieldName("reference");}}//added end by Fang@2018-08-06//added by@2018-06-11:增加MWA配置界面逻辑if (this.action.equals("MWA_SUBMIT") || this.action.equals("MWA_NEXTFIELD")) {if ((this.fieldBean instanceofInputableFieldBean)) {CuxWmsImManager.fieldValidIm(this.session,this.fieldBean);}}if (this.action == "MWA_SUBMIT") {if ((this.fieldBean instanceofButtonFieldBean)) {CuxWmsImManager.fieldValidIm(this.session,this.fieldBean);}}//added end by@2018-06-11
}
}

其中增加MWA配置界面逻辑的代码片段是MWA配置界面实现地方,由Fang添加的代码块是MWA配置界面不能实现的个性化修改。

替换LOV

在文件的方法里面添加如下代码:

//added by Fang@2018-10-15:批次替换增加物料字段,先扫描物料再扫描批次      
if (this.currentPage.getName().equals("oracle.apps.inv.lots.server.LotTranslateStartPage")){if (((String) this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_INV_MOB_LOT_TRANSLATE")){(new CuxWmsCusUtil()).addSplitItemInfoField(this.session, this.currentPage);if (this.fieldBean.getName().equals("StartLot")) {(new CuxWmsCusUtil()).replaceStartLotLov(this.session, this.currentPage); }}}  //added end by Fang@2018-10-15

具体中替换LOV的方法如下:

//替換批次LOV   
public void replaceStartLotLov(Session session, PageBean pageBean) throws AbortHandlerException {LOVFieldBean StartLotLovField = ((LotTranslateStartPage) pageBean).getStartLot();String[] arrayOfString1 = { " ", "WMSINSTALL", "ORGID", "TXNID", "oracle.apps.inv.lots.server.LotTranslateStartPage.CUX.ITEM_NUM", "oracle.apps.inv.lots.server.LotTranslateStartPage.StartLot", "", "" };StartLotLovField.setlovStatement("cux_dwms_split_lot_pkg.get_lot_num_lov");StartLotLovField.setInputParameters(arrayOfString1);}

效果如下:

我们前面替换掉了批次的LOV,增加物料限制,在此处,由于物料未启用批次控制,故未找到结果;

通过以上方式,我们可以替换一些标准界面的LOV,增加一些客户化的逻辑限制,无须修改标准源码,风险较低。

修改标准字段默认值

MWA中的表达式并不能将已有值得字段实现赋值,这样,我们就可以在修改中实现此种赋值,比如清空标准字段的默认值 ,在方法中添加如下代码:

  //addded by Fang@2018-06-12:转移并完工界面数量字段清空if (this.currentPage.getName().equals("oracle.apps.wip.wma.page.MovePage") && ((String) this.session.getObject("MWA_FUNCTION_NAME")).equals("CUX_WMA_MOVE_EZ_COMPLETE") && this.fieldBean.getName().equals("quantity")) {((InputableFieldBean) this.fieldBean).setValue("");}//added end by Fang@2018-06-12

标准界面的完工数量默认值并不准确,所以用户不想每次去删掉再重新输入,比较麻烦,此处就清掉标准完工界面的数量默认值,减少用户操作,增加效率;

效果如下:

小结

通过以上几个例子的简单说明,MWA个性化可以实现很多用户需求,对用户和开发人员都有很多益处;

用户:减少操作,增加效率;

开发人员:减少开发,开发高效便捷;

相对于MWA配置界面,修改个性化代码是对MWA配置界面的一个补充,修改完后也需重启端口才生效,没有MWA配置界面来的方便,但对一些标准界面的修改,MWA配置界面无法满足的情况下,修改个性化代码是一个非常不错的选择;

各位在后面的项目实战中就会发现,MWA个性化非常强大,能实现很多用户的常用需求,贴近实际业务操作,方便快捷;希望大家在后面的开发中熟悉并喜欢上MWA个性化开发。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了