Contact Us!
303|905-4110

Note: You must be running on BP Forms version 3 (Feb 2018) for the functionality described within this document to work.

This section describes a simple test program that is provided with Blue Prairie Forms.  This program  is similar to the provided bpi_simple_test_program but it packages different data and presents it within the template using an open office table as well as presenting it as an Open Office chart. This program produces a document called Q0___bpi_simple_test_chart.odt.  This document will, by default, be dropped into the .../queue/bpiform1 directory.  If the phantom is configured and running, it will attempt to deliver the document to a CUPS printer called Q0 on the Open Office Print Server. 

A Sample Program

Blue Prairie Forms in installed with a sample test program that:

  1. Uses a standard template (bpi_simple_test_chart_tpl.odt) provided with Blue Prairie Forms
  2. Requires no external data source
  3. Produces a finished odt document
  4. Is a good example that can be used as a starting point for your own chart integrations

This example program will be installed and tested to verify the stability of the Blue Prairie Forms by your installation technician.  It should be left unaltered as it may be used in the future as a diagnostic test to validate the stability of the installation.  You may make copies of the program for your own experimentation.

   * bpi_simple_test_chart
   * Copyright (c) 2016 by Blue Prairie, Inc.
   * Example program to test a simple form with common form elements
   * 2/4/2018 by Bruce Decker
   * ----------------------------------------------------------------
   * Requires that the form template be placed in the directory indicated
   * below.  This does not actually print the form, it just produces (drops)
   * a finished form into a specified location
   *
   * This example program will:
   * 1) Set some non-repeating tags and values  (see subroutine InitformVars)
   * 2) Set some repeating tags and values using multiValued arrays
   * 3) Call the templating system (see subroutine MakeAndPrint)
   * 4) Write a finished document based on the named template
   *
   * Note: This example does not actually print.  It just creates a document
   *
   * -----------------------------------------------------------------
   pgmId = \bpi_simple_test_chart\
   tag = \\; val = \\
   * Equate some vectors for our associated multiValue arrays
   EQU d.lineNo       TO 1
   EQU d.productLine  TO 2
   EQU d.revenue      TO 3
   EQU d.profit       TO 4
   EQU d.transactions TO 5
   *
   GOSUB ParseSentence; *171212
   GOSUB InitFormVars
   *
   * load the detail array with a simple loop
   totExtPrice = 0
   FOR lineNo = 1 TO 10
     detail< d.lineNo, lineNo> = lineNo                    ;* a line number
     detail< d.productLine, lineNo> = \Line-\:lineNo       ;* word Line- followed by lineNo
     detail< d.revenue, lineNo> = (lineNo*100)             ;* rev is lineNo x 100
     detail< d.profit, lineNo>  = (lineNo*100)*(.10)       ;* profit is 10% of rev
     detail< d.transactions, lineNo> = (lineNo*30)         ; *transaction count 30x lineNo
   NEXT lineNo
   * load footnotes array with static assignment
   footnotes<1,-1> = \This is line 1 of the footnotes array\
   footnotes<1,-1> = \This is line 2 of the footnotes array\
   *
   * Now make the document
   *
   GOSUB MakeAndPrint
   *
   GOTO Exit
   * ------------------------------------------------------------------------------
   * B L U E   P R A I R I E   F O R M S   S U B R O U T I N E S
   * ------------------------------------------------------------------------------
InitFormVars:
   verbose = 5
   blocks = \\; tags = \\; vals = \\; pos = 0;
   * note that the 4th param is the 'block' specifier.  Since blank these tags are not repeating
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%@PGM%\, pgmId, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%@WHO%\, @WHO, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%@LOGNAME%\, @LOGNAME, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%@USERNO%\, @USERNO, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%port%\, FIELD(OCONV(\\,\U50BB\), SPACE(1), 1), \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%TIME%\, OCONV(TIME(),\MTH\):SPACE(1):OCONV(DATE(),\D2/\), \\, vector, verbose); *|||BPI FORM|||
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%timeDate%\, TIMEDATE(), \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%dayOfWeek%\, OCONV(DATE(), 'DWAMADYL'), \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%powered_by%\, \Powered by Blue Prairie Forms (tm)\, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \\, \%reprint%\, \\, \\, vector, verbose)
   detail = \\
   footnotes = \\
   RETURN
   *
AddDetailLine:
   * reserved for future use
   RETURN
   *
MoveDetailToArrays:
   * now add the detail lines to the blocks/tags/vals arrays with a block name of 'det'.  The template should feed
   * these tags to a one-row table in openOffice.  The first column in the table should be made to contain the plug-in
   * directive "{repeat=tr;block=det}  This will cause the table row to be repeated for the number of multivalues
   * found in these tags.  So, if you have 10 lines represented by 10 multivalues for each of the tags, then the
   * table should be expanded automatically from 1 row as defined in the template to 10 rows (one for each multivalue)
   * because each line in the detail array is represented (properly) as a multivalue.
*
* Note the numeric tag names (111.111, 222.222), etc. This is not ideal but it is required because the open office
* chart editor does not permit non-numeric values in the chart data. Therefore, we needed to use numeric tag names
* and wanted to choose tag names that would not collide with 'real' data that may have existed within the document.
* We will investigate whether Open Office can be made to accept proper (non numeric) tag names within the chart table
   CALL bpi.set.tagval2(blocks, tags, vals, \mychart\, \%d.lineNo%\, detail<d.lineNo>, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \mychart\, \%d.productLine%\, detail<d.productLine>, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \mychart\, \111.111\, detail<d.revenue>, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \mychart\, \222.222\, detail<d.profit>, \\, vector, verbose)
   CALL bpi.set.tagval2(blocks, tags, vals, \mychart\, \333.333\, detail<d.transactions>, \\, vector, verbose)
   * load footnotes array to tag
   CALL bpi.set.tagval2(blocks, tags, vals, \foot\, \%f.footnotes%\, footnotes, \\, vector, verbose)
   RETURN
   *
MakeAndPrint:
   doc.format = \odt\
   pathToBpiForms = "/dbms/BPIFORMS/bpi_forms"; * <--- change to suit your install
   verbose = 5
   GOSUB MoveDetailToArrays
   CALL bpi.xmlencode( tags, tags, \all\, error)
   CALL bpi.xmlencode( vals, vals, \all\, error)
   *make a diag table from tags and vals
   CALL bpi.makediag( blocks, tags, vals, \odt\, diag, status)
   *add the diag table to the tags and vals array
   CALL bpi.set.tagval2( blocks, tags, vals, \\, \%diag%\, diag, \\, vector, verbose)
   GOSUB GetQueue
   *construct the filename of the document
   document_name_make = "%queueName%___bpi_simple_test_chart%copy%.odt"
   tag<2> = \%queueName%\; val<2> = bpiQueueName

   * set variables for the form maker
   params = \odt\
   templatePath = "%pathToBpiForms%/templates/bpi_simple_test_chart_tpl.odt"
   templatePath = CHANGE( templatePath, \%pathToBpiForms%\, pathToBpiForms)

   tempPath = "%pathToBpiForms%/working"
   tempPath = CHANGE( tempPath, \%pathToBpiForms%\, pathToBpiForms)
   * call the form maker
   verbose = 5
   FOR i = 1 TO copies
      IF copies EQ 1 THEN
         copyName = \\
      END ELSE
         copyName = \_\:i
      END
      output_docname = document_name_make
      CALL bpi.tagval( tag, val, output_docname )
      output_docname = CHANGE( output_docname, \%copy%\, copyName)
      outputPath = "%pathToBpiForms%/queue/bpiform1/":output_docname
      outputPath = CHANGE( outputPath, \%pathToBpiForms%\, pathToBpiForms)
      outputPath = CHANGE( outputPath, \%queueName%\, bpiQueueName)
      CRT \Making-> \:outputPath
      CALL bpi.set.tagval2( blocks, tags, vals, \\, \%chartHeading%\, "Revenue, Profit and Volume", \\, vector, verbose)
      CALL bpi.form.make2( templatePath, outputPath, tempPath, params, blocks, tags, vals, verbose, status, message)
      *should now have a completed form at output.path
   NEXT i
RETURN
   *
GetQueue:
   * We would normally grab the current assigned queue from a SP-ASSIGN or SETPTR command
   * but for this test, we'll just use the queue Q0
   bpiQueueName = \Q0\
   RETURN
   *
ParseSentence:
   pgm = \bpi_simple_test_program\
   sentence = CHANGE( @SENTENCE, SPACE(1), @AM)
   maxSentence = DCOUNT(sentence, @AM)
   start  = @FALSE
   copies = 1
   FOR i = 1 TO maxSentence
       word = sentence<i>
       uc.word = OCONV( word, \MCU\)
       BEGIN CASE
       CASE start
          BEGIN CASE
          CASE uc.word[1,2] = \-C\
             copies = OCONV( word, \MCN\)
             IF NOT( copies ) THEN copies = 1
          CASE @TRUE
          END CASE
       CASE word EQ pgm
          start = @TRUE
       CASE @TRUE
       END CASE
    NEXT i
RETURN
*
Exit:
   STOP

Narrative

The above program functions similarly to the other 'simple' example programs provided with Blue Prairie Forms.  The main differences are:

  1. The tag names are different
  2. The data values are not masked using MultiValue OCONV functions because Open Office requires raw numbers (without commas, currency symbols, etc.)
  3. 3The tag names of 111.111, 222.222 seem odd and instead we would have preferred to use our normal tagging style (e.g., %tagname% ).  But, because the Open Office chart object allows ONLY numeric data to be added to the chart's data table object for the Y axis values, we had to resort to using numeric tags.  As such, using tag names like a simple '1' could present issues because the tagging engine would attempt to swap all instances of '1' with the tag's value.  Therefore, in our example, we have used the tag names of 111.111, 222.222, etc because we believed that it would be unlikely that these values would exist natually either within the template itself or as values assigned to other tags.
  

Running the example program

