Oracle Apex交互式网格保存前验证:订单金额超限校验问题
订单金额校验问题解决方法
问题背景
- 涉及两张表:
purchase_order(含max_amount字段,存储订单允许的最大金额)、purchase_order_details(含item_id、price字段,存储订单明细) - 需求:保存订单明细前,必须校验订单的
max_amount大于等于所有明细price的总和 - 原PL/SQL验证函数的缺陷:交互式网格(IG)中新增的明细数据尚未写入数据库,导致查询到的总和仅包含旧数据,校验逻辑完全失效
原验证代码(存在问题)
DECLARE mx_amount number; sum_prices number; BEGIN select max_amount into mx_amount from purchase_order where id=:P11_ID; select sum(price) into sum_prices from purchase_order_details where order_id=:P11_ID; IF mx_amount<=sum_prices then return true; else return false; END IF; END;
注:原代码逻辑写反,正确逻辑应为
max_amount >= sum_prices时返回true(验证通过)
解决方案
方案1:前端实时校验(交互式网格内)
直接在IG中通过JavaScript实时计算所有行(含新增行)的金额总和,与订单限额对比:
- 先将当前订单的
max_amount赋值给页面项(如P11_MAX_AMOUNT) - 在IG的页面级验证中添加以下JavaScript代码:
// 替换成你的IG静态ID const igWidget = apex.region("PURCHASE_ORDER_IG").widget(); let totalPrice = 0; // 遍历IG所有行计算总和 igWidget.grid("getRows").forEach(row => { const price = row.data.price; // 替换成你的IG中price列的字段名 if (price) { totalPrice += parseFloat(price); } }); // 对比总金额与订单限额 return totalPrice <= parseFloat($v("P11_MAX_AMOUNT"));
- 优势:用户输入时即可实时反馈校验结果,无需等待提交
方案2:后端结合APEX集合的兜底校验
为避免前端校验被绕过,可在后端结合APEX临时集合实现完整校验:
- 在IG的「保存前」流程中,将所有IG数据(新增、修改、删除)同步到APEX集合(如
PURCHASE_ORDER_DETAILS),用集合的attr1存储订单ID,attr2存储price - 修改PL/SQL验证函数,同时计算数据库旧数据总和与集合中新数据总和:
DECLARE l_max_amount NUMBER; l_old_sum NUMBER := 0; l_new_sum NUMBER := 0; BEGIN -- 获取订单最大限额 SELECT max_amount INTO l_max_amount FROM purchase_order WHERE id = :P11_ID; -- 获取数据库中已存在的明细金额总和 SELECT NVL(SUM(price), 0) INTO l_old_sum FROM purchase_order_details WHERE order_id = :P11_ID; -- 获取集合中新增/修改的明细金额总和 SELECT NVL(SUM(TO_NUMBER(attr2)), 0) INTO l_new_sum FROM apex_collections WHERE collection_name = 'PURCHASE_ORDER_DETAILS' AND attr1 = :P11_ID; -- 校验总金额是否超出限额 IF l_max_amount >= l_old_sum + l_new_sum THEN RETURN TRUE; -- 验证通过 ELSE RETURN FALSE; -- 验证不通过 END IF; END;
- 优势:覆盖所有数据场景,确保后端数据一致性
内容的提问来源于stack exchange,提问作者imstuckaf2
相关产品推荐
相关产品推荐

