Consultor Eletrônico



Kbase P85717: ADM2: Without using an SBO, how to update parent records and refresh their linked DataVisual dataTar
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   27/10/2004
Status: Unverified

GOAL:

How to update a parent table and show the changes on the UI when saving a change in a child SDO?

GOAL:

How to update order.total in and show the changes in orderSDO dataTargets when saving a new orderline.amount in child orderlineSDO?

GOAL:

refreshRow in a parent SDO does not refresh visual objects data target

FACT(s) (Environment):

Dynamics

FIX:

The scenario is about a child SDO (orderline) that updates few parent table (instructions field order and comment of customer) in a EndTransactionValidate (code not given here). In the orderline viewer that did the update, an override of UpdateRecord does the following:
1) Checks that no update is pending in a parent Viewer (order or customer), so the light refresh will not result in loosing the pending update.
2) Fires a procedure in the parent SDO (or in its in Data Logic Procedure) that does the following:
2.1) Calls a function to retrieve the updated value of the field from the database.
=> in thin client mode, this function relays the call to the appServer side of the DataLogicProcedure
2.2) Then pushes this new value in the rowObject temp-table
2.3) Finally runs dataAvailable 'different' in all the dataVisual dataTarget.
=> Note it shall not run dataAvailable in children SDO otherwize it would reopen their queries and reposition them to a first row.
The advantages of this methods are:
1) The parent SDO's are still well in synch with their dataVisual dataTargets (it is not like cheeting in pushing the values only in the viewer)
2) If the updated fields in the parents is also visible in a browse, then they are refreshed correctly thanks to the dataAvaialble.
3) The child SDO is not repositioned, and no object is flashing (actually, no query is reopened with this process).
4) This method can be used as long as the field that is updated from the child is not used to join some children SDO's. (Otherwise it will have to be refined to reopen the child query so the join is not broken)
5) The updated fields to refresh do not need to be defined as updatable in the parent SDO's
It has been tested in Dynamics 2.1A03 with thin and fat clients and 3 levels of SDO's and a field updated in the parent and grand parent, fields that are also visible in a browse of each parent.
Override of Child ordrline SDV/updateRecord:
DEFINE VARIABLE hDataSource AS HANDLE NO-UNDO.
DEFINE VARIABLE hOrderSDO AS HANDLE NO-UNDO.
DEFINE VARIABLE hCustomerSDO AS HANDLE NO-UNDO.
DEFINE VARIABLE cdataTarget AS CHARACTER NO-UNDO.
DEFINE VARIABLE lDataModified AS LOGICAL NO-UNDO.
DEFINE VARIABLE hUpdateSource AS HANDLE NO-UNDO.
{get DataSource hDataSource}. /* get SDO of the child record */
IF VALID-HANDLE(hDataSource) THEN {get DataSource hOrderSDO hDataSource}. /* SDO of parent record */
IF VALID-HANDLE(hOrderSDO) THEN {get DataSource hCustomerSDO hOrderSDO}. /* SDO of parent record */
IF VALID-HANDLE(hOrderSDO) THEN DO:
{get UpdateSource hUpdateSource hOrderSDO}.
/* is an update pending in the Order Viewer ? */
{get dataModified lDataModified hUpdateSource}. /* SDO of parent record */
IF lDataModified THEN DO:
/* you should use the Dynamics message facilities instead */
MESSAGE "Please finish the update of the parent Order first before saving this orderLine"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
RETURN ERROR.
END.
END.
IF VALID-HANDLE(hCustomerSDO) THEN DO:
. {get UpdateSource hUpdateSource hCustomerSDO}.
/* is an update pending in the Order Viewer ? */
{get dataModified lDataModified hUpdateSource}. /* SDO of parent record */
IF lDataModified THEN DO:
/* you should use the Dynamics message facilities instead */
MESSAGE "Please finish the update of the parent Customer first saving this orderLine"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
RETURN ERROR.
END.
END.

RUN SUPER.

IF VALID-HANDLE(hCustomerSDO) THEN RUN refreshCommentsFieldInUI IN hCustomerSDO.
IF VALID-HANDLE(hOrderSDO) THEN RUN refreshInstructionsFieldInUI IN hOrderSDO.
END PROCEDURE.

Note the example with refreshInstructionsFieldInUI is similar to refreshCommentsFieldInUI.

Procedure in Parent SDO DLP Beware, DB-REQUIRED has to be *UNCHECKED*
refreshCommentsFieldInUI :
DEFINE VARIABLE cNewComments AS CHARACTER NO-UNDO.
DEFINE VARIABLE ccustomer_obj AS DECIMAL NO-UNDO.
DEFINE VARIABLE cdataTarget AS CHARACTER NO-UNDO.
DEFINE VARIABLE hdataTarget AS HANDLE NO-UNDO.
DEFINE VARIABLE iCount AS INTEGER NO-UNDO.
DEFINE VARIABLE hRowObject AS HANDLE NO-UNDO.

ccustomer_obj = DYNAMIC-FUNCTION('columnValue':U IN TARGET-PROCEDURE , 'customer_obj').
cNewComments = DYNAMIC-FUNCTION('getUpdatedComments':U IN TARGET-PROCEDURE, ccustomer_obj).
{get RowObject hRowObject}.

/* push that directly in the SDO RowObject temp-table */
hRowObject:BUFFER-FIELD("customer_comments"):BUFFER-VALUE = cNewComments.

{get dataTarget cdataTarget}.
DO iCount = NUM-ENTRIES(cdataTarget) TO 1 BY -1:
hDataTarget = WIDGET-HANDLE(ENTRY(icount,cdataTarget)).
IF DYNAMIC-FUNCTION('instanceOf':U IN hDataTarget , "datavisual" )
THEN RUN dataAvailable IN hDataTarget ('different').
END.
END PROCEDURE.

In Parent SDO DLP, beware, DB-REQUIRED has to be *UNCHECKED*:
FUNCTION getUpdatedComments
RETURNS CHARACTER
(pccustomer_obj AS CHAR) :
DEFINE VARIABLE hAS AS HANDLE NO-UNDO.

IF DYNAMIC-FUNCTION('getASDivision':U IN TARGET-PROCEDURE) = "client":U THEN DO:
ASSIGN hAS = DYNAMIC-FUNCTION("getASHandle" IN TARGET-PROCEDURE).
RETURN DYNAMIC-FUNCTION("getUpdatedComments" IN hAS, pccustomer_obj).
END.
ELSE DO: /*Fat client or AppServer*/
{&DB-REQUIRED-START}
FIND FIRST arm_customer NO-LOCK
WHERE arm_customer.customer_obj = DECIMAL(pccustomer_obj) NO-ERROR.

IF AVAIL arm_customer THEN RETURN arm_customer.customer_comments.
RETURN ERROR "no customer available for customer_obj" + pccustomer_obj.
{&DB-REQUIRED-END}
END.
END FUNCTION.


.