To run the sample, program, simply type bpi_simple_test_chart.  Diagnostic messages will be displayed to the screen and a document will be written to the queue directory declared in the program.  Depending on the specific location of directories in your Blue Prairie Forms installation, you may need to modify certain parts of the test program.  Specifically, the variable pathToBpiForms should be adjusted to fit your installation.

If you wish to run a number of copies of a document to the queue directory, you may add the -c switch followed by the number of copies you wish to create.  For example:

bpi_simple_test_chart -c5

Will generate 5 documents:

Q0___bpi_simple_test_chart_1.odt

Q0___bpi_simple_test_chart_2.odt

Q0___bpi_simple_test_chart_3.odt

Q0___bpi_simple_test_chart_4.odt

Q0___bpi_simple_test_chart_5.odt

Template Highlights

A detailed explanation of the template process is provided in the User Manual.  You can modify the example template but please make a backup of the original template (unchanged) before making modifications.  You can access this template at .../BPIFORMS/bpi_forms/template/bpi_simple_test_chart_tpl.odt

 The Header (for all pages of the template)

The header is much like other test programs

The Body (for page 1)

Page one of the template contains a normal table so that you can see the data values in table form.  Page 2 of the example contains the chart which will use the same data presented in the table but will show a chart-based visualization of that table data.

The body table is the same as the other bpi_simple example templates.  The {repeat} tag (which is clipped in the above image) is actually:

{repeat=tr;block=mychart;increment=1}%d.lineNo%

In this example, the block name has changed from the other bpi_simple examples to 'mychart'.  This is purely cosmetic and it really does not matter what the block name is, so long as it matches between the program declared block name and the block name referenced in the template.   In this case, the block name in the program was 'mychart' so this is what we have used in this template.

Tag: 111.111 222.222...

The tag 111.111 does indeed seem odd especially in considering that we normally advise the use of unambiguous tags.  The ONLY reason we have used the tag names 111.111, 222.222 and 333.333 is that the chart object editor does not allow alpha-numeric values to be entered as data values for feeding the chart. 

The Body (for page 2) "The Chart"

Page 2 of the template contains the chart object.  This is standard chart object that can be added to any Open Office template using the standard chart object.

 

 Note the following

  • The chart was created when the author created the template by simply selecting Insert>Chart from the Open Office menu
  • The chart type was chosen by double-clicking on the inserted chart on the inserted chart and choosing "Chart Type" from the pop-up menu
  • The tag %chartHeading% is showing in the template.  This will be replaced by a value passed to open office using a host-side tag called %chartHeader%
  • The {repeat} tag is showing at the bottom of the chart.  This will be replaced by the %d.productLine% tag's value when the actual data is inserted into the chart at run time.
  • The numbers 222.222 and 333.333 are showing because these are the tag names being used by the template.  These tag names will be replaced with the actual data passed from the MultiValue host at run time.  In the above example, 111.111 has been truncated by Open Office charts to 111.11 however the internally stored value is 111.111.  This is important because 111.111 is far more unlikely to occur in normal data than 111.11.  Don't be fooled by the above image.
  • In the template, only one record is present in the data set (the tag) and this explains why there are only three bars (blue, red and yellow).  When an actual set of data is passed into the chart object at run time, more records will be reflected in the chart.
  • The legend words are "Revenue", "Profit" and "Transactions."  These are hard coded into the chart in this example but just as easily could have been tag/value references passed from the MultiValue host (as we did with %chartHeading%.

Select the Chart

  • Click on the chart and it will be selected
  • Now, right-click and choose 'edit' from the pop-up menu

  • When selected, green anchors will appear in the four corners of the chart.
  • With the green anchors visible, right click on the chart and select 'edit' from the pop-up menu.  A grey border will appear around the chart and the green anchors will turn black.

Edit the Chart

  • Right click on the chart and a pop-up menu will appear with the following options:
  • Insert Titles will allow you to edit the chart's titles.  This is where we inserted the tag %chartHeading% in the example template
  • Chart Type will allow you to change the chart type
  • Data Table is where we will enter tag names to populate the chart

Insert Titles

Note the tag being used in the Title field.  When a tag is used, it will be replaced by the value passed from the multiValue host at run-time

Chart Type

Note: Experiment with the various chart types and options.

Data Table

The data table is where you will enter the repeat tags used

  • The actual values entered into the Y-axis data sets is 111.111 (note the three digits after decimal) even though in the above screen snip, the editor is truncating the display to 111.11.  We recommend using at least three digits after the decimal when forced to used pure numeric tags to lessen the change that a tag might be in conflict with normal data that exists elsewhere naturally in the document.
  • In the example above, we hard-coded the legend text as Revenue, Profit and Transactions.  However these could have been passed by the MultiValue host using normal tags
  • The Category column contains our normal {repeat} tag so that, at run time, additional rows will be inserted into the chart's data table based on data sent from the MultiValue Host.  In the example above, the full text of the Category field is:
{repeat=tr;block=mychart;increment=1}%d.productLine%

Where:

repeat=tr   Means that the table row (tr) will be repeated based on the number of data rows from the MultiValue host
block=mychart   specifies that the repeat will be based on the repeating block named 'mychart'
increment=1   (see the repeat tag documentation for a full explanation)
%d.productLine%   This is a tag passed from the MultiValue host that will contain the product line.  This value will be the label of each chart group at run time.

 

The Result

 

 

Congratulations.  Using the same techniques you have used to create documents with tables, you have now created your first chart!

Example MultiValue BASIC Integration

  1. Set your variables
  2. Check the server
  3. Make the document
  4. Send it to OpenOffice to render and print
  5. Set your variables

 

 

! initialize------------------------------------------------------------
tag=\\
val=\\
delim = “/” ; *for unix
template.id = “mytemplate.odt”
outfile.id  = “myfinaldoc.odt”
template.dir= ”/mydir/template/”
outfile.dir = “/mydir/output/”
outfile     = outfile.dir:outfile.id
template    = template.dir:template.id
host        = “192.168.1.1”
ux.user     = “myuser”
level       = “”
verbose     = 0
unix.printer= “HP_Laserjet”
!-----------------------------------------------------------------------
!set tags and values
this.tag = “%customer_name%  ; this.value = “John Galt”       ; GOSUB TagVal
this.tag = “%customer_addr1% ; this.value = “123 Abc Street”  ; GOSUB TagVal
this.tag = “%customer_city%” ; this.value = “New York”        ; GOSUB TagVal
this.tag = “%customer_state%”; this.value = “NY”              ; GOSUB TagVal
this.tag = “%customer_zip%”  ; this.value = “10019”           ; GOSUB TagVal
!check to see if server is alive
CALL bpi.server.checkalive( “192.168.1.1”, ux.user, level, status, verbose, ping.result, echo.result)
IF status THEN
   ! server is alive
   CALL bpi.oo.getstatus( host, ux.user, level, pid, verbose)
   IF pid THEN
      CRT \OpenOffice is busy on the server, can't render the document now.  Try again later\
   END ELSE
      ! OpenOffice is not busy, let's render a document
      CALL BPI.MakeDoc( template, outfile, tag, val, error, message)
      IF (error) THEN
         CRT \Ooops, there was an error when trying to makedoc.\
         CRT \error=\:error:\ \:message
         GOTO Exit
      END ELSE
         !Makedoc worked, lets send it to oo
         CALL bpi.oo.render( host, ux.user,template.id,template.dir, unix.printer, verbose, rstatus)
         IF rstatus EQ 1 THEN
            CRT \Congrats, OpenOffice is processing the print job, go pick it up\
         END ELSE
            CRT \Ooops, bpi.oo.render encountered an error\
            CRT \rstatus=\:rstatus
            GOTO Exit
         END
      END
  END
END ELSE
   CRT \Ooops, the server is not alive.  Host=\:host
   CRT \ping.result=\:ping.result
   CRT \echo.result=\:echo result
   GOTO Exit
END
!
TagVal:
   !Call the bpi.set.tagval which will update the tags and vals array
!Note, param 1 is the block. We are not using repeating data in this example so
| this can be blank

   CALL bpi.set.tagval2( \\,tags, vals, this.tag, this.value, \\, pos)
RETURN
!

Exit:
   CRT \I'm going to exit now\
  STOP
! 

 

Installation

The following sections explain the basic build of a Blue Prairie Forms system.  We will attempt to provide as much detail as possible with the intent to provide directions that could be used to re-build the MultiValue server side of a Blue Prairie Forms installation or the Print Server (LOOPS) side of a Blue Prairie Forms installation.  The chapter will be broken into two sections for the MultiValue Host side and the Print Server (LOOPS) server side.

On the MultiValue Host

On the MultiValue Host: Install the BPIFORMS account

  1. Ftp in place and extract
  2. Make sure the account is Pick style (or flavor)
  3. Change permissions as required so that all desired users and apps can reference the Blue Prairie Forms files and programs. When in doubt, 755 permissions can be used.

On the MultiValue Host: Compile the bpi.bp.form programs

  1. Compile with the switches/options suitable for your environment.
  2. Blue Prairie Forms programs are written in ‘Pick’ style so it is important to have the account in which the programs are compile a ‘Pick” style or flavor and to use Pick-style compile/catalog directives.
    1. For Unidata this is ECLTYPE P and BASICTYPE P.
    2. For uniVerse the account should be ‘Pick’ flavor
    3. For jBASE compile using the BASIC command with no switches.  No special config_EMULATE options are required.
  3. For uniData, use the -D switch so that debugging can be performed.
  4. For uniVerse, no special options are needed.
  5. Consult your IT director for custom switch setting preferred by your organization.

On the MultiValue Host: Catalog the bpi.bp.form programs

  1. Consult your IT director to obtain the preferred catalog method to be used on your system
  2. If you intend to globally catalog, verify that none of the compile program names in bpi.bp.form are reserved and/or already in use by other applications. The chances of this are rare since most program and subroutine names are prefixed with bpi or bpi.forms to avoid collision with legacy program names.
    1. Unidata catalogs globally by default.
    2. For uniVerse, no special options are needed.
    3. For jBASE, no special options are needed
  3. Consult your IT director for custom switch setting preferred by your organization.
  4. If you are not using global cataloging, then for each account where programs may access Blue Prairie Forms API, you will need to have pointers to bpi.bp.form file.
    1. For uniVerse, you will also need a Q or F pointer in each account where BP Forms is to be run for the bpi.bp.form.O file

On the MultiValue Host: In each MultiValue account where a phantom will be run

jBASE

The jBASE binaries and libraries should be installed and are working in the jBASE account BPIFORMS.  You will add the paths for the jBASE bin and lib directories to the account environment variables or SYSTEM file entries for each account that you wish to use to generate BP Forms documents.  No special cataloging is required.  If you wish to use the BP FORMS menus from an account other than BPIFORMS, you will need to add the BPIFORMS account directory to JEDIFILEPATH environent variable or simply place a Q-pointer into the MD of the account called BPI.FORM.PHANTOM.CONTROL that points to the file of the same name in the BPIFORMS account.

Universe and Unidata

  1. Create pointer to bpi.form.bp programs * (Note, on Unidata, programs are globally cataloged so cataloging in each account is not necessary).
  2. Create pointer to BPI.FORM.PHANTOM.CONTROL file

On the MultiValue Host: Install Samba Server if not already installed

Samba (aka CIFS) is a mechanism for sharing directories on a server with other systems on the network.  We use Samba/CIFS to ‘share’ the directories on the MultiValue server where the Blue Prairie Forms system placed finished documents that await rendering by OpenOffice.  The OpenOffice server will pick-up the document from shared directory then process it.  When finished, OpenOffice will notify Blue Prairie Forms that the rendering (printing) has completed and then Blue Prairie Forms will remove the document from the print queue.  Because Samba/CIFS is how OpenOffice has visibility to the OpenOffice documents that are created by Blue Prairie Forms, it is vital that the MultiValue server have Samba installed and that the bpi_forms directory in the BPIFORMS account is shared.

On the MultiValue Host: Install SWAT if not already installed

SWAT (Samba Web Admin Tool) is a web-based administration page for Samba.  It makes configuration of Samba shares on the host much simpler.  You can usually check to see if SWAT is running if you point a browser at the ip address of the host followed by :901 (example: 127.0.0.1:901.  If Samba and SWAT are installed, then a web admin page like this will be displayed:

Configure Samba mount point for /accts/BPFORMS/bpi_forms

Using the SWAT tool, setup a samba share called bpi_forms.  This share should point to the bpi_forms directory in your BPIFORMS account.  Here are common paths used by BPIFORMS for both uniVerse and Unidata

Universe: /uvdata/accts/BPIFORMS/bpi_forms

Unidata: /uddata/accts/BPIFORMS/bpi_forms

jBASE: /dbms/BPIFORMS

If neither of the above paths exist, look through your system to find the bpi_forms directory.  This is your share path.

In SWAT, follow these steps:

1) Click on the SHARES icon in the SWAT interface

2) In the box next to the “Create Share” button, enter “bpi_forms”  (don’t include the quote marks)

