Saltar a contenido

Programer's reference

Introduction

In each section you will find the explanation of the code segment that is being studied.

The section is divided as follows:

Program Name The name of the program to be detailed.

Objective Generic description of what this segment aims to achieve of code.

Tables The name of the tables and database to be to access. As well as a brief explanation of the use that is going to be given to this table.

Variables The most important variables to manipulate during execution. The reference column tells us if the variable is input (comes from a Web page or another program as a parameter). Or if it is global to the code being executed.

Sequence The logical sequence of steps that is followed during the execution of the program.

Some programming conventions

All variables that start with $rs are database access variables and contain recordsets with the result of a query.

Input variables from a web page are stored in the %in hash, and the value is accessed as follows: $in{'field name'}

Important

In the original installation, eFlow backs up only the following directories: /home/eflow/cron /home/eflowweb/cgi-bin /home/eflowweb/html perl library path/vendor_perl/Eflow

In order for the code you develop and everything related to it to be supported, you must install all the information in those directories. Or modify the program /home/eflow/cron/back_up.pl ; to adapt it to your needs.

Otherwise your developments will not be backed up during the backup procedure.

System constants

They are located in the file user_check.pm

Variable Meaning and use
$EF_ROOT Path to the directory where the eFlow routines are stored
$EF_CGI Path to the cgi-bin directory where all eFlow related programs are located
$EF_WEBCGI cgi-bin directory for URL construction
$EF_SERVER IP or domain of the Web server that contains the eFlow program
$EF_WEB Path to the server directory where eFlow pages and files are stored.
$EF_WEBS Path to the server directory where eFlow pages and files are stored in the secure server section
$EF_EMAIL Email address used in the from that the system sends
$AUTOMATIC 0 Running from Web, 1 Running with cron: automatic.pl

Common variables in all routines

Variable Meaning and use
%in Variable where the input data of a web form is stored
$in{'process'} Number of processes being executed
$in{'station'} Station being processed
$in{'folio'} Electronic folio being processed
$in{'opt_station'} Destination station
$user_name Name of the user who executes the routine
$Sdate System date (YYYY-MM-DD)
$Stime System Time (HH:MM:SS)
$Stimestamp System date and time
$Smon System month (1 to 12)
$Smonth System month (January -- February)
$Syear System year
$Sday System Day (1 Monday - 7 Sunday)

Important variables within update routines

