Jazz On Line Programming, Part
3. Handling Sets of Records
Dealing
with More than one Record - Introduction
Parent-Child Record Structures
A.
Create an update program with a
modified screen for the parent record
C. Add a scrolling section to the screen to
display them
E.
Processing Orders – General Concepts, and Processing Orders
G. Final Thoughts: Writing CICS4 and Order
Processing, Deleting Records.
Prerequisite
reading: Introduction to Jazz, Jazz On Line Programming, Introduction, Jazz On Line Programming, Part2. Updating Records
In the previous
chapter the introductory principles of on-line
programming were extended to include on line updating. In both cases we dealt with
a single record, looking up a CustF record from a VSAM file.
In this chapter we’ll cover the techniques of
handling sets of records, developing screens and programs to display and update
a record hierarchy, using the example of a customer record and the customer’s
current orders. First we’ll develop a program that will display the customer
information at the top and a scrolling section of orders lower down the screen.
This program will then be developed to allow us to edit the customer
information, or to add or change orders.
This chapter is about classical (3270) CICS programming: if your
interest is in web services handling record hierarchies then you should read
leave this chapter and read this instead.
A very common requirement is to show a variable length table that the user can scroll up and down with Page Up and Page Down (or PF7/PF8). For example, here we are going to display a screen like this: -
Like the previous example the first part of the screen can update or create a CustF record. Then comes a scrolling section, where up to 12 order lines can be displayed. You can do something with one of the orders – show it in more detail, process it (this might mean “dispatch it and invoice the customer”), delete it (subject to various rules), and so on.
This section will show you how to write such
programs. Currently the option to generate such programs hasn’t been
implemented for classical CICS programs (although it has for web services), so
we’ll design the screen and write the program manually. The process that we’ll follow is: -
A.
Create
an update program with a modified screen for the parent record
B.
Define
related records
C.
Add
a scrolling section to the screen to display them
D.
Write
logic into the program to handle this scrolling section
E.
Add
logic to create new orders
F.
Add
logic to process existing orders
This is the same logic before so the easiest way
to start is to create a single-record update program. We select New/CICS program and fill in
options for a program called (e.g.) CICS3, to update a single file
(Custf). Jazz creates a program exactly
as before: except for the program name being CICS3 this will be just like
program CICS2 of the previous chapter.
The standard layout used by programs CICS2
assumed that the whole screen was available for updating CustF and arranged the
screen accordingly. However for CICS3 we
don’t want the CustF record arranged vertically on the screen as this wouldn’t
leave enough room for the orders section. We could edit the screen field by
field, but here’s an easier way: -
1.
From
the Jazz workbench click the [Screen] button.
We want to delete the fields Region to DateCommenced, and re-insert them
in a different layout, so we start by selecting the area containing them. Press Delete to clear this area: -
2.
Now,
to reinsert the missing fields with the arrangement we want, we start by
selecting Custf. Select the whole
record, don’t expand the record layout.
Drag it to line 5.
This causes the Multi-item Drop Options form to be displayed. Select two-column layout: -
3.
Click [Select Items], and then check or
uncheck fields in the Select Fields form so that the fields that we want are
checked. Leave out the fields Account
and Name as they are already on the form’s search line. Click [Finish] to return to the Multi-Item
Drop Options form
4.
With 2 Cols layout selected, click [Close].
The selected fields are dropped on to the screen with 2-column layout, so now
the screen looks like this: -
5.
Save the screen and return to the program.
The program was previously generated with an ACCEPT statement for all fields
that were previously on the screen. If
our new screen has omitted some of these fields then we’ll need to correct the
ACCEPT statement in the Update/Add section to remove references to omitted
fields. With this correction (if necessary) we now have a program that functions
just like CICS2 of the previous chapter except for the different layout.
Our program so far, generated by Jazz and
identical in function to CICS2, looks like this: -
*# Last Updated by robertb at 24/02/2016 3:14:46 p.m.
PROGRAM CICS3 CICS INSCREEN(CICS3S) TRANSID(TRN3) COMMAREA(CICS3C) EXIT(menu1);
ACCEPT (CICS3S.Function);
CASE (CICS3C.Function);
WHEN
(Enquiry);
ACCEPT (CICS3S.Account OR
CICS3S.Name);
DEFINE TS1 TS DATA(
Account LIKE CustF.Account);
GET custf KEY(CustF.Account OR CustF.Name) SAVECOPY CICS3C.SAVE
TS(1);
#373 I GET statement returns one record at a time for
Name
END GET custf RESETFUNCTION;
WHEN
(Update);
GET custf WHERE(CustF.Account=CICS3C.Save.Account)
REWRITE CHECKCOPY(CICS3C.SAVE);
ACCEPT (CICS3S.Region,CICS3S.District, CICS3S.Name, CICS3S.SalesThisMonth, CICS3S.SalesYTD, CICS3S.Billingcycle, CICS3S.DateCommenced);
END GET custf REWRITE RESETFUNCTION;
WHEN
(Add);
CustF.Account
= custf.$LastKey
+ 1; [Will need to be changed if key is not a number
#361
E Assignment to a key field
GET custf KEY(CustF.Account) CREATE;
ACCEPT (CICS3S.Region,CICS3S.District, CICS3S.Name, CICS3S.SalesThisMonth, CICS3S.SalesYTD, CICS3S.Billingcycle, CICS3S.DateCommenced)
SETMDT;
END GET custf CREATE RESETFUNCTION;
WHEN
(Delete);
DELETE custf WHERE(CustF.Account=CICS3C.Save.Account)
CHECKCOPY(CICS3C.SAVE) RESETFUNCTION;
END CASE;
SEND Inscreen;
For this example the Orders record is defined
like this:-
*# Last Updated by JAZZUSER at 17/03/2018 4:09:42 p.m.
COPY Custf;
COPY Parts ;
DEFINE Orders VSAM DATA(
OrdNbr
DECIMAL(5) DPIC '99999' KEY,
OrdCustId
LIKE CustF.Account
DKEY 'jazzuser.vsam.Orders1'
EXISTS CustF.Account
,
ordDate
DATE,
OrdPart
LIKE Parts.Partnbr
DKEY 'jazzuser.vsam.Orders2'
EXISTS Parts.Partnbr,
OrdQty
SMALLINT,
OrdDiscount
DECIMAL (3,1) HEADING 'Order Discount',
OrdStatus
CHAR(1) CODES(I:Initial, C:Confirmed,Q:'Part Shipped',
S:Shipped, B:Billed, P:Paid))
DSNAME 'jazzuser.vsam.Orders';
Note the following: -
1
Like
any VSAM record there must be a primary key.
For the Orders record this is
OrdNbr
DECIMAL(5) DPIC
'99999' KEY,
2
OrdCustid
is the linking field that relates an order record to a customer record.
a.
By
defining this LIKE custf.account we have ensured that it has the same format as the field in Custf. This means that there must be a preceding definition
of CustF in our program: once again we’ve used the trick of including COPY here, knowing that if the program already has this definition the
duplication is harmlessly ignored.
b.
DKEY OrdCust defines it as an
alternate index and gives the index path name.
The linking field must be a key of some kind to be valid for use in a PROCESS statement in a
CICS program.
3
OrdPart is defined with EXISTS Parts.Partnbr. This means that it is a “Foreign Key”, i.e. the key of
another record. Here there is a record
called “Parts” with primary key Parts.Partnbr. Because these
fields must have the same format you should, as here, define the subordinate
field with LIKE. That not only ensures that its definition is
the same, but will change the definition if the parent field definition is
changed. Because of this definition, we
need to ensure that the definition for PARTS is included in the program and
once again we’ve put COPY into the record definition.
4
For a real situation there would be a lot
more information in the Parts record like the quantity on hand, lead time for
more deliveries, … anything that relates
to the part itself. For this example
we’ve defined only StandardPrice and PartName: -
*# Last Updated by IBMUSER at 8/01/2015 5:31:30 p.m.
DEFINE Parts VSAM DATA(
Partnbr
INTEGER KEY,
PartName
CHAR(30),
StandardPrice
DECIMAL(7,2))
DSNAME
'ibmuser.vsam.Parts';
You can see that we’ve defined a database
schema like this: -
This means that we create separate orders for each
part that a customer orders: not terribly realistic, more likely our system
will have an ORDER-LINE record to allow one order to have many lines, each line
linking to a different part. However
this schema without order lines is sufficient for our purpose which is to
demonstrate how to manage scrolling sections.
We add COPY
Orders; to our program, and then click [Screen] again to create the repeating
line.
1.
Drag
Orders to line 9. This causes the “Multi Drop Options form to be
displayed. We select “Scrolling” layout
from the Arrange Items alternatives: -
Note that if we simply click [Close]
now we’ll be attempting to create a line of 117 characters, more than the 80
characters maximum width. This will not be permitted unless we check Allow Line
Overflow. More likely, we’ll want to reduce the line size by selecting which
fields we want, and by shortening over-long headings.
2.
Click
[Select fields] to choose the fields that we want to have displayed across the
line. We don’t need to display OrdCustId
as this will be the linking field, and would have the same value as
Custf.Account” in every line. There may be other fields that we don’t want to
see, such as OrdField1 and OrdField2.
Uncheck the fields that we don’t want
3.
This
would have reduced the line size to 75, but we add 2 more characters by
checking “Function Code at Left”. We
also specify how many free lines we want at the end of the repeating section. We can remove more characters by shortening
the headings that take up more room than their fields, such as “Order
Discount”, but since we’re already down to 77 characters we mightn’t
bother. It only remains to enter the
condition that joins the orders record to the data already read, and we’re
ready to click [Close]
4.
When
we click [Close] Jazz adds the repeating section to the screen.
5.
We
save the screen, and return to program CICS3
We have now created the screen layout that we
want, but there is no logic in our program to put data into the repeating
lines. We need to modify the Enquiry
case to support this. Jazz has initially
given us: -
WHEN
(Enquiry);
ACCEPT (CICS3S.Account OR
CICS3S.Name);
DEFINE TS1 TS DATA(
Account LIKE CustF.Account);
GET custf KEY(CustF.Account OR CustF.Name) SAVECOPY CICS3C.SAVE
TS(1);
#373 I GET statement returns one record at a time for
Name
END GET custf RESETFUNCTION;
Whenever a GET statement in a Classical CICS program could return several records Jazz
1.
Creates
logic that will return the first record, but page through next/previous records
with PF10/11
2.
Add
a definition for a TS (Temporary Storage) file that will hold the record keys
of these records
3.
Add
a TS option to the GET statement
4.
Insert END GET following GET.
All this is omitted when the GET can only ever read one record, as with
GET custf KEY(CustF.Account) …
So this automatically handles the possibility
that there might be one or zero Custf records, or some indefinite number. Next: we want to get the related Orders
records for the current Custf record.
We write this logic within the GET group: -
GET custf KEY(CustF.Account OR CustF.Name) SAVECOPY CICS3C.SAVE
TS(1);
#373 I GET statement returns one record at a time for
Name
*
Logic to get related Orders records to be written here
END GET custf RESETFUNCTION;
We use PROCESS to read a set of records, writing PROCESS and END PROCESS. We write: -
PROCESS
Orders WHERE (Orders.ordcustid = Custf.Account) INDEX(JZ-INDEX2);
Jazz parses this and adds a TS option, a
definition of file TS2, and a closing END PROCESS: -
GET
Custf KEY(CustF.Account OR CustF.Name) SAVECOPY CICS3C.SAVE TS(1);
#373 I
GET statement returns one record at a time for Name
DEFINE
TS2 TS DATA(
OrdNbr
LIKE Orders.OrdNbr);
PROCESS
Orders WHERE (Orders.OrdCustId
= CustF.Account) INDEX(JZ.JZ-INDEX2) TS(2);
END
PROCESS Orders;
END GET Custf RESETFUNCTION;
Click [Check] again to parse this new Jazz
code.
As it did for GET, Jazz has added TS(2) to the PROCESS statement and created a definition for the temporary storage file TS2.
Our screen can display up to 13 lines of orders, but a customer may have many
more. Or none at all. So we need to use logic that can handle these extremes
and everything in between. The concept is simple: when we read a CustF record
we’ll also read all the corresponding Orders records, storing their record keys
in “Temporary Storage”. Then, when the screen is displayed the program will
read the keys of up to 13 records from temporary storage and read the
corresponding ORDERS records. Jazz creates PF7/8 (up/down) paging logic
automatically.
Secondly, by writing the PROCESS between GET custf and END GET custf they are included in the ‘GET Block”, telling Jazz that these
statements are related. If we use
PF11(Next) or PF10(Previous) paging then as we move forwards or backwards
through Custf the Orders list is refreshed, so we’ll always have the orders
corresponding to the current Custf record.
Just as we’ve written logic into the GET block, we can write logic between PROCESS/END PROCESS. For example, if we’d wanted to
include Parts.PartName in the display line we’d have written: -
PROCESS
Orders WHERE orders.ordcustid =
custf.account INDEX
JZ-N1 TS(2);
GET
PARTS WHERE(Parts.Partnbr = Orders.OrdPart);
END PROCESS orders;
(Actually I’d have written GET PARTS WHERE
(Parts.? = Orders.?) and clicked [Check] to invoke selection dialogs to choose
the field names that I wanted)
One more change before we leave “Handling Custf”. We need enhance Delete logic to check that there are no related orders. We don’t want to delete Custf records for which there are Orders records, as this would leave orphaned orders. We add NOCHILDREN(Orders) to the DELETE statement
DELETE
custf WHERE(CustF.Account=CICS3C.Save.Account) CHECKCOPY(CICS3C.SAVE)
NOCHILDREN(Orders) RESETFUNCTION;
Now if there any Orders the DELETE will be refused and a message returned.
With CHECKCOPY, which is the same as in in program CICS2, the DELETE will also be refused with a message if the record has changed since the
Enquiry.
Here is the complete program so far. At this stage it will read a customer and
their related orders, and if there are more than 13 orders you can use PF7 and
PF8 to go up and down through the list of orders. We can also update the customer record. However we haven’t yet provided any way of
doing anything except looking at the orders.
We can’t process an order, or create new ones. That will come next.
*# Last Updated by JAZZUSER at 18/03/2018 10:46:28
a.m.
PROGRAM CICS3 CICS INSCREEN(CICS3S) TRANSID(TRN3) COMMAREA(CICS3C) EXIT(Menu1);
COPY JZSMth;
COPY JZMDays;
COPY orders;
ACCEPT (CICS3S.Function);
#562 I CICS3S.Error used as message field
CASE (CICS3C.Function);
WHEN
(Enquiry);
ACCEPT (CICS3S.Account OR
CICS3S.Name);
#562
I CICS3S.Error used as message field
DEFINE TS1 TS DATA(
Account
LIKE CustF.Account);
GET Custf KEY(CustF.Account OR CustF.Name) SAVECOPY CICS3C.SAVE
TS(1);
#373 I GET statement returns one record at a time for
Name
DEFINE TS2 TS DATA(
OrdNbr LIKE Orders.OrdNbr);
PROCESS Orders WHERE (Orders.OrdCustId =
CustF.Account)
INDEX JZ.JZ-N1 TS(2);
END PROCESS Orders;
END GET Custf RESETFUNCTION;
WHEN
(Update);
GET Custf WHERE(CustF.Account=CICS3C.SAVE.Account)
REWRITE CHECKCOPY(CICS3C.SAVE);
ACCEPT (CICS3S.Region,CICS3S.District,CICS3S.Name,CICS3S.SalesThisMonth,CICS3S.SalesYTD,CICS3S.Billingcycle,CICS3S.DateCommenced);
#562 I CICS3S.Error used as message field
END GET Custf REWRITE RESETFUNCTION;
WHEN
(Add);
CustF.Account
= CustF.$LastKey
+ 1; [Will need to be changed if key is not a number
#361
E Assignment to a key field
GET Custf KEY(CustF.Account) CREATE;
ACCEPT (CICS3S.Region,CICS3S.District,CICS3S.Name,CICS3S.SalesThisMonth,CICS3S.SalesYTD,CICS3S.Billingcycle,CICS3S.DateCommenced)
SETMDT;
#562 I CICS3S.Error used as message field
END GET Custf CREATE RESETFUNCTION;
WHEN
(Delete);
DELETE Custf WHERE(CustF.Account=CICS3C.SAVE.Account)
CHECKCOPY(CICS3C.SAVE)
NOCHILDREN(Orders) RESETFUNCTION;
END CASE;
SEND Inscreen;
Although there is further logic to be added to this program, we’ll compile and test it before completing it.
Process program CICS3. This compiles the program into the CICS load library.
Create an Orders test file: -
1. Click [JazzGen] and select Data/VSAM. Browse to the definition Orders.jzc, enter an estimated number of records and check [ ] Cluster. Submit this JCL to define the VSAM Cluster
2. Click [Configure] and then [Add Training]. Download program OrdersW.jzz.
3. Open program OrdersW.jzz in the Jazz Workbench.
a. Right-click [Process] to open the Process form,
b. click [Generate JCL], then edit the JCL to remove the DD statements for //Orders1 and //Orders2. Leave the DD //Orders. Orders1 and Orders2 refer to the alternate indexes but we haven’t created these yet, and if we leave these DD statements in the job it will fail with a JCL error.
c. Click [Test] to compile and run program OrdersW with the revised JCL
4. From the Jazz Workbench, rerun process [JazzGen] Data/VSAM, this time checking AIX. Submit this JCL to define the VSAM Alternate Indexes required by Orders.
Define relevant entries into our CICS group with these CEDA commands: -
· DEF PROGRAM(CICS3) GROUP(MANAJAZZ)
· DEF MAPSET(CICS3S) GROUP(MANAJAZZ)
· DEF TRANS(TRN3) PROGRAM(CICS3) GROUP(MANAJAZZ)
· DEF FILE(ORDERS) GROUP(MANAJAZZ) DSNAME(IBMUSER.VSAM.ORDERS)
· DEF FILE(ORDERS1) GROUP(MANAJAZZ) DSNAME(IBMUSER.VSAM.ORDERS1)
· DEF FILE(ORDERS2) GROUP(MANAJAZZ) DSNAME(IBMUSER.VSAM.ORDERS2)
· ALT file(ORDERS) GROUP(MANAJAZZ) ADD(YES)
· ALT file(ORDERS) GROUP(MANAJAZZ) BROWSE(YES)
· ALT file(ORDERS) GROUP(MANAJAZZ) UPDATE(YES)
· Similarly, give ADD, BROWSE, and UPDATE rights to ORDERS1 and ORDERS2,
· Follow this up with INSTALL GROUP(MANAJAZZ)
Because ORDERS was defined with two alternate indexes the relevant paths should be defined. At this stage we’re not using the 2nd path, which provides access to ORDERS by ORDPartNbr, so we could have omitted DEF FILE(ORDERS2). However since the AIX exists we may as well define it now. And while ORDERS doesn’t need ADD and UPDATE rights yet, it will later.
Here is a display from the program so far. I asked for Name “APTHORPE”: there are several such records in my test data. I clicked PF11 to take me to the second of these, which has 32 orders, and I clicked PF8 to show lines 13 to 24 of these records: -
Now it only remains to add logic to create new orders and process the existing ones to complete this program
Jazz V15 not only supports Micro Focus, there have been a number of enhancements since the original z/OS development: Jazz now supports a DATE data type, and training objects to create test data for these and other programs are supplied with Jazz. The screens below therefore show different test data to the screens above.
Instead of using CEDA commands, CICS FCT, PCT, and PPT entries are defined with ESMAC (Micro Focus’ Enterprise Server and Management). Refer to JazzUGMFStep3 for more information. Here is the equivalent test with the current test data and Jazz V15.1: -
The business rules around creating and processing an order make the process more complicated than simply creating an order record in a VSAM file. Does the customer have an adequate credit status? Can you supply stock? When? Having created the order it will go through a life cycle, often something like “Initial => Order Accepted => Despatched => Invoiced => Payment received and so instead of simply CHAR(10) you’ll probably define Orders.OrdStatus as a coded field. There will be various situations like part supply or part payment, the customer may pay for several orders on one invoice, several invoices on one statement, and so on. We’ll build these rules into our programs so that we don’t accept an order from a customer who doesn’t exist, or has been denied credit, and we can’t despatch an order that hasn’t been accepted. So rather than write a fully detailed program that inevitably would not reflect your particular situation, this tutorial will show you the general principles of a solution leaving it to you to apply your particular rules.
When screen CICS3S was defined we placed a function code at the left of every detail line. Here’s what we want to do: if we’re in enquiry mode and there is an “S” against an order we want to invoke a program (CICS4) to process that order: -
The first issue: how do we detect that the line command for the 3rd line has value “S”, and relate this to the 27th order for this customer which has OrdNbr = 31?
Firstly, how do we refer to the Line Function? You will have put it in the line simply by checking when you created the scrolling section, so you don’t know its name.
You can locate it within the screen definition. Click the button [Show Data] in the Jazz workbench: this will show you a list of the definitions within your current program (CICS3): -
Scroll down to find the screen definition, CICS3S. Expand this definition by clicking [+]. Scrolling further you’ll come to the repeating line, JZREPEAT. Expand this also. The line function is the first field, JZ-LF. Click it and its Jazz field name is put in Output: -
Click [Finish], then paste the text into your program within the PROCESS block. Turn it into an IF statement like this: -
IF
CICS3S.JZREPEAT.JZ-LF(JZ-N1) = 'S';
* Do something
END IF;
If the condition is true we want to invoke a program called “CICS4”. We can write this program as we did CICS2 in the previous chapter: -
Except for program and file names, this is exactly like program CICS2 shown in the previous chapter. This won’t be what we want but it’s a start, and we’ll now have a basic program and screen that we can invoke from CICS3 or run independently. The logic of CICS4 will evolve as we learn more about the problem, and how Jazz can help. As we develop CICS4 we may come back to CICS3 several times, adding function and data.
We now have a program CICS4 that uses a screen CICS4S and a COMMAREA CICS4C that is invoked with Trancode Trn4. We define these to CICS, so that we could execute program CICS4 by entering transaction Trn4. Here are the CEDA commands that I used (yours may be different): -
· DEF PROGRAM(CICS4) GROUP(MANAJAZZ)
· DEF MAPSET(CICS4S) GROUP(MANAJAZZ)
· DEF TRANS(TRN4) PROGRAM(CICS4) GROUP(MANAJAZZ)
If we’re using Micro Focus Enterprise Developer we create the FCT, PCT, and PPT entries using ESMAC (Enterprise Server Management and Control).
Coming back to program CICS3, we add
COPY CICS4S;
COPY CICS4C;
and within the IF block we write
a couple of statements to set up the Commarea for CICS4, and a SEND statement to invoke the program: -
PROCESS Orders WHERE (Orders.OrdCustId =
CustF.Account)
INDEX JZ-N1
TS(2);
IF
CICS3S.JZREPEAT.JZ-LF(JZ.JZ-N1) = 'S' THEN;
CICS4C.Function
= Update;
CICS4C.SAVE
= Orders;
EXIT
TO CICS4 COMMAREA(CICS4C);
END
IF;
END PROCESS Orders;
Process this and it’s ready to test: enter “S”
as shown above and CICS4 is invoked: -
Our initial test shows that this works well, picking up the correct
order even when we have used PF7/8 to page up and down, or PF10/11 to go
forward or backward through the customer file.
Obviously the logic of CICS4 as generated is only a testing stub. We need to detail with the actual rules of
updating orders: for example we should not ever be able to change the order
number, once the order status is confirmed we won’t be able to change anything
else except status, and so on. The CICS4
testing stub has none of these rules, and would allow users to make changes
that would seriously compromise our database.
To create a new order we need to provide another case. We add another function to CICS3’s Commarea: -
*#
Created by IBMUSER at 8/01/2015 3:48:04 p.m.
COPY Custf;
DEFINE CICS3C COMMAREA DATA(
Function CHAR(1) CODES (E:Enquiry,U:Update,A:Add,D:Delete,R:Order) VALUE Enquiry,
SAVE LIKE Custf.*,
JZ-XCTL LIKE Jazz.Flag);
(I have added “R” for “Order” because I have an
aversion to using “O” which is easily confused with “0”).
We should add “R” to the text in the screen: -
[Process] the screen so that it is saved and
the physical map created, and return to our program logic.
We add another CASE to the logic of CICS3 to
handle this: -
WHEN
(Order);
…
Logic for this case is very similar to that for
handling an existing order. We
initialise an orders record then invoke program CICS4 as we did before, but
with function code Add: -
WHEN
(Order);
Orders
= JAZZ.$Init;
Orders.OrdCustId
= CustF.Account;
CICS4C.SAVE
= Orders;
EXIT TO CICS4 COMMAREA CICS4C;
Of course the actual logic of program CICS4 hasn’t been properly developed yet, there is only the automatically-created logic which won’t be correct for this situation, but we’ve finished with CICS3. Here is the complete program: -
*# Last Updated by IBMUSER at 18/04/2018 10:30:40 a.m.
PROGRAM CICS3 CICS INSCREEN(CICS3S) TRANSID(TRN3) COMMAREA(CICS3C) EXIT(Menu1);
COPY JZSMth;
COPY JZMDays;
COPY orders;
COPY CICS4C;
#036 W More than one TYPE(COMMAREA) definition. CICS4C
treated as Working Data
COPY CICS4S;
ACCEPT (CICS3S.Function);
#562 I CICS3S.Error used as message field
CASE (CICS3C.Function);
WHEN
(Enquiry);
ACCEPT (CICS3S.Account OR
CICS3S.Name);
#562
I CICS3S.Error used as message field
DEFINE TS1 TS DATA(
Account LIKE CustF.Account);
GET Custf KEY(CustF.Account OR CustF.Name) SAVECOPY CICS3C.SAVE
TS(1);
#373 I GET statement returns one record at a time for
Name
DEFINE TS2 TS DATA(
OrdNbr LIKE Orders.OrdNbr);
PROCESS
Orders WHERE (Orders.OrdCustId
= CustF.Account) INDEX JZ-N1 TS(2);
IF CICS3S.JZREPEAT.JZ-LF(JZ.JZ-N1) = 'S' THEN;
CICS4C.Function =
Update;
CICS4C.SAVE = Orders;
EXIT TO CICS4 COMMAREA(CICS4C);
END IF;
END PROCESS Orders;
END GET Custf RESETFUNCTION;
WHEN
(Update);
GET Custf WHERE(CustF.Account=CICS3C.SAVE.Account)
REWRITE CHECKCOPY(CICS3C.SAVE);
ACCEPT (CICS3S.Region,CICS3S.District,CICS3S.Name,CICS3S.SalesThisMonth,CICS3S.SalesYTD,CICS3S.Billingcycle,CICS3S.DateCommenced);
#562 I CICS3S.Error used as message field
END GET Custf REWRITE RESETFUNCTION;
WHEN
(Add);
CustF.Account
= CustF.$LastKey
+ 1; [Will need to be changed if key is not a number
#361
E Assignment to a key field
GET Custf KEY(CustF.Account) CREATE;
ACCEPT (CICS3S.Region,CICS3S.District,CICS3S.Name,CICS3S.SalesThisMonth,CICS3S.SalesYTD,CICS3S.Billingcycle,CICS3S.DateCommenced)
SETMDT;
#562 I CICS3S.Error used as message field
END GET Custf CREATE RESETFUNCTION;
WHEN
(Delete);
DELETE Custf WHERE(CustF.Account=CICS3C.SAVE.Account)
CHECKCOPY(CICS3C.SAVE)
NOCHILDREN(Orders) RESETFUNCTION;
WHEN
(Order);
Orders
= JAZZ.$Init;
Orders.OrdCustId
= CICS3C.SAVE.Account;
Orders.ordDate
= JAZZ.$Today;
CICS4C.SAVE
= Orders;
CICS4C.Function
= Add;
EXIT
TO CICS4 COMMAREA CICS4C;
END CASE;
SEND Inscreen;
These 44 lines of Jazz (some of which were inserted automatically by the Jazz workbench) result in this COBOL program of 2728 lines of COBOL. Here is the CICS map.
We’re now at the stage where we’ve finished program CICS3, which will invoke program CICS4 both to create a new order and to process an existing one. This tutorial won’t continue with the detail of CICS4: you now have enough tools to write it yourself, and its details will depend on your business rules such as the rules that allow it to progress from Initial to “Approved” to “Actioned” to “Invoiced” to “Completed”? Can you delete an Order once it progresses from its initial state? Can you delete a Custf record? Programs CICS2 and CICS3 allow users to simply delete records without any checks, not even an “Are you sure” message. This might be OK for demonstration programs, but unlikely to be satisfactory solutions in the real world. Still, you should now have enough tools to write whatever logic you need to within the classical CICS world of 3270 screens.
In the next section we’ll start considering how you write and implement programs that provide or use web services.