3) Press “Create Share”

4) Now in the pull-down box to the right of the “Choose Share” button, select bpi_forms

5) Press the “Choose Share” button

 

A number of fields will be displayed.  Verify the following fields are set as follows:

path: (to the path of the bpi_forms directory on your MultiValue host)
valid Users: bpiform1
Read only: Yes
Available: Yes
Browsable: Yes

 

Note: even though we may thread print jobs through multiple unix users (bpiform1, bpiform2, bpiform3, etc), we only need to make bpiform1 a valid user because this is the user that will we will use in our Linux side (LOOPS) configuration to access the share for users on the Linux (LOOPS) server.

6) Press ‘Commit Changes’

7) Click on the ‘PASSWORD’ icon in the SWAT menu

8) Enter ‘bpiform1’ into the User Name field

9) Enter the password ‘blueprairie’  (or whichever password you decide) into the “New Password” and “Re-Type New Password” fields

10) Press ‘Add New User’

11) Enter bpiform1 into the User Name field

12) Press the ‘Enable User’ field

 

Now test the connection using your PC and Windows Explorer

1) Open Window Explorer

2) Press ‘Map network drive’ in the to menu

3) Choose a driver letter (z is usually available)

4) In the ‘Folder’ field, enter \\<ip_address_of_MultiValue_host>\bpi_forms

            Example: \\192.168.2.3\bpi_forms

5) Windows will prompt you for a user name and password

Note: Your username and password may vary.  Consult your administrator

6) At the ‘User Name’ field, enter ‘bpiform1’  (do not type the quote marks)

7) At the ‘Password’ field, enter ‘blueprairie’ (do not type the quote marks)

 

If successful, Windows explorer will display a number of directories in our share.  It will look something like the image above.

 

This proves that the Samba share is properly setup.

If the samba share is not working, go back and verify the information above using the SWAT interface. 

 

The most common mistakes are:

1) Forgetting to set share property ‘Available’ to ‘Yes’

2) Not actually ‘adding’ the bpiform1 user because the user interface is odd

3) Not setting the password of the bpiform1 user properly

4) Not ‘enabling’ the bpiform1 user.

On the MultiValue Host: Create a bpifuser user group on the MultiValue host.

On the MultiValue Host: Make sure the ssh command and ssh-keygen commands are installed and visible in path

which ssh

which ssh-keygen

These command should return a valid path.  On linux systems this is almost always true.  But starting at AIX 6.1, they have elected to leave the bin directory where the ssh command live out of path.  Release 3.1 of Blue Prairie Forms expects ssh and ssh-keygen to be in path.  Therefore, you must manually configure users to include /usr/local/bin in path.

Precaution for AIX 6.1 or above installations regarding ssh and ssh-keygen

On AIX, we recommend that you modify /etc/security/.profile and add /usr/local/bin to the PATH definition.  This file is used when adding new users and will be copied to the new users /home directory.  By modifying it here, all new users will have /usr/local/bin in path saving you from having to manually modify it each time you add a user that dispatch ssh commands.

Next you should review all .profile scripts in each /home directory for each user that may be used to launch or use ssh commands using Blue Prairie Forms and add /usr/local/bin to the path.

We highly recommend that /usr/local/bin be added to path via these .profile scripts rather than updating PATH from within uniVerse or Unidata.  This is because commands maybe shelled via sudo/su as these unix users and they may not fire the uv shell and therefore not have the ssh command in path before ssh is executed.

Precaution for AIX 6.1 or above installations for sudo

On AIX 6.1 or above it appears that sudo is not installed by default. Blue Prairie Forms uses su and sudo to thread tasks and dispatch their execution for certain users.  Sudo is required This is not an issue for Linux nor is it a problem on AIX versions prior to 5.3.  You can install from the AIX Linux Toolbox CD which comes with your AIX media or you can download it from IBM using your IBM Partner ID.

Verify whether sudo and visudo are current installed and in path by issuing the commands:

which sudo

which visudo

http://www-03.ibm.com/systems/power/software/aix/linux/toolbox/alpha.html

Use the smit installer to install sudo and test ensure that visudo and sudo are in path and operational

 

On the MultiValue Host: Create a bpifadm user group.

On the MultiValue Host: Identify each unix user that will send SSH messages for phantom threads

The unix users associated with each BPI.FORM.PHANTOM.CONTROL record (phantom users) will need to be created on the MultiValue server.  We recommend creating one unix user for each phantom thread you intend to run.  Having a unique unix user for each thread facilitates multi-threading and will improve rendering performance especially in high-volume printing environments.  It is a good practice, if if you are not a high volume printing operation, to create multiple phantom threads each with its own UNIX user.  We recommend naming the users bpiform1, bpiform2 and so on for as many threads as you intend to run.

On the MultiValue Host: Create the Unix Users

Using the recommend names bpiform1, bpiform2 and so on.  Make sure these users are members of the unix group bpifuser.  It is not necessary (nor recommended) to make these users members of the bpifadm group

On the MultiValue Host: Update the sudoers file

See directions below for specific updated to sudoers using visudo

On The MultiValue Host: Install unzip (for AIX systems Only)

On AIX systems, Zip is not installed by default.  Obtain the zip-2.3-3.aix4.3.ppc.rpm (or newer) and install via smitty

On The MultiValue Host: Install unzip (for AIX systems Only)

On AIX systems, Zip is not installed by default.  Obtain the zip-2.3-3.aix4.3.ppc.rpm (or newer) and install via smitty

On the Linux/OpenOffice Server (LOOPS): Create unix users of the same name(s) that you created on the MultiValue host.

You do not need to make groups or add users to the groups as you did on the MultiValue host.

On the MultiValue Host, establish ssh shared keys between MultiValue host and Linux/OpenOffice print Server (LOOPS) for each unix user

A utility bpi.ssh.keygen is provided to help you establish shared keys between the MultiValue host and the remote OpenOffice server.  You must login to the MultiValue server using the UNIX user for which you wish to establish shared keys.  The unix user name must be created in advance on the

OpenOffice server.  Here is the usage documentation for bpi.ssh.keygen:

To assist with the setup of ssh keychains between this server and a remote OpenOffice linux print server.\

Usage:

bpi.ssh.keygen SERVER

where:

SERVER is the host name or ip address of the OpenOffice server

Note: The utility may need to prompt you for passwords so have those handy sometimes the first attempt to communication with the server will require a password.  Normally, after the first time the system asks for the password, it will remember it and subsequent commands will no longer require it.  You must be logged in as the user you wish to setup.

 

On the MultiValue Host: Update the sudoers file:

 

Note: On later releases of Linux (Centos 7 and above) it was decided that sudo processes should default to requiring a tty.  So, if you are running your MultiValue server on a Linux release later than CentOS 7 (or equivalent), you should comment out the !requiretty directive in the defaults section of the sudoers file thusly:

#
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.

#         You have to run "ssh -t hostname sudo <cmd>".
#
###bpi|||Defaults   !requiretty

 

