********************************************************************** * PROGRAM ORDTRG - TRIGGER PROGRAM FOR FILE ORDDTL * * This program is designed as a trigger program to be attached to * * the Sales Order Detail file, ORDDTL. It is designed to work for * * all trigger events, either before or after the record is updated. * * The purpose of this program is to maintain a total order amount in * * the Sales Order Header file (ORDHDR) whenever a detail (ORDDTL) * * record is added, changed or deleted. * * * * ********************************************************************** FORDHDR UF A E K DISK Cust/Prod History D********************************************************************** D* Data Structure Definitions * D********************************************************************** D*--------------------------------------------------------------------* D* Parm_01 is the first parameter passed into the trigger program by * D* OS/400 when the trigger is activated. * D*--------------------------------------------------------------------* DParm_01 DS Incoming Parameter D*-(Static Section = 96 bytes)----------------------------------------* D File_Name 1 10 Physical File Name D Lib_Name 11 20 File Library D Mbr_Name 21 30 Member Name D Trg_Event 31 31 Trigger Event D* 1=Insert New Record D* 2=Delete Existing Record D* 3=Update Existing Record D Trg_Time 32 32 Trigger Time D* 1=After Record Added/Deleted/Updated D* 2=Before Record Added/Deleted/Updated D Commit_Lck 33 33 Commit Lock Level D Reserved 34 36 Not Used D CCSID 37 40B 0 CCSID D RRN 41 44B 0 Relative Rcd Nbr D Filler_01 45 48 Not Used D Old_Offset 49 52B 0 Offset to Org Rcd D Old_RcdLen 53 56B 0 Length of Org Rcd D Old_NBMOff 57 60B 0 NullByteMap Offset D Old_NBMLen 61 64B 0 NullByteMap Length D New_Offset 65 68B 0 Offset to New Rcd D New_RcdLen 69 72B 0 Length of New Rcd D New_NBMOff 73 76B 0 NullByteMap Offset D New_NBMLen 77 80B 0 NullByteMap Length D Filler_02 81 96 NullByteMap Length D D*-(Variable Section = at least 2x (rcd len + number of fields)-------* D* This section contains the old and new record images as well as the D* old and new null-byte maps. The offset values point into the entire D* buffer which is addressed as a zero-based structure. Therefore, the D* offset values should be reduced by 95 (to allow for the 96 bytes D* used in the static section) when pointing to the 'Data' buffer. D D Data 8192 D*--------------------------------------------------------------------* D* Parm_02 is the second parameter passed into the trigger program by * D* OS/400 when the trigger is activated. This data structure contains * D* only one subfield representing the length of the entire buffer de- * D* fined in the first parameter (Parm_01). * D*--------------------------------------------------------------------* DParm_02 DS Incoming Parameter D Buffer_Len 4B 0 Trig Buffer Length D*--------------------------------------------------------------------* D* Old_ORDDTL is a data structure defining the layout of the original * D* record. It will be used to hold the contents of the order detail * D* record retrieved from the Data field in Parm_01. A prefix of O_ is * D* added to each of the field names to avoid conflicting with the new * D* data record. * D*--------------------------------------------------------------------* DOld_ORDDTL E DS ExtName(ORDDTL) Original Rcd Layout D Prefix(O_) D*--------------------------------------------------------------------* D* New_ORDDTL is a data structure defining the layout of the modified * D* record. It will be used to hold the contents of the order detail * D* record retrieved from the Data field in Parm_01. A prefix of N_ is * D* added to each of the field names to avoid conflicting with the old * D* data record. * D*--------------------------------------------------------------------* DNew_ORDDTL E DS ExtName(ORDDTL) Original Rcd Layout D Prefix(N_) D********************************************************************** D* Program Constants and Work Variable Definitions * D********************************************************************** DInsert S LIKE(Trg_Event) INZ('1') DDelete S LIKE(Trg_Event) INZ('2') DUpdate S LIKE(Trg_Event) INZ('3') DAfter S LIKE(Trg_Time ) INZ('1') DBefore S LIKE(Trg_Time ) INZ('2') C********************************************************************** C* Main Line Program Logic * C********************************************************************** C *Entry PList C Parm Parm_01 C Parm Parm_02 C* Determine if this is an INSERT, DELETE, UPDATE (with same key C* fields) or UPDATE (with different key fields). C Select C When Trg_Event = Insert C Eval New_ORDDTL = %subst(Data: New_Offset-95: C New_RcdLen) C ExSR $Add Add to history C When Trg_Event = Delete C Eval Old_ORDDTL = %subst(Data: Old_Offset-95: C Old_RcdLen) C ExSR $Remove Remove from history C When Trg_Event = Update C Eval Old_ORDDTL = %subst(Data: Old_Offset-95: C Old_RcdLen) C Eval New_ORDDTL = %subst(Data: New_Offset-95: C New_RcdLen) C* C* The following logic checks to see if the order# is the same in the C* old record image and the new record image. If so, the same ORDHDR C* record will be updated. Therefore, performance can be improved by C* updating only the difference in quantity instead of two different C* record updates to remove old quantity and add new quantity. C* C If (O_ODORD# = N_ODORD#) C Eval N_ODEAMT = N_ODEAMT-O_ODEAMT C Else C ExSR $Remove Remove from history C EndIf If Old = New Order# C* C ExSR $Add Add new amounts C EndSL Select C Return C*--------------------------------------------------------------------* C* $Add is a subroutine that will check for the existence of a ORDHDR * C* record. If found, it will add the extended amount from ORDDTL to * C* the total amount field (OHTOTL). If the record does not exist, a * C* new one will be initialized and added to the file. * C*--------------------------------------------------------------------* C $Add BegSR Compute Date Limits C N_ODORD# Chain FORDHDR C* No record found in ORDHDR. Create a new record with the total. C* C If Not %Found Initialize New Rcd C Reset FORDHDR C Eval OHORD# = N_ODORD# C Eval OHTOTL = N_ODEAMT C Write FORDHDR C* Otherwise ORDHDR record found. Update the total amount. C* C Else C Eval OHTOTL = OHTOTL + N_ODEAMT C Update FORDHDR C EndIf If Not %Found C EndSR $Add C*--------------------------------------------------------------------* C* $Remove is a subroutine that will check for the existence of a * C* ORDHDR record. If found, it will subtract the ORDDTL amount from * C* the ORDHDR total value. * C*--------------------------------------------------------------------* C $Remove BegSR Compute Date Limits C O_ODORD# Chain FORDHDR C* Note: Referential integrity would require a ORDHDR record to exist C* for any given ORDDTL record. Therefore, we ignore the case of the C* ORDHDR record not being found as it is beyond the scope of this C* example. C* C If %Found C Eval OHTOTL = OHTOTL - O_ODEAMT C Update FORDHDR C EndIf If %Found C EndSR $Remove