The vendor number must already exist on the vendor file, thus this program will have only SEE and CHG maintenance (cont.)
functions. To add or delete vendors the operator will have a different vendor maintenance screen.
**Auto-Join**
To begin, you define the screen and MMP headers just as you would for any other new application. You specify the vendor (cont.)
file as your primary data class. Using the fully-automated development process to create the screen, you select the (cont.)
invoice file for MAGEC to join to. *Note, this presumes that the vendor number is the high-order portion of the invoice (cont.)
file key and that it belongs to the same domain as the vendor number in the vendor file.* MAGEC will generate a (cont.)
partial-key join ("left Join") to the invoice file; that is, it will generate (in %JOIN) a LOCKY, REDLE to read the (cont.)
first invoice for this vendor. You will be able to customize this join to then do REDNX to get subsequent invoices. If (cont.)
you are not familiar with these database I/O commands, refer to the Database Administration section of your (cont.)
Programmer's Reference manual.
**Screen Painting**
After you have selected the fields (Data Items) you wish to present on your screen from both the vendor and invoice (cont.)
record elements, MAGEC will generate a screen containing fields to display one vendor's data and one invoice's data. (cont.)
Using the manual screen painter, arrange the vendor data at the top of the screen and arrange the invoice data across (cont.)
one line. Delete the screen prompts which were generated to the left of each invoice field, you will be drawing a (cont.)
column heading above the invoice fields to replace these prompts. Leave one blank line (optional) below the vendor (cont.)
data, plus one line for the column headings. Place the invoice fields on the next line below the column headings line. (cont.)
Manually draw one column heading field with appropriate literals in the line immediately above the invoice data (cont.)
line.
Modify each invoice field by cursor-selecting it using PF18. Change the Occurrence to "*10", this will cause MAGEC to (cont.)
repeat that field ten times vertically. Of course, if you wished to have other than ten occurrences, you would modify (cont.)
the entry into Occurrence. Also modify the Source/Target to be an arrayed Working-Storage field, rather than the (cont.)
database field name which was generated for you. For ease of understanding, you should use a similar name with only the (cont.)
prefix altered. For instance: if the database name was IVC01-AMOUNT, you might alter it to WS-AMOUNT (*). The asterisk (cont.)
in the subscript tells MAGEC to generate MOVE's back and forth between the arrayed screen fields and their (cont.)
corresponding occurrences of "WS-" fields. Do not forget to add a one-byte Action-Code field which OCCURS just like the (cont.)
invoice fields. Its Source/Target might be WS-ACTION (*).
**%DATADEF**
Define a table of Working-Storage Source/Target fields. Use Cobol level 03 for the group item defining the entire (cont.)
table. Use Cobol level 05 (or as desired) for the entry below the group item. This 05 item should contain the OCCURS 10 (cont.)
TIMES clause. Define each "WS-" field using Cobol level 07 below it. Also define an index or subscript [PIC S9(4) COMP (cont.)
SYNC is recommended].
MAGEC will generate MOVE's from the fields in this table to the screen for displays and from the screen fields to this (cont.)
table for updates. For all intents and purposes, MAGEC now "thinks" this table is the database record which was read or (cont.)
will be updated. Do not forget the action code which also occurs.
Be sure to include all the primary key fields necessary to read each invoice record. If some of the key fields will not (cont.)
be displayed on the screen, include them in the table anyhow--you will need the complete primary key to add, delete, or (cont.)
update these records.
Also, add a field in %DATADEF to store the "beginning invoice number". This field will be used to start the browse looking for invoices for this vendor.
**%REDKY**
The default logic here does an exact key read of the vendor record, then it performs the join logic. Add one line of (cont.)
code before performing JA100-LOGICAL-JOIN to set the beginning invoice number to zero.
**%JOIN**
In %JOIN you will find generated logic to read the first invoice for the vendor being processed. That means that at the (cont.)
bottom of this generated join logic you will have the vendor data and one invoice's data in their appropriate element (cont.)
copybook areas.
First, alter the logic which builds the generic key for the invoice records. The generated logic fills in the (cont.)
high-order portion of the key using the vendor number and sets the low-order portion (the invoice number) to zeros. You (cont.)
must move the beginning invoice number from your %DATADEF holding field into the invoice number portion (low-order (cont.)
portion) of the key. This results in positioning to the first invoice for this vendor having an invoice number equal to (cont.)
or greater than the beginning invoice number.
Next, you must initialize the "WS-" table which you have defined in %DATADEF. In Cobol II you may use the INITIALIZE verb, or you may move appropriate spaces or zeros in older Cobol implementations.
Next, you must move the appropriate fields from the first invoice record into the first entry of the table (occurrence (cont.)
1). Be sure to move the key fields into the table entry. Set the subscript or index to 1.
Then, you must do the REDNX I/O command to get the next invoice, increment the subscript, and move its data to the (cont.)
table entry using that subscript. You loop back through this REDNX processing. Of course, you will test for your (cont.)
subscript reaching the end of the table or your REDNX getting a NOT-FOUND, or reaching an invoice for the next vendor (cont.)
to know when to stop looping.
At the end of this, your table will be loaded with invoices. Any unused entries at the bottom of the table will contain (cont.)
the initial values you set earlier. The action codes will all be set to their initial value, normally (cont.)
spaces.
**%RDUKY**
In this insertion point the defailt logic reads the primary record (vendor record) for update, getting exclusive (cont.)
control of it; then performs the join logic. Reading for update is a prerequisite for updating or deleting a record. If (cont.)
you will be updating the vendor record, leave the RDUKY for it alone, but remove the perform of JA100-LOGICAL-JOIN. If (cont.)
you will not be updating the primary record, also remove the perform of AA840-CALL-MAGEC-IO. The reason you do not want (cont.)
to re-do the join logic is because 1) it is unnecessary since the data is preserved in your table in %DATADEF, and 2) (cont.)
you do not yet know which, if any, of the invoice records will be updated, deleted, or added--that will be determined (cont.)
later in %UPDAT. If you remove the call to AA840-CALL-MAGEC-IO you should replace it with MOVE SPACES TO (cont.)
TWA-DB-RETURN-CODE, or SET REC-FOUND TO TRUE.
**%UPDAT**
In this insertion point the defaiult logic updates the primary record (vendor record, in this example). If you do not (cont.)
want to update the primary record, remove the call to AA840-CALL-MAGEC-IO and move spaces to TWA-DB-RETURN-CODE (or SET (cont.)
REC-FOUND TO TRUE). Next, you will code a routine to loop through your table interrogating the action codes to (cont.)
determine whether to add, update, delete, or ignore each invoice.
For each invoice to be added, you must do the ADDIT I/O command after moving the fields from the appropriate occurrence (cont.)
in the table to the invoice element copybook. Be sure to fill in all key fields completely--in some designs this would (cont.)
involve reading a control record to assign the next available invoice number.
For each invoice to be deleted, you must do the RDUKY I/O command followed by the DELET I/O command.
For each invoice to be updated, you must do the RDUKY I/O command, then move the fields from the table to the invoice element copybook fields, then do the UPDAT I/O command.
It is important to save the TWA-DB-REQUEST area into TWA-DB-REQ-SAV after the primary file's I/O and before your (cont.)
routine to update the joined file (even if you have removed the call to update the primary file), and then to restore (cont.)
it to TWA-DB-REQUEST after you have finished looping through your table. The standard logic of the MMP expects the (cont.)
TWA-DB-REQUEST area to reflect the status resulting from the update of the primary file after exiting from this point (cont.)
in the program.
As you are updating, adding, or deleting records based upon the action code on the screen you should also be setting (cont.)
the action code off (by moving space to it) for each item. You may prefer to move something to the screen indicating (cont.)
which lines were processed, as well.
**%GOODCHG**
The default logic in this insertion points will set a message into SCOMPL indicating successful completion and will (cont.)
fetch to the SEE function to display the results of the changes. You may not wish to execute the SEE function, but (cont.)
rather just send the screen as is with any messages or statuses you have inserted into the array to show what was (cont.)
added, changed, or deleted. To accomplish that you should merely remove the line of code which says: MOVE FTH-FUNCT TO (cont.)
TWA-NONTP-REQUEST. The program will still change the function code in SFUNCT to the SEE function, but will not execute (cont.)
the SEE function. It will just send the screen as is.
**%PFKEYM**
The default logic for handling PF7 (page back to prior vendor) and PF8 (page forward to next vendor) will remain (cont.)
intact. It works just as we want it to. We will, however, add logic to handle PF4 (scroll up the list of invoices) and (cont.)
PF5 (scroll down the list of invoices). The scrolling operations will limit themselves to only those invoices which (cont.)
belong to this vendor. The invoice scrolling depends upon the fact that you have the table in %DATADEF which contains (cont.)
data for each invoice listed on the screen, including the invoice numbers.
For PF5, move the invoice number from the last invoice listed on the screen into the %DATADEF field used to hold the (cont.)
beginning invoice number, add one to it, then perform JA100-LOGICAL-JOIN THRU JA199-EXIT, perform BB200-FILL-SCREEN (cont.)
thru BB299-EXIT and GO TO AA800-SEND-SCREEN.
For PF4, you do a similar process, except that you must use the invoice number from the first invoice listed on the (cont.)
screen, then do the REDPR I/O command to "back up" ten invoices (or until you reach the Beginning-of-File or an invoice (cont.)
for another vendor) to obtain the appropriate beginning invoice number to start listing from.
It may also be prudent, prior to accepting a PF4 or PF5 or PF7 or PF8 key) to add a check of the screens action codes (cont.)
for each invoice listed on the screen to see if any were marked for database action. If any were marked, you might wish (cont.)
to ignore the scrolling or paging by resetting the key to ENTER, as: SET TWA-MSK-ENTER-HIT TO TRUE, or MOVE QUOTE TO (cont.)
TWA-MSK-AID. This must be done before the processing for PF4 or PF5, obviously.
##
Other Techniques
The technique discussed above has been successfully used many times. You may wish to modify it with your own (cont.)
refinements. One common modification is to eliminate the action code on each detail line of the screen and compare the (cont.)
screen data to the data in the "WS-" table to determine if anything has been altered. You might retain the action codes (cont.)
in the "WS-" table and set them to "A", "C", or "D" internally. A delete might be indicated by finding a zero invoice (cont.)
number on the screen corresponding to an occurrence in the table which is non-zero. An addition might be indicated by (cont.)
finding a non-zero invoice number on the screen corresponding to a zero entry in the table, and so forth, a change (cont.)
might be indicated by finding the same invoice number on the screen for its corresponding table entry, but with other (cont.)
values on that line altered from what was in the table.
## Beware - Avoid a Deadly Embrace
A potential problem in any multi-tasking systen you should be aware of is called "Deadly Embrace". Here is what it (cont.)
means: a task is waiting for a resource that is held with exclusive control (i.e. read for update) by another task that (cont.)
is waiting for a resource that the first task is holding, As a result both tasks are in an endless wait status. Both (cont.)
tasks may even be the same program. MAGEC generates MMP's With a keen awareness of this classic danger and a problem (cont.)
like this may never, or very rarely, occur among MAGEC applications. But, your ability to do virtually unlimited (cont.)
customization--including calling non-MAGEC programs--makes it impossible to eliminate every possibility for (cont.)
error.
The tasks may be MAGEC-generated MMP(s), other programs, or any combination. The resource being held may be a file, a record, an element, or any other resource.
The best way to make it as unlikely as possible for the problem to occur is some simple standards.Obtain exclusive (cont.)
condtrol (i.e. read for update) as late as possible in your procedureRelease it as early as pssible after no longer (cont.)
neededAlways do either an implicit (i.e. UPDAT) or explicit (i.e. RELES) Process in a predictable order (i.e. key (cont.)
sequence) in all tasks
Of course, a task can get exclusive control over other types of resources (i.e. main memory storage) that you might (cont.)
have little ability to control, but file or database I/O is the type you will most likely be involved with and these (cont.)
simple standards might afford you the luxury of *never* being involved at all.