If the path to the ssh command is /usr/bin/ssh, then...

#------------------------------------------------------------------------------#
# Blue Prairie Forms -- Bruce Decker -- This email address is being protected from spambots. You need JavaScript enabled to view it. -- 720.733.0459 --#
#
# Privs for Blue Prairie Forms Admin members only (grant complete ssh access)
%bpifadm ALL=(ALL) NOPASSWD: /usr/bin/ssh -l bpiform*
#Privs for Blue Prairie Forms normal print users (grant selective ssh access)
%bpifuser        ALL=(ALL) NOPASSWD: /usr/bin/ssh -l bpiform*ls -x1*
%bpifuser        ALL=(ALL) NOPASSWD: /usr/bin/ssh -l bpiform*soffice -headless -nofirststartwizard*
%bpifuser        ALL=(ALL) NOPASSWD: /usr/bin/ssh -l bpiform*OpenOffice* -headless -nofirststartwizard*
%bpifuser        ALL=(ALL) NOPASSWD: /usr/bin/ssh -l bpiform*pidof -s *
%bpifuser        ALL=(ALL) NOPASSWD: /usr/bin/ssh -l bpiform*echo*

 If the path to the ssh command is /usr/local/bin/ssh, then...

 #------------------------------------------------------------------------------#

# Blue Prairie Forms -- Bruce Decker -- This email address is being protected from spambots. You need JavaScript enabled to view it. -- 720.733.0459 --#
#
# Privs for Blue Prairie Forms Admin members only (grant complete ssh access)
%bpifadm ALL=(ALL) NOPASSWD: /usr/local/bin/ssh -l bpiform*
#Privs for Blue Prairie Forms normal print users (grant selective ssh access)
%bpifuser        ALL=(ALL) NOPASSWD: /usr/local/bin/ssh -l bpiform*ls -x1*
%bpifuser        ALL=(ALL) NOPASSWD: /usr/local/bin/ssh -l bpiform*soffice -headless
 -nofirststartwizard*
%bpifuser        ALL=(ALL) NOPASSWD: /usr/local/bin/ssh -l bpiform*OpenOffice* -headless -nofirststartwizard*
%bpifuser ALL=(ALL) NOPASSWD: /usr/local/bin/ssh -l bpiform*pidof -s *
%bpifuser ALL=(ALL) NOPASSWD: /usr/local/bin/ssh -l bpiform*echo*

 

Additional Changes to sudoers file

In some distributions of Linux, the ability to shell sudo commands without being connected to a tty is disabled.  For Blue Prairie Forms phantom to function properly, this functionality must be enabled either globally, or at the user, group or command level.  Generally, our customers enable globally.  If you have a concern about this, there are resources on the internet that you can find that will walk you through the steps to enable tty-less sudo for specific commands.  The commands are shown above.  Incidentally, Redhat has acknowledged that the change to their distribution to require a tty for sudo was pointless and it will be removed in a future release: https://bugzilla.redhat.com/show_bug.cgi?id=1020147

Enabling tty-less sudo globally:

# Defaults specification
#
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
#         You have to run "ssh -t hostname sudo <cmd>".
#
#bpiforms|180124|Defaults    requiretty
Defaults !requiretty
#

If you encounter messages in your phantom log file which read "sudo: sorry, you must have a tty to run sudo" then this can be remedied by making this modification to your /etc/sudoers file.  Remember, use visudo to make changes, don't edit the file directly.

 

Verify that SSH is installed (primarily for AIX 6.1 or later)

Install from AIX Expansion Pack if not present

 

Verify that sudo is installed (primarily for AIX 6.1 or later)

Install from AIX Expansion Pack if not present

 

Configure threads in the BPI.FORM.PHANTOM.CONTROL file

Queue directories and Symlink Alias

In most instances, the administrator will want to allow a background process to pick up and process documents that are dropped into a directory by a foreground print process.  Documents can be dropped anywhere on the system but we have created a structure that we have used that is recommended.  On U2 or jBASE systems, we create a directory in the BPIFORMS account at:

./bpi_forms/queue

For D3, locations vary.  Contact your Blue Prairie Forms support agent for more information.

We create a queue directory for each phantom thread to be run.  For example, if we had decided to run four phantom threads, we would see the following in our ./bpi_forms/queue directory:

 

aixdevunidata:(/home/s7)ls -la
total 32
drwxrwxrwx  6 s7        mygroup    4096 Mar 11 10:05 .
drwxrwxrwx  7 s7        mygroup    256 Jun 16 2014  ..
drwxrwxrwx  2 s7        mygroup    256 Mar 11 10:11 bpiform1
drwxrwxrwx  2 s7        mygroup    256 Mar 09 12:38 bpiform2
drwxrwxrwx  2 s7        mygroup    256 Jun 11 2014  bpiform3
drwxrwxrwx  2 s7        mygroup    256 Apr 03 2014  bpiform4

This works for most applications but in some cases, you may want to distribute inbound documents without respect to knowing which phantom thread the document is to be sent.  For example, at the time you are rendering the document, you may know the location/branch number and you may wish to design your application interface in a way that allows you to simply drop the document on a folder that is specific for that location instead of having to look up which phantom thread processes documents for that location.

To alias a phantom thread queue directory to another more useful and recognizable name, we can use symbolic links (symlinks).  This allows us to create a virtual folder name that really is just an alias for another folder name. For example, if we wanted to be able to drop documents on a folder called ./bpi_forms/queue/loc13 but have that folder swept and processed by the bpiform1 phantom who really sweeps ./bpi_forms/queue/bpiform1, then we could alias the loc13 directory to bpiform1 so that when the application drops the document onto loc13, it really is writing it to bpiform1’s queue.  Here’s an example of symlinks that have been setup in the above example:

 

lrwxrwxrwx     1 s7   mygroup       8 Mar 01 00:38 loc1 -> bpiform1
lrwxrwxrwx     1 s7   mygroup       8 Mar 01 00:38 loc118 -> bpiform1
lrwxrwxrwx     1 s7   mygroup       8 Mar 01 00:38 loc119 -> bpiform3
lrwxrwxrwx     1 s7   mygroup       8 Mar 11 10:05 loc13 -> bpiform1
lrwxrwxrwx     1 s7   mygroup       8 Mar 01 00:38 loc7 -> bpiform1
-rwxrwxrwx     1 s7   mygroup       11369 Jul 05 2014  testout.odt
aixdevunidata:(/home/s7)

In the right-most side of this directory listing, you’ll see that the word loc1 points to bpiform1.  Now any reference to ./bpi_forms/queue/loc1 will actually be referencing ./bpi_forms/queue/bpiform1.

The syntax to create a symlink is (based on an actual Unidata installation):

 cd /uddata/accts/BPIFORMS/bpi_forms/queue

ln -s <nameOfPhantomQueue> loc<locationNumber>

Example for loc13:

ln -s bpiform1 loc13

Then do a ls -la and see the link is pointing at the desired thread.

 

On the Linux/OpenOffice Print Server (LOOPS)

On the LOOPS: Install a supported OS

The operating systems supported by Blue Prairie, Inc are:

Redhat Enterprise Linux release 5 and above

Fedora Linux release 20 and above

CentOS version 7 and above

Other distributions may be used but it will be the responsibility of the customer to provide configuration assistance by an engineer familiar with the tools available for that distribution.  The directions provided below will work on the supported distributions and should work, perhaps with some adaptation, on others.

On the LOOPS: Make sure that SE/LINUX is turned off!  CRITICAL.

For Redhat/CentOS releases, SE/Linux (Security Enhanced Linux) MUST be turned off and disabled.  You can check the status of SE/Linux on Redhat by logging in as root and issuing the command sestatus:

 

[root@PT-Dev truetype]# sestatus
SELinux status:               disabled

The status should say disabled.  If it is not disabled, you can disable it by editing the file /etc/selinux/config and changing the param SELINUX from enabled to disabled.  Pay careful attention to the spelling.

It is a good idea to reboot the server if a change to selinux status is made and then re-verify that SE/LINUX is off before proceeding with any further installation or configuration steps.  If SE/LINUX is left enabled and you install new software or create new files/directories, additional bits will be added to these resources called ACCESS CONTROL LIST bits.  These are not removed by later disabling SE/LINUX and a tedius process to remove/reset these bits.  Assistance removing ACLs is a billable event and is not covered by support.

If you are using Fedora 20+Fedora 20’s VNC implementation is problematic.  A better solution is to use Windows Remote Desktop and connect using XFDE and the XFCE desktop.  To configure Fedora this way, do the following:

# yum install xrdp

# systemctl enable xrdp.service
# systemctl start xrdp.service
# systemctl enable xrdp-sesman.service
# systemctl start xrdp-sesman.service

reboot the machine.

Now, ssh to the Fedora machine

#yum groupinstall xfce-desktop
#yum install switchdesk
#switchdesk xfce

reboot the machine

Now, connect using Windows remote desktop

Connect to the ip of the Fedora box

Login using root’s credentials

 

The XFCE desktop should be presented with the ability to right-click and summon the power menus

On the LOOPS: Verify that CUPS is installed and configured.

Install and configure CUPS on the Linux server.  On the supported releases, CUPS is already configured.  Make sure that for this linux server, port 631 is accessible.  Point a browser at the ip address of the target LOOPS and to port 631.  For example, if the ip address of your LOOPS is 192.168.1.1, then the browser url will be 192.168.1.1:631.

If CUPS is running and the firewall is allowing access to port 631, you should see a page like this:

 

This page will be used often and it is vital that it be configured correctly.

Access to various functions of the CUPS web page above is controlled by a file /etc/cups/cupsd.conf.  You may need to edit this file to allow for the level of access you wish to provide to your users and administrators.   Here is an example file with relevant params highlighted in yellow  (this is just one example from one customer.  You may wish to modify your configuration based on your preferences).  Pay careful attention to the fact the original Listen localhost:631 has been commented out and Port 631 as replaced it.  This is vital to allow PC’s on the network to access the cups printer page.  If you are unable to land this web page (above) by pointing your browser at <ip_address_of_your_server>:631, then try to go to the console, bring up a browser and point it at localhost:631.  If it works there but not from your local PC, it is either that your firewall is blocking port 631 or that you still have a configuration issue with cupsd.conf.

