Provides the functional program logic linked to the GUI via a form (session). 4GL contains sections and function for standard form controls, directly called by the standard program (BaanERP: 4GL Engine).
The 4GL script is called by the standard program upon:
- User action
- Activation (other session, job mode)
- Database events
The UI / 4GL script has the following layout:
For BaanERP the sections are printed in
|******************************************************************************* |* tibom1110 0 VRC B50b |* Maintain Production Bill of Material (tibom010) |* N. Author |* 1995-04-15 |******************************************************************************* |* Description |* This program maintains the Bill of Material (BOM). |* A BOM shows components (materials) of a parent assembly, |* quantities, units, effective dates. |* In this program for all operations the link with the table |* -Reference Designators- (tibom020) should be maintained. |******************************************************************************* |* Modifications |* Rev.No. 3 whB50bsy03 12 Dec 95 ndev |* SER_ITEM, N. Developer, 1995-12-12 |* Checks for new field tibom010.wxyz added |* |* Rev.No. 4 whB50bsy03 20 Mar 96 nsolve |* ID 100/21667, N. Solver, 1996-03-20 |* Estimated quantity (tibom010.estq) not calculated correctly. |******************************************************************************* #ident "@(#)tibom1110 whB50bsy03 walker Rev.No. 3 12 Dec 95 ndev" #ident "@(#)tibom1110 whB50bsy03 walker Rev.No. 4 20 Mar 96 nnsolv" #ident "@(#)SER_ITEM, N. Developer, 1998-04-27" #ident "@(#) ID 100/21667, N. Solver, 1998-05-04" |*************************** declaration section ****************************** declaration: table long extern long double extern double string extern string domain extern domain #define #include |*************************** program section ********************************** before.program: after.form.read: on.error after.program before.new.object: <BaanERP 5.1 and beyond> before.display.object: |*************************** zoom section ************************************* zoom.from.<fieldname>: on.entry: |*************************** form section ************************************* <when non Dynamic Form session> form.all:/ form.<form.number>:/ form.other: init.form: before.form: after.form: |*************************** group section ************************************ < when Dynamic Form Session, BaanERP 5.1 and beyond> |* group <description, like warehouse, order dates etc> group.<number>: init.group: before.group: after.group: |*************************** choice section *********************************** <see programmers manual for all choice sections> choice.start.set: choice.print.data: |* The order of the choices must be before.choice: |* as written in section 2.1.3 of the on.choice: |* Programmers Manual |*************************** field section ************************************ field.all:/ field.<fieldname>:/ field.other: before.field: before.display: after.display: ref.display: before.input: selection.filter: |* BaanERP 5.2 new 4GL section to use filter for |* "autocomplete" too before.zoom: |* BaanERP 5.2 do not put filters here after.zoom: before.checks: domain.error: ref.input: on.input: when.field.changes: check.input: after.input: after.field: <in BaanERP this section do not have (table) mnemonics in function name, except for table field field sections > |*************************** main table section ******************************* < not recommended to use from BaanERP and beyond, since the DAL sections should be used for database checks / consistency > main.table.io: before.read: after.read: read.view: before.write: after.write after.skip.rewrite: after.skip.write: after.skip.rewrite: before.delete after.delete after.skip.delete: |*************************** after commit ************************************* after.update.db.commit: |************************* function section *********************************** functions: |++++++++++++++++++++++++++++ form commands ++++++++++++++++++++++++++++++++++++ function extern display.item.drawing() { } |++++++++++++++++++++++++++++ lead time ++++++++++++++++++++++++++++++++++++++++ function get.lead.time() { ... } function update.leadtime() { ... } |************************* misc functions section =**************************** function read.signal.code.of.item(domain tcitem i.item, domain tccsig o.signal) { ... }
Note
In BaanERP, the main table sections are rarely used, since the checks are typically carried out in the DAL. Please use FunctionUsage for BaanERP 5.1 and beyond.
In BaanERP, choice.user.0 will be rarely used, since functions can be directly linked
choice.user.0: |* Validate Production Planning on.choice: validate.planning()
Note
In BaanERP, function validate.planning() should be called directly using form commands).
When marking more than one record in the Overview screen of a session, and then pressing (for example) the Delete button, the 4GL engine will only execute the choice.mark.delete section once. So, the following piece of code is not correct when more than one record is selected:
choice.mark.delete: before.choice: select tccom112.cfcg from tccom112 where tccom112.cfcg = :tfacr001.ficu selectdo mess("tfacrs01101", 1) |* Business Partner exist in Group, |* cannot delete record remove.mark() choice.again() endselect
Instead of this, use the function do.all.occ() and specify as parameter a function that does the delete action for one record. This applies also to the other standard commands, but in practice the problem arises most often when using the choice.mark.delete standard command.
(BaanERP 5.0 and beyond)
Often in BaanERP the user intends to fill in a form field, zooms to the related session, selects a record, and returns to the form field with a value filled in. A user may also fill in a field and zoom to the related session to look for more detailed information. A browse session is of type “Modal, Secondary Window”. “Modal” means that the parent session is blocked for user input until the browse list ends. Another characteristic of a browse session is that it may have a browse filter implemented, to show only a relevant subset of the data. A zooming action contains 2 steps:
- the browse list session imports one or more variables from the parent session
- after the user selects a record in the browse list and ends the session by pressing OK, the browse list session has to export the data of the selected record to the parent session
In the Programmers Guide (Chapter 4GL Language Features/ Guidelines on browsing/zooming ) the mechanism of browsing, (automatic) import of data from parent session in child session, and (automatic) export of data from child session to parent session has been described extensively. Please study these chapters before implementing zooming !
The SPS will only provide additional information and best practices and, were needed, references are mentioned.
In the Programmers Guide (Chapter 4GL Language Features/ Guidelines on browsing/zooming/Importing of variables ) 5 situations are described in which the 4GL Engine automatic controls the import. These situations are:
- Table reference exists from parent field to main table of child session
- Table reference exists from main table of child session to main table of parent field.
- Same main table for parent session and child session
- Parent session without main table
- Same packages, no relation between main table of parent session and main table of child session
However as indicated in the Programming Standards some of the situations require extra code in the 4GL scripts. These examples refer to zooming to sessions in the same package, however when zooming to a session in a different package no table reference is allowed (except with the tc package).
-
Parent and child session in different packages
Case:
From the parent session with main table X a child session of a different package starts with main table Y.
Example:
Parent session “Routing Parameters” (tirou0100m000)/field “Label Layout” (tirou001.labl) zooms to session “Label Layouts” (whwmd5520m000).
Result:
Automatic import of primary key values is not allowed, due to different packages.
Consequences for programming in UI script:
Integration function needed to pass variables and to start the child session.
|****************************** field section ***************************** field.tirou000.labl: before.zoom: tiint.dllwhwmd.start.session.label.layout(tirou000.labl) attr.zoomcode = 0
Hereafter some interesting examples will be given of specific cases
Parent session “Warehouse Orders”
extern domain tccwar hold.warehouse |* Ship from location field.whinh200.sflo: before.zoom: hold.warehouse = whinh200.sfco selection.filter: query.extend.where.in.zoom( "(whwmd300.loct = whwmd.loct.pick or " & " whwmd300.loct = whwmd.loct.bulk or " & " whwmd300.loct = whwmd.loct.staging) and " & " whwmd300.ball = tcyesno.no ")
Browse session Warehouse – Locations
zoom.from.all: on.entry: import("hold.warehouse", whwmd300.cwar)
In this example a filter is defined in the DAL of the “parent session”. The reason to have this in the DAL is the fact that fields have often restrictions programmed in the “.check” or “.is.valid” hook, and when zooming these restrictions should also apply to the child session, to avoid a selection of a record in the child table, which is not allowed when returned to the parent session. This means that from a maintainability point of view the field constraints and filters should match and in the same source (DAL),
Parent session “Warehouse Orders”
extern domain tccwar hold.warehouse |* Ship from location field.whinh200.sflo: before.zoom: hold.warehouse = whinh200.sfco selection.filter: SET.BROWSE.FILTER.UI(whinh200, "sflo")
Browse session Warehouse – Locations
zoom.from.all: on.entry: import("hold.warehouse", whwmd300.cwar)
DAL Warehouse Orders
function extern long whinh200.sflo.filter( ref string o.select, ref string o.from, ref string o.where) { o.select = "" o.from = "" o.where = "(whwmd300.loct = whwmd.loct.pick or " & " whwmd300.loct = whwmd.loct.bulk or " & " whwmd300.loct = whwmd.loct.staging) and " & " whwmd300.ball = tcyesno.no ") return(0) }
Zooming from field segments needs extra attention of the developer, because during development the content of the field segments is not known. The content of the field segments will be specified during implementation. Therefore it is for example not allowed to add specific functionality for one segment only. All functionality must be available for five segments
To keep development easy, two defines are available in function ‘Disable/enable and segmentation support’ (tcmcs2010): FILL_ZOOM_VARIABLES and GET_ZOOM_CONTENT
Item segmentation means that the item domain (e.g. tcitem, cpitem) can have maximum 5 segments and per segment the zoom session can be specified (e.g. project segment zooms to Session “General Projects” (tcmcs0552m000) with zoom return tcmcs052.cprj. The segmentation settings are defined in session “Item Code Segmentation” (tcibd0500m000).
The define FILL_ZOOM_VARIABLES can be used if exceptions with default values, as specified in session “Item Code Segmentation” (tcibd0500m000), are needed.
These define can be used to set the predefined variables:
- attr.zoomsession$
- attr.zoomindex
- attr.zoomreturn$
If predefined variable ‘attr.zoomsession$’ or define ‘FILL_ZOOM_VARIABLES’ is used in the program script, the session must be added to the list of used data dictionary components with ‘#pragma used session ppmmmsfxxoycc’ at the end of the declaration section. The pragma codes can be placed anywhere in the source, but it is clearer to use the same section in all scripts.
For segmented fields the arguments consist of one or more pair of variables:
- Application content segment [CLUSTER_SEGMENT, PROJECT_SEGMENT or ITEM_SEGMENT] (mandatory)
- Child session (string)
- Number of table index of child session (string or long)
- Name of return field of child session (string)
The first argument is mandatory and the other arguments are optional. So, only new values can be entered. Also the sequence of the arguments is free, but it is better to keep a standard sequence. If the first argument (application content of segment) is not defined, the whole pair of arguments will be ignored.
This define is applicable for segmented and not segmented fields and has one mandatory argument, the mapping of the current field and the zoom to field. In case of segmented fields, the define will transfer as much as possible segments.
For example, if the segment content of the parent field is Cluster/Project/Item and the segment content of the zoom to field is Project/Item, the project and the item segment will be transferred to the child session. If the segments of the zoom to field are switched from Project/Item to Item/Project, even the define will switch the segments.
|****************************** declaration section *********************** declaration: table ttipcs020 | Projects table ttcibd001 | Items table ttcemm135 | Clusters #include "itcmcs2010" |* Disable/enable and segmentation support #pragma used session "tipcs2101m000" |****************************** field section ***************************** field.cprpd750.plni.segment.1: before.zoom: handle.before.zoom.plan.item.segments() field.cprpd750.plni.segment.2: before.zoom: handle.before.zoom.plan.item.segments() field.cprpd750.plni.segment.3: before.zoom: handle.before.zoom.plan.item.segments() field.cprpd750.plni.segment.4: before.zoom: handle.before.zoom.plan.item.segments() field.cprpd750.plni.segment.5: before.zoom: handle.before.zoom.plan.item.segments() |****************************** functions ********************************* function handle.before.zoom.plan.item.segments() { |* this function overrides the attribute settings of the default zoom session |* "General Projects"(tcmcs0552m000) to those of session tipcs2101m000 |* "(Manufacturing) |* It is possible to override the index to index2 of the child session |* by filling 3rd arg with 2 FILL_ZOOM_VARIABLES( PROJECT_SEGMENT, "tipcs2101m000" ) |* map the segments of current field (segment number, position and length) |* to the "zoom to field" (argument) which can be segmented as well according |* to the "Item Code Segmentation". |* the define returns a ready to use zoom value in the child session |* zoom to field tipcs020.cprj = GET_ZOOM_CONTENT( "tipcs020.cprj" ) tcemm135.clus = GET_ZOOM_CONTENT( "tcemm135.clus" ) tcibd001.item = GET_ZOOM_CONTENT( "tcibd001.item" ) }
You can start other sessions in a script. For this, you must consider the following three situations:
- Session A always calls session B.
- Session A needs a variable defined in session B (for example, the calculator; the calculator transfers the calculated value to the field from which the calculator is activated).
- Session B needs a variable defined in session A, and session A needs a variable defined in session B.
Situation 1
The proposed solution is to state an import command in session B. This solution is based on a technical aspect: you cannot export variables to a session that does not exist.
In the examples, the section could also be before.program, init.form, init.group (BaanERP 5.1 and beyond):
zoom.from.table.field: on.entry: import("variable.sess.B", variable.sess.A)
Situation 2
The proposed solution is to state an export command in session B. This solution is also based on a technical aspect: you cannot import variables to a session that is closeable.
zoom.from.table.field: on.exit: export("variable.sess.A", variable.sess.B)
Situation 3
The proposed solution is the sum of Situation 1 and Situation 2. In other words, a separate import and a separate export command are necessary.
zoom.from.table.field: on.entry: import("variable.sess.B", variable.sess.A) on.exit: export("variable.sess.A", variable.sess.B)
Automatic importing means importing of the primary key that is shared by sessions (see also Programmers Manual, ‘Automatic Importing of Variables’).
Do not used import/export as alternative for input/output variables in functions.