Variable Meaning and use
$in{'process'} Number of processes being executed
$in{'station'} Station being processed
$in{'folio'} Electronic folio being processed
$in{'folio_label'} Label of the folio being processed
$in{'opt_station'} Destination station
$ef_user Empty is ignored. If value > 0, the folio is forced to be assigned to the user number
@a_ef_user $a_ef_user[#stage] equal to ef_user, but applies to parallel stages
$in{'ff##'} Values from the web page that correspond to fields in the folio related to the process being executed.
$EF_USER Slot number to be occupied by the user
$ef_account Account of the user who is logged in
$ef_ip IP from which the user registered
$ruser User number
$user Depreciated, should not be used, position number (use $EF_USER)
$BB 1 = Connection from mobile device
$EXT Preferred extension for images (png, gif)
$EF Site number you connected to
$user_permissions Active permissions for the user according to the groups to which they belonged at the time of registration.
$lib Lib object with various functionality described in Lib.pm

Environment variables (%ENV)

Variable Meaning and use
$ENV{'REMOTE_ADDR'} IP of the computer that accesses this server
$ENV{'HTTP_HOST'} Machine domain
$ENV{'DOCUMENT_ROOT'} Path to the directory where the web pages are located

eFlow Engine Flowchart

How to program without entering into conflicts with the automatic update system

Establish basic programming rules so that the programmer responsible for creating flows in eFlow does not have conflicts with the eFlow engine and components and the automatic update system.

  1. Use local variables in all your subroutines and functions, no create new global variables. This is always declare your variables within the subroutine you are developing by prefixing the my keyword, which tells the compiler that the variable It has local reach.
  2. If it is absolutely necessary to create a global variable, to use it at different times of the execution of the process, always prefix __my___ to the name of your variables, so that there is no possibility of altering variables of the system, for having taken a name that eFlow already uses. (Example : $my_id)
  3. Do not alter eFlow global variables unless you understand the impact it will have on the execution of the code. Later on explains the use of global variables that you can alter with your own subroutines, and the impact they will have when the eFlow engine runs.
  4. In some eFlow codes, there is a "tag comment" that separates the eFlow routines from the code used to create the HTML documents that are presented to the end user, this tag is # USER_DEFINED. Below this label you can alter the code and HTML tags to modify virtually the entire graphic design of the application, as well as creating new leagues or functionalities you may need. As long as you alter the code in this section, any updates sent will not change the code you have developed. Do not change the name of this label.
  5. If you create modifications above the USER_DEFINED tag, When there are updates, your modifications will be overwritten and you will have to rewrite your code. If it is absolutely necessary to make changes above the USER_DEFINED tag, since you cannot solve your problem otherwise, then They recommend one of the following two options:
    1. If your modification is required for a single process and is not going to be use in more processes. The first preferred method is that always use post-processes and personal pages so that Create code as complex as you want. You can even copy subroutines that currently exist in the eFlow engine to the code generated in the post-process that can replace code real engine, simply writing the same name of the subroutine in your engine. The result of this is that the modifications will only have an impact on the process where they require really these special changes and not in all processes that develops.
    2. If your modification is permanent and will be used in all processes: copy the subroutine you want to alter below the USER_DEFINED tag and in the copy below make your changes. The result is that the compiler will write the code that was already there before you to overloaded below the USER_DEFINED tag. This must be the least used method since it causes the problem that at send new updates, this subroutine will not have improvements introduced into the engine and in this case you will have to check manually the changes introduced in the engine and copy them and adapt them to your copy after each update.
    3. In any of the two previous cases you can send us the modification made, indicate the reasons why it has been required to make this change, and whether the modification is valuable for the general eFlow user base and does not impact important way in the performance of the application, will be incorporated into the standard eFlow engine and thus in the next update and you can have an engine again eFlow standard in your company.
  6. There are several files with termination_def.pl These files contain the definition of how the elements of the form in the station stages. You can modify these freely to adapt the forms if required.
  7. The libraries inside the Eflow folder, installed on the Perl library directory, contains the eFlow engine, Try not to move anything in those codes.

List of programs that you can modify, because they are not subject to automatic updates.

Microflow tries not to move the files that allow a user to redefine the image of the product and add its functionalities. Except in rare cases where you have to eliminate a security problem or functionality that does not work properly, these files must be updated. Otherwise they are not modified from the installation. Yeah At some point the development team needs to move these codes for reasons other than security (example: adding functionality to eFlow), they would be released with a new version of eFlow so that they do not generate problems with current developments.

The list of files that are outside of normal eFlow updates are:

  • /home/eflow/cron
    • back_up.pl
  • /home/eflowweb/cgi-bin/eflow
    • comments.cgi, display_def.pl, login_def.pl, mmenu.cgi, pstation_def.pl, station.cgi, station_def.cgi, work_window.cgi, top.cgi
  • /home/eflowweb/cgi-bin/eflow/admin
    • back_up.cgi, menu_add_folio.cgi, style.cgi, delete_all_folios.cgi
  • /home/eflowweb/html
    • New elements are added, such as images, etc. Nothing existing is replaced.

List of files you should not move because eFlow will always update. (Unless there is the possibility of creating your own developments under the label USER_DEFINED

  • .. path perl libraries ../Eflow
    • No files in this place, except for system constants to suit your installation.
  • /home/eflow/cron
    • webupdate.pl
  • /home/eflowweb/cgi-bin/eflow
    • login.cgi, locked_station.cgi, start.cgi, eflow_webservice.cgi, email_station.cgi
  • /home/eflowweb/cgi-bin/eflow/admin
    • add_folio.cgi, install.cgi, webupdate.cgi, WUinstall.cgi, padd_folio.cgi
  • /home/eflowweb/cgi-bin/designer
    • Do not move any files, all are subject to modifications.
  • /home/eflowweb/cgi-bin/documentta
  • Do not move any files, all are subject to modifications.

All other files not mentioned in the previous two lists.

  • These can be modified, because there is a low probability that they will require changes, but they may rarely require them.

If you have made modifications to any of the files and do not want any updates to alter them again, change the file permissions to read execute if necessary, or even change the owner of the file so that eFlow cannot update it.

Integration with PHP

Integrating PHP-based solutions or developments that interact with eFlow is very simple.

Firstly, to have your scripts run only when the user has registered with eFlow, place them inside a subdirectory containing an .htaccess file with the following code.

AuthType None
require valid-user
TKTAuthLoginURL cgi-bin/eflow/start.cgi
TKTAuthIgnoreIP on
TKTAuthTimeout 0
TKTAuthCookieExpires 2d

Seguido se presenta un pequeño script, de ejemplo.

<?php
    require_once('/home/eflowweb/cgi-bin/eflow/lib/user_check.php');
    $uc = new EflowUser();
    $user = $uc->user_check();
?>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="/css/eflow.css">
</head>
<body>
<?php
    echo "<a href='javascript:self.close();'><img src='/images/close.$uc->EXT' border='0' title='Cerrar' align='right'></a>n";
?>
<br>
<br>
<b>Validación de PHP</b><br>
<br>
<table border="0" cellspacing="1">
<?php
    echo "<tr><td class='title'>Usuario</td><td class='folio'>$user ($uc->EF_RUSER)</td></tr>n";
    echo "<tr><td class='title'>Nombre</td><td class='folio'>$uc->user_name</td></tr>n";
    echo "<tr><td class='title'>Cuenta</td><td class='folio'>$uc->ef_account</td></tr>n";
    echo "<tr><td class='title'>IP</td><td class='folio'>$uc->ef_ip</td></tr>n";
    echo "<tr><td class='title'>Imágenes</td><td class='folio'>.$uc->EXT</td></tr>n";
    echo "<tr><td class='title'>Empresa</td><td class='folio'>$uc->EF</td></tr>n";
    echo "<tr><td colspan='2' class='folio'>PHP funcionando y validaciones de seguridad correctas</td></tr>";
?>
</table>
</body>
</html>

eFlow already has a php directory created and with the .htaccess file so you can develop the applications you want within it.

The development examples located at the end of the manual are developed in Perl, but with very little effort they can be written in PHP and achieve exactly the same results.

login.cgi

Objective

Register the user as logged in so they can interact with it system.

Tables

Name Type DB Description
users Table WorkFlow Table containing the position data.
rusers Table WorkFlow Table containing user data
general Table WorkFlow In the menu field, the full path to the program that displays the menu is indicated.

Variables

Name Type Reference Description
$in{'user'} String Web Variable comes from the log in page and contains the user account
$in{'passwd'} String Web Variable comes from the log in page and contains the user's password

Secuencia:

  1. Load libraries
    1. Eflow::user_check to read form and access database
    2. Net::Netmask for manipulation of IP addresses and ranges.
  2. Read data from the form and store it in %in
  3. Connects to the database and reads the user who has the account $in{'user'}
  4. Validate that the account exists (if it doesn't appear)
  5. Validate that the password for the account is correct (if it doesn't work)
  6. Validates that the user is active in the system. (if it doesn't come out)
  7. Validate that the IP, from which the user wishes to connect, is within the authorized ranges. (if it doesn't come out)
  8. If the user is already logged in, verify: that they are authorized to open more sessions and that they have not exceeded the allowed number of open sessions. If so, it opens another session, otherwise it exits.
  9. Copy username to users password.
  10. If everything is correct, create an encrypted string to record section data and record cookies in the browser to identify the user.
  11. Presents menu for this user. It can be a generally defined one (where the name of the menu must be written in the menu field). If no menu exists, the standard eFlow menu is presented.

logout.cgi

Objetive

Register user exit in the system.

If you are called from another program you must receive at least the number of user that you want to remove from the system and an error message.

Table

Name Type DB Description
users Table WorkFlow Table containing the position data.

Variables

Name Type DB Description
$user Integer Global User number that accesses the system

Sequence:

  1. Load libraries
    1. Eflow::user_check to be able to read forms
  2. User_check is executed to read the user accessing the system.
  3. Read data from the form or input parameters if called from another program.
  4. Delete user from the browser so that it can no longer be used again without logging in
  5. Validate that the account exists and is logged in (if it does not come up with an error)
  6. Discount 1 session from open sessions, remove ip registration.
  7. Delete cookies from the browser.
  8. Display login menu. The website verifies that it is in the main window, if not (it is in a frame), and returns to present login menu. The log in menu is printed only if the user has JavaScript enabled.

display.cgi

Objetive

It looks for the pages that correspond to the user who makes the query and displays the pages assigned to them.

Tables

Name Type Reference Description
station_folio Table WorkFlow Table where the folios are located and to which station each one is assigned.
folio Table WorkFlow Gets the general data of the folio. Values such as creation date, comments, folio number and status are read.
station Table WorkFlow Data is obtained from display_extras so that the data that the user wants to appear in the table of pending pages in the station that is being processed is printed.

Variables

Name Type Reference
$in{'view_process'} Web Indicates which process is being viewed (0 = all)
$in{'view_station'} Web Indicates which station is being viewed (0 = all)
$user Web Indicates which user is accessing the system
$in{'supervise'} Web If folios should be deployed under supervision
$in{'order'} Web Data sort order
$in{'max'} Web Maximum number of sheets to be displayed per station
%tv Global Stores external database queries to minimize connections.

Sequence:

  1. Read data from the form or parameters if it was called from another program.
  2. Run user_check and receive user # if the user is valid.
  3. Read in general whether holidays should be deducted from the display of pending days.
  4. Verify whether all processes or a defined one should be deployed.
  5. The recordset is created with all the numbers of processes that we are going to deploy.
  6. Enter a while loop to display all the selected processes.
  7. The station table is accessed and the station numbers and their names are obtained and loaded into an array for quick access to the data.
  8. The folio_station table is accessed, and the folios assigned to this user for the process being deployed are obtained.
  9. Display page header: header subroutine
  10. Enter loop to display found pages
    1. If the station has been changed, the station titles are displayed (subroutine title executes the display of the titles)
    2. It is verified that we have not exceeded the maximum number of pages to be presented per station. If it exceeds, exit the loop and see the next process.
    3. Print values from the folio on the web page with the print_values subroutine.
    4. Increase displayed pages. 1.Loop a 11.Loop 8
  11. Print end of page: footer subroutine

Sub header: Displays HTML page header

Sub footer: Final HTML page display

sub title

  1. Displays the fixed value titles: Folio creation date, station entry date, user number assigned to the folio, number of days, folio number.
  2. Check if there is additional data to display.
  3. Enter loop to display additional data in table
    1. Extract from display_extras the titles of the fields to be displayed
    2. Print the title 1.Loop a
  4. Displays last comment title.

sub print_values

  1. The calendar days that the folio has to live from the assignment and its creation are calculated.
  2. If business days must be submitted, holidays are deducted from the total days.
  3. Gets comments from the folio and extracts the last one of them.
  4. If the folio is expired at this station, select red to mark the cell.
  5. Displays the fixed values of: Folio creation date, station entry date, user number assigned to the folio, number of days, folio number.
  6. Check if there are extra values to display.
  7. Enter Loop to display extra values
    1. Get the list of values
    2. Check where to get the value from: from a Folio, or from a local database, or from an external database.
    3. Get the value from the correct source.
    4. If the value comes from a FOLIO, the real value of this field is obtained, call true_value
    5. Display the data 1.Loop b.
  8. Display the last comment.

sub true_value

  1. A query is performed to determine the type of field from which you want to obtain the value.
  2. If the data type is greater than 7, return with the field empty, this data cannot be displayed.
  3. Check if the real value of this field is a fixed value or is obtained from an external database.
  4. If it is from an external base, enter THEN
    1. It is first verified if this array of values has already been obtained previously. Check variable %tv
    2. If it had already been processed before, the values are obtained without consulting the external database again.
    3. If you enter a loop to obtain all possible values from the external table.
    4. The data is put in $opt_str, so that they are seen as fixed values for the next part of the code.
    5. The loop is exited and the query is saved in variable %tv
  5. All values from $opt_str are extracted.
  6. The array of values is swept and the correct value is returned.
  7. If no real value was found, the originally sent value is returned.

comments.cgi

Objetive

And displays the comments in a new window that closes automatically.

Table

Name Type DB Description
folio Table WorkFlow The comments field is read to extract all comments

Variables

Name Type Subtype Description
$in{'folio'} Integer Web Folio number to be consulted
$in{'process'} Integer Web Process to which the folio to be consulted belongs

Sequence:

  1. The connection is made to the folio table of the process $in{'process'}
  2. The comments field is formatted to display it in a new window. The formatting consists of replacing |D with Date: |N with User: |C with Comment: |E with
    n

Format of the comments field:

|Date added|User|Comment|E

station.cgi

Objetive

Deploy the workstation to the user accessing the station.

Tables

Name Type DB Description
station Table WorkFlow Table containing the information necessary to display the data required for this station.
Process Table WorkFlow Process table
Folio_station Table WorkFlow Table of folios per station

Variables

Name Type Subtype Description
$in{'process'} Web Process number
$in{'station'} Web Station that should be deployed for the process in question
$in{'folio'} Web Folio to be displayed
@Areq Global Arrangement that indicates which formats may be required by the user and which may not, even when the user has marked them in the designer.
$p_name Global Process name
$user_int Global Integer value stored in the folio as user data
$user_char Global Character value that the folio has stored as user data
$obj_id Global Electronic folio number associated with this process
$folio_label Global Folio number display format
$comments Global Contains the last comment of the folio

Sequence

  1. Run user_check to get user # and validate that it can see station.
  2. Verify that the folio has not been moved by another user, if so displays display again.
  3. Get global values.
  4. Check if the station has a splash page personalized, if so it validates that you have access to the routine external by running get_path. If page ends with .htm, it is loaded the page is displayed and exits, if it ends with .pl it loads the library and the main_page() block is called, otherwise runs the program and exits station.
  5. If there is a preprocess, it is validated if it ends with .pl and executed main. If it has another termination, the external code is executed, handing over control or not depending on the case.
  6. The HTML page header is displayed. Subroutine print_header
  7. Opt_destiny is executed to print the destinations.
  8. If there is a custom page and it ends with .pl, it will be run main_page2.
  9. If there is a folio number associated with this station, it is displayed the electronic folio to the user using the obj_folio subroutine
  10. If there is a custom page with a .pl ending, it is executed main_page3
  11. The end of the HTML page is printed.

Suroutines

sub print_header: Print the header of the HTML page

sub html_footer: Print the end of the HTML page

sub get_path

It receives as a parameter the name of the file to be verified.

  1. Validate if you are in the eFlow root directory
  2. If not, check if the file name already has the correct path.
  3. If not, check if it can be located using the addresses stored in Path.
  4. If the file is not located, print an error.
  5. If it exists, return the full address.

sub opt_destiny

Configure the web page to return the destination later correct to update.cgi

The important fields of the station shape are:

opt_station: contains the destination station number

ef_selection: Contains 0 as long as no target option has been selected

If the option is not to display the stations, hidden values are printed.

opt_station = "."

ef_selection="1"

In any other case, ef_selection=0 is initialized and the format type is verified to display the destinations.

Combo select format: Destinations are displayed in a combo select

Radio button format: Each destination associated with a radio button is displayed.

In both cases, if the option to present the option is activated Update comments is printed as the first option of the combo or radio buttons the option "Update comments"

sub obj_folio

  1. All fields of the folio that must be drop-down are obtained in this station. Both to view and to edit.
  2. The values of the folio and the name of the folio are obtained.
  3. The recordset is scanned to display all the fields that can be view or edit on this station.
  4. We enter the Loop
    1. The format data of the field in question is obtained.
    2. If there is a personal page with a .pl ending, it is executed main_value.
      1. If the returned value is <> 0, the field is considered to be has processed
      2. Advance to the next record.
      3. Printing of the field is skipped.
    3. The common subroutine is called. So that you get all the values common to all fields of a folio. How are they if it is or not required, and obtains the external data of a field in case that the format requires access to an external table.
    4. The subroutine that knows how to display the field is called. according to its format. The call is achieved by concatenating the value "F" with the format number ranging from 0 to 10. Therefore For each format there is a subroutine Fn that displays the value of the field on the web page.
    5. Advance to the next record in the recordset.
    6. Loop a a.

Summary of formats:

Function Description
F0 Displays the fields with formats: File Upload, User Selection, User Defined, Java or Active X, Expiration Selection, Electronic Signature.
F1 Display fields with text format
F2 Displays the field with possible values in combo select format
F3 Displays the field with possible values in radio button format
F4 Displays the field with possible values in check box format
F5 Displays a password type text field
F6
F7
F8
F9
F10 Displays a textarea field to enter text on multiple lines.

Summary of field types

Value Type
1 Boolean
2 Date
3 Whole
4 Numeric
5 Text
6 Time
7 Attachment
8 Digital signature
9 User Selection
10 Alarm Time
11 User defined
12 Link
13 Java-ActiveX

Example Personal page with .pl ending:

sub main_page {

}

sub main_page2 {
}

sub main_page3 {
    print qq¡
    <script type="text/javascript" src="/lib/milibreria.js"></script>
    <script>
    function myvalidation() {
        if (DF.elemento.checked==false) {
            setWarning("Debe seleccionar el checkbox. !");
            return false;
        }
        return true;
    }
    Id('combo1234').onclick = function() {
        // Hacer algo con mi librería
        llenacombo(Id('combo1234').option[Id('combo1234').selectedIndex()].value);
    };
    </script>
    ¡;
}

sub main_value {
    return 0;
}

1;

The system has a JavaScript routine that performs basic validations: required fields, that the user has selected an action, and confirming the selected action if the system has been parameterized to request confirmation.

Custom validations with JavaScript

The system validates whether a "myvalidation()" function has been created.

If the function exists, it is executed to give your Javascript code a chance to perform any type of validation on the form elements. If validation is successful your routine should return "true", otherwise it should return "false".

It must additionally present an error message to the user.

update.cgi

Objetive

Transfer folios through stages.

Tables

Name Type DB Description
station Table WorkFlow Table containing the information necessary to display the data required for this station.
folio_station Table WorkFlow Table of the stations in which a folio is located

Variables

Name Type Subtype Description
$in{'process'} Web Process number
$in{'station'} Web Station number to be updated
$in{'folio'} Web Folio number to be moved
$AUTOMATIC Global If the movement comes from automatic.pl
$obj_id Global Electronic folio number associated with this process
$process_name Global
$process_relax Global Apply relaxed rules for this process
$in{'opt_station'} Web Destination

Sequence:

  1. Run user_check to validate user access.
  2. Validate access: call must be post, must have a referrer and referrer = server host
  3. Validate that the folio has not been moved previously and there are permissions to access it.
  4. If the station has a signature, it is validated and aborted if it is not valid.
  5. If there is a post process 1: load and execute main1.
  6. Validate that skipped destinations have been configured
  7. It is validated that the destination station is not end. If it is final, it is deleted folio from folio_station and folio is inactivated, changing status to 0.
  8. Destination station is checked to see if it is not a process split parallels:
    1. If it is split, delete folios from folio_station related to this move, split the options, separated by commas and assign to array options.
    2. Sweep the options array and obtain for each case the user at that the folio will be assigned at the next station (subroutine select_user). The folio, station, is inserted into folio_station. process to which the folio was assigned. It is repeated until finished with all options data.
    3. Read station to find out if the station you are processing is a join (meeting of several process flows into a point, after having previously separated them with a split)
      1. If it is a join, delete the folio of the station from folio_station station that was just joined, remove from join_station this station, find out if there are no more stations left pending to meet, if not then it is done display true, if there are missing stations to join, it is done false display.
    4. Folio_station is updated so that folio remains with the data correct: station assigned, user to whom the station was assigned Invoice.
  9. If the destination station is not null, the entry date of folio to station.
  10. Comments are saved in case they changed.
  11. If there is an electronic folio number associated with the process, They save the data that may appear on the website. If one of the fields to update is marked as register, it is saved in $register
  12. The transaction is recorded in log_update ($register is recorded)
  13. If destination station is not null, statistics and costs are updated.
  14. Main2 is executed in case there is a post-process 1
  15. Main21 is executed if a post-process2 exists.
  16. Verify that the new station is not mandatory, if necessary So, update locked in users so that user_check caches the status, and send directly to the blocked station.
  17. If it was not mandatory, return the user to the display list with the folio format that was being used.

Important subroutines:

sub select_user

If destination station is null, the current user number is returned.

It is validated if we must define the expiration of the folio. If ef_alarm is not null, the value of the date of expiration of the folio.

If $ef_user is defined, the programmer defined the user, return this user to the update process.

Depending on the type of next_user of the destination station, the user to whom the folio must be assigned, the types can be:

Value update
< 0 The absolute value of next_user is the user number to which the folio should be assigned.
0 Users are read from the work_group to which the station belongs and the next one in the list is returned according to last_user
1 Users are read from the work_group to which the station belongs and it is verified which ones are registered in the system, and it is assigned to the next one according to last_user.
2 It is assigned to the user who has the folio assigned at that moment
3 User is assigned that comes in the input variable $in{user} (of the form station)
4 It is assigned to user 0 which is the system
5 Assigned to the user who is updating at that time
6 Assigned to the user who registered the folio
7 Assigned to the boss of the user who updates
8 Assigned to the boss of the user who created the folio
10 GetNextUser from post-process1

sub statistics

Calculates average station update time (based on all the pages that have been processed)

Calculate the maximum, minimum time, the folio that represented the maximum folio, the minimum.

Update station_history table, in hourly interval.

sub save_obj_folio

  1. All valid fields of this electronic folio are obtained from obj_def.
  2. A Loop is started with the values of the electronic folio
    1. If the value is defined on the web page, the execution. Otherwise, the pointer is moved to the next recordset.
    2. The value of the web page is saved in the %data hash.
    3. It is validated if the field has format 7. If so, we must upload the Attachment of this folio to the server.
    4. If the format is date type, the field is reordered to the standard format (yyyy-mm-dd)
    5. If the format is a check box type, the input values are added if it is numeric or concatenated if it is a string
  3. Loop to 2
  4. The data in the electronic folio is updated with the fields obtained from the website.

post-procesos

Post-processes are programs that can be executed at certain points in the code that perform page updates, as explained in the section corresponding to update.cgi.

To develop a post-process

  • The program must have a .pl ending and must be written in Perl. The advantages are: it is incorporated into the code that is being executed (the code is loaded using a require statement), which allows you to see all the global variables and routines of eFlow, it allows you to control the flow of the program (abort, transfer to other routines, etc).

We are going to carry out a more detailed explanation of calls to Perl libraries.

The basic skeleton of a program called from the post-processing option is:

sub main1 {
    código ..
}

sub main2 {
    código ..
}

sub getNextUser {
    my $rsw->Pg_VB->new();
    $rsw->connectdb("dbname=workflow$EF");
    código ..
    $rsw->execute("select * from users where ??");
    return ($rsw->itemvalue('id'),$rsw->itemvalue('ruser_id'));
}

more subroutines with code

1;

Important

Use local variables in all subroutines to prevent global system variables from being inadvertently overwritten or altered. It is recommended to prefix the prefix mi_ to all the last ones that are incorporated so that there are no problems of duplication of subroutine names.

The basic skeleton of a program called from the post-process2 option is:

sub main21 {
    código ..
}

more subroutines with code

1;

The most frequent uses of main1 are:

  • Validate values of the form before moving the folio (that they are logical, have appropriate ranges, etc.)
  • Alter the destination or user that receives a folio, according to the data captured in the form.
  • Make updates to other external tables or databases of other systems.

The most frequent uses of main2 are:

  • Email notifications once the folio movement has been made.
  • Updates from other external systems, once the folio has been moved correctly and we know the user to whom the folio was assigned.

All values that come from the form are stored in the hash variable %in with the format $in{'ff###'} where ### is the number that was assigned to the field during the design stage of the folio.

Traditional post-process example:

sub main1 {
    #Validar si se están actualizando comentarios
    if (!$in{'opt_station'}) {return 0;}

    if ($in{'opt_station'} == 3) {
        #Si estación destino es 3 ejecutar los siguiente
        #Se crea un Nuevo objeto de acceso a base de datos
        my $rs = Pg_VB->new();
        #Se realiza conexión a base de datos
        $rs->connectdb("dbname=workflow");
        #Actualiza tabla con SQL
        $rs->execute("update obj1 set ff1='$user_name' where folio=$in{'folio'}");
        #Regresar sin seguir ejecutando más
        return 0;
    }
    if (!$in{'comments'}) {
        #Si la actualización viene sin comentarios enviar mensaje de error
        $lib->("Debe escribir un comentatio, NO SE PUEDE CONTINUAR",'',1);
    }
}

sub main2 {
    #Llamar a rutina local que envía un correo electrónico
    $lib->email_user(2,"Título","Mensaje");
}

sub getNextUser {
    if ($in{'opt_station'} == 1) {
        return 4;
    }
    return 19;
}

1;

When a station is declared as Automatic or Manual/Automatic. Note that post-processes are executed even when the program is running through a cron job. In these cases you are not interacting with a user.

Therefore you must design your process to fit this condition. To know if we are running from cron check $AUTOMATIC (value of 1, we are running in cron)

The second important thing to understand is that you should not run the exit function in a post-process that runs with cron, because the entire cron stops and this can leave pages unmoved. To prevent the folio from updating do $in{'opt_station'} = '';

When we are running in AUTO mode, we have no information coming from the shape of the station. If your script requires these values you will have to obtain them through a query and add them to the %in hash. The variable $obj_id has the ID of the Electronic Document to which we must connect to obtain the values.

add_folio.cgi

Objetive

Register folios. It receives as primary data the process number to be registered.

Data bases

Name Type Subtype Description
users Table WorkFlow Table that contains the user data and is used to obtain the user data necessary for registration.
Folio Table WorkFlow Table where the folio will be registered.
folio_station Table Workflow Table where some folio and station data will be saved.
$sdk Global Object Object to SDK package

Sequence:

  1. We validate that the user is valid.
  2. The connection is made to the workflow database.
  3. Validate that process exists and addnew is configured.
  4. It is validated that if the process has an associated electronic folio, the data table exists.
  5. Check if the addnew$in{'process'}.pl library exists
    1. Yes, load and call routine before_addnew();
  6. $sdk->insert_folio is called to insert the new document into the process.
  7. If addnew$in{'process'}.pl exists
    1. Yes, Call routine after_addnew();
  8. The user is sent to station n so that he can enter the necessary data for this new folio.

If you create a library addnew#.pl in the directory: /home/eflowweb/cgi-bin/eflow/admin

(# is the process number)

This is loaded and custom code is executed before and after the new folio is created and inserted into the process pipeline.

## Código ejemplo

addnew.pl

sub before_addnew {
    if ($in{'process'} == 8) {
        Ejecuta este código ...
    }
}

sub after_addnew {
    if ($in{'process'} == 3) {
        Ejecuta este código ...
    }
}

1;

admin/dell_all_folios.cgi

Objetive

Delete the existing pages and reset the page counter to 1.

Data base

Name Type Subtype Description
folio_station Table WorkFlow Table where the assigned folios are located.
Folio Table WorkFlow Table where the folio will be registered.
obj# Table Workflow Table where the values of each sheet are stored

Sequence:

  1. Presents warning
  2. Allows you to select a group of processes
  3. Shows the processes assigned to the group that have less than 20 created folios.
  4. Folio removal code is executed:
    1. Truncates associated folio table in workflow, obj#
    2. Reset the page counter to 0
    3. truncate table folio#
    4. truncate the folio_station# table
    5. truncate the station_history# table
    6. truncate the log_update# table
    7. Perform the same steps from 3 to 6 but in efhistory to delete any previous history
    8. Run my_clean_up(), where the user performs their own cleaning routines
    9. Send success message when finished.

How to perform your own cleanups in case you have additional tables or links to other systems that need to be restarted.

In step 8, the cleanup routine executes the my_clean_up() subroutine, and is sent as parameters the process number being cleaned and the workflow database obj number to remove any additional data.

Example of how to use:

sub my_clean_up {
    my $process=shift;
    my $objid=shift;
    if ($process == 18) {
        my $rsx = Pg_VB;
        $rsx->connectdb("dbname=usertable");
        $rsx->execute("truncate table det_facturas");
    }
}

$rs : you already have a connection established to the workflow database

$rsf : you already have a connection established to the workflow database

$rsh - you already have a connection established to the efhistory database

If you require additional connections, you must create them within the subroutine as local variables.

How to modify the graphic design of the system

Objetive

Explain the procedure to make modifications to the system's graphic design without losing them when performing updates.

CSS

Manipulating cascading style sheets located in the directory: /home/eflowweb/html/css

There is a general definition: eflow.css and other auxiliaries that are used in certain codes.

It is recommended to log in as an administrator to eFlow and select one of the existing color schemes that you feel is appropriate to modify.

Once selected, enter the terminal and edit the files found in:

WEB_PAGE_PATH/html/css

Create a directory with the name of your schema (without spaces, accents or Latin characters).

Modify all the colors of the style sheets to your liking. View the changes in your Internet browser by reloading pages.

Once finished, copy all the style sheets to the directory I created.

Edit the file:

PATH_CGI-BIN/eflow/admin/style.cgi

Locate the code where the SELECT statement is located, and add an OPTION line, where the value of the label is the name of the directory where you saved your style sheets and the value of deploy in the application is the name you want to give to this color scheme.

Save the code. And now you can select this scheme from the web interface.

Modify Print encoding of the pages.

The files with termination_def.pl contain the instructions to display the different elements of the form. You can modify these files so that the graphic design of the forms suits your taste.

You can even write new routines if required. When updates are sent these files are not replaced.

It is possible for any programmer to modify printing routines, add icons, images, etc. You can also even modify the structure with which the pages are printed so that you can change the layout of how the information is distributed in the window.

Use of personalized page in "Personal Page" station

In these cases, the design of the page remains entirely under the responsibility of the programmer. In this case, the page designer must create all fields that are editable, hidden or omitted.

You must create a way to indicate possible destinations to eFlow using buttons like eFlow does or any other method that leaves the destination station in the opt_station variable of the form.

In order for the values that have been processed on the page to be displayed, the programmer must leave the following tags for eflow to replace before displaying their page:

%VALUE###%: where ### represents the field number defined in the electronic document (for example, field ff48, it would have the label in the html document %VALUE48%)

%LABEL###% : if the field is composed of values and labels (as is usually the case in select or radio fields) the designer makes the value of the label appear in that place instead of the value of the database.

%OPT###% : Replaces the label with the available options of a select field (example, if field ff34 is a select field, replaces the label with ...)

%RADIO###%: Replaces the label with the options of a radio button format field (example: if field ff40 is a field with radio options, it is replaced by )

"NOTE

eFlow will automatically add the hidden fields of the values: process, station, folio, view_process, view_station, supervise and max, before the tag, therefore "do not include these hidden fields in your form".

user_check.pm

Objetive

Review the current status of the user. It receives skip_action (1 locked) as a parameter.

Validate the user's status. Check if it is blocked in any other process or station.

Cookies are used to know which user is calling.

Variables, validations and Databases

Name Type Subtype Description
users Table WorkFlow Table that contains the user data and is used to obtain the user data necessary for registration.

Sequence:

  1. Cookie is read to know who the connected user is
  2. Encrypted string is verified to validate that they are valid cookies and not created by the user.
  3. It is verified which user is really registered and it is verified that Your IP is the same as the one from which you initially registered.
  4. Verify that the user's locked field is empty, otherwise the user It is blocked and displays the station that must end.
  5. Returns the user number of the user.

This library also leaves some standard variables for all processes such as:

Variable Description
$user_name Full name of the user that was detected
$Sdate System date at the time of user verification
$Stime Access time at the time the user is detected
$Stimestamp User access date and time
$session_id Session being connected (if user has multiple)
SetSystemTime() Function that updates time values $Sdate, $Stime, etc.
UserName(n) Function that updates the user's full name (in the variable $user_name) according to the user number n that is sent to it.
$skip_action Variable that defines whether access_id validation should be used or not, this is useful because sometimes when many frames are displayed at the same time, the access_ids are changed in disarray and the frames are displayed with loggin error messages.
$Sday Day
$Shour Hour
$Smin Minute
$Ssec Seconds
$Smon Month
$Syear Year
$Stime Time in seconds since 1900
$BB 0, access from PC, 1 access from mobile device
$ef_account User account
$user_permissions Integer with the encoding of bits on according to the groups to which it belongs
$EXT Preferred Image Extension
$ruser User ID
$EF_USER Position Id

To validate your scripts with user_check

Use Eflow::user_check;

$user = user_check(); print PrintHeader();

Pg_VB

Command interface similar to that of Visual Basic~®~ for accessing SQL data.

Method Parameters Return Use
new None Object created to access Postgresql $rs=Pg_VB->new();
connectdb Connection string
format:
dbname=database name;
port=Port;
host= host;
user=user;
passwd=password;
If it cannot connect, the program stops $rs->connectdb("dbname=workflow");
execute Execute a query notes $rs->execute("query");
recordcount None Record I am in $rs->recordcount;
recordtotal None Total records of the last query $rs->recordtototal;
EOF None True if I am in the last record $rs->EOF;
BOF None True if I am at the beginning of the records $rs->BOF;
movefirst None Move the start of the records $rs->movefirst
movelast None Moves to last record $rs->movelast;
move Position Moves to position N $rs->move(position);
moveprevious None Go to previous position $rs->moveprevious;
movenext None Moves next position $rs->movenext
itemvalue Field name Field value $rs->itemvalue(field_name);
error_description None Returns the description of the last error $rs->errordescription;
error_number None 1 Error, 0 No error $rs->errornumber;
findfirst Search field Positions the first record that meets the condition $rs->findfirst(field,regex);
findlast Go to Last record that meets condition $rs->findlast(field,regex);
findnext None Find next $rs->findnext;
findprevious None Find previous $rs->findprevious;
getHash None Hash with recordset %hash = $rs->getHash();
getHash_ref None Reference to recordset $ref =$rs->getHash
getType Table Hash with types %hash = $rs->getType;
fType field Returns the type of a specific field $type = $rs->fType(field_name);
update Table name,hash_data,where,flag Error stops $rs->update("table",%hash[,where][,1]);
insert Table name,hash_data,flag Error stops $rs->insert("table",%hash*[,1]);
NOMATCH None If find could not be located $rs->NOMATCH;

Notes

Insert and return last inserted Id

If the insert is executed through the method: execute.

Use returning in SQL statement, and add column name to the call

$id = $rs->execute("insert into table (value) values (2) returning id",'id');

If the insert is executed through the method: insert

Add pseudocolumn: RETURN_LAST_ID with the name of the serial column

$data{'RETURN_LAST_ID'} = 'id';
$id = $rs->insert('tabla',\%data,1);

Delete, Update

The number of affected records returns

$n_eliminados = $rs->execute("delete from tabla where x = 1");
$n_modificados = $rs->execute("update tabla set y=0 where x = 1");
$n_modificados = $rs->update("tabla",\%data,"x=1",1);

use Eflow::Libs

Library of common methods for eFlow. Available in post-processes and personal pages.

Method Parameters Returns Usage
new None Create Object $lib=Libs->new();
Alert message[,image,printheader] Nothing $lib->Alert("Hello","Ok.png",1);
Error message[,image,printheader] Nothing $lib->Error($DBI::errstr,'',1);
fnumeric Number,decimals Formatted number $numS = $lib->fnuemric(1000,2);
fnumeric_hash %hash,decimal Format the entire hash $lib->fnumeric_hash(%h,2)
redirect (url, seconds, message) Nothing $lib->redirect('start.cgi',4,"message");
round (number,decimals) Rounded number $num = $lib->round($number,3);
email_user user=user number or email
subj=Title
message=Text message
Nothing $lib->email_user(34,'Test','Review eFlow');
$lib->email_user('juan@x,com','Test','Review eFlow');
email_user_html user=user number or email
subj=Title
message=Text message
Nothing $lib->email_user_html(34,'Test',$html);
$lib->email_user_html('juan@x.com','Test',$html);
hash_decode %hash[,'encoding'] Decode $lib->hash_decode(%hash,'iso-8859-1');
hash_encode %hash[,'encoding] Encode $lib->hash_encode(%hash,'iso-8859-1');
str_decode $str[,'encoding] Decode string $lib->str_decode($str,'iso-8859-1');
str_encode $str[,'encoding] Encode string $lib->str_encode($str,'iso-8859-1');
FileUpload file handle,fine name Save File $lib->FileUpload($q->Upload('var'),"/path/fmyile.png");

use Eflow::Libs2

Bookstore to provide handling of non-working dates.

Method Data Return Use
new None Create object $lib=Libs2->new();
holiday Year, month, day Empty or event description $workday = $lib->holiday($y,$m,$d,$wd,0,1,$rs);

This library must be adapted to events that do not have a fixed date in the year, as an example we have the Catholic holy weeks.

This library is not updated with the automatic update system.

SDK

The Software Development Kit was created with the purpose of supporting the development of daily programming activities and thus facilitating the creation of post-processes in workflows.

use Eflow::sdk

To facilitate the programming of own developments, this library has been developed that performs some actions that may be of interest to the user. Eflow uses them internally so that this ensures that they will work as they do for the system in general.

Method Parameters He comes back and what does he do Use
new $EF Create object $sdk=Eflow::sdk->new($EF,$Stimestamp,$rswf,$rsfd,$cookie{'modperl'},$rsh);
insert_folio Process (folio number, label) $sdk->insert_folio($process,$station,$user,$ruser,'my label');
splash_display Process Nothing $sdk->splash_display($in{'process'}."my message",$in{'view_process'},$in{'view_station'},$in{'supervise'},$in{'max'} );
splash_go Message Nothing $sdk->splash_go("my message","http://www.google.com",3);
finish_related_folios Finish folio and parallels $sdk->finish_related_folios($in{'process'},$in{'station'},$in{'folio'},$user,$user_name[,"3,4,5"]);

JavaScript

validate.js

Function Parameters Options Example Usage
validate Object,type,options,event onkeypress="return validate(this,'type','options',event)";
Integer none validate(this,'int','',event);
Integer negative validate(this,'int','-',event);
decimal validate(this,'dec',' 10|2',event);
negative decimal validate(this,'dec','-15|3',event);
alphabetical Characters validate(this,'alpha','.,-',event);
capitalize validate(this,'alpha-1-0','.,-',event);
validate(this,'alpha-1-1','.,-',event);
validate(this,'alpha-0-1','.,-',event);
alphanumeric Characters validate(this,'alfn','.-,',event);
Free Characters validate(this,'free','abc123',event);
Mask Mask validate(this,'mask','(nnn) nnn nnnn',event);
Date validate(this,'date','',event);
validate2 Use in onblur onblur="validate2(this,'type','options')";
Function Parameters Use
openWindow Popup window openWindow('x','url.cgi',1,800,600);
addShadowMarkUp AddShadowMarkUp();
ShadowOn onsubmit="ShadowOn()";
ShadowOff ShadowOff();
BlockCR BlockCR();
GetContent URL GetContent('myscript.cgi?values');
setCookie Name,value,days setCookie('key','48',360);
delCookie Name delCookie('key');
readCookie Name readCookie('key');
setWarning Message setWarning("Message to user");
setMsg ID setMsg('msgid',"Message",'on');
setMsg('msgid',"",'off');
suppressBackspace Send which user uses onload="suppressBackspace();"
Id element id var obj = Id('row'+i);

eflow.js

Contains in minified form: validate.js + navigate.js + calendar.js

To use calendar you must load: overlib.js

Example :

<head>
<link rel="stylesheet" type="text/css" href="/css/eflow.css">
<script language='JavaScript' src="/lib/overlib.js"></script>
<script language='JavaScript' src="/lib/eflow.js"></script>
</head>

### calendar.js + overlib.js

Open a calendar to fill a text field with the selected date

Example:

<head>
<link rel="stylesheet" type="text/css" href="/css/eflow.css">
<script language='JavaScript' src="/lib/overlib.js"></script>
<script language='JavaScript' src="/lib/caledar.js"></script>
</head>

<form name="Forma">
<input type="text" name="fecha" value="" size="10" class="form" readonly><a href="javascript:show_calendar('Forma.fecha');"><img src="/images/cal.png"></a>
</form>

Cron programs

List of programs that run with cron and their function

Name Periodicity Description
automatic.pl Every 15 minutes Moves folios from stations declared as automatic when the folio has reached its expiration date.
move_pool.pl Every 15 minutes Move the pages that are in the assignment queue.
station_delayed.pl Every 15 minutes Send an email to the supervisors with a list of all the pages that are delayed in the processes.
move2history.pl Weekends Every weekend it searches for pages that are more than 3 months old and moves them to the historical database.
clean_up_daily.pl 1 AM every day Clear user records, clear flags of sent emails so that station_delayed.pl notifies again.
clean_up_weekly.pl 1 AM every Saturday Deletes all folios from the system that have already expired according to the configuration of each folio. To free up hard drive space.
back_up.pl 4 AM daily Back up the eflow databases and directory every Saturday.

All cron files come with comments to understand their functionality.

To add, modify or delete programs that the cron scheduled task service runs, you must enter the /home/eflow/cron directory and edit the eflow.cron file

For details on how to use the cron service, read the manual with: man cron

A basic explanation is:

Stop cron services: crontab -r or crontab -e Start cron services: crontab cron_file Var scheduled services: crontab -l

Cron file:

Route/program time units

minute hour day month day_of_week route/program

*Every unit of time
*/nn Every nn time units
nn,nn,nn At nn and nn and nn units of time
nn-nn Each unit of time in the interval from nn to nn
n In the specific unit minutes from 0 to 59
hours from 0 to 23 hours
days from 1 to 31
months from 1 to 12
day week 0 Sunday, 1 Monday, 2 Tuesday, 3 Wednesday, 4 Thursday, 5 Friday, 6 Saturday

Examples:
Each minute * * * * *
Every 15 minutes */15 * * * *
At 3:20 AM 20 3 * * *
Saturday at 2:35 PM 35 14 * * 6
On the 15th of each month at 3 PM 0 3 15 * *
On January 1,7,15 and 25, March and September at 1:20 PM 20 13 1,7,15,25 1,3,9 *
The 1st of each month that is Saturday or Sunday at 8:00 AM 8 1 * 6.0

eFlow leaves these programs installed with a low execution frequency to minimize the resources used by eFlow on the server. But if these frequencies are not appropriate at the time of operation. You can increase the execution time by modifying the parameters in the eflow.cron file and running:

crontab eflow.cron

automatic.pl

This cron program deserves a special explanation, because it is very likely that you will eventually have to interact with it, when developing post-processes that work in stages of having them run automatically.

  1. When the document is moved automatically, the constant $AUTOMATIC has the value 1 (or true).
  2. To maintain the same variables between the automatic and manual method, the same variables are defined and maintain their meaning as they are the %Sin hash. Examples: $in{'process'}, $in{'station'}, $in{'folio'}.
  3. Shape data is not passed to the script in automatic mode. If you require the values to perform actions, you can run the get_foliodata routine to obtain the values. For example: %fd = get_foliodata();
  4. automatic.pl, resets the following values with each new update of a folio, in case it manipulates them in a previous update. %in{'process'}, $in{'station'}, $in{'folio'}, $in{'opt_station'}, $ef_user, $user, $ruser, $user_name
  5. Never execute the "exit" statement, in code that runs with automatic.pl, because this will stop the entire update process, and any other pending folios in the queue will not be updated. If you want to exit without doing anything else or moving the document, assign empty to $in{'opt_station'}, which will be interpreted by the engine as a comment update.
    Example:
    $in{'opt_station'} = '';
    return 0;