[root@PT-Dev cups]# cat cupsd.conf

MaxLogSize 0
#
# "$Id: cupsd.conf.in 8805 2009-08-31 16:34:06Z mike $"
#
# Sample configuration file for the CUPS scheduler.  See "man cupsd.conf" for a
# complete description of this file.
#

# Log general information in error_log - change "warn" to "debug"
# for troubleshooting...
LogLevel warn

# Administrator user group...
SystemGroup sys root

# Only listen for connections from the local machine.
#Listen localhost:631

Port 631

Listen /var/run/cups/cups.sock

# Show shared printers on the local network.
Browsing On
BrowseOrder allow,deny
BrowseAllow all
BrowseLocalProtocols CUPS dnssd

# Default authentication type, when authentication is required...
DefaultAuthType Basic
DefaultEncryption IfRequested
# Restrict access to the server...
<Location />
  Order allow,deny
Allow all
</Location>

# Restrict access to the admin pages...
<Location /admin>
  Order allow,deny
Allow all
</Location>
 
# Restrict access to configuration files...
<Location /admin/conf>
  AuthType Default
  Require user @SYSTEM
  Order allow,deny
Allow all
</Location
# Set the default printer/job policies...
<Policy default>
  # Job-related operations must be done by the owner or an administrator...
  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job CUPS-Get-Document>
       Require user @OWNER @SYSTEM
       Order deny,allow
  </Limit>
  # All administration operations require an administrator to authenticate...
  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-
Delete-Class CUPS-Set-Default CUPS-Get-Devices>
       AuthType Default
       Require user @SYSTEM
       Order deny,allow
  </Limit>
  # All printer operations require a printer operator to authenticate...
  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After CUPS-Accept-Jobs CUPS-Reject-Jobs>
       AuthType Default
       Require user @SYSTEM
       Order deny,allow
  </Limit>

  # Only the owner or an administrator can cancel or authenticate a job...
  <Limit Cancel-Job CUPS-Authenticate-Job>
       Require user @OWNER @SYSTEM
       Order deny,allow
  </Limit>
  <Limit All>
       Order deny,allow
  </Limit>
</Policy>
# Set the authenticated printer/job policies...
<Policy authenticated>
  # Job-related operations must be done by the owner or an administrator...
  <Limit Create-Job Print-Job Print-URI>
       AuthType Default
       Order deny,allow
  </Limit>
  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job CUPS-Get-Document>
       AuthType Default
       Require user @OWNER @SYSTEM
       Order deny,allow
  </Limit>
 
  # All administration operations require an administrator to authenticate...
  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
       AuthType Default
       Require user @SYSTEM
       Order deny,allow
  </Limit>

  # All printer operations require a printer operator to authenticate...
  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Print
er-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Acti
vate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedu
le-Job-After CUPS-Accept-Jobs CUPS-Reject-Jobs>
       AuthType Default
       Require user @SYSTEM
       Order deny,allow
  </Limit>

  # Only the owner or an administrator can cancel or authenticate a job...
  <Limit Cancel-Job CUPS-Authenticate-Job>
       AuthType Default
       Require user @OWNER @SYSTEM
       Order deny,allow
  </Limit>
  <Limit All>
       Order deny,allow
  </Limit>
</Policy>

#
# End of "$Id: cupsd.conf.in 8805 2009-08-31 16:34:06Z mike $".

 

Notes about CUPS and logs

The CUPS system is used on the OpenOffice server to direct output to the printer.  CUPS has a number of configuration options that may be important.  For example, if OpenOffice is configured to produce job files (logs) it may soon consume all available inodes in the file system.  Care should be taken to ensure that only job and log files that you wish to have are produced.  Alternatively, you can monitor and purge these types of files to ensure that your print server’s CUPS system won’t consume all file space or available inodes.

Beware of the job history which is stored in:

/var/spool/cups

 

So to prevent junk of being stored in there.

Edit cupsd.conf

(/etc/cups/cupsd.conf)

 

Add the two parameters:

PreserveJobFiles Off
PreserveJobHistory Off

Manual link is located here:

http://www.cups.org/doc-1.1/sam.html#PreserveJobFiles

In /etc/cups/cupsd.conf you can set:

 

#New options to deal with many print jobs at once.

#Setting to no limits which is not very secure, but, oh well.

#Tired of complaints about jobs getting squashed. John Thompson. 01-10-2012

MaxJobs 0

MaxJobsPerPrinter 0

MaxJobsPerUser 0

MaxRequestSize 0

LimitRequestBody 0

ListenBackLog 4096

FilterNice 0

MaxClients 4096

PreserveJobHistory Off

PreserveJobFiles Off

#

 

Additionally, you may want to open permissions for the cups printer page (web admin).  Here is a sample cupsd.conf file with modifications highlighted in yellow.  Be warned, this allows nearly any user with the URL to perform administrative tasks.  Consider carefully if all users you intend to provide with the cups printer page should have

 

MaxLogSize 0

#

# "$Id: cupsd.conf.in 8805 2009-08-31 16:34:06Z mike $"

#

# Sample configuration file for the CUPS scheduler.  See "man cupsd.conf" for a

# complete description of this file.

#

 

# Log general information in error_log - change "warn" to "debug"

# for troubleshooting...

LogLevel warn

# Administrator user group...

SystemGroup sys root

 

# Only listen for connections from the local machine.

#Listen localhost:631

Port 631

Listen /var/run/cups/cups.sock

 

# Show shared printers on the local network.

Browsing On

BrowseOrder allow,deny

BrowseAllow all

BrowseLocalProtocols CUPS dnssd

 

# Default authentication type, when authentication is required...

DefaultAuthType Basic

DefaultEncryption IfRequested

# Restrict access to the server...

<Location />

  Order allow,deny

Allow all

</Location>

 

# Restrict access to the admin pages...

<Location /admin>

  Order allow,deny

Allow all

</Location>

 

# Restrict access to configuration files...

<Location /admin/conf>

  AuthType Default

  Require user @SYSTEM

  Order allow,deny

Allow all

</Location>

 

# Set the default printer/job policies...

<Policy default>

  # Job-related operations must be done by the owner or an administrator...

  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job CUPS-Get-Document>

      Require user @OWNER @SYSTEM

      Order deny,allow

Allow all

  </Limit>

 

  # All administration operations require an administrator to authenticate...

  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices>

      AuthType Default

      Require user @SYSTEM

      Order deny,allow

  </Limit>

 

  # All printer operations require a printer operator to authenticate...

  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After CUPS-Accept-Jobs CUPS-Reject-Jobs>

      AuthType Default

      Require user @SYSTEM

      Order deny,allow

  </Limit>

 

  # Only the owner or an administrator can cancel or authenticate a job...

  <Limit Cancel-Job CUPS-Authenticate-Job>

      Require user @OWNER @SYSTEM

      Order deny,allow

  </Limit>

 

  <Limit All>

      Order deny,allow

  </Limit>

</Policy>

 

# Set the authenticated printer/job policies...

<Policy authenticated>

  # Job-related operations must be done by the owner or an administrator...

  <Limit Create-Job Print-Job Print-URI>

      AuthType Default

      Order deny,allow

  </Limit>

 

  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job CUPS-Get-Document>

      AuthType Default

      Require user @OWNER @SYSTEM

      Order deny,allow

  </Limit>

 

  # All administration operations require an administrator to authenticate...

  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>

      AuthType Default

      Require user @SYSTEM

      Order deny,allow

  </Limit>

 

  # All printer operations require a printer operator to authenticate...

  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After CUPS-Accept-Jobs CUPS-Reject-Jobs>

      AuthType Default

      Require user @SYSTEM

      Order deny,allow

  </Limit>

 

  # Only the owner or an administrator can cancel or authenticate a job...

  <Limit Cancel-Job CUPS-Authenticate-Job>

      AuthType Default

      Require user @OWNER @SYSTEM

      Order deny,allow

  </Limit>

 

  <Limit All>

      Order deny,allow

  </Limit>

</Policy>

 

#

# End of "$Id: cupsd.conf.in 8805 2009-08-31 16:34:06Z mike $".

#

 

Manual is located here:

http://www.cups.org/documentation.php/doc-1.5/man-cupsd.conf.html

On the LOOPS: Configure Remote Desktop Access (VNC)

Remote access to the Linux console is mandatory the administration of the server.  We recommend that you turn on remote access. Remote access for root is generally very handy for performing routine admin tasks on the print server.  With VNC remote access, you will be able to connect to the print server and obtain a full graphical desktop.  From there, administrative menus can be very convenient for performing tasks such as copying printers, setting up classes, managing users, etc.  This is especially true for users not comfortable working at the Linux command line.  Setting up VNC can be a little tricky.  You’ll first want to ensure that the vncserver package has been installed on linux.  To do this, you’ll need to login to the print server as root or if access to your print server from your multiValue server has been setup, you can simply use the $ option on the Blue Prairie Forms menu to connect to the print server automatically.  Remember however, that when connecting this way, you’ll be connected as the user defined for that phantom thread and not as root.  Once you connect this way and you are at the $ prompt on the print server, you can issue the command su - root to become root.  You’ll need the root password for the print server to elevate yourself to root.  The other approach is to simply ssh directly to the print server using your SSH client on your PC, enter root at the login prompt and then enter the root password. 

 

If you have console access and it presents a GUI

 On Redhat Linux, this can be accomplished by making the following configuration change using the console GUI:

Goto the GUI desktop and choose from the top menu System > Preferences > Remote Desktop

 

We recommend making the password the same as your root password for simplicity but if you have a security concern, please follow the password policy of your company and notify Blue Prairie technical support so that we can make note of your password.

