Using the error attributes in the sample procedures
In this section, you will add a simple validation check to the updateOrder.p procedure, set the ERROR and REJECTED flags and the ERROR-STRING, and check for these back in the window procedure.
To add a validation check to the updateOrder.p procedure:
1. In updateOrder.p, retrieve the after-table row for each before-table row in the change ProDataSet. Add this dynamic FIND statement at the top of the FOR EACH ttOlineBefore block:
FOR EACH ttOlineBefore:
/* This code illustrates setting the ERROR status and the REJECTED
status for a row. */
BUFFER ttOline:FIND-BY-ROWID(BUFFER ttOlineBefore:AFTER-ROWID).
Remember that even though the change ProDataSet is created as a dynamic ProDataSet in the window procedure, updateOrder.p receives it into a static definition, so you can reference both the before- and after-table buffers by their static names.
2. Now that you have both versions of the row, compare the price and generate an ERROR-STRING if the price has been increased by more than 10 percent. For example:
IF ttOline.Price > (ttOlineBefore.Price * 1.1) THEN
ASSIGN
DATASET dsorder:ERROR = TRUE
BUFFER ttOlineBefore:ERROR = TRUE
BUFFER ttOlineBefore:REJECTED = TRUE
BUFFER ttOlineBefore:ERROR-STRING = "Line " +
BUFFER ttOlineBefore:BUFFER-FIELD("LineNum"):STRING-VALUE +
" price change from " +
TRIM(BUFFER ttOlineBefore:BUFFER-FIELD("Price"):STRING-VALUE) +
" to " + TRIM(BUFFER ttOline:BUFFER-FIELD("Price"):STRING-VALUE) +
" is too high.".
ELSE /* else SAVE-ROW-CHANGES below */
Here you are first setting the ERROR attribute for the whole change ProDataSet. This makes it easy to determine in the calling procedure if there were any errors.
Next, you set ERROR for the individual buffer along with the REJECTED attribute to signal to MERGE-CHANGES that this update did not make it into the database.
Then you construct an error message and attach it to the buffer in error. The text of the message, when assembled, will look something like this:
Line 5 price change from 34.00 to 44.00 is too high.
If the validation check does not fail, the ELSE keyword invokes the SAVE-ROW-CHANGES method to save the changes to the database. Note that this is one kind of error you can generate, one that is detected by your own code. The SAVE-ROW-CHANGES method itself can also generate errors if a native AVM error results from the change. In this case, the AVM sets ERROR at all levels, but not REJECTED or the ERROR-STRING.
3. Change dsOrderWinUpd.w to check for the error.
4. Add an editor control to the bottom of the window, called cStatus.
5. Give cStatus a vertical scrollbar, but no horizontal scrollbar.
6. Make cStatus enabled, but read-only.
7. Make cStatus tall enough to display one or two rows, as shown:
8. In the CHOOSE OF BtnSave trigger, add this block of code after you run updateOrder.p:
RUN updateOrder.p (INPUT-OUTPUT DATASET-HANDLE hDSChanges BY-REFERENCE).
/* Check the ERROR status that might have been returned. */
cStatus = "".
IF hDSChanges:ERROR THEN DO:
/* There was an error somewhere in the updates. Find it. */
CREATE QUERY hQuery.
hBuffer = hDSChanges:GET-BUFFER-HANDLE(2).
hQuery:ADD-BUFFER(hBuffer).
hQuery:QUERY-PREPARE("FOR EACH " + hBuffer:NAME).
hQuery:QUERY-OPEN().
hQuery:GET-FIRST().
DO WHILE NOT hQuery:QUERY-OFF-END:
IF hBuffer:ERROR THEN
cStatus = cStatus + hBuffer:ERROR-STRING + CHR(10).
hQuery:GET-NEXT().
END.
hQuery:QUERY-CLOSE().
DELETE OBJECT hQuery.
END.
DISPLAY cStatus WITH FRAME dsFrame.
/* END of Error status checking. */
This first checks the ERROR attribute on the ProDataSet as a whole. This is why you set this attribute at this level, so that you know at once that there was an error in one of the updates.
To locate each error, you need to create a dynamic query for the ttOline buffer, prepare it, open it, and walk through all its rows. For each one with the ERROR status, you append the ERROR-STRING message to the editor text, with a line feed in between each one.
After closing and deleting the query, you display the status string.
Following this, the code already runs MERGE-CHANGES on the ProDataSet. When this happens, MERGE-CHANGES checks the REJECTED attribute of each row and restores the original row to the values it had before the update. Once again, this might not always be the behavior you want, but we use it here to illustrate what MERGE-CHANGES does for you.
9. Rerun the window to see the effect of your changes.
10. Select an Order and change the Price of one or more of its OrderLines to be more than 10% higher than before:
11. Select Save Changes to try to save these invalid changes:
The error strings are displayed in the status editor, and the changed prices have been rolled back in the ttOline table and its browse. Any successful updates would be displayed, along with the updated Extended Price, in the browse as well.