We recommend leaving the console logged in since this is how the remote desktop configuration will work.  If the console is not logged in, you may not be able to remote connect to it.  Again, check with your IT director for policies regarding this procedure and always follow the recommended security policies of your company when they differ from our recommendations.

 

Manually Configuring VNC

Unfortunately, some Linux distributions do not provide a graphical desktop by default nor do they install the VNC server package by default.   To verify whether VNC server has been installed on the print server, follow these directives as root:

 

 

[root@bpfserver_1 sysconfig]# rpm -qa |grep vnc

tigervnc-1.1.0-16.el6.centos.x86_64

tigervnc-server-1.1.0-16.el6.centos.x86_64

[root@bpfserver_1 sysconfig]#

 

The above display indicates that the tigervnc client and tiger vnc-server package have been installed.  TigerVNC is one of many available VNC packages and is common on Linux systems.  We recommend tigerVNC.  VNC comes in two parts:

vnc client   -- (aka vnc)

This is an app that you run to connect to another vnc server.  It’s like the Windows RDP client.  You’ll install VNC client on your PC and then run it to connect to a VNC server.  When you see a ‘vnc’ package (i.e., a package with a name that has vnc in its name but is not vnc-server such as what is shown above on the first green line, this is a client package).  It’s okay to have a client package installed on the Print Server (Linux server) but we’ll probably not use it.  Instead, we’ll be installing our own VNC-Client on our PC and connecting from our PC.  Nonetheless, it does not hurt to have vnc client installed on the Print Server

vnc-server

This is what we must have installed and running on our Linux server to allow a remote vnc-client to connect to this server and present a graphical desktop.  If we have no vnc-server package installed, you will need to install one in order to have remote access via VNC.  Blue Prairie Forms will function without VNC.  But it is handy to have VNC access to the print server to perform certain administrative tasks (as shown above) so we highly recommend having it installed and running.

How VNC Works

VNC must be installed on the Linux print server

A service must be started on the print server.  This service listens for inbound VNC-Client requests on a certain port number (usually port numbers starting at 5900).  A configuration file on the Linux server determines how many VNC listeners will be running.  The configuration file will define each listener and determine to which Linux user that listener port will be connected.

Example vnc configuration file:

/etc/sysconfig/vncservers

[root@bpfserver_1 sysconfig]# cat vncservers

# The VNCSERVERS variable is a list of display:user pairs.

#

# Uncomment the lines below to start a VNC server on display :2

# as my 'myusername' (adjust this to your own).  You will also

# need to set a VNC password; run 'man vncpasswd' to see how

# to do that.

#

# DO NOT RUN THIS SERVICE if your local area network is

# untrusted!  For a secure way of using VNC, see this URL:

# https://access.redhat.com/knowledge/solutions/7027

 

# Use "-nolisten tcp" to prevent X connections to your VNC server via TCP.

 

# Use "-localhost" to prevent remote VNC clients connecting except when

# doing so through a secure tunnel.  See the "-via" option in the

# `man vncviewer' manual page.

 

# VNCSERVERS="2:myusername"

# VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -localhost"

 

VNCSERVERS="1:root 2:bpiform1 3:bpiform2"

VNCSERVERARGS[1]="-geometry 800x600"

VNCSERVERARGS[2]="-geometry 800x600"

VNCSERVERARGS[3]="-geometry 800x600"

 

Explanation

The red line tells the VNC service that when it starts, it should establish three listeners:

            The first is for the user root

            The second is for the user bpiform1

            The third is for the user bpiform2

The green lines define the GUI desktop dimensions for each of the above three listeners.  So, when the vnc client connects (using the example above) this says that the desktop geometry of the display will be 800x600 pixels

 

You may define other users in your vncservers file by adding more users to the red line then adding a corresponding green line

When adding new users

It is important to understand that all VNC users are Linux users but not all Linux users are VNC users.  The first step in creating a VNC user (such as bpiform1 above) is to make sure that this user name is a valid Linux username.  You can create the user from the console or by CLI commands like useradd. Obviously in the example above, root was an already established Linux user.  But even though root was already defined as a Linux user, it had not been declared to be a valid VNC user. 

Making a Linux User a valid VNC User

To make a unix user a valid VNC user, you simply need to run the command vncpasswd as the desired Linux user.  The easiest way to do this is to:

  1. Login as root
  2. su - <desired_user_name>
  3. vncpasswd
  4. Assign a password

Note that the vnc password does not need to be the same password used for the Linux user.  However, it may be handy to make it the same password.  Likewise, if you change the Linux password for a user, it will not automatically update the vncpassword for that user.  You’ll need to run vncpasswd to make the vnc password match the linux password.

Starting the VNC server and Listeners

  1. Login as root
  2. service vncserver start

[root@bpfserver_1 sysconfig]# service vncserver start

Starting VNC server: 1:root xauth: (stdin):1:  bad display name "bpfserver_1:1"

in "add" command

 

New 'bpfserver_1:1 (root)' desktop is bpfserver_1:1

 

Starting applications specified in /root/.vnc/xstartup

Log file is /root/.vnc/bpfserver_1:1.log

 

2:bpiform1 xauth: (stdin):1:  bad display name "bpfserver_1:2" in "add" command

 

New 'bpfserver_1:2 (bpiform1)' desktop is bpfserver_1:2

 

Starting applications specified in /home/bpiform1/.vnc/xstartup

Log file is /home/bpiform1/.vnc/bpfserver_1:2.log

 

3:bpiform2 xauth: (stdin):1:  bad display name "bpfserver_1:3" in "add" command

 

New 'bpfserver_1:3 (bpiform2)' desktop is bpfserver_1:3

 

Starting applications specified in /home/bpiform2/.vnc/xstartup

Log file is /home/bpiform2/.vnc/bpfserver_1:3.log

 

                                                            [  OK  ]

 

I do not understand why the service start throws the ‘bad display name’ warning but since it works, I’m going to track that down later.  For now, ignore those warnings.

 

 

You can observe the listeners in the linux process stack by using the following command:

# ps -ef |grep vnc

root 16077       1  0 02:17 pts/1  00:00:00 /usr/bin/Xvnc :1 -desktop bpfserver_1:1 (root) -auth /root/.Xauthority -geometry 800x600 -rfbwait 30000 -rfbauth /root/.vnc/passwd -rfbport 5901 -catalogue:/etc/X11/fontpath.d -pn

 

bpiform1 16181    1  0 02:17 ?      00:00:00 /usr/bin/Xvnc :2 -desktop bpfserver_1:2 (bpiform1) -auth /home/bpiform1/.Xauthority -geometry 800x600 -rfbwait 30000 -rfbauth /home/bpiform1/.vnc/passwd -rfbport 5902 -fp catalogue:/etc/X11/fontpath.d -pn

 

bpiform2 16581    1  0 02:17 ?      00:00:00 /usr/bin/Xvnc :3 -desktop bpfserver_1:3 (bpiform2) -auth /home/bpiform2/.Xauthority -geometry 800x600 -rfbwait 30000 -rfbauth /home/bpiform2/.vnc/passwd -rfbport 5903 -fp catalogue:/etc/X11/fontpath.d -pn

 

Explanation

With the vnc-server service started, three listeners as defined in the vncservers file have been spawned.  The three lines above are separated by a blank like for clarity and extraneous lines resulting from the ps -ef command have been stripped for clarity.

The orange word indicates the Linux user that this listener is running as

The red word indicates the VNC listener number that is assigned to this listener.  This is the number that you enter into the VNC client when making a connection.

The yellow word indicates the VNC user name associated with this listener

The green word indicates the actually port number where the listener is running.  Do not confuse VNC listener number with the port number.  You will see the following parallels however:

 

VNC Listener :1 is on port number 5901

VNC Listener :2 is on port number 5902

VNC Listener :3 is on port number 5903

Make the VNC Service start on reboot

[root@bpfserver_1 sysconfig]# chkconfig vncserver on

[root@bpfserver_1 sysconfig]#

Making the connection from your PC

If you have not already installed the vnc client (aka VNC Viewer) on your PC, then google for a download site and install it.  I’ve had good luck with TightVNC.  With VNCserver installed and running on your Linux Print server, and assuming you have visibility to the ip address of the Linux Print server from your PC and that VNC server has been installed and is running on the Linux print server, simply run TightVNC on your PC.  For the example below, we’ll going to connect to the system shown in the above example and connect to VNC listener :2 which will connect us to the bpiform1 user

 

Click “Connect” and you’ll be challenged with a password

 

Enter the VNC password that you assigned for this listener and press OK.  The GUI desktop will be displayed and you may be challenged for the LINUX user password depending on whether the desktop has timed out at the Linux level.

 

Enter the LINUX password for this Linux user and press Unlock to display the desktop

 

When you are finished, just close the vnc client.

 

On the LOOPS: Setup the Linux users corresponding to the MultiValue users

You will need to configure a Linux user with the same name as the user on the MultiValue host that will own the Blue Prairie Form phantom thread.  Generally, these are called bpiform1, bpiform2 and so on for as many threads and you may wish to configure.  An example of these users using the Redhat User Manager is shown below:

 

This is covered in the section “On the MultiValue Server” but you’ll need to create a unix user for each unix user on the MultiValue side that intends to send OpenOffice print jobs.  Normally, this is only the UNIX users that run the phantom threads on the MultiValue host and NOT every application user.  These users are normally named bpiform1, bpiform2 and so on… on the MultiValue host.  These are the only users you need to create on the Linux  OpenOffice server.  You do NOT need to create the bpifuser or bpifadm users on the Linux/OpenOffice server.

On the LOOPS: Install Desired Specialized FONTS

Depending on your requirements, you may wish to use specialized fonts such as 3 of 9 barcode fonts within your Blue Prairie Forms.  To use specialized fonts such as barcode fonts, you must legally obtain the desired true type or open type font (.ttf) then upload the font to the Linux/OpenOffice server.  The installation is straight-forward as defined below:

 Prepare a directory

  1. Login to your Linux/OpenOffice server using ssh.
  2. cd to /usr/share/fonts
  3. See if there already exists a directory called truetype
    1. If not: mkdir truetype
    2. chmod 755 truetype

 Upload the .ttf file to this directory

  1. Using a ftp tool, upload the .ttf file to /usr/share/fonts/truetype

 Check the permissions

  1. Using your ssh session, cd to the truetype directory and chmod 644 *
  2. cd /usr/share/fonts/truetype

Generate the index files

  1. ttmkfdir > fonts.scale
  2. mkfontdir

Verify that the index files were generated

  1. ls -la

 

You should now see a listing somewhat like this:

[root@PT-Dev fonts]# cd truetype
[root@PT-Dev truetype]# ls -la
total 60
drwxr-xr-x  2 root root  4096 Jun 20 18:04 .
drwxr-xr-x 31 root root  4096 Jun 20 17:46 ..
-rw-r--r--  1 root root   171 Jun 20 18:04 fonts.dir
-rw-r--r--  1 root root   171 Jun 20 18:04 fonts.scale
-rw-r--r--  1 root root 41732 Jun 20 17:57 IDAutomationHC39M.ttf

[root@PT-Dev truetype]#

 

Note the size of the fonts.dir and fonts.scale files.  These contain a directory listing describing the fonts found in this directory.  This is what OpenOffice reads when populating the ‘font’ pull-down within the product and/or to reference a font specified within a document.

You should now be able to call up OpenOffice on the console or via a remote desktop connection and create a new Writer document. Then choose the font pull-down to confirm that your font is indeed visible to OpenOffice.

On the LOOPS: Verify/Install Office Installation

For the version of Office we recommend for the LOOPS server, please refer to this Recommended Office Versions article.  The recommended Office software is available as a RPM download and may be installed using yum.  See the installation directions recommended by the office project page for installation of this package on your Linux distribution.  You may need to download the correct Office rpm package directly from the project page. Make sure to choose the correct package for your Linux distribution and pay careful attention to ensure that you have chosen the correct bit (32 vs. 64) and correct architecture (intel vs. ppc or ia64, etc).  When in doubt, call for assistance or use your Redhat Support access for advice.

Typical yum installation syntax:

yum install <path_to_office_rpm_file>

 

After installation, verify that OpenOffice is accessible using the ‘which’ Linux command:

[root@PT-Dev /]# which soffice

A path will show

[root@PT-Dev /]#

If no path shows, you may need to locate the soffice binary in the office installation bin directory and place a symlink into a directory within path (e.g, /usr/bin for example) that points at the actual soffice binary.

 

 

On the LOOPS: Configure the Samba Mount to the MultiValue share

The Linux/OpenOffice server will use Samba (aka CIFS) to connect to the MultiValue server to access documents generated by the Blue Prairie Forms library.  Generally, Samba/CIFS is part of the Linux distribution and no additional installation of packages should be required.  However, you will need add directives to the Linux/OpenOffice server’s /etc/fstab file to provide the Linux/OpenOffice server with the information it needs to connect to the MultiValue Host and access the Samba share that has been created on the MultiValue Host.  Note, the Share must be created and published on the MultiValue host before you can configure the Linux/OpenOffice server to mount the share on the MultiValue host.

Once the Share has been created on the MultiValue host, you can connect the Linux/OpenOffice server to it by modifying /etc/fstab as shown below and then issuing a mount -a command to cause Linux to remount all of its declared file systems defined in /etc/fstab.

 

The Linux-side mount

Here is an example /etc/fstab file from a client’s Linux/OpenOffice server

 

[root@PT-Dev etc]# cat fstab

#

# /etc/fstab

# Created by anaconda on Sat May 31 21:55:01 2014

#

# Accessible filesystems, by reference, are maintained under '/dev/disk'

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info

#

/dev/mapper/vg_ptdev-lv_root /                       ext4    defaults       1 1

UUID=f11f9c06-f9bc-41c9-b363-72599f750a99 /boot                     ext4    defaul

ts      1 2

/dev/mapper/vg_ptdev-lv_home /home                   ext4    defaults       1 2

/dev/mapper/vg_ptdev-lv_swap swap                    swap    defaults       0 0

tmpfs                  /dev/shm               tmpfs   defaults       0 0

devpts                 /dev/pts               devpts  gid=5,mode=620  0 0

sysfs                  /sys                   sysfs   defaults       0 0

proc                   /proc                  proc    defaults       0 0

 

//192.168.xxx.xxx/bpi_forms  /mnt/192.168.xxx.xxx/bpi_forms   cifs   username=bpiform1,password=

xxxxxxx,nocase,noperm,file_mode=0777,dir_mode=0777  0  0

The line above with the color coding actually wraps around onto a second line.  The color coded params in this line represent information for the samba/cifs connection.  Where lower case x’s appear, these were inserted into this document to hide the actual information to protect the security of this user’s installation.  The color coded information is as follows:

Breakdown of CIFS connection syntax

//192.168.xxx.xxx                      is the ip address or server name of the MultiValue host

bpi_forms                      is the name of the share as published on the MultiValue host

/mnt/192.168.xxx.xxx/bpi_forms

is the point point on the Linux OpenOffice server where the share will be mounted.  192.168.xxx.xxx is replaced with the ip address of the MultiValue server to which this LOOPS server wishes to connect.  Of course you need to cd to /mnt and make the directories 192.168.xxx.xxx and then cd to it and make the directory bpi_forms under that.  This path is what will be placed into the BPI.FORM.PHANTOM.CONTROL record for the remote mount point.

We include the MultiValue server name or ip address in the mount name in case we wish to later work with more than one MultiValue server (for example, a production server and a backup server) so that it is clear by the mount point path to which MultiValue server we are connecting.  You could technically make this value anything you wish (e.g., /mnt/bpi_forms) but then if you had more than one MultiValue server, it would be unclear which of the MultiValue servers this CIFS mount would be connecting to

cifs     is the protocol being used to make the connection

bpiform1           is the cifs/samba user name as defined on the MultiValue host.  Note,You must create a samba user on the MultiValue host.  The Unix user name is not enough.  After creating the unix user, use the SWAT tool to create the samba user (using the same name as the unix user)

xxxxxxx is the password of the samba user on the MultiValue host.  Note, the samba user password can be, but is not required to be, the same as the unix user password as defined on the MultiValue host.

On the LOOPS:  Configure printer and test

Configure a test printer through the chosen CUPS interface and test it.  Become familiar with the operation and administration of CUPS, you will be using this frequently.

Installation Location

The Blue Prairie Forms Basic API lives, by default, in the BPIFORMS account on your multivalue server.   The API lives in the bpi.bp.form directory and should be fully functional, at the time of installation, within the BPIFORMS account.

Exposing the API in your application accounts

If you wish to call the API from another account, the BASIC objects need to be exposed within that account.  The recommended method to be used for exposing the API will be determined by your MultiValue platform using the normal methods appropriate for that Multivalue platform. 

JBASE

To expose the API in another account, the following procedure will work.  However, remember that on a jBASE system, there are a variety of ways that accounts can be configured.  Some installations make use of the SYSTEM to establish environmental configurations.  Other jBASE installations prefer to use UNIX initialization scripts to setup the jBASE environment. 

The main goal in exposing the Blue Prairie Forms API in JBASE is to ensure that two environment variables hold the path to the Blue Prairie Forms bin and lib directories. 

If you use the jBASE SYSTEM file method of environment setup, this procedure will work

For this example, we will assume that the account into which we wish to expose the Blue Prairie Forms API is called EXAMPLE:

Example SYSTEM file entry

FILE=SYSTEM, ITEM=EXAMPLE

0001 D
0002 /dbms/BARCODE
0003
0004
0005
0006
0007
0008
0009 L
0010 10
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 ESYSTEM_START
0021
0022 /dbms/EXAMPLE
0022 /dbms/EXAMPLE
0023 /dbms/EXAMPLE/bin
0024 /dbms/EXAMPLE/lib
0025 /dbms/BPIFORMS/bin:/dbms/EXAMPLE/bin:/dbms/bin:/dbms/ACCUTERM/bin
0026 /dbms/BPIFORMS/lib:/dbms/EXAMPLE/lib:/dbms/lib:/dbms/ACCUTERM/lib
0027 .:/dbms/ACCUTERM
0028 /dbms/EXAMPLE/MD
0029
0030
0031
0032
0033

The jBASE SYSTEM file is defined on the jBASE website at this URL:  https://www.jbase.com/r5/knowledgebase/manuals/3.0/30manpages/man/sup22_SYSTEM.ENTRIES.htm

For convenience, the definitions for attributes 25 and 26 (as highlighted above) are excerpted here:

025 PATH
026 JBCOBJECTLIST

PATH refers the environment variable $PATH.  This is the normal operating system $PATH variable.  The operating system $PATH variable will be set to the value defined in this attribute.

JBCOBJECTLIST refers to the environment variable $JBCOBJECTLIST.  This environment variable is specific to jBASE and defines the location where subroutine shared objects live.

Some users of jBASE configure their environments using the SYSTEM file but others prefer to control their environment using UNIX scripts.   In that case, you will need to look into the the environment setup scipts (usually .profile or .bash_profile).  For a full explanation of the jBASE Environment Variables, please refer to the jBASE documentation at: https://jbase.com/r5/knowledgebase/manuals/3.0/30manpages/man/env1.htm

UniVerse

To expose the API in another account, the following procedure will work

  1. LOGTO your target account
  2. SET.FILE BPIFORMS bpi.bp.form BPIFORMS.bpi.bp.form
  3. SSELECT BPIFORMS.bpi.bp.form
  4. CATALOG BPIFORMS.bpi.bp.form

Unidata

Simple login to the BPIFORMS account and globally catalog all items in bpi.bp.form.

Implementation of Blue Prairie Forms is most easily performed by using an existing print program that does not currently support Blue Prairie Forms.  We generally copy a legacy print program to a new name and then modify it to make it Blue Prairie Forms aware.   We usually name the copied program BPI.<originalProgramName>.  This makes it clear that the program is a special version of the original program that has been modified for Blue Prairie Forms

Basic Modification Steps

  1. Copy a legacy program to a new name
  2. Modify the legacy program as follows
    1. Insert the Blue Prairie Forms internal subroutines at the bottom of the program
    2. Comment-out all PRINTER ON, PRINTER OFF, PRINTER CLOSE statements
    3. Comment-out all PRINT statements and add equivalent calls to the Blue Prairie Forms bpi.set.tagval2 subroutine
    4. Call the MakeDocument routine
    5. Your done

Comment, don’t remove

The process of modifying a legacy print program for Blue Prairie Forms can take from 1-4 hours depending on the complexity of the print job,  It is good practice to NOT remove any original code at first but instead to comment it out using a unique comment tag.  Likewise, any added instructions should be commented at the end of the line with a readily identifiable tag.

 

Example:

*|||bpiforms|||PRINTER ON
*|||bpiforms|||PRINT  “INVOICE: “: INVNO
CALL bpi.set.tagval2(blocks, tags, vals, \\, \%invNo%\, INVNO \\, vector, verbose);*|||bpiforms|||
*|||bpiforms|||PRINTER CLOSE
*|||bpiforms|||PRINTER OFF

As you can see, we have commented out the original code with the preceding comment text *|||bpiforms|||.  We also used that comment tag on the line we added (at the end).

By commenting code this way, it is easy to follow and you can always refer back to what the original code was doing if you get lost or miss something during the integration.  After the program is successfully working with Blue Prairie Forms, you can remove the commented lines to streamline the program.

We also recommend that you place the call to bpi.set.tagval2 after each PRINT directive you have commented.  By keeping the new call together with its predecessor comment line, it’s easier to read the code,  Remember that legacy print programs may print several variables with one print directive.  In these cases, you may end up with multiple calls to bpi.set.tagval2 for a commented legacy PRINT directive.  For purposes of documentation and style, we recommend adding a comment to the end of the instruction of ;*|||BPIFORMS|||.

Ultimate/AutoShims Transfer Ticket Printing

The Ultimate transfer processing program is XP.2.1 on most ultimate systems.  The program that actually prints the transfer ticket is called from XP.2.1.  A user may have a customized transfer ticket print program (or programs).  These are defined in the CONTROL file in a item called COMPANY.  Attributes 11 and 12 define names of the transfer print programs.

 

>ED CONTROL COMPANY
0001: ONLINEINV.WHSE:EAW5
0002: PRINT-INVOICE:AWI
0003: OLDINV.WHSE.AWI2
0004: OLDINV.STORE.API.EAW.ROUTE
0005: ONLINEORD.WHSE.AWI2
0006: PRINT-INVOICE:TRIAD2
0007: ROA.STORE.TRIAD
0008: ROA.STORE.TRIAD
0009: STATEMENTS:TRIAD:EAW
0010: AP-PRINT-CHECKS:LAAP2
0011: ONLINEXFER.WHSE.AWI.EAS             ←- for the warehouse
0012: ONLINEXFER.STORE.EAW                ←- for the store
0013: ONLINEINV.STORE.API
0014: ONLINEORD.STORE.API2
Bottom at line 14.

Attribute 11 is the name of the transfer print program for the warehouse and attribute 12 is the transfer print program for the store

 

 

CONTROL WHSE-TRANSFER-PRINTQ

This is a standard part of most Ultimate systems and has been around for years.  This record defines the print queue names to be used when printing a ticket.  There is one transfer printer per location.  Attribute 1 of this record is multivalued and the queue is the ordinal position of the location number.  So, if you are printing for location 4, then look in multivalue 4 and that is the queue number for the printer where the transfer ticket is to be printed.

CONTROL WHSE-TRANSFER-PRINTQ-BPI_FORMS

This is a new control record that I use to define whether a specific location is to use Blue Prairie Forms or the legacy print routine.  It’s possible for some customers that they’ll install Blue Prairie Forms at one locations but not at another.  This could be because they are rolling out laser printers one location at a time over a period of months.  So, the integration needs to be smart enough to be able to enable Blue Prairie Forms at one location but not another.

This record contains only one attribute that is multivalued.  Each multivalue position is a location where location 1 is the first multivalue and location 999 is the 999th multivalue position.  You may place any value that evaluated to boolean @TRUE in the multivalue position for a location and this will enable Blue Prairie Forms for that location for transfer printing.  Leaving a location’s multivalue position undefined (or boolean @FALSE) will cause the legacy print routine to be called.

Routing

I like to use routing to control whether my routine is to be called or the legacy application’s routines.  A router is basically a subroutine that determines which routine should be called next.  When I perform a tight integration of Blue Prairie Forms into a legacy application, I do this by replacing the first level call with a router.  For example, in the above listing of CONTROL COMPANY, I’d replace attribute 12 with ONLINEXFER.STORE.EAW.ROUTE. This new program will perform some checks (such as checking the values in the above control records) and then either call my new BPI_FORMS enabled version of the print program or call the old legacy (character) print program.  Here is an example of my router for ONLINEXFER.STORE.EAW.ROUTE

Example Router: ONLINEXFER.STORE.EAW.ROUTE

 

SUBROUTINE ONLINEXFER.STORE.EAW.ROUTE(arg1, arg2, arg3, arg4, arg5)
* Written by Bruce Decker, Blue Prairie, Inc.
* 1/12/2013 for Effingham Auto Warehouse.
* Source license to this work granted to Effingham Auto Warehouse
*
* This subroutine is simply a router meaning that it's sole roles is to determine
* which invoice print program should be called.
* At the time written, this router is to simply determine if the bpi_form version
* or the legacy character / preprinted / dot matrix form of the invoice is to
* be called.
*
* For testing, simply ensure that in the test user's environment, tht you define
* the environment variable BPI_FORMS_INVOICE to the name of the BPI_FORM enabled
* subroutine that you wish to have the router call.  If the environment variable
* is defined, then it will be called, otherwise, the legacy routine will be called.
* Example: BPI_FORMS_INVOICE=OLDINV.STORE.API:EAW will cause the router
*      to call ONLINEINV.STORE.API:EAW
*
* This program name should be placed in the appropriate attribute (usually 1 or 13)
* of the CONTROL COMPANY record.  This is what the calling program references to
* understand which subroutine to call.
*
* ------------------------------------------------------------------------------
* Include the common variables just in case we want to reference something in
* in this router
$INCLUDE BP SOE.COMMON
$INCLUDE BP SOE.COMMON.EXPANSION
EQU colon  TO CHAR(58); * colon
EQU period TO CHAR(46); * period
*
* ------------------------------------------------------------------------------
GOSUB Init
GOSUB CheckEnabled
GOSUB GetMethod
GOSUB Route
GOTO  Exit

* ------------------------------------------------------------------------------

CheckEnabled:
   * decide if this print is a 'from' location print or a 'to' location print 
   * so we can decide if bpi_forms enabled for this location for routing 
   * have to do it this way because app doesn't pass in this info and it's not 
   * discernable with exposed variables.  This subroutine leaves bpi.forms.enabled 
   * set to value in WHSE-TRANSFER-PRINTQ-BPI_FORMS if that record exists in
   * control.  Otherwise it will default to @FALSE and bpi_forms will not function
   queue = CHANGE( OCONV(arg3,\MCN\), \-\, \\); *strip out formatting, just num
   READ whse.transfer.printq FROM F.CONTROL, \WHSE-TRANSFER-PRINTQ\ THEN
     READ i.transfer FROM F.TRANSFER, arg1 THEN
        BEGIN CASE
        CASE whse.transfer.printq<1,i.transfer<1>> EQ queue
        copy.for = \from\
           pos = i.transfer<1>
        CASE whse.transfer.printq<1,i.transfer<3>> EQ queue
           copy.for = \to\
           pos = i.transfer<3>
        CASE 1
           copy.for = \to\
           pos = i.transfer<1>
        END CASE
        * if pos is 1, it's a from copy, if pos is 3, it's to copy.
        READ i.control FROM F.CONTROL, \WHSE-TRANSFER-PRINTQ-BPI_FORMS\ THEN
        bpi.forms.enabled = i.control<1,pos>
        END ELSE        
           bpi.forms.enabled = @FALSE             
        END      
    END ELSE 
        bpi.forms.enabled = @FALSE     
    END
END

RETURN

* ------------------------------------------------------------------------------
GetMethod:
   * right now this looks at a env variable, but it could be changed to get from 
   * a database record if that works better for the user... 
   IF bpi.forms.enabled THEN
        CALL bpi.GetEnv( \BPI_FORMS_METHOD_SUFFIX\, suffix, error )
   END ELSE
       suffix = \\
   END 
RETURN

* ------------------------------------------------------------------------------
Route:
   method = \ONLINEXFER.STORE.EAW\ 
   IF bpi.forms.enabled THEN 
     * the control record says this location is bpi_form enabled
     IF suffix NE \\ THEN    
     * get rid of colons to make editing with unix editors and ftp client easier          
        method = CHANGE( method:suffix, colon, period)
     END      
   END
   CALL @method( arg1, arg2, arg3, arg4, arg5)
RETURN

* ------------------------------------------------------------------------------
Init:
        OPEN 'TRANSFER' TO F.TRANSFER ELSE STOP 201, \TRANSFER\      
RETURN
* ------------------------------------------------------------------------------
Exit:
   RETURN  

UltiForm Emulation

In release 2.1 of Blue Prairie Forms, we added a set of conversion tools that allow Ultimate/AutoShims users that are using the ULTIFORM templating system (also known as PP-TEMPLATE) to easily integrate and use Blue Prairie Forms instead.  Details about this integration can be found in a separate technical note.

To determine if you are using the UltiForms system within your apps, login to you main account and type SORT PP-TEMPLATE.  If this lists items, there is a good chance that you are using UltiForms and that the switch to Blue Prairie Forms will be easier than hand-coded integration.