--- /dev/null
+Notifications / Action Triggers
+-------------------------------
+
+indexterm:[action triggers, event definitions, notifications]
+
+Action Triggers give administrators the ability to set up actions for
+specific events. They are useful for notification events such as hold notifications.
+
+To access the Action Triggers module, select *Admin* -> *Local Administration* -> *Notifications / Action triggers*.
+
+[NOTE]
+==========
+You must have Local Administrator permissions to access the Action Triggers module.
+==========
+
+You will notice four tabs on this page: <<event_definitions, Event Definitions>>, <<hooks, Hooks>>, <<reactors, Reactors>> and <<validators, Validators>>.
+
+
+anchor:event_definitions[]
+
+Event Definitions
+~~~~~~~~~~~~~~~~~
+
+Event Definitions is the main tab and contains the key fields when working with action triggers. These fields include:
+
+Table 1: Action Trigger Event Definitions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+|==============================================
+|*Field* |*Description*
+| Owning Library |The shortname of the library for which the action / trigger / hook is defined.
+| Name |The name of the trigger event, that links to a trigger event environment containing a set of fields that will be returned to the <<validators, Validators>> and/or <<reactors, Reactors>> for processing.
+| <<hooks, Hook>> |The name of the trigger for the trigger event. The underlying action_trigger.hook table defines the Fieldmapper class in the core_type column off of which the rest of the field definitions ``hang''.
+| Enabled |Sets the given trigger as enabled or disabled. This must be set to enabled for the Action trigger to run.
+| Processing Delay |Defines how long after a given trigger / hook event has occurred before the associated action (``Reactor'') will be taken.
+| Processing Delay Context Field |Defines the field associated with the event on which the processing delay is calculated. For example, the processing delay context field on the hold.capture hook (which has a core_type of ahr) is _capture_time_.
+| Processing Group Context Field |Used to batch actions based on its associated group.
+| <<reactors, Reactor>> |Links the action trigger to the Reactor.
+| <<validators, Validator>> |The subroutines receive the trigger environment as an argument (see the linked Name for the environment definition) and returns either _1_ if the validator is _true_ or _0_ if the validator returns _false_.
+| Event Repeatability Delay |Allows events to be repeated after this delay interval.
+| Failure Cleanup |After an event is reacted to and if there is a failure a cleanup module can be run to clean up after the event.
+| Granularity |Used to group events by how often they should be run. Options are Hourly, Daily, Weekly, Monthly, Yearly, but you may also create new values.
+| Max Event Validity Delay |Allows events to have a range of time that they are valid. This value works with the *Processing Delay* to define a time range.
+| Opt-In Settings Type |Choose which User Setting Type will decide if this event will be valid for a certain user. Use this to allow users to Opt-In or Opt-Out of certain events.
+| Opt-In User Field |Set to the name of the field in the selected hook's core type that will link the core type to the actor.usr table.
+| Success Cleanup |After an event is reacted to successfully a cleanup module can be run to clean up after the event.
+| Template |A Template Toolkit template that can be used to generate output. The output may or may not be used by the reactor or another external process.
+|===============================================
+
+
+Creating Action Triggers
+~~~~~~~~~~~~~~~~~~~~~~~~
+. From the top menu, select *Admin* -> *Local Administration* -> *Notifications / Action triggers*.
+. Click on the _New_ button.
+. Select an _Owning Library_.
+. Create a unique _Name_ for your new action trigger.
+. Select the _Hook_.
+. Check the _Enabled_ check box.
+. Set the _Processing Delay_ in the appropriate format. E.g. _7 days_ to run 7 days from the trigger event or _00:01:00_ to run 1 hour after the _Processing Delay Context Field_.
+. Set the _Processing Delay Context Field_ and _Processing Group Context Field_.
+. Select the _Reactor_, _Validator_, _Failure Cleanup_.
+. Select the _Granularity_.
+
+. Set the _Max Event Validity Delay_.
+
+. Select the _Opt-In Setting Type_.
+
+. Set the _Opt-In User Field_.
+
+. Select the _Success Cleanup_.
+
+. Enter text in the _Template_ text box if required. These are for email messages. Here is a sample template for sending 90 day overdue notices:
+
+
+ [%- USE date -%]
+ [%- user = target.0.usr -%]
+ To: [%- params.recipient_email || user.email %]
+ From: [%- helpers.get_org_setting(target.home_ou.id, 'org.bounced_emails') || lib.email || params.sender_email || default_sender %]
+ Subject: Overdue Items Marked Lost
+ Auto-Submitted: auto-generated
+
+ Dear [% user.family_name %], [% user.first_given_name %]
+ The following items are 90 days overdue and have been marked LOST.
+ [%- params.recipient_email || user.email %][%- params.sender_email || default_sender %]
+ [% FOR circ IN target %]
+ Title: [% circ.target_copy.call_number.record.simple_record.title %]
+ Barcode: [% circ.target_copy.barcode %]
+ Due: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+ Item Cost: [% helpers.get_copy_price(circ.target_copy) %]
+ Total Owed For Transaction: [% circ.billable_transaction.summary.total_owed %]
+ Library: [% circ.circ_lib.name %]
+ [% END %]
+
+ [% FOR circ IN target %]
+ Title: [% circ.target_copy.call_number.record.simple_record.title %]
+ Barcode: [% circ.target_copy.barcode %]
+ Due: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+ Item Cost: [% helpers.get_copy_price(circ.target_copy) %]
+ Total Owed For Transaction: [% circ.billable_transaction.summary.total_owed %]
+ Library: [% circ.circ_lib.name %]
+ [% END %]
+
+. Once you are satisfied with your new event trigger, click the _Save_ button located at the bottom of the form.
+
+[TIP]
+=========
+A quick and easy way to create new action triggers is to clone an existing action trigger.
+=========
+
+Cloning Existing Action Triggers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+. Check the check box next to the action trigger you wish to clone.
+. Click _Clone Selected_ on the top left of the page.
+. An editing window will open. Notice that the fields will be populated with content from the cloned action trigger. Edit as necessary and give the new action trigger a unique Name.
+. Click _Save_.
+
+Editing Action Triggers
+^^^^^^^^^^^^^^^^^^^^^^^
+
+. Double-click on the action trigger you wish to edit.
+. The edit screen will appear. When you are finished editing, click _Save_ at the bottom of the form. Or click _Cancel_ to exit the screen without saving.
+
+[NOTE]
+============
+Before deleting an action trigger, you should consider disabling it through the editing form. This way you can keep it for future use or cloning.
+============
+
+Deleting Action Triggers
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+. Check the check box next to the action trigger you wish to delete
+. Click _Delete Selected_ on the top-right of the page.
+
+
+anchor:hooks[]
+
+Hooks
+^^^^^
+Hooks define the Fieldmapper class in the core_type column off of which the rest of the field definitions ``hang''.
+
+Table 2. Hooks
+++++++++++++++
+|=======================
+| *Field* | *Description*
+| Hook Key | A unique name given to the hook.
+| Core Type | Used to link the action trigger to the IDL class in fm_IDL.xml
+| Description | Text to describe the purpose of the hook.
+| Passive | Indicates whether or not an event is created by direct user action or is circumstantial.
+|=======================
+
+You may also create, edit and delete Hooks but the Core Type must refer to an IDL class in the fm_IDL.xml file.
+
+
+anchor:reactors[]
+
+Reactors
+^^^^^^^^
+
+Reactors link the trigger definition to the action to be carried out.
+
+Table 3. Action Trigger Reactors
+++++++++++++++++++++++++++++++++
+
+|=======================
+| Field | Description
+| Module Name | The name of the Module to run if the action trigger is validated. It must be defined as a subroutine in `/openils/lib/perl5/OpenILS/Application/Trigger/Reactor.pm` or as a module in `/openils/lib/perl5/OpenILS/Application/Trigger/Reactor/*.pm`.
+| Description | Description of the Action to be carried out.
+|=======================
+
+You may also create, edit and delete Reactors. Just remember that there must be an associated subroutine or module in the Reactor Perl module.
+
+
+anchor:validators[]
+
+Validators
+^^^^^^^^^^
+
+Validators set the validation test to be preformed to determine whether the action trigger is executed.
+
+Table 4. Action Trigger Validators
+++++++++++++++++++++++++++++++++++
+
+|=======================
+| Field | Description
+| Module Name | The name of the subroutine in `/openils/lib/perl5/OpenILS/Application/Trigger/Reactor.pm` to validate the action trigger.
+| Description | Description of validation test to run.
+|=======================
+
+You may also create, edit and delete Validators. Just remember that their must be an associated subroutine in the Reactor.pm Perl module.
+
+Processing Action Triggers
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To run the action triggers, an Evergreen administrator will need to run the trigger processing script. This should be set up as a cron job to run periodically. To run the script, use this command:
+
+----
+/openils/bin/action_trigger_runner.pl --process-hooks --run-pending
+----
+
+You have several options when running the script:
+
+* --run-pending: Run pending events to send emails or take other actions as
+specified by the reactor in the event definition.
+
+* --process-hooks: Create hook events
+
+* --osrf-config=[config_file]: OpenSRF core config file. Defaults to:
+/openils/conf/opensrf_core.xml
+
+* --custom-filters=[filter_file]: File containing a JSON Object which describes any hooks
+that should use a user-defined filter to find their target objects. Defaults to:
+/openils/conf/action_trigger_filters.json
+
+* --max-sleep=[seconds]: When in process-hooks mode, wait up to [seconds] for the lock file to go
+away. Defaults to 3600 (1 hour).
+
+* --hooks=hook1[,hook2,hook3,...]: Define which hooks to create events for. If none are defined, it
+defaults to the list of hooks defined in the --custom-filters option.
+Requires --process-hooks.
+
+* --granularity=[label]: Limit creating events and running pending events to
+those only with [label] granularity setting.
+
+* --debug-stdout: Print server responses to STDOUT (as JSON) for debugging.
+
+* --lock-file=[file_name]: Sets the lock file for the process.
+
+* --verbose: Show details of script processing.
+
+* --help: Show help information.
+
+Examples:
+
+* Run all pending events that have no granularity set. This is what you tell
+CRON to run at regular intervals.
++
+----
+perl action_trigger_runner.pl --run-pending
+----
+
+* Batch create all "checkout.due" events
++
+----
+perl action_trigger_runner.pl --hooks=checkout.due --process-hooks
+----
+
+* Batch create all events for a specific granularity and to send notices for all
+pending events with that same granularity.
++
+----
+perl action_trigger_runner.pl --run-pending --granularity=Hourly --process-hooks
+----
--- /dev/null
+*Administration*
+
+Commandline Adminitstrator!
+
+The Evergreen database already contains information from the Library of Congress\92s MARC 21 format standards that includes possible values for select fixed fields. Users may also add values to these and other fixed fields through the MARC Coded Value Maps interface. Once new values are added, the right-click context menu for the selected fixed field will display those values in the MARC Editor for any Record Type that utilizes that fixed field.
+There are three relevant tables that contain the values that display in the fixed field context menu options:
+
+. *config.marc21_ff_pos_map* describes, for the given record type, where a fixed field is located, its start position, and its length.
+. *config.coded_value_map* defines the set of valid values for many of the fixed fields and the translatable, human-friendly labels for them.
+. *config.record_attr_definition* links together the information from the config.marc21_ff_pos_map and config.coded_value_map tables.
--- /dev/null
+*Administration*
+keep it for command line administrator!
+
+The information driving the MARC 007 Field Physical Characteristics Wizard is already a part of the Evergreen database. This data can be customized by individual sites and / or updated when the Library of Congress dictates new values or positions in the 007 field.
+There are three relevant tables where the information that drives the wizard is stored:
+
+. *config.marc21_physical_characteristic_type_map* contains the list of materials, or values, for the positions of the 007 field.
+. *config.marc21_physical_characteristic_subfield_map* contains rows that list the meaning of the various positions in the 007 field for each Category of Material.
+. *config.marc21_physical_characteristic_value_map* lists all of the values possible for all of the positions in the config.marc21_physical_characteristic_subfield_map table.
+
--- /dev/null
+Apache Access Handler Perl Module
+---------------------------------
+The OpenILS::WWW::AccessHandler Perl module is intended for limiting patron
+access to configured locations in Apache. These locations could be folder
+trees, static files, non-Evergreen dynamic content, or other Apache
+features/modules. It is intended as a more patron-oriented and transparent
+version of the OpenILS::WWW::Proxy and OpenILS::WWW:Proxy::Authen modules.
+
+Instead of using Basic Authentication the AccessHandler module instead redirects
+to the OPAC for login. Once logged in additional checks can be performed, based
+on configured variables:
+
+ * Permission Checks (at Home OU or specified location)
+ * Home OU Checks (Org Unit or Descendant)
+ * "Good standing" Checks (Not Inactive or Barred)
+
+Use of the module is a simple addition to a Location block in Apache:
+
+[source,conf]
+----
+<Location /path/to/be/protected>
+ PerlAccessHandler OpenILS::WWW::AccessHandler
+ # For each option you wish to set:
+ PerlSetVar OPTION "VALUE"
+</Location>
+----
+
+The available options are:
+
+OILSAccessHandlerLoginURL::
+ Default: /eg/opac/login +
+ The page to redirect to when Login is needed
+OILSAccessHandlerLoginURLRedirectVar::
+ Default: redirect_to +
+ The variable the login page wants the "destination" URL stored in
+OILSAccessHandlerFailURL::
+ Default: <unset> +
+ URL to go to if Permission, Good Standing, or Home OU checks fail. If not set
+ a 403 error is generated instead. To customize the 403 you could use an
+ ErrorDocument statement.
+OILSAccessHandlerCheckOU::
+ Default: <User Home OU> +
+ Org Unit to check Permissions at and/or to load Referrer from. Can be a
+ shortname or an ID.
+OILSAccessHandlerPermission::
+ Default: <unset> +
+ Permission, or comma- or space-delimited set of permissions, the user must have to
+ access the protected area.
+OILSAccessHandlerGoodStanding::
+ Default: 0 +
+ If set to a true value the user must be both Active and not Barred.
+OILSAccessHandlerHomeOU::
+ Default: <unset> +
+ An Org Unit, or comma- or space-delimited set of Org Units, that the user's Home OU must
+ be equal to or a descendant of to access this resource. Can be set to
+ shortnames or IDs.
+OILSAccessHandlerReferrerSetting::
+ Default: <unset> +
+ Library Setting to pull a forced referrer string out of, if set.
+
+As the AccessHandler module does not actually serve the content it is
+protecting, but instead merely hands control back to Apache when it is done
+authenticating, you can protect almost anything else you can serve with Apache.
+
+Use Cases
+~~~~~~~~~
+The general use of this module is "protect access to something else" - what that
+something else is will vary. Some possibilities:
+
+ * Apache features
+ ** Automatic Directory Indexes
+ ** Proxies (see below)
+ *** Electronic Databases
+ *** Software on other servers/ports
+ * Non-Evergreen software
+ ** Timekeeping software for staff
+ ** Specialized patron request packages
+ * Static files and folders
+ ** Semi-public Patron resources
+ ** Staff-only downloads
+
+Proxying Websites
+~~~~~~~~~~~~~~~~~
+One potentially interesting use of the AccessHandler module is to protect an
+Apache Proxy configuration. For example, after installing and enabling
+mod_proxy, mod_proxy_http, and mod_proxy_html you could proxy websites like so:
+
+[source,conf]
+----
+<Location /proxy/>
+ # Base "Rewrite URLs" configuration
+ ProxyHTMLLinks a href
+ ProxyHTMLLinks area href
+ ProxyHTMLLinks link href
+ ProxyHTMLLinks img src longdesc usemap
+ ProxyHTMLLinks object classid codebase data usemap
+ ProxyHTMLLinks q cite
+ ProxyHTMLLinks blockquote cite
+ ProxyHTMLLinks ins cite
+ ProxyHTMLLinks del cite
+ ProxyHTMLLinks form action
+ ProxyHTMLLinks input src usemap
+ ProxyHTMLLinks head profile
+ ProxyHTMLLinks base href
+ ProxyHTMLLinks script src for
+
+ # To support scripting events (with ProxyHTMLExtended On)
+ ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \
+ onmouseover onmousemove onmouseout onkeypress \
+ onkeydown onkeyup onfocus onblur onload \
+ onunload onsubmit onreset onselect onchange
+
+ # Limit all Proxy connections to authenticated sessions by default
+ PerlAccessHandler OpenILS::WWW::AccessHandler
+
+ # Strip out Evergreen cookies before sending to remote server
+ RequestHeader edit Cookie "^(.*?)ses=.*?(?:$|;)(.*)$" $1$2
+ RequestHeader edit Cookie "^(.*?)eg_loggedin=.*?(?:$|;)(.*)$" $1$2
+</Location>
+
+<Location /proxy/example/>
+ # Proxy example.net
+ ProxyPass http://www.example.net/
+ ProxyPassReverse http://www.example.net/
+ ProxyPassReverseCookieDomain example.net example.com
+ ProxyPassReverseCookiePath / /proxy/example/
+
+ ProxyHTMLEnable On
+ ProxyHTMLURLMap http://www.example.net/ /proxy/example/
+ ProxyHTMLURLMap / /proxy/mail/
+ ProxyHTMLCharsetOut *
+
+ # Limit to BR1 and BR3 users
+ PerlSetVar OILSAccessHandlerHomeOU "BR1,BR3"
+</Location>
+----
+
+As mentioned above, this can be used for multiple reasons. In addition to
+websites such as online databases for patron use you may wish to proxy software
+for staff or patron use to make it appear on your catalog domain, or perhaps to
+keep from needing to open extra ports in a firewall.
--- /dev/null
+Apache Rewrite Tricks
+---------------------
+It is possible to use Apache's Rewrite Module features to perform a number of
+useful tricks that can make people's lives much easier.
+
+Short URLs
+~~~~~~~~~~
+Making short URLs for common destinations can simplify making printed media as
+well as shortening or simplifying what people need to type. These are also easy
+to add and require minimal maintenance, and generally can be implemented with a
+single line addition to your eg_vhost.conf file.
+
+[source,conf]
+----
+# My Account - http://host.ext/myaccount -> My Account Page
+RewriteRule ^/myaccount https://%{HTTP_HOST}/eg/opac/myopac/main [R]
+
+# ISBN Search - http://host.ext/search/isbn/<ISBN NUMBER> -> Search Page
+RewriteRule ^/search/isbn/(.*) /eg/opac/results?_special=1&qtype=identifier|isbn&query=$1 [R]
+----
+
+Domain Based Content with RewriteMaps
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+One creative use of Rewrite features is domain-based configuration in a single
+eg_vhost.conf file. Regardless of how many VirtualHost blocks use the
+configuration you don't need to duplicate things for minor changes, and can in
+fact use wildcard VirtualHost blocks to serve multiple subdomains.
+
+For the wildcard blocks you will want to use a ServerAlias directive, and for
+SSL VirtualHost blocks ensure you have a wildcard SSL certificate.
+
+[source,conf]
+----
+ServerAlias *.example.com
+----
+
+For actually changing things based on the domain, or subdomain, you can use
+RewriteMaps. Each RewriteMap is generally a lookup table of some kind. In the
+following examples we will generally use text files, though database lookups
+and external programs are also possible.
+
+Note that in the examples below we generally store things in Environment
+Variables. From within Template Toolkit templates you can access environment
+variables with the ENV object.
+
+.Template Toolkit ENV example, link library name/url if set
+[source,html]
+----
+[% IF ENV.eglibname && ENV.egliburl %]<a href="[% ENV.egliburl %]">[% ENV.eglibname %]</a>[% END %]
+----
+
+The first lookup to do is a domain to identifier, allowing us to re-use
+identifiers for multiple domains. In addition we can also supply a default
+identifier, for when the domain isn't present in the lookup table.
+
+.Apache Config
+[source,conf]
+----
+# This internal map allows us to lowercase our hostname, removing case issues in our lookup table
+# If you prefer uppercase you can use "uppercase int:toupper" instead.
+RewriteMap lowercase int:tolower
+# This provides a hostname lookup
+RewriteMap eglibid txt:/openils/conf/libid.txt
+# This stores the identifier in a variable (eglibid) for later use
+# In this case CONS is the default value for when the lookup table has no entry
+RewriteRule . - [E=eglibid:${eglibid:${lowercase:%{HTTP_HOST}}|CONS}]
+----
+
+.Contents of libid.txt File
+[source,txt]
+----
+# Comments can be included
+# Multiple TLDs for Branch 1
+branch1.example.com BRANCH1
+branch1.example.net BRANCH1
+# Branches 2 and 3 don't have alternate TLDs
+branch2.example.com BRANCH2
+branch3.example.com BRANCH3
+----
+
+Once we have identifiers we can look up other information, when appropriate.
+For example, say we want to look up library names and URLs:
+
+.Apache Config
+[source,conf]
+----
+# Library Name Lookup - Note we provide no default in this case.
+RewriteMap eglibname txt:/openils/conf/libname.txt
+RewriteRule . - [E=eglibname:${eglibname:%{ENV:eglibid}}]
+# Library URL Lookup - Also with no default.
+RewriteMap egliburl txt:/openils/conf/liburl.txt
+RewriteRule . - [E=egliburl:${egliburl:%{ENV:eglibid}}]
+----
+
+.Contents of libname.txt File
+[source,txt]
+----
+# Note that we cannot have spaces in the "value", so instead   is used. is also an option.
+BRANCH1 Branch One
+BRANCH2 Branch Two
+BRANCH3 Branch Three
+CONS Example Consortium Name
+----
+
+.Contents of liburl.txt File
+[source,txt]
+----
+BRANCH1 http://branch1.example.org
+BRANCH2 http://branch2.example.org
+BRANCH3 http://branch3.example.org
+CONS http://example.org
+----
+
+Or, perhaps set the "physical location" variable for default search/display library:
+
+.Apache Config
+[source,conf]
+----
+# Lookup "physical location" IDs
+RewriteMap eglibphysloc txt:/openils/conf/libphysloc.txt
+# Note: physical_loc is a variable used in the TTOPAC and should not be re-named
+RewriteRule . - [E=physical_loc:${eglibphysloc:%{ENV:eglibid}}]
+----
+
+.Contents of libphysloc.txt File
+[source,txt]
+----
+BRANCH1 4
+BRANCH2 5
+BRANCH3 6
+CONS 1
+----
+
+Going further, you could also replace files to be downloaded, such as images or
+stylesheets, on the fly:
+
+.Apache Config
+[source,conf]
+----
+# Check if a file exists based on eglibid and the requested file name
+# Say, BRANCH1/opac/images/main_logo.png
+RewriteCond %{DOCUMENT_ROOT}/%{ENV:eglibid}%{REQUEST_URI} -f
+# Serve up the eglibid version of the file instead
+RewriteRule (.*) /%{ENG:eglibid}$1
+----
+
+Note that template files themselves cannot be replaced in that manner.
+
--- /dev/null
+Authentication Proxy
+--------------------
+
+indexterm:[authentication, proxy]
+
+indexterm:[authentication, LDAP]
+
+To support integration of Evergreen with organizational authentication systems, and to reduce the proliferation of user names and passwords, Evergreen offers a service called open-ils.auth_proxy. If you enable the service, open-ils.auth_proxy supports different authentication mechanisms that implement the authenticate method. You can define a chain of these authentication mechanisms to be tried in order within the *_<authenticators>_* element of the _opensrf.xml_ configuration file, with the option of falling back to the native mode that uses Evergreen’s internal method of password authentication.
+
+This service only provides authentication. There is no support for automatic provisioning of accounts. To authenticate using any authentication system, the user account must first be defined in the Evergreen database. The user will be authenticated based on the Evergreen username and must match the user's ID on the authentication system.
+
+In order to activate Authentication Proxy, the Evergreen system administrator will need to complete the following steps:
+
+. Edit *_opensrf.xml_*.
+.. Set the *_open-ils.auth_proxy_* app settings *_enabled_* tag to *_true_*
+.. Add the *_authenticator_* to the list of authenticators or edit the existing example authenticator:
++
+[source,xml]
+----
+
+<authenticator>
+ <name>ldap</name>
+ <module>OpenILS::Application::AuthProxy::LDAP_Auth</module>
+ <hostname>name.domain.com</hostname>
+ <basedn>ou=people,dc=domain,dc=com</basedn>
+ <authid>cn=username,ou=specials,dc=domain,dc=com</authid>
+ <id_attr>uid</id_attr>
+ <password>my_ldap_password_for_authid_user</password>
+ <login_types>
+ <type>staff</type>
+ <type>opac</type>
+ </login_types>
+ <org_units>
+ <unit>103</unit>
+ <unit>104</unit>
+ </org_units>
+</authenticator>
+----
++
+* *_name_* : Used to identify each authenticator.
+* *_module_* : References to the perl module used by Evergreen to process the request.
+* *_hostname_* : Hostname of the authentication server.
+* *_basedn_* : Location of the data on your authentication server used to authenticate users.
+* *_authid_* : Administrator ID information used to connect to the Authentication server.
+* *_id_attr_* : Field name in the authenticator matching the username in the Evergreen database.
+* *_password_* : Administrator password used to connect to the authentication server. Password for the *_authid_*.
+* *_login_types_* : Specifies which types of logins will use this authenticator. This might be useful if staff use a different LDAP directory than general users.
+* *_org_units_* : Specifies which org units will use the authenticator. This is useful in a consortium environment where libraries will use separate authentication systems.
++
+. Restart Evergreen and Apache to activate configuration changes.
+
+[TIP]
+====================================================================
+If using proxy authentication with library employees that will use the _Admin > Change Operator: New_ feature in the client software, then add "temp" as a *_login_types_*.
+====================================================================
--- /dev/null
+Describing your people
+======================
+
+Many different members of your staff will use your Evergreen system to perform
+the wide variety of tasks required of the library.
+
+When the Evergreen installation was completed, a number of permission groups
+should have been automatically created. These permission groups are:
+
+* Users
+* Patrons
+* Staff
+* Catalogers
+* Circulators
+* Acquisitions
+* Acquisitions Administrator
+* Cataloging Administrator
+* Circulation Administrator
+* Local Administrator
+* Serials
+* System Administrator
+* Global Administrator
+* Data Review
+* Volunteers
+
+Each of these permission groups has a different set of permissions connected to
+them that allow them to do different things with the Evergreen system. Some of
+the permissions are the same between groups; some are different. These
+permissions are typically tied to one or more working location (sometimes
+referred to as a working organizational unit or work OU) which affects where a
+particular user can exercise the permissions they have been granted.
+
+Setting the staff user's working location
+-----------------------------------------
+To grant a working location to a staff user in the staff client:
+
+. Search for the patron. Select *Search > Search for Patrons* from the top menu.
+. When you retrieve the correct patron record, select *Other > User Permission
+ Editor* from the upper right corner. The permissions associated with this
+ account appear in the right side of the client, with the *Working Location*
+ list at the top of the screen.
+. The *Working Location* list displays the Organizational Units in your
+ consortium. Select the check box for each Organization Unit where this user
+ needs working permissions. Clear any other check boxes for Organization Units
+ where the user no longer requires working permissions.
+. Scroll all the way to the bottom of the page and click *Save*. This user
+ account is now ready to be used at your library.
+
+As you scroll down the page you will come to the *Permissions* list. These are
+the permissions that are given through the *Permission Group* that you assigned
+to this user. Depending on your own permissions, you may also have the ability
+to grant individual permissions directly to this user.
+
+Comparing approaches for managing permissions
+---------------------------------------------
+The Evergreen community uses two different approaches to deal with managing
+permissions for users:
+
+* *Staff Client*
++
+Evergreen libraries that are most comfortable using the staff client tend to
+manage permissions by creating different profiles for each type of user. When
+you create a new user, the profile you assign to the user determines their
+basic set of permissions. This approach requires many permission groups that
+contain overlapping sets of permissions: for example, you might need to create
+a _Student Circulator_ group and a _Student Cataloger_ group. Then if a new
+employee needs to perform both of these roles, you need to create a third
+_Student Cataloger / Circulator_ group representing the set of all of the
+permissions of the first two groups.
++
+The advantage to this approach is that you can maintain the permissions
+entirely within the staff client; a drawback to this approach is that it can be
+challenging to remember to add a new permission to all of the groups. Another
+drawback of this approach is that the user profile is also used to determine
+circulation and hold rules, so the complexity of your circulation and hold
+rules might increase significantly.
++
+* *Database Access*
++
+Evergreen libraries that are comfortable manipulating the database directly
+tend to manage permissions by creating permission groups that reflect discrete
+roles within a library. At the database level, you can make a user belong to
+many different permission groups, and that can simplify your permission
+management efforts. For example, if you create a _Student Circulator_ group and
+a _Student Cataloger_ group, and a new employee needs to perform both of these
+roles, you can simply assign them to both of the groups; you do not need to
+create an entirely new permission group in this case. An advantage of this
+approach is that the user profile can represent only the user's borrowing
+category and requires only the basic _Patrons_ permissions, which can simplify
+your circulation and hold rules.
+
+Permissions and profiles are not carved in stone. As the system administrator,
+you can change them as needed. You may set and alter the permissions for each
+permission group in line with what your library, or possibly your consortium,
+defines as the appropriate needs for each function in the library.
+
+Managing permissions in the staff client
+----------------------------------------
+In this section, we'll show you in the staff client:
+
+* where to find the available permissions
+* where to find the existing permission groups
+* how to see the permissions associated with each group
+* how to add or remove permissions from a group
+
+We also provide an appendix with a listing of suggested minimum permissions for
+some essential groups. You can compare the existing permissions with these
+suggested permissions and, if any are missing, you will know how to add them.
+
+Where to find existing permissions and what they mean
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In the staff client, in the upper right corner of the screen, click on *Admin >
+Server Administration > Permissions*.
+
+The list of available permissions will appear on screen and you can scroll down
+through them to see permissions that are already available in your default
+installation of Evergreen.
+
+There are over 500 permissions in the permission list. They appear in two
+columns: *Code* and *Description*. Code is the name of the permission as it
+appear in the Evergreen database. Description is a brief note on what the
+permission allows. All of the most common permissions have easily
+understandable descriptions.
+
+Where to find existing Permission Groups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In the staff client, in the upper right corner of the screen, navigate to *Admin
+> Server Administration > Permission Groups*.
+
+Two panes will open on your screen. The left pane provides a tree view of
+existing Permission Groups. The right pane contains two tabs: Group
+Configuration and Group Permissions.
+
+In the left pane, you will find a listing of the existing Permission Groups
+which were installed by default. Click on the + sign next to any folder to
+expand the tree and see the groups underneath it. You should see the Permission
+Groups that were listed at the beginning of this chapter. If you do not and you
+need them, you will have to create them.
+
+Adding or removing permissions from a Permission Group
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+First, we will remove a permission from the Staff group.
+
+. From the list of Permission Groups, click on *Staff*.
+. In the right pane, click on the *Group Permissions* tab. You will now see a
+ list of permissions that this group has.
+. From the list, choose *CREATE_CONTAINER*. This will now be highlighted.
+. Click the *Delete Selected* button. CREATE_CONTAINER will be deleted from the
+ list. The system will not ask for a confirmation. If you delete something by
+ accident, you will have to add it back.
+. Click the *Save Changes* button.
+
+You can select a group of individual items by holding down the _Ctrl_ key and
+clicking on them. You can select a list of items by clicking on the first item,
+holding down the _Shift_ key, and clicking on the last item in the list that
+you want to select.
+
+Now, we will add the permission we just removed back to the Staff group.
+
+. From the list of Permission Groups, click on *Staff*.
+. In the right pane, click on the *Group Permissions* tab.
+. Click on the *New Mapping* button. The permission mapping dialog box will
+ appear.
+. From the Permission drop down list, choose *CREATE_CONTAINER*.
+. From the Depth drop down list, choose *Consortium*.
+. Click the checkbox for *Grantable*.
+. Click the *Add Mapping* button. The new permission will now appear in the
+ Group Permissions window.
+. Click the *Save Changes* button.
+
+If you have saved your changes and you don't see them, you may have to click
+the Reload button in the upper left side of the staff client screen.
+
+Managing role-based permission groups in the staff client
+---------------------------------------------------------
+
+Main permission groups are granted in the staff client through Edit in the patron record using the Main (Profile) Permission Group field. Additional permission
+groups can be granted using secondary permission groups.
+
+[[secondaryperms]]
+Secondary Group Permissions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The _Secondary Groups_ button functionality enables supplemental permission
+groups to be added to staff accounts. The *CREATE_USER_GROUP_LINK* and
+*REMOVE_USER_GROUP_LINK* permissions are required to display and use this
+feature.
+
+In general when creating a secondary permission group do not grant the
+permission to login to Evergreen.
+
+Granting Secondary Permissions Groups
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+. Open the account of the user you wish to grant secondary permission group to.
+. Click _Edit_.
+. Click _Secondary Groups_, located to the right of the _Main (Profile) Permission Group_.
++
+image::media/sup-permissions-1.png[Secondary Permissions Group]
++
+. From the dropdown menu select one of the secondary permission groups.
++
+image::media/sup-permissions-2.png[Secondary Permission Group List]
++
+. Click _Add_.
+. Click _Save_.
++
+image::media/sup-permissions-3.png[Secondary Permission Group Save]
++
+. Click _Save_ in the top right hand corner of the _Edit Screen_ to save the user's account.
+
+
+Removing Secondary Group Permissions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+. Open the account of the user you wish to remove the secondary permission group from.
+. Click _Edit_.
+. Click _Secondary Groups_, located to the right of the _Main (Profile) Permission Group_.
++
+image::media/sup-permissions-1.png[Secondary Permissions Group]
++
+. Click _Delete_ beside the permission group you would like to remove.
++
+image::media/sup-permissions-4.png[Secondary Permissions Group Delete]
++
+. Click _Save_.
++
+image::media/sup-permissions-5.png[Secondary Permissions Group Save]
++
+. Click _Save_ in the top right hand corner of the _Edit Screen_ to save the user's account.
+
+Managing role-based permission groups in the database
+-----------------------------------------------------
+While the ability to assign a user to multiple permission groups has existed in
+Evergreen for years, a staff client interface is not currently available to
+facilitate the work of the Evergreen administrator. However, if you or members
+of your team are comfortable working directly with the Evergreen database, you
+can use this approach to separate the borrowing profile of your users from the
+permissions that you grant to staff, while minimizing the amount of overlapping
+permissions that you need to manage for a set of permission groups that would
+otherwise multiply exponentially to represent all possible combinations of
+staff roles.
+
+In the following example, we create three new groups:
+
+* a _Student_ group used to determine borrowing privileges
+* a _Student Cataloger_ group representing a limited set of cataloging
+ permissions appropriate for students
+* a _Student Circulator_ group representing a limited set of circulation
+ permissions appropriate for students
+
+Then we add three new users to our system: one who needs to perform some
+cataloging duties as a student; one who needs perform some circulation duties
+as a student; and one who needs to perform both cataloging and circulation
+duties. This section demonstrates how to add these permissions to the users at
+the database level.
+
+To create the Student group, add a new row to the _permission.grp_tree_ table
+as a child of the _Patrons_ group:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO permission.grp_tree (name, parent, usergroup, description, application_perm)
+SELECT 'Students', pgt.id, TRUE, 'Student borrowers', 'group_application.user.patron.student'
+FROM permission.grp_tree pgt
+ WHERE name = 'Patrons';
+------------------------------------------------------------------------------
+
+To create the Student Cataloger group, add a new row to the
+_permission.grp_tree_ table as a child of the _Staff_ group:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO permission.grp_tree (name, parent, usergroup, description, application_perm)
+SELECT 'Student Catalogers', pgt.id, TRUE, 'Student catalogers', 'group_application.user.staff.student_cataloger'
+FROM permission.grp_tree pgt
+WHERE name = 'Staff';
+------------------------------------------------------------------------------
+
+To create the Student Circulator group, add a new row to the
+_permission.grp_tree_ table as a child of the _Staff_ group:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO permission.grp_tree (name, parent, usergroup, description, application_perm)
+SELECT 'Student Circulators', pgt.id, TRUE, 'Student circulators', 'group_application.user.staff.student_circulator'
+FROM permission.grp_tree pgt
+WHERE name = 'Staff';
+------------------------------------------------------------------------------
+
+We want to give the Student Catalogers group the ability to work with MARC
+records at the consortial level, so we assign the UPDATE_MARC, CREATE_MARC, and
+IMPORT_MARC permissions at depth 0:
+
+[source,sql]
+------------------------------------------------------------------------------
+WITH pgt AS (
+ SELECT id
+ FROM permission.grp_tree
+ WHERE name = 'Student Catalogers'
+)
+INSERT INTO permission.grp_perm_map (grp, perm, depth)
+SELECT pgt.id, ppl.id, 0
+FROM permission.perm_list ppl, pgt
+WHERE ppl.code IN ('UPDATE_MARC', 'CREATE_MARC', 'IMPORT_MARC');
+------------------------------------------------------------------------------
+
+Similarly, we want to give the Student Circulators group the ability to check
+out copies and record in-house uses at the system level, so we assign the
+COPY_CHECKOUT and CREATE_IN_HOUSE_USE permissions at depth 1 (overriding the
+same _Staff_ permissions that were granted only at depth 2):
+
+[source,sql]
+------------------------------------------------------------------------------
+WITH pgt AS (
+ SELECT id
+ FROM permission.grp_tree
+ WHERE name = 'Student Circulators'
+) INSERT INTO permission.grp_perm_map (grp, perm, depth)
+SELECT pgt.id, ppl.id, 1
+FROM permission.perm_list ppl, pgt
+WHERE ppl.code IN ('COPY_CHECKOUT', 'CREATE_IN_HOUSE_USE');
+------------------------------------------------------------------------------
+
+Finally, we want to add our students to the groups. The request may arrive in
+your inbox from the library along the lines of "Please add Mint Julep as a
+Student Cataloger, Bloody Caesar as a Student Circulator, and Grass Hopper as a
+Student Cataloguer / Circulator; I've already created their accounts and given
+them a work organizational unit." You can translate that into the following SQL
+to add the users to the pertinent permission groups, adjusting for the
+inevitable typos in the names of the users.
+
+First, add our Student Cataloger:
+
+[source,sql]
+------------------------------------------------------------------------------
+WITH pgt AS (
+ SELECT id FROM permission.grp_tree
+ WHERE name = 'Student Catalogers'
+)
+INSERT INTO permission.usr_grp_map (usr, grp)
+SELECT au.id, pgt.id
+FROM actor.usr au, pgt
+WHERE first_given_name = 'Mint' AND family_name = 'Julep';
+------------------------------------------------------------------------------
+
+Next, add the Student Circulator:
+
+[source,sql]
+------------------------------------------------------------------------------
+WITH pgt AS (
+ SELECT id FROM permission.grp_tree
+ WHERE name = 'Student Circulators'
+)
+INSERT INTO permission.usr_grp_map (usr, grp)
+SELECT au.id, pgt.id
+FROM actor.usr au, pgt
+WHERE first_given_name = 'Bloody' AND family_name = 'Caesar';
+------------------------------------------------------------------------------
+
+Finally, add the all-powerful Student Cataloger / Student Circulator:
+
+[source,sql]
+------------------------------------------------------------------------------
+ WITH pgt AS (
+ SELECT id FROM permission.grp_tree
+ WHERE name IN ('Student Catalogers', 'Student Circulators')
+)
+INSERT INTO permission.usr_grp_map (usr, grp)
+SELECT au.id, pgt.id
+FROM actor.usr au, pgt
+WHERE first_given_name = 'Grass' AND family_name = 'Hopper';
+------------------------------------------------------------------------------
+
+While adopting this role-based approach might seem labour-intensive when
+applied to a handful of students in this example, over time it can help keep
+the permission profiles of your system relatively simple in comparison to the
+alternative approach of rapidly reproducing permission groups, overlapping
+permissions, and permissions granted on a one-by-one basis to individual users.
--- /dev/null
+Designing your catalog
+======================
+
+When people want to find things in your Evergreen system, they will check the
+catalog. In Evergreen, the catalog is made available through a web interface,
+called the _OPAC_ (Online Public Access Catalog). In the latest versions of the
+Evergreen system, the OPAC is built on a set of programming modules called the
+Template Toolkit. You will see the OPAC sometimes referred to as the _TPAC_.
+
+In this chapter, we'll show you how to customize the OPAC, change it from its
+default configuration, and make it your own.
+
+Configuring and customizing the public interface
+------------------------------------------------
+
+The public interface is referred to as the TPAC or Template Toolkit (TT) within
+the Evergreen community. The template toolkit system allows you to customize the
+look and feel of your OPAC by editing the template pages (.tt2) files as well as
+the associated style sheets.
+
+Locating the default template files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The default URL for the TPAC on a default Evergreen system is
+_http://localhost/eg/opac/home_ (adjust _localhost_ to match your hostname or IP
+address).
+
+The default template file is installed in _/openils/var/templates/opac_.
+
+You should generally avoid touching the installed default template files, unless
+you are contributing changes for Evergreen to adopt as a new default. Even then,
+while you are developing your changes, consider using template overrides rather
+than touching the installed templates until you are ready to commit the changes
+to a branch. See below for information on template overrides.
+
+Mapping templates to URLs
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The mapping for templates to URLs is straightforward. Following are a few
+examples, where _<templates>_ is a placeholder for one or more directories that
+will be searched for a match:
+
+* _http://localhost/eg/opac/home => /openils/var/<templates>/opac/home.tt2_
+* _http://localhost/eg/opac/advanced =>
+/openils/var/<templates>/opac/advanced.tt2_
+* _http://localhost/eg/opac/results =>
+/openils/var/<templates>/opac/results.tt2_
+
+The template files themselves can process, be wrapped by, or include other
+template files. For example, the _home.tt2_ template currently involves a number
+of other template files to generate a single HTML file.
+
+Example Template Toolkit file: _opac/home.tt2_.
+----
+[% PROCESS "opac/parts/header.tt2";
+ WRAPPER "opac/parts/base.tt2";
+ INCLUDE "opac/parts/topnav.tt2";
+ ctx.page_title = l("Home") %]
+ <div id="search-wrapper">
+ [% INCLUDE "opac/parts/searchbar.tt2" %]
+ </div>
+ <div id="content-wrapper">
+ <div id="main-content-home">
+ <div class="common-full-pad"></div>
+ [% INCLUDE "opac/parts/homesearch.tt2" %]
+ <div class="common-full-pad"></div>
+ </div>
+ </div>
+[% END %]
+----
+Note that file references are relative to the top of the template directory.
+
+How to override template files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Overrides for template files or TPAC pages go in a directory that parallels the
+structure of the default templates directory. The overrides then get pulled in
+via the Apache configuration.
+
+The following example demonstrates how to create a file that overrides the
+default "Advanced search page" (_advanced.tt2_) by adding a new
+_templates_custom_ directory and editing the new file in that directory.
+
+----
+bash$ mkdir -p /openils/var/templates_custom/opac
+bash$ cp /openils/var/templates/opac/advanced.tt2 \
+ /openils/var/templates_custom/opac/.
+bash$ vim /openils/var/templates_custom/opac/advanced.tt2
+----
+
+Configuring the custom templates directory in Apache's eg.conf
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You now need to teach Apache about the new custom template directory. Edit
+_/etc/apache2/sites-available/eg.conf_ and add the following _<Location /eg>_
+element to each of the _<VirtualHost>_ elements in which you want to include the
+overrides. The default Evergreen configuration includes a VirtualHost directive
+for port 80 (HTTP) and another one for port 443 (HTTPS); you probably want to
+edit both, unless you want the HTTP user experience to be different from the
+HTTPS user experience.
+
+----
+<VirtualHost *:80>
+ # <snip>
+
+ # - absorb the shared virtual host settings
+ Include eg_vhost.conf
+ <Location /eg>
+ PerlAddVar OILSWebTemplatePath "/openils/var/templates_custom"
+ </Location>
+
+ # <snip>
+</VirtualHost>
+----
+
+Finally, reload the Apache configuration to pick up the changes. You should now
+be able to see your change at _http://localhost/eg/opac/advanced_ where
+_localhost_ is the hostname of your Evergreen server.
+
+Adjusting colors for your public interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You may adjust the colors of your public interface by editing the _colors.tt2_
+file. The location of this file is in
+_/openils/var/templates/opac/parts/css/colors.tt2_. When you customize the
+colors of your public interface, remember to create a custom file in your custom
+template folder and edit the custom file and not the file located in you default
+template.
+
+Adjusting fonts in your public interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Font sizes can be changed in the _colors.tt2_ file located in
+_/openils/var/templates/opac/parts/css/_. Again, create and edit a custom
+template version and not the file in the default template.
+
+Other aspects of fonts such as the default font family can be adjusted in
+_/openils/var/templates/opac/css/style.css.tt2_.
+
+Media file locations in the public interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The media files (mostly PNG images) used by the default TPAC templates are stored
+in the repository in _Open-ILS/web/images/_ and installed in
+_/openils/var/web/images/_.
+
+Changing some text in the public interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Out of the box, TPAC includes a number of placeholder text and links. For
+example, there is a set of links cleverly named Link 1, Link 2, and so on in the
+header and footer of every page in TPAC. Here is how to customize that for a
+_custom templates_ skin.
+
+To begin with, find the page(s) that contain the text in question. The simplest
+way to do that is with the grep -s command. In the following example, search for
+files that contain the text "Link 1":
+
+----
+bash$ grep -r "Link 1" /openils/var/templates/opac
+/openils/var/templates/opac/parts/topnav_links.tt2
+4: <a href="http://example.com">[% l('Link 1') %]</a>
+----
+
+
+Next, copy the file into our overrides directory and edit it with vim.
+
+Copying the links file into the overrides directory.
+
+----
+bash$ cp /openils/var/templates/opac/parts/topnav_links.tt2 \
+/openils/var/templates_custom/opac/parts/topnav_links.tt2
+bash$ vim /openils/var/templates_custom/opac/parts/topnav_links.tt2
+----
+
+Finally, edit the link text in _opac/parts/header.tt2_. Content of the
+_opac/parts/header.tt2_ file.
+
+----
+<div id="gold-links-holder">
+ <div id="gold-links">
+ <div id="header-links">
+ <a href="http://example.com">[% l('Link 1') %]</a>
+ <a href="http://example.com">[% l('Link 2') %]</a>
+ <a href="http://example.com">[% l('Link 3') %]</a>
+ <a href="http://example.com">[% l('Link 4') %]</a>
+ <a href="http://example.com">[% l('Link 5') %]</a>
+ </div>
+ </div>
+</div>
+----
+
+For the most part, the page looks like regular HTML, but note the `[%_(" ")%]`
+that surrounds the text of each link. The `[% ... %]` signifies a TT block,
+which can contain one or more TT processing instructions. `l(" ... ");` is a
+function that marks text for localization (translation); a separate process can
+subsequently extract localized text as GNU gettext-formatted PO (Portable
+Object) files.
+
+As Evergreen supports multiple languages, any customization to Evergreen's
+default text must use the localization function. Also, note that the
+localization function supports placeholders such as `[_1]`, `[_2]` in the text;
+these are replaced by the contents of variables passed as extra arguments to the
+`l()` function.
+
+Once the link and link text has been edited to your satisfaction, load the page
+in a Web browser and see the live changes immediately.
+
+Adding and removing MARC fields from the record details display page
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is possible to add and remove the MARC fields and subfields displayed in the
+record details page. In order to add MARC fields to be displayed on the details
+page of a record, you will need to map the MARC code to variables in the
+_/openils/var/templates/opac/parts/misc_util.tt2 file_.
+
+For example, to map the template variable _args.pubdates_ to the date of
+publication MARC field 260, subfield c, add these lines to _misc_util.tt2_:
+
+----
+args.pubdates = [];
+FOR sub IN xml.findnodes('//*[@tag="260"]/*[@code="c"]');
+ args.pubdates.push(sub.textContent);
+END;
+args.pubdate = (args.pubdates.size) ? args.pubdates.0 : ''
+----
+
+You will then need to edit the
+_/openils/var/templates/opac/parts/record/summary.tt2_ file in order to get the
+template variable for the MARC field to display.
+
+For example, to display the date of publication code you created in the
+_misc_util.tt2_ file, add these lines:
+
+----
+[% IF attrs.pubdate; %]
+ <span itemprop="datePublished">[% attrs.pubdate | html; %]</span>
+[% END; %]
+----
+
+You can add any MARC field to your record details page. Moreover, this approach
+can also be used to display MARC fields in other pages, such as your results
+page.
+
+Setting the default physical location for your library environment
+------------------------------------------------------------------
+
+_physical_loc_ is an Apache environment variable that sets the default physical
+location, used for setting search scopes and determining the order in which
+copies should be sorted. This variable is set in
+_/etc/apache2/sites-available/eg.conf_. The following example demonstrates the
+default physical location being set to library ID 104:
+
+----
+SetEnv physical_loc 104
+----
+
+Setting a default language and adding optional languages
+--------------------------------------------------------
+
+_OILSWebLocale_ adds support for a specific language. Add this variable to the
+Virtual Host section in _/etc/apache2/sites-available/eg.conf_.
+
+_OILSWebDefaultLocale_ specifies which locale to display when a user lands on a
+page in TPAC and has not chosen a different locale from the TPAC locale picker.
+The following example shows the _fr_ca_ locale being added to the locale picker
+and being set as the default locale:
+
+----
+PerlAddVar OILSWebLocale "fr_ca"
+PerlAddVar OILSWebLocale "/openils/var/data/locale/opac/fr-CA.po"
+PerlAddVar OILSWebDefaultLocale "fr-CA"
+----
+
+Below is a table of the currently supported languages packaged with Evergreen:
+
+[options="header"]
+|================================================================
+|Language| Code| PO file
+|Czech| cs_cz| /openils/var/data/locale/opac/cs-CZ.po
+|English - Canada| en_ca| /openils/var/data/locale/opac/en-CA.po
+|English - Great Britain| en_gb| /openils/var/data/locale/opac/en-GB.po
+|*English - United States| en_us| not applicable
+|French - Canada| fr_ca| /openils/var/data/locale/opac/fr-CA.po
+|Portuguese - Brazil| pt_br| /openils/var/data/locale/opac/pt_BR.po
+|Russian| ru_ru| /openils/var/data/locale/opac/ru_RU.po
+|=================================================================
+*American English is built into Evergreen so you do not need to set up this
+language and there are no PO files.
+
+Editing the formats select box options in the search interface.
+---------------------------------------------------------------
+
+You may wish to remove, rename or organize the options in the formats select
+box. This can be accomplished from the staff client.
+
+. From the staff client, navigate to *Admin > Server Administration > Marc Coded
+Value Maps*
+. Select _Type_ from the *Record Attribute Type* select box.
+. Double click on the format type you wish to edit.
+
+To change the label for the type, enter a value in the *Search Label* field.
+
+To move the option to a top list separated by a dashed line from the others,
+check the *Is Simple Selector* check box.
+
+To hide the type so that it does not appear in the search interface, uncheck the
+*OPAC Visible* checkbox.
+
+Changes will be immediate.
+
+Adding and removing search fields in advanced search
+-----------------------------------------------------
+
+It is possible to add and remove search fields on the advanced search page by
+editing the _opac/parts/config.tt2_ file in your template directory. Look for
+this section of the file:
+
+----
+search.adv_config = [
+ {adv_label => l("Item Type"), adv_attr => ["mattype", "item_type"]},
+ {adv_label => l("Item Form"), adv_attr => "item_form"},
+ {adv_label => l("Language"), adv_attr => "item_lang"},
+ {adv_label => l("Audience"), adv_attr => ["audience_group", "audience"], adv_break => 1},
+ {adv_label => l("Video Format"), adv_attr => "vr_format"},
+ {adv_label => l("Bib Level"), adv_attr => "bib_level"},
+ {adv_label => l("Literary Form"), adv_attr => "lit_form", adv_break => 1},
+ {adv_label => l("Search Library"), adv_special => "lib_selector"},
+ {adv_label => l("Publication Year"), adv_special => "pub_year"},
+ {adv_label => l("Sort Results"), adv_special => "sort_selector"},
+];
+----
+
+For example, if you delete the line:
+
+----
+{adv_label => l("Language"), adv_attr => "item_lang"},
+----
+
+the language field will no longer appear on your advanced search page. Changes
+will appear immediately after you save your changes.
+
+You can also add fields based on Search Facet Groups that you create in the
+staff client's Local Administration menu. This can be helpful if you want to
+simplify your patrons' experience by presenting them with only certain
+limiters (e.g. the most commonly used languages in your area). To do this,
+
+. Click *Admin -> Local Administration -> Search Facet Groups*.
+. Click *New*.
+. Enter descriptive values into the code and label fields. The owner needs to
+be set to your consortium.
+. Once the Facet Group is created, click on the blue hyperlinked code value.
+. Click the *New* button to create the necessary values for your field.
+. Go to the _opac/parts/config.tt2_ file, and add a line like the following,
+where *Our Library's Field* is the name you'd like to be displayed next to
+your field, and *facet_group_code* is the code you've added using the staff
+client.
++
+----
+ {adv_label => l("Our Library's Field"), adv_filter => "facet_group_code"},
+----
+
+Changing the display of facets and facet groups
+-----------------------------------------------
+
+Facets can be reordered on the search results page by editing the
+_opac/parts/config.tt2_ file in your template directory.
+
+Edit the following section of _config.tt2_, changing the order of the facet
+categories according to your needs:
+
+----
+
+facet.display = [
+ {facet_class => 'author', facet_order => ['personal', 'corporate']},
+ {facet_class => 'subject', facet_order => ['topic']},
+ {facet_class => 'series', facet_order => ['seriestitle']},
+ {facet_class => 'subject', facet_order => ['name', 'geographic']}
+];
+
+----
+
+You may also change the default number of facets appearing under each category
+by editing the _facet.default_display_count_ value in _config.tt2_. The default
+value is 5.
+
+Change Date Format in Patron Account View
+-----------------------------------------
+Libraries with same-day circulations may want their patrons to be able to view
+the due *time* as well as due date when they log in to their OPAC account. To
+accomplish this, go to _opac/myopac/circs.tt2_. Find the line that reads:
+
+----
+[% date.format(due_date, DATE_FORMAT) %]
+----
+
+Replace it with:
+
+----
+[% date.format(due_date, '%D %I:%M %p') %]
+----
+
+
+Including External Content in Your Public Interface
+---------------------------------------------------
+
+The public interface allows you to include external services and content in your
+public interface. These can include book cover images, user reviews, table of
+contents, summaries, author notes, annotations, user suggestions, series
+information among other services. Some of these services are free while others
+require a subscription.
+
+The following are some of the external content services which you can configure
+in Evergreen.
+
+OpenLibrary
+~~~~~~~~~~~
+
+The default install of Evergreen includes OpenLibrary book covers. The settings
+for this are controlled by the <added_content> section of
+_/openils/conf/opensrf.xml_. Here are the key elements of this configuration:
+
+----
+<module>OpenILS::WWW::AddedContent::OpenLibrary</module>
+----
+
+This section calls the OpenLibrary perl module. If you wish to link to a
+different book cover service other than OpenLibrary, you must refer to the
+location of the corresponding Perl module. You will also need to change other
+settings accordingly.
+
+----
+<timeout>1</timeout>
+----
+
+Max number of seconds to wait for an added content request to return data. Data
+not returned within the timeout is considered a failure.
+----
+<retry_timeout>600</retry_timeout>
+----
+
+This setting is the amount of time to wait before we try again.
+
+----
+<max_errors>15</max_errors>
+----
+
+Maximum number of consecutive lookup errors a given process can have before
+added content lookups are disabled for everyone. To adjust the site of the cover
+image on the record details page edit the config.tt2 file and change the value
+of the record.summary.jacket_size. The default value is "medium" and the
+available options are "small", "medium" and "large."
+
+ChiliFresh
+~~~~~~~~~~
+
+ChiliFresh is a subscription-based service which allows book covers, reviews and
+social interaction of patrons to appear in your catalog. To activate ChiliFresh,
+you will need to open the Apache configuration file _/etc/apache2/eg_vhost.conf_
+and edit several lines:
+
+. Uncomment (remove the "#" at the beginning of the line) and add your ChiliFresh
+account number:
+
+----
+#SetEnv OILS_CHILIFRESH_ACCOUNT
+----
+
+. Uncomment this line and add your ChiliFresh Profile:
+
+----
+#SetEnv OILS_CHILIFRESH_PROFILE
+----
+
+Uncomment the line indicating the location of the Evergreen JavaScript for
+ChiliFresh:
+
+----
+#SetEnv OILS_CHILIFRESH_URL http://chilifresh.com/on-site /js/evergreen.js
+----
+
+. Uncomment the line indicating the secure URL for the Evergreen JavaScript :
+
+----
+#SetEnv OILS_CHILIFRESH_HTTPS_URL https://secure.chilifresh.com/on-site/js/evergreen.js
+----
+
+[id="_content_cafe"]
+Content Café
+~~~~~~~~~~~~
+
+Content Café is a subscription-based service that can add jacket images,
+reviews, summaries, tables of contents and book details to your records.
+
+In order to activate Content Café, edit the _/openils/conf/opensrf.xml_ file and
+change the _<module>_ element to point to the ContentCafe Perl Module:
+
+----
+<module>OpenILS::WWW::AddedContent::ContentCafe</module>
+----
+
+To adjust settings for Content Café, edit a couple of fields with the
+_<ContentCafe>_ Section of _/openils/conf/opensrf.xml_.
+
+Edit the _userid_ and _password_ elements to match the user id and password for
+your Content Café account.
+
+Change the _return_behavior_on_no_jacket_image_ to set the behavior of your
+service when an image is not available for an item. By default this value is set
+to T which will result in a small image with the text "No Image Available" in
+place of a book cover. If you set this value to 1 a 1X1 blank image will be in
+place of a book cover.
+
+Obalkyknih.cz
+~~~~~~~~~~~~~
+
+Setting up Obalkyknih.cz account
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If your library wishes to use added content provided by Obalkyknih.cz, a service based in the Czech Republic, you have to http://obalkyknih.cz/signup[create an Obalkyknih.cz account].
+Please note that the interface is only available in Czech. After logging in your Obalkyknih.cz account, you have to add your IP address and Evergreen server address to your account settings.
+(In case each library uses an address of its own, all of these addresses have to be added.)
+
+Enabling Obalkyknih.cz in Evergreen
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Set obalkyknih_cz.enabled to true in '/openils/var/templates/opac/parts/config.tt2':
+
+[source,perl]
+----
+obalkyknih_cz.enabled = 'true';
+----
+
+Enable added content from Obalkyknih.cz in '/openils/conf/opensrf.xml' configuration file (and – at the same time – disable added content from Open Library, i.e., Evergreen's default added content provider):
+
+[source,xml]
+----
+<!-- <module>OpenILS::WWW::AddedContent::OpenLibrary</module> -->
+<module>OpenILS::WWW::AddedContent::ObalkyKnih</module>
+----
+
+Using default settings for Obalkyknih.cz means all types of added content from Obalkyknih.cz are visible in your online catalog.
+If the module is enabled, book covers are always displayed. Other types of added content (summaries, ratings or tables of contents) can be:
+
+* switched off using _false_ option,
+* switched on again using _true_ option.
+
+The following types of added content are used:
+
+* summary (or annotation)
+* tocPDF (table of contents available as image)
+* tocText (table of contents available as text)
+* review (user reviews)
+
+An example of how to switch off summaries:
+
+[source,xml]
+----
+<summary>false</summary>
+----
+
+
+Google Analytics
+~~~~~~~~~~~~~~~~
+
+Google Analytics is a free service to collect statistics for your Evergreen
+site. Statistic tracking is disabled by default through the Evergreen
+client software when library staff use your site within the client, but active
+when anyone uses the site without the client. This was a preventive measure to
+reduce the potential risks for leaking patron information. In order to use Google
+Analytics you will first need to set up the service from the Google Analytics
+website at http://www.google.com/analytics/. To activate Google Analytics you
+will need to edit _config.tt2_ in your template. To enable the service set
+the value of google_analytics.enabled to true and change the value of
+_google_analytics.code_ to be the code in your Google Analytics account.
+
+NoveList
+~~~~~~~~
+
+Novelist is a subscription-based service providing reviews and recommendation
+for books in you catalog. To activate your Novelist service in Evergreen, open
+the Apache configuration file _/etc/apache2/eg_vhost.conf_ and edit the line:
+
+----
+#SetEnv OILS_NOVELIST_URL
+----
+
+You should use the URL provided by NoveList.
+
+RefWorks
+~~~~~~~~
+
+RefWorks is a subscription-based online bibliographic management tool. If you
+have a RefWorks subscription, you can activate RefWorks in Evergreen by editing
+the _config.tt2_ file located in your template directory. You will need to set
+the _ctx.refworks.enabled_ value to _true_. You may also set the RefWorks URL by
+changing the _ctx.refworks.url_ setting on the same file.
+
+SFX OpenURL Resolver
+~~~~~~~~~~~~~~~~~~~~
+
+An OpenURL resolver allows you to find electronic resources and pull them into
+your catalog based on the ISBN or ISSN of the item. In order to use the SFX
+OpenURL resolver, you will need to subscribe to the Ex Libris SFX service. To
+activate the service in Evergreen edit the _config.tt2_ file in your template.
+Enable the resolver by changing the value of _openurl.enabled_ to _true_ and
+change the _openurl.baseurl_ setting to point to the URL of your OpenURL
+resolver.
+
+Syndetic Solutions
+~~~~~~~~~~~~~~~~~~
+
+Syndetic Solutions is a subscription service providing book covers and other
+data for items in your catalog. In order to activate Syndetic, edit the
+_/openils/conf/opensrf.xml_ file and change the _<module>_ element to point to
+the Syndetic Perl Module:
+
+----
+<module>OpenILS::WWW::AddedContent::Syndetic</module>
+----
+
+You will also need to edit the _<userid>_ element to be the user id provided to
+you by Syndetic.
+
+Then, you will need to uncomment and edit the _<base_url>_ element so that it
+points to the Syndetic service:
+
+----
+<base_url>http://syndetics.com/index.aspx</base_url>
+----
+
+For changes to be activated for your public interface you will need to restart
+Evergreen and Apache.
+
+
+Clear External/Added Content Cache
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On the catalog’s record summary page, there is a link for staff that will forcibly clear
+the cache of the Added Content for that record. This is helpful for when the Added Content
+retrieved the wrong cover jacket art, summary, etc. and caches the wrong result.
+
+image::media/clear-added-content-cache-1.png[Clear Cache Link]
+
+Once clicked, there is a pop up that will display what was cleared from the cache.
+
+image::media/clear-added-content-cache-2.jpg[Example Popup]
+
+You will need to reload the record in the staff client to obtain the new images from your
+Added Content Supplier.
+
+
+Configure a Custom Image for Missing Images
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can configure a "no image" image other than the standard 1-pixel
+blank image. The example eg_vhost.conf file provides examples in the
+comments. Note: Evergreen does not provide default images for these.
+
+
+Including Locally Hosted Content in Your Public Interface
+---------------------------------------------------------
+
+It is also possible to show added content that has been generated locally
+by placing the content in a specific spot on the web server. It is
+possible to have local book jackets, reviews, TOC, excerpts or annotations.
+
+File Location and Format
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default the files will need to be placed in directories under
+*/openils/var/web/opac/extras/ac/* on the server(s) that run Apache.
+
+The files need to be in specific folders depending on the format of the
+added content. Local Content can only be looked up based on the
+record ID at this time.
+
+.URL Format:
+\http://catalog/opac/extras/ac/*\{type}/\{format}/r/\{recordid}*
+
+ * *type* is one of *jacket*, *reviews*, *toc*, *excerpt* or *anotes*.
+ * *format* is type dependent:
+ - for jacket, one of small, medium or large
+ - others, one of html, xml or json ... html is the default for non-image added content
+ * *recordid* is the bibliographic record id (bre.id).
+
+Example
+~~~~~~~
+
+If you have some equipment that you are circulating such as a
+laptop or eBook reader and you want to add an image of the equipment
+that will show up in the catalog.
+
+[NOTE]
+=============
+If you are adding jacket art for a traditional type of media
+(book, CD, DVD) consider adding the jacket art to the http://openlibrary.org
+project instead of hosting it locally. This would allow other
+libraries to benefit from your work.
+=============
+
+Make note of the Record ID of the bib record. You can find this by
+looking at the URL of the bib in the catalog.
+http://catalog/eg/opac/record/*123*, 123 is the record ID.
+These images will only show up for one specific record.
+
+Create 3 different sized versions of the image in png or jpg format.
+
+ * *Small* - 80px x 80px - named _123-s.jpg_ or _123-s.png_ - This is displayed in the browse display.
+ * *Medium* - 240px x 240px - named _123-m.jpg_ or _123-m.png_ - This is displayed on the summary page.
+ * *Large* - 400px x 399px - named _123-l.jpg_ or _123-l.png_ - This is displayed if the summary page image is clicked on.
+
+[NOTE]
+The image dimensions are up to you, use what looks good in your catalog.
+
+Next, upload the images to the evergreen server(s) that run apache,
+and move/rename the files to the following locations/name.
+You will need to create directories that are missing.
+
+ * Small - Move the file *123-s.jpg* to */openils/var/web/opac/extras/ac/jacket/small/r/123*
+ * Medium - Move the file *123-m.jpg* to */openils/var/web/opac/extras/ac/jacket/medum/r/123*.
+ * Large - Move the file *123-l.jpg* to */openils/var/web/opac/extras/ac/jacket/large/r/123*.
+
+[NOTE]
+The system doesn't need the file extension to know what kind of file it is.
+
+Reload the bib record summary in the web catalog and your new image will display.
+
+Sitemap generator
+-----------------
+A http://www.sitemaps.org[sitemap] directs search engines to the pages of
+interest in a web site so that the search engines can intelligently crawl
+your site. In the case of Evergreen, the primary pages of interest are the
+bibliographic record detail pages.
+
+The sitemap generator script creates sitemaps that adhere to the
+http://sitemaps.org specification, including:
+
+* limiting the number of URLs per sitemap file to no more than 50,000 URLs;
+* providing the date that the bibliographic record was last edited, so
+ that once a search engine has crawled all of your sites' record detail pages,
+ it only has to reindex those pages that are new or have changed since the last
+ crawl;
+* generating a sitemap index file that points to each of the sitemap files.
+
+Running the sitemap generator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The `sitemap_generator` script must be invoked with the following argument:
+
+* `--lib-hostname`: specifies the hostname for the catalog (for example,
+ `--lib-hostname https://catalog.example.com`); all URLs will be generated
+ appended to this hostname
+
+Therefore, the following arguments are useful for generating multiple sitemaps
+per Evergreen instance:
+
+* `--lib-shortname`: limit the list of record URLs to those which have copies
+ owned by the designated library or any of its children;
+* `--prefix`: provides a prefix for the sitemap index file names
+
+Other options enable you to override the OpenSRF configuration file and the
+database connection credentials, but the default settings are generally fine.
+
+Note that on very large Evergreen instances, sitemaps can consume hundreds of
+megabytes of disk space, so ensure that your Evergreen instance has enough room
+before running the script.
+
+Scheduling
+~~~~~~~~~~
+To enable search engines to maintain a fresh index of your bibliographic
+records, you may want to include the script in your cron jobs on a nightly or
+weekly basis.
+
+Sitemap files are generated in the same directory from which the script is
+invoked, so a cron entry will look something like:
+
+------------------------------------------------------------------------
+12 2 * * * cd /openils/var/web && /openils/bin/sitemap_generator
+------------------------------------------------------------------------
+
+Troubleshooting TPAC errors
+---------------------------
+
+If there is a problem such as a TT syntax error, it generally shows up as an
+ugly server failure page. If you check the Apache error logs, you will probably
+find some solid clues about the reason for the failure. For example, in the
+following example, the error message identifies the file in which the problem
+occurred as well as the relevant line numbers.
+
+Example error message in Apache error logs:
+
+----
+bash# grep "template error" /var/log/apache2/error_log
+[Tue Dec 06 02:12:09 2011] [warn] [client 127.0.0.1] egweb: template error:
+ file error - parse error - opac/parts/record/summary.tt2 line 112-121:
+ unexpected token (!=)\n [% last_cn = 0;\n FOR copy_info IN
+ ctx.copies;\n callnum = copy_info.call_number_label;\n
+----
+
--- /dev/null
+Setting Up EDI Acquisitions
+---------------------------
+
+Introduction
+~~~~~~~~~~~~
+
+Electronic Data Interchange (EDI) is used to exchange information between
+participating vendors and Evergreen. This chapter contains technical
+information for installation and configuration of the components necessary
+to run EDI Acquisitions for Evergreen.
+
+Installation
+~~~~~~~~~~~~
+
+Install EDI Translator
+^^^^^^^^^^^^^^^^^^^^^^
+
+The EDI Translator is used to convert data into EDI format. It runs
+on localhost and listens on port 9191 by default. This is controlled via
+the edi_webrick.cnf file located in the edi_translator directory. It should
+not be necessary to edit this configuration if you install EDI Translator
+on the same server used for running Action/Triggers events.
+
+[NOTE]
+If you are running Evergreen with a multi-server configuration, make sure
+to install EDI Translator on the same server used for Action/Trigger event
+generation.
+
+.Steps for Installing
+
+1. As the *opensrf* user, copy the EDI Translator code found in
+ Open-ILS/src/edi_translator to somewhere accessible
+ (for example, /openils/var/edi):
++
+[source, bash]
+--------------------------------------------------
+cp -r Open-ILS/src/edi_translator /openils/var/edi
+--------------------------------------------------
+2. Navigate to where you have saved the code to begin next step:
++
+[source, bash]
+-------------------
+cd /openils/var/edi
+-------------------
+3. Next, as the *root* user (or a user with sudo rights), install the
+ dependencies, via "install.sh". This will perform some apt-get routines
+ to install the code needed for the EDI translator to function.
+ (Note: subversion must be installed first)
++
+[source, bash]
+-----------
+./install.sh
+-----------
+4. Now, we're ready to start "edi_webrick.bash" which is the script that calls
+ the "Ruby" code to translate EDI. This script needs to be started in
+ order for EDI to function so please take appropriate measures to ensure this
+ starts following reboots/upgrades/etc. As the *opensrf* user:
++
+[source, bash]
+-----------------
+./edi_webrick.bash
+-----------------
+5. You can check to see if EDI translator is running.
+ * Using the command "ps aux | grep edi" should show you something similar
+ if the script is running properly:
++
+[source, bash]
+------------------------------------------------------------------------------------------
+root 30349 0.8 0.1 52620 10824 pts/0 S 13:04 0:00 ruby ./edi_webrick.rb
+------------------------------------------------------------------------------------------
+ * To shutdown EDI Translator you can use something like pkill (assuming
+ no other ruby processes are running on that server):
++
+[source, bash]
+-----------------------
+kill -INT $(pgrep ruby)
+-----------------------
+
+Install EDI Scripts
+^^^^^^^^^^^^^^^^^^^
+
+The EDI scripts are "edi_pusher.pl" and "edi_fetcher.pl" and are used to
+"push" and "fetch" EDI messages for configured EDI accounts.
+
+1. As the *opensrf* user, copy edi_pusher.pl and edi_fetcher.pl from
+ Open-ILS/src/support-scripts into /openils/bin:
++
+[source, bash]
+--------------------------------------------------
+cp Open-ILS/src/support-scripts/edi_pusher.pl /openils/bin
+cp Open-ILS/src/support-scripts/edi_fetcher.pl /openils/bin
+--------------------------------------------------
+2. Setup the edi_pusher.pl and edi_fetcher.pl scripts to run as cron jobs
+ in order to regularly push and receive EDI messages.
+ * Add to the opensrf user's crontab the following entries:
++
+[source, bash]
+-----------------------------------------------------------------------
+10 * * * * cd /openils/bin && /usr/bin/perl ./edi_pusher.pl > /dev/null
+0 1 * * * cd /openils/bin && /usr/bin/perl ./edi_fetcher.pl > /dev/null
+-----------------------------------------------------------------------
+ * The example for edi_pusher.pl sets the script to run at
+ 10 minutes past the hour, every hour.
+ * The example for edi_fetcher.pl sets the script to run at
+ 1 AM every night.
+
+[NOTE]
+You may choose to run the EDI scripts more or less frequently based on the
+necessary response times from your vendors.
+
+Configuration
+~~~~~~~~~~~~~
+
+Configuring Providers
+^^^^^^^^^^^^^^^^^^^^^
+
+Look in Admin > Server Administration > Acquisitions > Providers
+
+[options="header"]
+|======================================================================================
+|Column |Description/Notes
+|Provider Name |A unique name to identify the provider
+|Code |A unique code to identify the provider
+|Owner |The org unit who will "own" the provider.
+|Currency |The currency format the provider accepts
+|Active |Whether or not the Provider is "active" for use
+|Default Claim Policy|??
+|EDI Default |The default "EDI Account" to use (see EDI Accounts Configuration)
+|Email |The email address for the provider
+|Fax Phone |A fax number for the provider
+|Holdings Tag |The holdings tag to be utilized (usually 852, for Evergreen)
+|Phone |A phone number for the provider
+|Prepayment Required |Whether or not prepayment is required
+|SAN |The vendor provided, org unit specific SAN code
+|URL |The vendor website
+|======================================================================================
+
+Configuring EDI Accounts
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Look in Admin > Server Administration > Acquisitions > EDI Accounts
+
+[options="header"]
+|===============================================================================================================
+|Column |Description/Notes
+|Label |A unique name to identify the provider
+|Host |FTP/SFTP/SSH hostname - vendor assigned
+|Username |FTP/SFTP/SSH username - vendor assigned
+|Password |FTP/SFTP/SSH password - vendor assigned
+|Account |Vendor assigned account number associated with your organization
+|Owner |The organizational unit who owns the EDI account
+|Last Activity |The date of last activity for the account
+|Provider |This is a link to one of the "codes" in the "Providers" interface
+|Path |The path on the vendor's server where Evergreen will send it's outgoing .epo files
+|Incoming Directory |The path on the vendor's server where "incoming" .epo files are stored
+|Vendor Account Number|Vendor assigned account number.
+|Vendor Assigned Code |Usually a sub-account designation. Can be used with or without the Vendor Account Number.
+|===============================================================================================================
+
+Configuring Organizational Unit SAN code
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Look in Admin > Server Settings > Organizational Units
+
+This interface allows a library to configure their SAN, alongside
+their address, phone, etc.
+
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+PO JEDI Template Issues
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Some libraries may run into issues with the action/trigger (PO JEDI).
+The template has to be modified to handle different vendor codes that
+may be used. For instance, if you use "ingra" instead of INGRAM this
+may cause a problem because they are hardcoded in the template. The
+following is an example of one modification that seems to work.
+
+.Original template has:
+
+[source, bash]
+----------------------------------------------------------------------------------------------------------------------------------------------
+"buyer":[
+ [% IF target.provider.edi_default.vendcode && (target.provider.code == 'BT' || target.provider.name.match('(?i)^BAKER & TAYLOR')) -%]
+ {"id-qualifier": 91, "id":"[% target.ordering_agency.mailing_address.san _ ' ' _ target.provider.edi_default.vendcode %]"}
+ [%- ELSIF target.provider.edi_default.vendcode && target.provider.code == 'INGRAM' -%]
+ {"id":"[% target.ordering_agency.mailing_address.san %]"},
+ {"id-qualifier": 91, "id":"[% target.provider.edi_default.vendcode %]"}
+ [%- ELSE -%]
+ {"id":"[% target.ordering_agency.mailing_address.san %]"}
+ [%- END -%]
+],
+----------------------------------------------------------------------------------------------------------------------------------------------
+
+.Modified template has the following where it matches on provider SAN instead of code:
+
+[source, bash]
+------------------------------------------------------------------------------------------------------------------------------------------
+"buyer":[
+ [% IF target.provider.edi_default.vendcode && (target.provider.san == '1556150') -%]
+ {"id-qualifier": 91, "id":"[% target.ordering_agency.mailing_address.san _ ' ' _ target.provider.edi_default.vendcode %]"}
+ {"id-qualifier": 91, "id":"[% target.ordering_agency.mailing_address.san _ ' ' _ target.provider.edi_default.vendcode %]"}
+ [%- ELSIF target.provider.edi_default.vendcode && (target.provider.san == '1697978') -%]
+ {"id":"[% target.ordering_agency.mailing_address.san %]"},
+ {"id-qualifier": 91, "id":"[% target.provider.edi_default.vendcode %]"}
+ [%- ELSE -%]
+ {"id":"[% target.ordering_agency.mailing_address.san %]"}
+ [%- END -%]
+],
+------------------------------------------------------------------------------------------------------------------------------------------
+
--- /dev/null
+Migrating Patron Data
+=====================
+
+This section will explain the task of migrating your patron data from comma
+delimited files into Evergreen. It does not deal with the process of exporting
+from the non-Evergreen system since this process may vary depending on where you
+are extracting your patron records. Patron could come from an ILS or it could
+come from a student database in the case of academic records.
+
+When importing records into Evergreen you will need to populate 3 tables in your
+Evergreen database:
+
+* actor.usr - The main table for user data
+* actor.card - Stores the barcode for users; Users can have more than 1 card but
+only 1 can be active at a given time;
+* actor.usr_address - Used for storing address information; A user can
+have more than one address.
+
+Before following the procedures below to import patron data into Evergreen, it
+is a good idea to examine the fields in these tables in order to decide on a
+strategy for data to include in your import. It is important to understand the
+data types and constraints on each field.
+
+. Export the patron data from your existing ILS or from another source into a
+comma delimited file. The comma delimited file used for importing the records
+should use Unicode (UTF8) character encoding.
+
+. Create a staging table. A staging table will allow you to tweak the data before
+importing. Here is an example sql statement:
++
+[source,sql]
+----------------------------------
+ CREATE TABLE students (
+ student_id int, barcode text, last_name text, first_name text, email text,
+ address_type text, street1 text, street2 text,
+ city text, province text, country text, postal_code text, phone text, profile
+ int DEFAULT 2, ident_type int, home_ou int, claims_returned_count int DEFAULT
+ 0, usrname text, net_access_level int DEFAULT 2, password text
+ );
+-----------------------------------
++
+NOTE: The _default_ variables allow you to set default for your library or to populate
+required fields in Evergreen if your data includes NULL values.
++
+The data field profile in the above SQL script refers to the user group and should be an
+integer referencing the id field in permission.grp_tree. Setting this value will affect
+the permissions for the user. See the values in permission.grp_tree for possibilities.
++
+ident_type is the identification type used for identifying users. This is a integer value
+referencing config.identification_type and should match the id values of that table. The
+default values are 1 for Drivers License, 2 for SSN or 3 for other.
++
+home_ou is the home organizational unit for the user. This value needs to match the
+corresponding id in the actor.org_unit table.
++
+. Copy records into staging table from a comma delimited file.
++
+[source,sql]
+----------------------------------
+ COPY students (student_id, last_name, first_name, email, address_type, street1, street2,
+ city, province, country, postal_code, phone)
+ FROM '/home/opensrf/patrons.csv'
+ WITH CSV HEADER;
+-----------------------------------
++
+The script will vary depending on the format of your patron load file (patrons.csv).
++
+. Formatting of some fields to fit Evergreen filed formatting may be required. Here is an example
+of sql to adjust phone numbers in the staging table to fit the evergreen field:
++
+[source,sql]
+----------------------------------
+ UPDATE students phone = replace(replace(replace(rpad(substring(phone from 1 for 9), 10, '-') ||
+ substring(phone from 10), '(', ''), ')', ''), ' ', '-');
+----------------------------------
++
+Data ``massaging'' will be required to fit formats used in Evergreen.
++
+. Insert records from the staging table into the actor.usr Evergreen table:
++
+[source,sql]
+----------------------------------
+ INSERT INTO actor.usr (
+ profile, usrname, email, passwd, ident_type, ident_value, first_given_name,
+ family_name, day_phone, home_ou, claims_returned_count, net_access_level)
+ SELECT profile, students.usrname, email, password, ident_type, student_id,
+ first_name, last_name, phone, home_ou, claims_returned_count, net_access_level
+ FROM students;
+----------------------------------
++
+. Insert records into actor.card from actor.usr .
++
+[source,sql]
+----------------------------------
+ INSERT INTO actor.card (usr, barcode)
+ SELECT actor.usr.id, students.barcode
+ FROM students
+ INNER JOIN actor.usr
+ ON students.usrname = actor.usr.usrname;
+----------------------------------
++
+This assumes a one to one card patron relationship. If your patron data import has multiple cards
+assigned to one patron more complex import scripts may be required which look
+for inactive or active flags.
++
+. Update actor.usr.card field with actor.card.id to associate active card with the user:
++
+[source,sql]
+----------------------------------
+ UPDATE actor.usr
+ SET card = actor.card.id
+ FROM actor.card
+ WHERE actor.card.usr = actor.usr.id;
+----------------------------------
++
+. Insert records into actor.usr_address to add address information for users:
++
+[source,sql]
+----------------------------------
+ INSERT INTO actor.usr_address (usr, street1, street2, city, state, country, post_code)
+ SELECT actor.usr.id, students.street1, students.street2, students.city, students.province,
+ students.country, students.postal_code
+ FROM students
+ INNER JOIN actor.usr ON students.usrname = actor.usr.usrname;
+----------------------------------
++
+. Update actor.usr.address with address id from address table.
+
+[source,sql]
+----------------------------------
+ UPDATE actor.usr
+ SET mailing_address = actor.usr_address.id, billing_address = actor.usr_address.id
+ FROM actor.usr_address
+ WHERE actor.usr.id = actor.usr_address.usr;
+----------------------------------
+
+This assumes 1 address per patron. More complex scenarios may require more sophisticated SQL.
+
+Creating an sql Script for Importing Patrons
+--------------------------------------------
+
+The procedure for importing patron can be automated with the help of an sql script. Follow these
+steps to create an import script:
+
+. Create an new file and name it import.sql
+. Edit the file to look similar to this:
+
+[source,sql]
+----------------------------------
+ BEGIN;
+
+ -- Create staging table.
+ CREATE TABLE students (
+ student_id int, barcode text, last_name text, first_name text, email text, address_type text,
+ street1 text, street2 text, city text, province text, country text, postal_code text, phone
+ text, profile int, ident_type int, home_ou int, claims_returned_count int DEFAULT 0, usrname text,
+ net_access_level int DEFAULT 2, password text
+ );
+
+ --Copy records from your import text file
+ COPY students (student_id, last_name, first_name, email, address_type, street1, street2, city, province,
+ country, postal_code, phone, password)
+ FROM '/home/opensrf/patrons.csv' WITH CSV HEADER;
+
+
+ --Insert records from the staging table into the actor.usr table.
+ INSERT INTO actor.usr (
+ profile, usrname, email, passwd, ident_type, ident_value, first_given_name, family_name,
+ day_phone, home_ou, claims_returned_count, net_access_level)
+ SELECT profile, students.usrname, email, password, ident_type, student_id, first_name,
+ last_name, phone, home_ou, claims_returned_count, net_access_level FROM students;
+
+ --Insert records from the staging table into the actor.usr table.
+ INSERT INTO actor.card (usr, barcode)
+ SELECT actor.usr.id, students.barcode
+ FROM students
+ INNER JOIN actor.usr
+ ON students.usrname = actor.usr.usrname;
+
+ --Update actor.usr.card field with actor.card.id to associate active card with the user:
+ UPDATE actor.usr
+ SET card = actor.card.id
+ FROM actor.card
+ WHERE actor.card.usr = actor.usr.id;
+
+ --INSERT records INTO actor.usr_address from staging table.
+ INSERT INTO actor.usr_address (usr, street1, street2, city, state, country, post_code)
+ SELECT actor.usr.id, students.street1, students.street2, students.city, students.province,
+ students.country, students.postal_code
+ FROM students
+ INNER JOIN actor.usr ON students.usrname = actor.usr.usrname;
+
+
+ --Update actor.usr mailing address with id from actor.usr_address table.:
+ UPDATE actor.usr
+ SET mailing_address = actor.usr_address.id, billing_address = actor.usr_address.id
+ FROM actor.usr_address
+ WHERE actor.usr.id = actor.usr_address.usr;
+
+ COMMIT;
+----------------------------------
+
+Placing the sql statements between BEGIN; and COMMIT; creates a transaction
+block so that if any sql statements fail, the entire process is canceled and the
+database is rolled back to its original state. Lines beginning with -- are
+comments to let you you what each sql statement is doing and are not processed.
+
+Batch Updating Patron Data
+--------------------------
+
+For academic libraries, doing batch updates to add new patrons to the Evergreen
+database is a critical task. The above procedures and import script can be
+easily adapted to create an update script for importing new patrons from
+external databases. If the data import file contains only new patrons, then, the
+above procedures will work well to insert those patrons. However, if the data
+load contains all patrons, a second staging table and a procedure to remove
+existing patrons from that second staging table may be required before importing
+the new patrons. Moreover, additional steps to update address information and
+perhaps delete inactive patrons may also be desired depending on the
+requirements of the institution.
+
+After developing the scripts to import and update patrons have been created,
+another important task for library staff is to develop an import strategy and
+schedule which suits the needs of the library. This could be determined by
+registration dates of your institution in the case of academic libraries. It is
+important to balance the convenience of patron loads and the cost of processing
+these loads vs staff adding patrons manually.
+
--- /dev/null
+Migrating from a legacy system
+==============================
+
+When you migrate to Evergreen, you generally want to migrate the bibliographic
+records and copy information that existed in your previous library system. For
+anything more than a few thousand records, you should import the data directly
+into the database rather than use the tools in the staff client. While the data
+that you can extract from your legacy system varies widely, this section
+assumes that you or members of your team have the ability to write scripts and
+are comfortable working with SQL to manipulate data within PostgreSQL. If so,
+then the following section will guide you towards a method of generating common
+data formats so that you can then load the data into the database in bulk.
+
+Making electronic resources visible in the catalog
+--------------------------------------------------
+Electronic resources generally do not have any call number or copy information
+associated with them, and Evergreen enables you to easily make bibliographic
+records visible in the public catalog within sections of the organizational
+unit hierarchy. For example, you can make a set of bibliographic records
+visible only to specific branches that have purchased licenses for the
+corresponding resources, or you can make records representing publicly
+available electronic resources visible to the entire consortium.
+
+Therefore, to make a record visible in the public catalog, modify the records
+using your preferred MARC editing approach to ensure the 856 field contains the
+following information before loading records for electronic resources into
+Evergreen:
+
+.856 field for electronic resources: indicators and subfields
+[width="100%",options="header"]
+|=============================================================================
+|Attribute | Value | Note
+|Indicator 1 |4 |
+|Indicator 2 |0 or 1 |
+|Subfield u |URL for the electronic resource |
+|Subfield y |Text content of the link |
+|Subfield z |Public note | Normally displayed after the link
+|Subfield 9 |Organizational unit short name | The record will be visible when
+ a search is performed specifying this organizational unit or one of its
+ children. You can repeat this subfield as many times as you need.
+|=============================================================================
+
+Once your electronic resource bibliographic records have the required
+indicators and subfields for each 856 field in the record, you can proceed to
+load the records using either the command-line bulk import method or the MARC
+Batch Importer in the staff client.
+
+Migrating your bibliographic records
+------------------------------------
+Convert your MARC21 binary records into the MARCXML format, with one record per
+line. You can use the following Python script to achieve this goal; just
+install the _pymarc_ library first, and adjust the values of the _input_ and
+_output_ variables as needed.
+
+[source,python]
+------------------------------------------------------------------------------
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import codecs
+import pymarc
+
+input = 'records_in.mrc'
+output = 'records_out.xml'
+
+reader = pymarc.MARCReader(open(input, 'rb'), to_unicode=True)
+writer = codecs.open(output, 'w', 'utf-8')
+for record in reader:
+ record.leader = record.leader[:9] + 'a' + record.leader[10:]
+ writer.write(pymarc.record_to_xml(record) + "\n")
+------------------------------------------------------------------------------
+
+Once you have a MARCXML file with one record per line, you can load the records
+into your Evergreen system via a staging table in your database.
+
+. Connect to the PostgreSQL database using the _psql_ command. For example:
++
+------------------------------------------------------------------------------
+psql -U <user-name> -h <hostname> -d <database>
+------------------------------------------------------------------------------
++
+. Create a staging table in the database. The staging table is a temporary
+ location for the raw data that you will load into the production table or
+ tables. Issue the following SQL statement from the _psql_ command line,
+ adjusting the name of the table from _staging_records_import_, if desired:
++
+[source,sql]
+------------------------------------------------------------------------------
+CREATE TABLE staging_records_import (id BIGSERIAL, dest BIGINT, marc TEXT);
+------------------------------------------------------------------------------
++
+. Create a function that will insert the new records into the production table
+ and update the _dest_ column of the staging table. Adjust
+ "staging_records_import" to match the name of the staging table that you plan
+ to create when you issue the following SQL statement:
++
+[source,sql]
+------------------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION staging_importer() RETURNS VOID AS $$
+DECLARE stage RECORD;
+BEGIN
+FOR stage IN SELECT * FROM staging_records_import ORDER BY id LOOP
+ INSERT INTO biblio.record_entry (marc, last_xact_id) VALUES (stage.marc, 'IMPORT');
+ UPDATE staging_records_import SET dest = currval('biblio.record_entry_id_seq')
+ WHERE id = stage.id;
+ END LOOP;
+ END;
+ $$ LANGUAGE plpgsql;
+------------------------------------------------------------------------------
++
+. Load the data from your MARCXML file into the staging table using the COPY
+ statement, adjusting for the name of the staging table and the location of
+ your MARCXML file:
++
+[source,sql]
+------------------------------------------------------------------------------
+COPY staging_records_import (marc) FROM '/tmp/records_out.xml';
+------------------------------------------------------------------------------
++
+. Load the data from your staging table into the production table by invoking
+ your staging function:
++
+[source,sql]
+------------------------------------------------------------------------------
+SELECT staging_importer();
+------------------------------------------------------------------------------
+
+When you leave out the _id_ value for a _BIGSERIAL_ column, the value in the
+column automatically increments for each new record that you add to the table.
+
+Once you have loaded the records into your Evergreen system, you can search for
+some known records using the staff client to confirm that the import was
+successful.
+
+Migrating your call numbers, copies, and parts
+----------------------------------------------
+'Holdings', comprised of call numbers, copies, and parts, are the set of
+objects that enable users to locate and potentially acquire materials from your
+library system.
+
+'Call numbers' connect libraries to bibliographic records. Each call number has a
+'label' associated with a classification scheme such as a the Library of Congress
+or Dewey Decimal systems, and can optionally have either or both a label prefix
+and a label suffix. Label prefixes and suffixes do not affect the sort order of
+the label.
+
+'Copies' connect call numbers to particular instances of that resource at a
+particular library. Each copy has a barcode and must exist in a particular copy
+location. Other optional attributes of copies include circulation modifier,
+which may affect whether that copy can circulate or for how long it can
+circulate, and OPAC visibility, which controls whether that particular copy
+should be visible in the public catalog.
+
+'Parts' provide more granularity for copies, primarily to enable patrons to
+place holds on individual parts of a set of items. For example, an encyclopedia
+might be represented by a single bibliographic record, with a single call
+number representing the label for that encyclopedia at a given library, with 26
+copies representing each letter of the alphabet, with each copy mapped to a
+different part such as _A, B, C, ... Z_.
+
+To migrate this data into your Evergreen system, you will create another
+staging table in the database to hold the raw data for your materials from
+which the actual call numbers, copies, and parts will be generated.
+
+Begin by connecting to the PostgreSQL database using the _psql_ command. For
+example:
+
+------------------------------------------------------------------------------
+psql -U <user-name> -h <hostname> -d <database>
+------------------------------------------------------------------------------
+
+Create the staging materials table by issuing the following SQL statement:
+
+[source,sql]
+------------------------------------------------------------------------------
+CREATE TABLE staging_materials (
+ bibkey BIGINT, -- biblio.record_entry_id
+ callnum TEXT, -- call number label
+ callnum_prefix TEXT, -- call number prefix
+ callnum_suffix TEXT, -- call number suffix
+ callnum_class TEXT, -- classification scheme
+ create_date DATE,
+ location TEXT, -- shelving location code
+ item_type TEXT, -- circulation modifier code
+ owning_lib TEXT, -- org unit code
+ barcode TEXT, -- copy barcode
+ part TEXT
+);
+------------------------------------------------------------------------------
+
+For the purposes of this example migration of call numbers, copies, and parts,
+we assume that you are able to create a tab-delimited file containing values
+that map to the staging table properties, with one copy per line. For example,
+the following 5 lines demonstrate how the file could look for 5 different
+copies, with non-applicable attribute values represented by _\N_, and 3 of the
+copies connected to a single call number and bibliographic record via parts:
+
+------------------------------------------------------------------------------
+1 QA 76.76 A3 \N \N LC 2012-12-05 STACKS BOOK BR1 30007001122620 \N
+2 GV 161 V8 Ref. Juv. LC 2010-11-11 KIDS DVD BR2 30007005197073 \N
+3 AE 5 E363 1984 \N \N LC 1984-01-10 REFERENCE BOOK BR1 30007006853385 A
+3 AE 5 E363 1984 \N \N LC 1984-01-10 REFERENCE BOOK BR1 30007006853393 B
+3 AE 5 E363 1984 \N \N LC 1984-01-10 REFERENCE BOOK BR1 30007006853344 C
+------------------------------------------------------------------------------
+
+Once your holdings are in a tab-delimited format--which, for the purposes of
+this example, we will name _holdings.tsv_--you can import the holdings file
+into your staging table. Copy the contents of the holdings file into the
+staging table using the _COPY_ SQL statement:
+
+[source,sql]
+------------------------------------------------------------------------------
+COPY staging_items (bibkey, callnum, callnum_prefix,
+ callnum_suffix, callnum_class, create_date, location,
+ item_type, owning_lib, barcode, part) FROM 'holdings.tsv';
+------------------------------------------------------------------------------
+
+Generate the copy locations you need to represent your holdings:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO asset.copy_location (name, owning_lib)
+ SELECT DISTINCT location, 1 FROM staging_materials
+ WHERE NOT EXISTS (
+ SELECT 1 FROM asset.copy_location
+ WHERE name = location
+ );
+------------------------------------------------------------------------------
+
+Generate the circulation modifiers you need to represent your holdings:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO config.circ_modifier (code, name, description, sip2_media_type)
+ SELECT DISTINCT circmod, circmod, circmod, '001'
+ FROM staging_materials
+ WHERE NOT EXISTS (
+ SELECT 1 FROM config.circ_modifier
+ WHERE circmod = code
+ );
+------------------------------------------------------------------------------
+
+Generate the call number prefixes and suffixes you need to represent your
+holdings:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO asset.call_number_prefix (owning_lib, label)
+ SELECT DISTINCT aou.id, callnum_prefix
+ FROM staging_materials sm
+ INNER JOIN actor.org_unit aou
+ ON aou.shortname = sm.owning_lib
+ WHERE NOT EXISTS (
+ SELECT 1 FROM asset.call_number_prefix acnp
+ WHERE callnum_prefix = acnp.label
+ AND aou.id = acnp.owning_lib
+ ) AND callnum_prefix IS NOT NULL;
+
+INSERT INTO asset.call_number_suffix (owning_lib, label)
+ SELECT DISTINCT aou.id, callnum_suffix
+ FROM staging_materials sm
+ INNER JOIN actor.org_unit aou
+ ON aou.shortname = sm.owning_lib
+ WHERE NOT EXISTS (
+ SELECT 1 FROM asset.call_number_suffix acns
+ WHERE callnum_suffix = acns.label
+ AND aou.id = acns.owning_lib
+ ) AND callnum_suffix IS NOT NULL;
+------------------------------------------------------------------------------
+
+Generate the call numbers for your holdings:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO asset.call_number (
+ creator, editor, record, owning_lib, label, prefix, suffix, label_class
+)
+ SELECT DISTINCT 1, 1, bibkey, aou.id, callnum, acnp.id, acns.id,
+ CASE WHEN callnum_class = 'LC' THEN 1
+ WHEN callnum_class = 'DEWEY' THEN 2
+ END
+ FROM staging_materials sm
+ INNER JOIN actor.org_unit aou
+ ON aou.shortname = owning_lib
+ INNER JOIN asset.call_number_prefix acnp
+ ON COALESCE(acnp.label, '') = COALESCE(callnum_prefix, '')
+ INNER JOIN asset.call_number_suffix acns
+ ON COALESCE(acns.label, '') = COALESCE(callnum_suffix, '')
+;
+------------------------------------------------------------------------------
+
+Generate the copies for your holdings:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO asset.copy (
+ circ_lib, creator, editor, call_number, location,
+ loan_duration, fine_level, barcode
+)
+ SELECT DISTINCT aou.id, 1, 1, acn.id, acl.id, 2, 2, barcode
+ FROM staging_materials sm
+ INNER JOIN actor.org_unit aou
+ ON aou.shortname = sm.owning_lib
+ INNER JOIN asset.copy_location acl
+ ON acl.name = sm.location
+ INNER JOIN asset.call_number acn
+ ON acn.label = sm.callnum
+ WHERE acn.deleted IS FALSE
+;
+------------------------------------------------------------------------------
+
+Generate the parts for your holdings. First, create the set of parts that are
+required for each record based on your staging materials table:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO biblio.monograph_part (record, label)
+ SELECT DISTINCT bibkey, part
+ FROM staging_materials sm
+ WHERE part IS NOT NULL AND NOT EXISTS (
+ SELECT 1 FROM biblio.monograph_part bmp
+ WHERE sm.part = bmp.label
+ AND sm.bibkey = bmp.record
+ );
+------------------------------------------------------------------------------
+
+Now map the parts for each record to the specific copies that you added:
+
+[source,sql]
+------------------------------------------------------------------------------
+INSERT INTO asset.copy_part_map (target_copy, part)
+ SELECT DISTINCT acp.id, bmp.id
+ FROM staging_materials sm
+ INNER JOIN asset.copy acp
+ ON acp.barcode = sm.barcode
+ INNER JOIN biblio.monograph_part bmp
+ ON bmp.record = sm.bibkey
+ WHERE part IS NOT NULL
+ AND part = bmp.label
+ AND acp.deleted IS FALSE
+ AND NOT EXISTS (
+ SELECT 1 FROM asset.copy_part_map
+ WHERE target_copy = acp.id
+ AND part = bmp.id
+ );
+------------------------------------------------------------------------------
+
+At this point, you have loaded your bibliographic records, call numbers, call
+number prefixes and suffixes, copies, and parts, and your records should be
+visible to searches in the public catalog within the appropriate organization
+unit scope.
--- /dev/null
+Patron Address City/State/County Pre-Populate by ZIP Code
+---------------------------------------------------------
+
+indexterm:[zips.txt, Populate Address by ZIP Code, ZIP code]
+
+This feature saves staff time and increases accuracy when entering patron address information by
+automatically filling in the City, State and County information based on the
+ZIP code entered by the staff member.
+
+*Released:* Evergreen 0.1, available in all versions.
+
+Please be aware of the following when using this feature.
+
+* ZIP codes do not always match 1 to 1 with City, State and County. ZIP codes were designed for postal delivery and represent postal delivery zones that may cover more than one city, state or county.
+** It is currently only possible to have one match per ZIP code, but you can add an alert to those entries to prompt staff to double check the entered data.
+* Only the first 5 digits of the ZIP are used. ZIP+4 is not currently supported.
+* The zips.txt data is loaded once at service startup and stored in memory, so changes to the zips.txt data file require that Evergreen be restarted. Specifically, you need to restart the "open-ils.search" OpenSRF service.
+
+
+Scoping and Permissions
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There are no staff client permissions associated with this feature since there is no staff client interface.
+
+This feature affects all users of the system; there is no way to have separate settings per Org Unit.
+
+Setup Steps
+~~~~~~~~~~~
+
+Step 1 - Setup Data File
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The default location and name of the data file is /openils/var/data/zips.txt on your Evergreen server. You can choose a different location if needed.
+
+The file format of your zips.txt will look like this (delimited by the .):
+
+ID|*StateAbb*|*City*|*ZIP*|*IsDefault*|StateID|*County*|AreaCode|*AlertMesg*
+
+The only fields that are used are *StateAbb*, *City*, *ZIP*, *IsDefault*, *County* and *AlertMesg*.
+
+Most fields can be left blank if the information is not available and that data will not be entered.
+
+.Data Field Descriptions
+. ID - ID field to uniquely identify this row. Not required, can be left blank.
+. *StateAbb* - State abbreviation like "MN" or "ND".
+. *City* - Name of city.
+. *ZIP* - ZIP code, only first 5 digits used.
+. *IsDefault* - Must be set to 1 for the row to be used. Easy way to disable/enable a row.
+. StateID - Unknown and unused.
+. *County* - County name.
+. AreaCode - Phone number area code, unused.
+. *AlertMesg* - Message to display to staff to alert them of any special circumstances.
+
+TIP: The <<_address_alert,Address Alerts>> feature can also be used to alert staff about certain addresses.
+
+Here is an example of what the data file should look like.
+
+.Example zips.txt
+----
+|MN|Moorhead|56561|1||Clay||
+|MN|Moorhead|56562|1||Clay||
+|MN|Moorhead|56563|1||Clay||
+|MN|Sabin|56580|1||Clay||
+|MN|Ulen|56585|1||Clay||
+|MN|Lake Itasca|56460|1||Clearwater County||
+|MN|Bagley|56621|1||Clearwater||
+|MN|Clearbrook|56634|1||Clearwater||
+|MN|Gonvick|56644|1||Clearwater||
+----
+
+Step 2 - Enable Feature
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The next step is to tell the system to use the zips.txt file that you created. This is done by editing /openils/conf/opensrf.xml. Look about halfway into the file and you may very well see a commented section in the file that looks similar to this:
+
+----
+ <!-- zip code database file -->
+ <!--<zips_file>/openils/var/data/zips.txt</zips_file>-->
+ </app_settings>
+</open-ils.search>
+----
+
+Uncomment the area by . .. Change the file path if you placed your file in a different location. The file should look like this after you are done.
+
+----
+ <!-- zip code database file -->
+ <zips_file>/openils/var/data/zips.txt</zips_file>
+ </app_settings>
+</open-ils.search>
+----
+
+.Save and Restart
+Save your changes to the opensrf.xml file, restart Evergreen and restart Apache.
+
+NOTE: The specific opensrf services you need to restart are "opensrf.setting" and "open-ils.search".
+
+Step 3 - Test
+^^^^^^^^^^^^^
+
+Open up the staff client and try to register a new patron. When you get to the address section, enter a ZIP code that you know is in your zips.txt file. The data from the file that matches your ZIP will auto fill the city, state and county fields.
+
+ZIP Code Data
+~~~~~~~~~~~~~
+
+There are several methods you can use to populate your zips.txt with data.
+
+Manual Entry
+^^^^^^^^^^^^
+
+If you only have a few communities that you serve, entering data manually may be the simplest approach.
+
+Geonames.org Data
+^^^^^^^^^^^^^^^^^
+
+Geonames.org provides free ZIP code to city, state and county information licensed under the Creative Commons Attribution 3.0 License, which means you need to put a link to them on your website. Their data includes primary city, state and county information only. It doesn't include info about which other cities are included in a ZIP code. Visit http://www.geonames.org for more info.
+
+The following code example shows you how to download and reformat the data into the zips.txt format. You have the option to filter the data to only include certain states also.
+
+[source,bash]
+----
+## How to get a generic Evergreen zips.txt for free
+wget http://download.geonames.org/export/zip/US.zip
+unzip US.zip
+cut -f2,3,5,6 US.txt \
+| perl -ne 'chomp; @f=split(/\t/); print "|" . join("|", (@f[2,1,0], "1", "", $f[3], "")), "|\n";' \
+> zips.txt
+
+##Optionally filter the data to only include certain states
+egrep "^\|(ND|MN|WI|SD)\|" zips.txt > zips-mn.txt
+----
+
+Commercial Data
+^^^^^^^^^^^^^^^
+
+There are many vendors that sell databases that include ZIP code to city, state and county information. A web search will easily find them. Many of the commercial vendors will include more information on which ZIP codes cover multiple cities, counties and states, which you could use to populate the alert field.
+
+Existing Patron Database
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Another possibility is to use your current patron database to build your zips.txt. Pull out the current ZIP, city, state, county unique rows and use them to form your zips.txt.
+
+.Small Sites
+
+For sites that serve a small geographic area (less than 30 ZIP codes), an sql query like the following will create a zips.txt for you. It outputs the number of matches as the first field and sorts by ZIP code and number of matches. You would need to go through the resulting file and deal with duplicates manually.
+
+[source,bash]
+----
+psql egdb26 -A -t -F $'|' \
+ -c "SELECT count(substring(post_code from 1 for 5)) as zipcount, state, \
+ city, substring(post_code from 1 for 5) as pc, \
+ '1', '', county, '', '' FROM actor.usr_address \
+ group by pc, city, state, county \
+ order by pc, zipcount DESC" > zips.txt
+----
+
+.Larger Sites
+For larger sites Ben Ostrowsky at ESI created a pair of scripts that handles deduping the results and adding in county information. Instructions for use are included in the files.
+
+* http://git.esilibrary.com/?p=migration-tools.git;a=blob;f=elect_ZIPs
+* http://git.esilibrary.com/?p=migration-tools.git;a=blob;f=enrich_ZIPs
+
+
+Development
+~~~~~~~~~~~
+
+If you need to make changes to how this feature works, such as to add support for other postal code formats, here is a list of the files that you need to look at.
+
+. *Zips.pm* - contains code for loading the zips.txt file into memory and replying to search queries. Open-ILS / src / perlmods / lib / OpenILS / Application / Search / Zips.pm
+. *register.js* - This is where patron registration logic is located. The code that queries the ZIP search service and fills the address is located here. Open-ILS / web / js / ui / default / actor / user / register.js
--- /dev/null
+Adding an Evergreen search form to a web page
+=============================================
+
+To enable users to quickly search your Evergreen catalog, you can add a
+simple search form to any HTML page. The following code demonstrates
+how to create a quick search box suitable for the header of your web
+site:
+
+Simple search form
+------------------
+
+[source,html]
+------------------------------------------------------------------------------
+<form action="http://example.com/eg/opac/results" method="get" accept-charset="UTF-8"> <!-- <1> -->
+ <input type="search" alt="Catalog Search" maxlength="200"
+ size="20" name="query"
+ placeholder="Search catalog for..." />
+ <input type="hidden" name="qtype" value="keyword" /> <!-- <2> -->
+ <input type="hidden" name="locg" value="4" /> <!-- <3> -->
+ <input type="submit" value="Search" />
+</form>
+------------------------------------------------------------------------------
+<1> Replace ''example.com'' with the hostname for your catalog. To link to
+ the Kid's OPAC instead of the TPAC, replace ''opac'' with ''kpac''.
+<2> Replace ''keyword'' with ''title'', ''author'', ''subject'', or ''series''
+ if you want to provide more specific searches. You can even specify
+ ''identifier|isbn'' for an ISBN search.
+<3> Replace ''4'' with the ID number of the organizational unit at which you
+ wish to anchor your search. This is the value of the ''locg'' parameter in
+ your normal search.
+
+Advanced search form
+--------------------
+
+[source,html]
+--------------------------------------------------------------------------------
+<form role="search" id="searchForm" method="get" class="searchform" action="http://your_catalog/eg/opac/results" accept-charset="UTF-8">
+ <label id="searchLabel" for="search"><b>Search the Catalog: </b></label>
+ <input type="search" value="" name="query" id="search" size="30">
+ <label id="search_qtype_label"><b>Type:</b>
+ <select name="qtype" id="qtype" aria-label="Select query type:">
+ <option value='keyword' selected="selected">Keyword</option>
+ <option value='title'>Title</option>
+ <option value='jtitle'>Journal Title</option>
+ <option value='author'>Author</option>
+ <option value='subject'>Subject</option>
+ <option value='series'>Series</option>
+ </select>
+ </label>
+
+ <label id="search_itype_label"><b>Format: </b>
+ <select id='item_type_selector' name='fi:item_type' aria-label="Select item type:">
+ <option value=''>All Formats</option>
+ <option value='a'>Books and Journals</option>
+ <option value='i'>Nonmusical Sound Recording</option>
+ <option value='j'>Musical Sound Recording</option>
+ <option value='g'>Video</option>
+ </select>
+ </label>
+
+ <label id="search_locg_label"><b>Library: </b>
+ <select aria-label='Select search library' name='locg'>
+ <option value='1' class="org_unit">
+ All Libraries
+ </option>
+ <option value='2' selected="selected" class="org_unit">
+ Central Library
+ </option>
+ <option value='10' class="org_unit">
+ Little Library
+ </option>
+ </select>
+ </label>
+ <input class="searchbutton" type="submit" value="SEarch" />
+</form>
+--------------------------------------------------------------------------------
+
+Encoding
+--------
+
+For non English characters it is vital to set the attribute `accept-charset="UTF-8"` in the form tag (as in the examples above). If the parameter is not set, records with non English characters will not be retrieved.
+
+Setting the document type
+-------------------------
+
+You can set the document types to be searched using the attribute `option value=` in the form. For the value use MARC 21 code defining the type of record (i.e. https://www.loc.gov/marc/bibliographic/bdleader.html[Leader, position 06]).
+
+For example, for musical recordings you could use `<option value='j'>Musical Sound Recording</option>`
+
+Setting the library
+-------------------
+
+Instead of searching the entire consortium, you can set the Library to be searched in using the attribute `option value=` in the form. For the value use Evergreen database.organization unit ID.
+
+
--- /dev/null
+Installing the Evergreen server
+===============================
+:toc:
+:numbered:
+
+Preamble: referenced user accounts
+----------------------------------
+
+In subsequent sections, we will refer to a number of different accounts, as
+follows:
+
+ * Linux user accounts:
+ ** The *user* Linux account is the account that you use to log onto the
+ Linux system as a regular user.
+ ** The *root* Linux account is an account that has system administrator
+ privileges. On Debian and Fedora you can switch to this account from
+ your *user* account by issuing the `su -` command and entering the
+ password for the *root* account when prompted. On Ubuntu you can switch
+ to this account from your *user* account using the `sudo su -` command
+ and entering the password for your *user* account when prompted.
+ ** The *opensrf* Linux account is an account that you create when installing
+ OpenSRF. You can switch to this account from the *root* account by
+ issuing the `su - opensrf` command.
+ ** The *postgres* Linux account is created automatically when you install
+ the PostgreSQL database server. You can switch to this account from the
+ *root* account by issuing the `su - postgres` command.
+ * PostgreSQL user accounts:
+ ** The *evergreen* PostgreSQL account is a superuser account that you will
+ create to connect to the PostgreSQL database server.
+ * Evergreen administrator account:
+ ** The *egadmin* Evergreen account is an administrator account for
+ Evergreen that you will use to test connectivity and configure your
+ Evergreen instance.
+
+Preamble: developer instructions
+--------------------------------
+
+[NOTE]
+Skip this section if you are using an official release tarball downloaded
+from http://evergreen-ils.org/egdownloads
+
+Developers working directly with the source code from the Git repository,
+rather than an official release tarball, must perform one step before they
+can proceed with the `./configure` step.
+
+As the *user* Linux account, issue the following command in the Evergreen
+source directory to generate the configure script and Makefiles:
+
+[source, bash]
+------------------------------------------------------------------------------
+autoreconf -i
+------------------------------------------------------------------------------
+
+Installing prerequisites
+------------------------
+
+ * **PostgreSQL**: Version 9.3 is recommended. The minimum supported version
+ is 9.1.
+ * **Linux**: Evergreen 2.8 has been tested on Debian Jessie (8.0),
+ Debian Wheezy (7.0), Ubuntu Xenial Xerus (16.04),
+ Ubuntu Trusty Tahr (14.04), and Fedora.
+ If you are running an older version of these distributions, you may want
+ to upgrade before upgrading Evergreen. For instructions on upgrading these
+ distributions, visit the Debian, Ubuntu or Fedora websites.
+ * **OpenSRF**: The minimum supported version of OpenSRF is 2.4.0.
+
+
+Evergreen has a number of prerequisite packages that must be installed
+before you can successfully configure, compile, and install Evergreen.
+
+1. Begin by installing the most recent version of OpenSRF (2.4.0 or later).
+ You can download OpenSRF releases from http://evergreen-ils.org/opensrf-downloads/
+2. On some distributions, it is necessary to install PostgreSQL 9.1+ from external
+ repositories.
++
+ * Debian (Wheezy and Jessie) and Ubuntu (Trusty and Xenial) comes with
+ PostgreSQL 9.1+, so no additional steps are required.
+ * Fedora 19 and 20 come with PostgreSQL 9.2+, so no additional steps are required.
++
+3. On Debian and Ubuntu, run `aptitude update` as the *root* Linux account to
+ retrieve the new packages from the backports repository.
+4. Issue the following commands as the *root* Linux account to install
+ prerequisites using the `Makefile.install` prerequisite installer,
+ substituting `debian-jessie`, `debian-wheezy`, `fedora`,
+ `ubuntu-xenial`, or `ubuntu-trusty` for <osname> below:
++
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install <osname>
+------------------------------------------------------------------------------
++
+5. Add the libdbi-libdbd libraries to the system dynamic library path by
+ issuing the following commands as the *root* Linux account:
++
+[NOTE]
+You should skip this step if installing on Ubuntu Trusty, Ubuntu Xenial or Debian Jessie. The Ubuntu
+and Debian Jessie targets use libdbd-pgsql from packages.
++
+.Debian Wheezy
+[source, bash]
+------------------------------------------------------------------------------
+echo "/usr/local/lib/dbd" > /etc/ld.so.conf.d/eg.conf
+ldconfig
+------------------------------------------------------------------------------
++
+.Fedora
+[source, bash]
+------------------------------------------------------------------------------
+echo "/usr/lib64/dbd" > /etc/ld.so.conf.d/eg.conf
+ldconfig
+------------------------------------------------------------------------------
+
+6. OPTIONAL: Developer additions
++
+To perform certain developer tasks from a Git source code checkout,
+additional packages may be required. As the *root* Linux account:
++
+ * To install packages needed for retriving and managing web dependencies,
+ use the <osname>-developer Makefile.install target. Currently,
+ this is only needed for building and installing the (preview) browser
+ staff client.
++
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install <osname>-developer
+------------------------------------------------------------------------------
++
+ * To install packages required for building Evergreen release bundles, use
+ the <osname>-packager Makefile.install target.
++
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install <osname>-packager
+------------------------------------------------------------------------------
+
+Optional: Extra steps for browser-based staff client
+----------------------------------------------------
+
+[NOTE]
+Skip this entire section if you are using an official release tarball downloaded
+from http://evergreen-ils.org/downloads
+
+[NOTE]
+You make skip the subsection `Install dependencies for browser-based staff client'
+if you are installing on either Debian Jessie, Ubuntu Trusty, or Ubuntu Xenial and you have
+installed the `Optional: Developer Additions' described above. You will still
+need to do the steps in `Install files for browser-based staff client' below.
+
+Install dependencies for browser-based staff client
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Install Node.js. For more information see also:
+ https://github.com/joyent/node/wiki/installation[Node.js Installation]
++
+[source,sh]
+------------------------------------------------------------------------------
+# Go to a temporary directory
+cd /tmp
+
+# Clone the code and checkout the necessary version
+git clone https://github.com/joyent/node.git
+cd node
+git checkout -b v0.10.28 v0.10.28
+
+# set -j to the number of CPU cores on the server + 1
+./configure && make -j2 && sudo make install
+
+# update packages
+% sudo npm update
+------------------------------------------------------------------------------
++
+2. Install Grunt CLI
++
+[source,sh]
+------------------------------------------------------------------------------
+% sudo npm install -g grunt-cli
+------------------------------------------------------------------------------
++
+3. Install Bower
++
+[source,sh]
+------------------------------------------------------------------------------
+% sudo npm install -g bower
+------------------------------------------------------------------------------
+
+Install files for browser-based staff client
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Building, Testing, Minification: The remaining steps all take place within
+ the staff JS web root:
++
+[source,sh]
+------------------------------------------------------------------------------
+cd $EVERGREEN_ROOT/Open-ILS/web/js/ui/default/staff/
+------------------------------------------------------------------------------
++
+2. Install Project-local Dependencies. npm inspects the 'package.json' file
+ for dependencies and fetches them from the Node package network.
++
+[source,sh]
+------------------------------------------------------------------------------
+npm install # fetch Grunt dependencies
+bower install # fetch JS dependencies
+------------------------------------------------------------------------------
++
+3. Run the build script.
++
+[source,sh]
+------------------------------------------------------------------------------
+# build, run tests, concat+minify
+grunt all
+------------------------------------------------------------------------------
+
+
+Configuration and compilation instructions
+------------------------------------------
+
+For the time being, we are still installing everything in the `/openils/`
+directory. From the Evergreen source directory, issue the following commands as
+the *user* Linux account to configure and build Evergreen:
+
+[source, bash]
+------------------------------------------------------------------------------
+PATH=/openils/bin:$PATH ./configure --prefix=/openils --sysconfdir=/openils/conf
+make
+------------------------------------------------------------------------------
+
+These instructions assume that you have also installed OpenSRF under `/openils/`.
+If not, please adjust PATH as needed so that the Evergreen `configure` script
+can find `osrf_config`.
+
+Installation instructions
+-------------------------
+
+1. Once you have configured and compiled Evergreen, issue the following
+ command as the *root* Linux account to install Evergreen, build the server
+ portion of the staff client, and copy example configuration files to
+ `/openils/conf`.
+ Change the value of the `STAFF_CLIENT_STAMP_ID` variable to match the version
+ of the staff client that you will use to connect to the Evergreen server.
++
+[source, bash]
+------------------------------------------------------------------------------
+make STAFF_CLIENT_STAMP_ID=rel_name install
+------------------------------------------------------------------------------
++
+2. The server portion of the staff client expects `http://hostname/xul/server`
+ to resolve. Issue the following commands as the *root* Linux account to
+ create a symbolic link pointing to the `server` subdirectory of the server
+ portion of the staff client that we just built using the staff client ID
+ 'rel_name':
++
+[source, bash]
+------------------------------------------------------------------------------
+cd /openils/var/web/xul
+ln -sf rel_name/server server
+------------------------------------------------------------------------------
+
+Change ownership of the Evergreen files
+---------------------------------------
+
+All files in the `/openils/` directory and subdirectories must be owned by the
+`opensrf` user. Issue the following command as the *root* Linux account to
+change the ownership on the files:
+
+[source, bash]
+------------------------------------------------------------------------------
+chown -R opensrf:opensrf /openils
+------------------------------------------------------------------------------
+
+Additional Instructions for Developers
+--------------------------------------
+
+[NOTE]
+Skip this section if you are using an official release tarball downloaded
+from http://evergreen-ils.org/egdownloads
+
+Developers working directly with the source code from the Git repository,
+rather than an official release tarball, need to install the Dojo Toolkit
+set of JavaScript libraries. The appropriate version of Dojo is included in
+Evergreen release tarballs. Developers should install the Dojo 1.3.3 version
+of Dojo by issuing the following commands as the *opensrf* Linux account:
+
+[source, bash]
+------------------------------------------------------------------------------
+wget http://download.dojotoolkit.org/release-1.3.3/dojo-release-1.3.3.tar.gz
+tar -C /openils/var/web/js -xzf dojo-release-1.3.3.tar.gz
+cp -r /openils/var/web/js/dojo-release-1.3.3/* /openils/var/web/js/dojo/.
+------------------------------------------------------------------------------
+
+
+Configure the Apache Web server
+-------------------------------
+
+. Use the example configuration files in `Open-ILS/examples/apache/` (for
+Apache versions below 2.4) or `Open-ILS/examples/apache_24/` (for Apache
+versions 2.4 or greater) to configure your Web server for the Evergreen
+catalog, staff client, Web services, and administration interfaces. Issue the
+following commands as the *root* Linux account:
++
+.Debian Wheezy
+[source,bash]
+------------------------------------------------------------------------------
+cp Open-ILS/examples/apache/eg.conf /etc/apache2/sites-available/
+cp Open-ILS/examples/apache/eg_vhost.conf /etc/apache2/
+cp Open-ILS/examples/apache/eg_startup /etc/apache2/
+# Now set up SSL
+mkdir /etc/apache2/ssl
+cd /etc/apache2/ssl
+------------------------------------------------------------------------------
++
+.Ubuntu Trusty, Ubuntu Xenial, and Debian Jessie
+[source,bash]
+------------------------------------------------------------------------------------
+cp Open-ILS/examples/apache_24/eg_24.conf /etc/apache2/sites-available/eg.conf
+cp Open-ILS/examples/apache_24/eg_vhost_24.conf /etc/apache2/eg_vhost.conf
+cp Open-ILS/examples/apache/eg_startup /etc/apache2/
+# Now set up SSL
+mkdir /etc/apache2/ssl
+cd /etc/apache2/ssl
+------------------------------------------------------------------------------------
++
+.Fedora
+[source,bash]
+------------------------------------------------------------------------------
+cp Open-ILS/examples/apache_24/eg_24.conf /etc/httpd/conf.d/
+cp Open-ILS/examples/apache_24/eg_vhost_24.conf /etc/httpd/eg_vhost.conf
+cp Open-ILS/examples/apache/eg_startup /etc/httpd/
+# Now set up SSL
+mkdir /etc/httpd/ssl
+cd /etc/httpd/ssl
+------------------------------------------------------------------------------
++
+. The `openssl` command cuts a new SSL key for your Apache server. For a
+production server, you should purchase a signed SSL certificate, but you can
+just use a self-signed certificate and accept the warnings in the staff client
+and browser during testing and development. Create an SSL key for the Apache
+server by issuing the following command as the *root* Linux account:
++
+[source,bash]
+------------------------------------------------------------------------------
+openssl req -new -x509 -days 365 -nodes -out server.crt -keyout server.key
+------------------------------------------------------------------------------
++
+. As the *root* Linux account, edit the `eg.conf` file that you copied into
+place.
+ a. To enable access to the offline upload / execute interface from any
+ workstation on any network, make the following change (and note that
+ you *must* secure this for a production instance):
+ * (Apache 2.2): Replace `Allow from 10.0.0.0/8` with `Allow from all`
+ * (Apache 2.4): Replace `Require host 10.0.0.0/8` with `Require all granted`
+ b. (Fedora): Change references from the non-existent `/etc/apache2/` directory
+ to `/etc/httpd/`.
+. Change the user for the Apache server.
+ * (Debian and Ubuntu): As the *root* Linux account, edit
+ `/etc/apache2/envvars`. Change `export APACHE_RUN_USER=www-data` to
+ `export APACHE_RUN_USER=opensrf`.
+ * (Fedora): As the *root* Linux account , edit `/etc/httpd/conf/httpd.conf`.
+ Change `User apache` to `User opensrf`.
+. As the *root* Linux account, configure Apache with KeepAlive settings
+ appropriate for Evergreen. Higher values can improve the performance of a
+ single client by allowing multiple requests to be sent over the same TCP
+ connection, but increase the risk of using up all available Apache child
+ processes and memory.
+ * (Debian and Ubuntu): Edit `/etc/apache2/apache2.conf`.
+ a. Change `KeepAliveTimeout` to `1`.
+ b. Change `MaxKeepAliveRequests` to `100`.
+ * (Fedora): Edit `/etc/httpd/conf/httpd.conf`.
+ a. Change `KeepAliveTimeout` to `1`.
+ b. Change `MaxKeepAliveRequests` to `100`.
+. As the *root* Linux account, configure the prefork module to start and keep
+ enough Apache servers available to provide quick responses to clients without
+ running out of memory. The following settings are a good starting point for a
+ site that exposes the default Evergreen catalogue to the web:
++
+.Debian Wheezy (`/etc/apache2/apache2.conf`) and Fedora (`/etc/httpd/conf/httpd.conf`)
+[source,bash]
+------------------------------------------------------------------------------
+<IfModule mpm_prefork_module>
+ StartServers 15
+ MinSpareServers 5
+ MaxSpareServers 15
+ MaxClients 75
+ MaxRequestsPerChild 500
+</IfModule>
+------------------------------------------------------------------------------
++
+.Ubuntu Trusty, Ubuntu Xenial, Debian Jessie (`/etc/apache2/mods-available/mpm_prefork.conf`)
+[source,bash]
+------------------------------------------------------------------------------
+<IfModule mpm_prefork_module>
+ StartServers 15
+ MinSpareServers 5
+ MaxSpareServers 15
+ MaxRequestWorkers 75
+ MaxConnectionsPerChild 500
+</IfModule>
+------------------------------------------------------------------------------
++
+. (Ubuntu Trusty, Ubuntu Xenial, Debian Jessie) As the *root* user,
+ enable the mpm_prefork module:
++
+[source,bash]
+------------------------------------------------------------------------------
+a2dismod mpm_event
+a2enmod mpm_prefork
+------------------------------------------------------------------------------
++
+. (Fedora): As the *root* Linux account, edit the `/etc/httpd/eg_vhost.conf`
+ file to change references from the non-existent `/etc/apache2/` directory
+ to `/etc/httpd/`.
+. (Debian Wheezy): As the *root* Linux account, enable the Evergreen site:
++
+[source,bash]
+------------------------------------------------------------------------------
+a2dissite default # OPTIONAL: disable the default site (the "It Works" page)
+a2ensite eg.conf
+------------------------------------------------------------------------------
++
+(Ubuntu Trusty, Ubuntu Xenial, Debian Jessie):
++
+[source,bash]
+------------------------------------------------------------------------------
+a2dissite 000-default # OPTIONAL: disable the default site (the "It Works" page)
+a2ensite eg.conf
+------------------------------------------------------------------------------
++
+. (Ubuntu): As the *root* Linux account, enable Apache to write
+ to the lock directory; this is currently necessary because Apache
+ is running as the `opensrf` user:
++
+[source,bash]
+------------------------------------------------------------------------------
+chown opensrf /var/lock/apache2
+------------------------------------------------------------------------------
+
+Learn more about additional Apache options in the following sections:
+
+ * <<_apache_rewrite_tricks,Apache Rewrite Tricks>>
+ * <<_apache_access_handler_perl_module,Apache Access Handler Perl Module>>
+
+Configure OpenSRF for the Evergreen application
+-----------------------------------------------
+There are a number of example OpenSRF configuration files in `/openils/conf/`
+that you can use as a template for your Evergreen installation. Issue the
+following commands as the *opensrf* Linux account:
+
+[source, bash]
+------------------------------------------------------------------------------
+cp -b /openils/conf/opensrf_core.xml.example /openils/conf/opensrf_core.xml
+cp -b /openils/conf/opensrf.xml.example /openils/conf/opensrf.xml
+------------------------------------------------------------------------------
+
+When you installed OpenSRF, you created four Jabber users on two
+separate domains and edited the `opensrf_core.xml` file accordingly. Please
+refer back to the OpenSRF README and, as the *opensrf* Linux account, edit the
+Evergreen version of the `opensrf_core.xml` file using the same Jabber users
+and domains as you used while installing and testing OpenSRF.
+
+[NOTE]
+The `-b` flag tells the `cp` command to create a backup version of the
+destination file. The backup version of the destination file has a tilde (`~`)
+appended to the file name, so if you have forgotten the Jabber users and
+domains, you can retrieve the settings from the backup version of the files.
+
+`eg_db_config`, described in <<_creating_the_evergreen_database,Creating the Evergreen
+database>>, sets the database connection information in `opensrf.xml` for you.
+
+Configure action triggers for the Evergreen application
+-------------------------------------------------------
+_Action Triggers_ provide hooks for the system to perform actions when a given
+event occurs; for example, to generate reminder or overdue notices, the
+`checkout.due` hook is processed and events are triggered for potential actions
+if there is no checkin time.
+
+To enable the default set of hooks, issue the following command as the
+*opensrf* Linux account:
+
+[source, bash]
+------------------------------------------------------------------------------
+cp -b /openils/conf/action_trigger_filters.json.example /openils/conf/action_trigger_filters.json
+------------------------------------------------------------------------------
+
+For more information about configuring and using action triggers, see
+<<_notifications_action_triggers,Notifications / Action Triggers>>.
+
+Creating the Evergreen database
+-------------------------------
+
+Setting up the PostgreSQL server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For production use, most libraries install the PostgreSQL database server on a
+dedicated machine. Therefore, by default, the `Makefile.install` prerequisite
+installer does *not* install the PostgreSQL 9 database server that is required
+by every Evergreen system. You can install the packages required by Debian or
+Ubuntu on the machine of your choice using the following commands as the
+*root* Linux account:
+
+.(Debian / Ubuntu / Fedora) Installing PostgreSQL server packages
+
+Each OS build target provides the postgres server installation packages
+required for each operating system. To install Postgres server packages,
+use the make target 'postgres-server-<OSTYPE>'. Choose the most appropriate
+command below based on your operating system.
+
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-jessie
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-wheezy
+make -f Open-ILS/src/extras/Makefile.install postgres-server-ubuntu-trusty
+make -f Open-ILS/src/extras/Makefile.install postgres-server-ubuntu-xenial
+make -f Open-ILS/src/extras/Makefile.install postgres-server-fedora
+------------------------------------------------------------------------------
+
+.(Fedora) Postgres initialization
+
+Installing Postgres on Fedora also requires you to initialize the PostgreSQL
+cluster and start the service. Issue the following commands as the *root* user:
+
+[source, bash]
+------------------------------------------------------------------------------
+postgresql-setup initdb
+systemctl start postgresql
+------------------------------------------------------------------------------
+
+For a standalone PostgreSQL server, install the following Perl modules for your
+distribution as the *root* Linux account:
+
+.(Debian Wheezy, Ubuntu Trusty, and Ubuntu Xenial)
+No extra modules required for these distributions.
+
+.(Fedora)
+[source, bash]
+------------------------------------------------------------------------------
+cpan Rose::URI
+------------------------------------------------------------------------------
+
+You need to create a PostgreSQL superuser to create and access the database.
+Issue the following command as the *postgres* Linux account to create a new
+PostgreSQL superuser named `evergreen`. When prompted, enter the new user's
+password:
+
+[source, bash]
+------------------------------------------------------------------------------
+createuser -s -P evergreen
+------------------------------------------------------------------------------
+
+.Enabling connections to the PostgreSQL database
+
+Your PostgreSQL database may be configured by default to prevent connections,
+for example, it might reject attempts to connect via TCP/IP or from other
+servers. To enable TCP/IP connections from localhost, check your `pg_hba.conf`
+file, found in the `/etc/postgresql/` directory on Debian and Ubuntu, and in
+the `/var/lib/pgsql/data/` directory on Fedora. A simple way to enable TCP/IP
+connections from localhost to all databases with password authentication, which
+would be suitable for a test install of Evergreen on a single server, is to
+ensure the file contains the following entries _before_ any "host ... ident"
+entries:
+
+------------------------------------------------------------------------------
+host all all ::1/128 md5
+host all all 127.0.0.1/32 md5
+------------------------------------------------------------------------------
+
+When you change the `pg_hba.conf` file, you will need to reload PostgreSQL to
+make the changes take effect. For more information on configuring connectivity
+to PostgreSQL, see
+http://www.postgresql.org/docs/devel/static/auth-pg-hba-conf.html
+
+Creating the Evergreen database and schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you have created the *evergreen* PostgreSQL account, you also need to
+create the database and schema, and configure your configuration files to point
+at the database server. Issue the following command as the *root* Linux account
+from inside the Evergreen source directory, replacing <user>, <password>,
+<hostname>, <port>, and <dbname> with the appropriate values for your
+PostgreSQL database (where <user> and <password> are for the *evergreen*
+PostgreSQL account you just created), and replace <admin-user> and <admin-pass>
+with the values you want for the *egadmin* Evergreen administrator account:
+
+[source, bash]
+------------------------------------------------------------------------------
+perl Open-ILS/src/support-scripts/eg_db_config --update-config \
+ --service all --create-database --create-schema --create-offline \
+ --user <user> --password <password> --hostname <hostname> --port <port> \
+ --database <dbname> --admin-user <admin-user> --admin-pass <admin-pass>
+------------------------------------------------------------------------------
+
+This creates the database and schema and configures all of the services in
+your `/openils/conf/opensrf.xml` configuration file to point to that database.
+It also creates the configuration files required by the Evergreen `cgi-bin`
+administration scripts, and sets the user name and password for the *egadmin*
+Evergreen administrator account to your requested values.
+
+You can get a complete set of options for `eg_db_config` by passing the
+`--help` parameter.
+
+Loading sample data
+~~~~~~~~~~~~~~~~~~~
+If you add the `--load-all-sample` parameter to the `eg_db_config` command,
+a set of authority and bibliographic records, call numbers, copies, staff
+and regular users, and transactions will be loaded into your target
+database. This sample dataset is commonly referred to as the _concerto_
+sample data, and can be useful for testing out Evergreen functionality and
+for creating problem reports that developers can easily recreate with their
+own copy of the _concerto_ sample data.
+
+Creating the database on a remote server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In a production instance of Evergreen, your PostgreSQL server should be
+installed on a dedicated server.
+
+PostgreSQL 9.1 and later
+^^^^^^^^^^^^^^^^^^^^^^^^
+To create the database instance on a remote database server running PostgreSQL
+9.1 or later, simply use the `--create-database` flag on `eg_db_config`.
+
+Starting Evergreen
+------------------
+1. As the *root* Linux account, start the `memcached` and `ejabberd` services
+(if they aren't already running):
++
+[source, bash]
+------------------------------------------------------------------------------
+/etc/init.d/ejabberd start
+/etc/init.d/memcached start
+------------------------------------------------------------------------------
++
+2. As the *opensrf* Linux account, start Evergreen. The `-l` flag in the
+following command is only necessary if you want to force Evergreen to treat the
+hostname as `localhost`; if you configured `opensrf.xml` using the real
+hostname of your machine as returned by `perl -ENet::Domain 'print
+Net::Domain::hostfqdn() . "\n";'`, you should not use the `-l` flag.
++
+[source, bash]
+------------------------------------------------------------------------------
+osrf_control -l --start-all
+------------------------------------------------------------------------------
++
+ ** If you receive the error message `bash: osrf_control: command not found`,
+ then your environment variable `PATH` does not include the `/openils/bin`
+ directory; this should have been set in the *opensrf* Linux account's
+ `.bashrc` configuration file. To manually set the `PATH` variable, edit the
+ configuration file `~/.bashrc` as the *opensrf* Linux account and add the
+ following line:
++
+[source, bash]
+------------------------------------------------------------------------------
+export PATH=$PATH:/openils/bin
+------------------------------------------------------------------------------
++
+3. As the *opensrf* Linux account, generate the Web files needed by the staff
+ client and catalogue and update the organization unit proximity (you need to do
+ this the first time you start Evergreen, and after that each time you change the library org unit configuration.
+):
++
+[source, bash]
+------------------------------------------------------------------------------
+autogen.sh
+------------------------------------------------------------------------------
++
+4. As the *root* Linux account, restart the Apache Web server:
++
+[source, bash]
+------------------------------------------------------------------------------
+/etc/init.d/apache2 restart
+------------------------------------------------------------------------------
++
+If the Apache Web server was running when you started the OpenSRF services, you
+might not be able to successfully log in to the OPAC or staff client until the
+Apache Web server is restarted.
+
+Testing connections to Evergreen
+--------------------------------
+
+Once you have installed and started Evergreen, test your connection to
+Evergreen via `srfsh`. As the *opensrf* Linux account, issue the following
+commands to start `srfsh` and try to log onto the Evergreen server using the
+*egadmin* Evergreen administrator user name and password that you set using the
+`eg_db_config` command:
+
+[source, bash]
+------------------------------------------------------------------------------
+/openils/bin/srfsh
+srfsh% login <admin-user> <admin-pass>
+------------------------------------------------------------------------------
+
+You should see a result like:
+
+ Received Data: "250bf1518c7527a03249858687714376"
+ ------------------------------------
+ Request Completed Successfully
+ Request Time in seconds: 0.045286
+ ------------------------------------
+
+ Received Data: {
+ "ilsevent":0,
+ "textcode":"SUCCESS",
+ "desc":" ",
+ "pid":21616,
+ "stacktrace":"oils_auth.c:304",
+ "payload":{
+ "authtoken":"e5f9827cc0f93b503a1cc66bee6bdd1a",
+ "authtime":420
+ }
+
+ }
+
+ ------------------------------------
+ Request Completed Successfully
+ Request Time in seconds: 1.336568
+ ------------------------------------
+[[install-troubleshooting-1]]
+If this does not work, it's time to do some troubleshooting.
+
+ * As the *opensrf* Linux account, run the `settings-tester.pl` script to see
+ if it finds any system configuration problems. The script is found at
+ `Open-ILS/src/support-scripts/settings-tester.pl` in the Evergreen source
+ tree.
+ * Follow the steps in the http://evergreen-ils.org/dokuwiki/doku.php?id=troubleshooting:checking_for_errors[troubleshooting guide].
+ * If you have faithfully followed the entire set of installation steps
+ listed here, you are probably extremely close to a working system.
+ Gather your configuration files and log files and contact the
+ http://evergreen-ils.org/communicate/mailing-lists/[Evergreen development
+mailing list] for assistance before making any drastic changes to your system
+ configuration.
+
+Getting help
+------------
+
+Need help installing or using Evergreen? Join the mailing lists at
+http://evergreen-ils.org/communicate/mailing-lists/ or contact us on the Freenode
+IRC network on the #evergreen channel.
+
+License
+-------
+This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
+Unported License. To view a copy of this license, visit
+http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative
+Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
--- /dev/null
+Upgrading the Evergreen Server
+------------------------------
+Before upgrading, it is important to carefully plan an upgrade strategy to minimize system downtime and service interruptions.
+All of the steps in this chapter are to be completed from the command line.
+
+Software Prerequisites
+~~~~~~~~~~~~~~~~~~~~~~
+
+ * **PostgreSQL**: Version 9.3 is recommended. The minimum supported version
+ is 9.1.
+ * **Linux**: Evergreen 2.10.1 has been tested on Debian Jessie (8.0),
+ Debian Wheezy (7.0), Ubuntu Xenial Xerus (16.04), Ubuntu Trusty Tahr (14.04),
+ and Fedora.
+ If you are running an older version of these distributions, you may want
+ to upgrade before upgrading Evergreen. For instructions on upgrading these
+ distributions, visit the Debian, Ubuntu or Fedora websites.
+ * **OpenSRF**: The minimum supported version of OpenSRF is 2.4.0.
+
+
+In the following instructions, you are asked to perform certain steps as either the *root* or *opensrf* user.
+
+ * **Debian**: To become the *root* user, issue the `su` command and enter the password of the root user.
+ * **Ubuntu**: To become the *root* user, issue the `sudo su` command and enter the password of your current user.
+
+To switch from the *root* user to a different user, issue the `su - [user]`
+command; for example, `su - opensrf`. Once you have become a non-root user, to
+become the *root* user again simply issue the `exit` command.
+
+Upgrade the Evergreen code
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+The following steps guide you through a simplistic upgrade of a production
+server. You must adjust these steps to accommodate your customizations such
+as catalogue skins.
+
+. Stop Evergreen and back up your data:
+ .. As *root*, stop the Apache web server.
+ .. As the *opensrf* user, stop all Evergreen and OpenSRF services:
++
+[source, bash]
+-----------------------------
+osrf_control --localhost --stop-all
+-----------------------------
++
+ .. Back up the /openils directory.
+. Upgrade OpenSRF. Download and install the latest version of OpenSRF from
+the https://evergreen-ils.org/opensrf-downloads/[OpenSRF download page].
+. As the *opensrf* user, download and extract Evergreen 2.10.1:
++
+[source, bash]
+-----------------------------------------------
+wget https://evergreen-ils.org/downloads/Evergreen-ILS-2.10.1.tar.gz
+tar xzf Evergreen-ILS-2.10.1.tar.gz
+-----------------------------------------------
++
+[NOTE]
+For the latest edition of Evergreen, check the https://evergreen-ils.org/egdownloads/[Evergreen download page] and adjust upgrading instructions accordingly.
+
+. As the *root* user, install the prerequisites:
++
+[source, bash]
+---------------------------------------------
+cd /home/opensrf/Evergreen-ILS-2.10.1
+---------------------------------------------
++
+On the next command, replace `[distribution]` with one of these values for your
+distribution of Debian or Ubuntu:
++
+indexterm:[Linux, Debian]
+indexterm:[Linux, Ubuntu]
++
+ * `debian-jessie` for Debian Jessie (8.0) (See https://bugs.launchpad.net/evergreen/+bug/1342227[Bug 134222] if you want to use EDI)
+ * `debian-wheezy` for Debian Wheezy (7.0)
+ * `ubuntu-xenial` for Ubuntu Xenial Xerus (16.04) (EDI compatibility in progress)
+ * `ubuntu-trusty` for Ubuntu Trusty Tahr (14.04) (See https://bugs.launchpad.net/evergreen/+bug/1342227[Bug 134222] if you want to use EDI)
+ * `fedora` for Fedora
+
++
+[source, bash]
+------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install [distribution]
+------------------------------------------------------------
++
+. As the *opensrf* user, configure and compile Evergreen:
++
+[source, bash]
+------------------------------------------------------------
+cd /home/opensrf/Evergreen-ILS-2.10.1
+PATH=/openils/bin:$PATH ./configure --prefix=/openils --sysconfdir=/openils/conf
+make
+------------------------------------------------------------
++
+These instructions assume that you have also installed OpenSRF under /openils/. If not, please adjust PATH as needed so that the Evergreen configure script can find osrf_config.
++
+. As the *root* user, install Evergreen:
++
+[source, bash]
+------------------------------------------------------------
+cd /home/opensrf/Evergreen-ILS-2.10.1
+make STAFF_CLIENT_STAMP_ID=rel_2_10_1 install
+------------------------------------------------------------
++
+. As the *root* user, change all files to be owned by the opensrf user and group:
++
+[source, bash]
+------------------------------------------------------------
+chown -R opensrf:opensrf /openils
+------------------------------------------------------------
++
+. As the *opensrf* user, update the server symlink in /openils/var/web/xul/:
++
+[source, bash]
+-----------------------------------------------------------
+cd /openils/var/web/xul/
+rm server
+ln -sf rel_2_10_1/server server
+----------------------------------------------------------
++
+. As the *opensrf* user, update opensrf_core.xml and opensrf.xml by copying the
+ new example files (/openils/conf/opensrf_core.xml.example and
+ /openils/conf/opensrf.xml). The _-b_ option creates a backup copy of the old file.
++
+[source, bash]
+----------------------------------------------------------
+cp -b /openils/conf/opensrf_core.xml.example /openils/conf/opensrf_core.xml
+cp -b /openils/conf/opensrf.xml.example /openils/conf/opensrf.xml
+----------------------------------------------------------
++
+[CAUTION]
+Copying these configuration files will remove any customizations you have made to them. Remember to redo your customizations after copying them.
++
+. As the *opensrf* user, update the configuration files:
++
+[source, bash]
+-------------------------------------------------------------------------
+cd /home/opensrf/Evergreen-ILS-2.10.1
+perl Open-ILS/src/support-scripts/eg_db_config --update-config --service all \
+--create-offline --database evergreen --host localhost --user evergreen --password evergreen
+-------------------------------------------------------------------------
++
+. As the *root* user, update the Apache files:
++
+indexterm:[Apache]
++
+Use the example configuration files in `Open-ILS/examples/apache/` (for
+Apache versions below 2.4) or `Open-ILS/examples/apache_24/` (for Apache
+versions 2.4 or greater) to configure your Web server for the Evergreen
+catalog, staff client, Web services, and administration interfaces. Issue the
+following commands as the *root* Linux account:
++
+[CAUTION]
+Copying these Apache configuration files will remove any customizations you have made to them. Remember to redo your customizations after copying them.
+For example, if you purchased an SSL certificate, you will need to edit eg.conf to point to the appropriate SSL certificate files.
+The diff command can be used to show the differences between the distribution version and your customized version. `diff <customized file> <dist file>`
++
+.. Update _/etc/apache2/eg_startup_ by copying the example from _Open-ILS/examples/apache/eg_startup_.
++
+[source, bash]
+----------------------------------------------------------
+cp /home/opensrf/Evergreen-ILS-2.10.1/Open-ILS/examples/apache/eg_startup /etc/apache2/eg_startup
+----------------------------------------------------------
++
+.. Update /etc/apache2/eg_vhost.conf by copying the example from Open-ILS/examples/apache/eg_vhost.conf.
++
+[source, bash]
+----------------------------------------------------------
+cp /home/opensrf/Evergreen-ILS-2.10.1/Open-ILS/examples/apache/eg_vhost.conf /etc/apache2/eg_vhost.conf
+----------------------------------------------------------
++
+.. Update /etc/apache2/sites-available/eg.conf by copying the example from Open-ILS/examples/apache/eg.conf.
++
+[source, bash]
+----------------------------------------------------------
+cp /home/opensrf/Evergreen-ILS-2.10.1/Open-ILS/examples/apache/eg.conf /etc/apache2/sites-available/eg.conf
+----------------------------------------------------------
+
+Upgrade the Evergreen database schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+indexterm:[database schema]
+
+The upgrade of the Evergreen database schema is the lengthiest part of the
+upgrade process for sites with a significant amount of production data.
+
+Before running the upgrade script against your production Evergreen database,
+back up your database, restore it to a test server, and run the upgrade script
+against the test server. This enables you to determine how long the upgrade
+will take and whether any local customizations present problems for the
+stock upgrade script that require further tailoring of the upgrade script.
+The backup also enables you to cleanly restore your production data if
+anything goes wrong during the upgrade.
+
+[NOTE]
+=============
+Evergreen provides incremental upgrade scripts that allow you to upgrade
+from one minor version to the next until you have the current version of
+the schema. For example, if you want to upgrade from 2.5.1 to 2.10.1, you
+would run the following upgrade scripts:
+
+- 2.5.1-2.5.2-upgrade-db.sql
+- 2.5.2-2.5.3-upgrade-db.sql
+- 2.5.3-2.6.0-upgrade-db.sql (this is a major version upgrade)
+- 2.6.2-2.6.3-upgrade-db.sql
+- 2.6.3-2.7.0-upgrade-db.sql (this is a major version upgrade)
+- 2.7.0-2.7.1-upgrade-db.sql
+- 2.7.1-2.7.2-upgrade-db.sql
+- 2.7.2-2.7.3-upgrade-db.sql
+- 2.7.3-2.7.4-upgrade-db.sql
+- 2.7.4-2.8.0-upgrade-db.sql (this is a major version upgrade)
+- 2.8.0-2.8.1-upgrade-db.sql
+- 2.8.1-2.8.2-upgrade-db.sql
+- 2.8.2-2.8.3-upgrade-db.sql
+- 2.8.3-2.8.4-upgrade-db.sql
+- 2.8.4-2.9.0-upgrade-db.sql (this is a major version upgrade)
+- 2.9.0-2.9.1-upgrade-db.sql
+- 2.9.1-2.9.2-upgrade-db.sql
+- 2.9.2-2.9.3-upgrade-db.sql
+- 2.9.3-2.10.0-upgrade-db.sql
+- 2.10.0-2.10.1-upgrade-db.sql
+
+Note that you do *not* want to run additional 2.5 scripts to upgrade to the
+newest version of 2.5, since currently there is no automated way to upgrade
+from 2.5.4+ to 2.6. Only upgrade as far as necessary to reach the major
+version upgrade script (in this example, as far as 2.5.3).
+
+To upgrade across multiple major versions (e.g. from 2.3.0 to 2.10.1), use
+the same logic to utilize the provided major version upgrade scripts. For
+example:
+
+- 2.3-2.4.0-upgrade-db.sql
+- 2.3-2.4-supplemental.sh
+- (run all incremental scripts from 2.4.0 to 2.4.3)
+- 2.4.3-2.5.0-upgrade-db.sql
+- (run all incremental scripts from 2.5.0 to 2.5.3)
+- 2.5.3-2.6.0-upgrade-db.sql
+- (run all incremental scripts from 2.6.0 to 2.6.3)
+- 2.6.3-2.7.0-upgrade-db.sql
+- (run all incremental scripts from 2.7.0 to 2.7.4)
+- 2.7.4-2.8.0-upgrade-db.sql
+- (run all incremental scripts from 2.8.0 to 2.8.4)
+- 2.8.4-2.9.0-upgrade-db.sql
+- (run all incremental scripts from 2.9.0 to 2.9.3)
+- 2.9.3-2.10.0-upgrade-db.sql
+- (run all incremental scripts from 2.10.0 to 2.10.1)
+=============
+
+[CAUTION]
+Pay attention to error output as you run the upgrade scripts. If you encounter errors
+that you cannot resolve yourself through additional troubleshooting, please
+report the errors to the https://evergreen-ils.org/communicate/mailing-lists/[Evergreen
+Technical Discussion List].
+
+Run the following steps (including other upgrade scripts, as noted above)
+as a user with the ability to connect to the database server.
+
+[source, bash]
+----------------------------------------------------------
+cd /home/opensrf/Evergreen-ILS-2.10.0/Open-ILS/src/sql/Pg
+psql -U evergreen -h localhost -f version-upgrade/2.10.0-2.10.1-upgrade-db.sql evergreen
+----------------------------------------------------------
+
+[TIP]
+After the some database upgrade scripts finish, you may see a
+note on how to reingest your bib records. You may run this after you have
+completed the entire upgrade and tested your system. Reingesting records
+may take a long time depending on the number of bib records in your system.
+
+Restart Evergreen and Test
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+. As the *root* user, restart memcached to clear out all old user sessions.
++
+[source, bash]
+--------------------------------------------------------------
+service memcached restart
+--------------------------------------------------------------
++
+. As the *opensrf* user, start all Evergreen and OpenSRF services:
++
+[source, bash]
+--------------------------------------------------------------
+osrf_control --localhost --start-all
+--------------------------------------------------------------
++
+. As the *opensrf* user, run autogen to refresh the static organizational data files:
++
+[source, bash]
+--------------------------------------------------------------
+cd /openils/bin
+./autogen.sh
+--------------------------------------------------------------
++
+. Start srfsh and try logging in using your Evergreen username and password:
++
+[source, bash]
+--------------------------------------------------------------
+/openils/bin/srfsh
+srfsh% login username password
+--------------------------------------------------------------
++
+You should see a result like:
++
+[source, bash]
+------------------------------------------------------
+Received Data: "250bf1518c7527a03249858687714376"
+ ------------------------------------
+ Request Completed Successfully
+ Request Time in seconds: 0.045286
+ ------------------------------------
+
+ Received Data: {
+ "ilsevent":0,
+ "textcode":"SUCCESS",
+ "desc":" ",
+ "pid":21616,
+ "stacktrace":"oils_auth.c:304",
+ "payload":{
+ "authtoken":"e5f9827cc0f93b503a1cc66bee6bdd1a",
+ "authtime":420
+ }
+
+ }
+
+ ------------------------------------
+ Request Completed Successfully
+ Request Time in seconds: 1.336568
+ ------------------------------------
+----------------------------------------------------------
++
+If this does not work, it's time to do some <<install-troubleshooting-1,troubleshooting>>.
++
+. As the *root* user, start the Apache web server.
++
+If you encounter errors, refer to the <<install-troubleshooting-1,troubleshooting>> section
+of this documentation for tips on finding solutions and seeking further assistance
+from the Evergreen community.
+
+Review Release Notes
+~~~~~~~~~~~~~~~~~~~~
+
+Review the <<_evergreen_2_10_release_notes,2.10 release notes>> for other tasks
+that need to be done after upgrading. If you have upgraded over several
+major versions, you will need to review the release notes for each version also.
--- /dev/null
+Installing the Staff Client
+---------------------------
+
+Installing on Windows
+~~~~~~~~~~~~~~~~~~~~~
+
+anchor:installing_staff_client_on_Windows[]
+
+indexterm:[staff client, installation, Windows]
+
+Official Evergreen releases have corresponding Windows based staff clients ready
+to use.
+
+. Download the staff client from http://www.open-ils.org/downloads.php.
++
+[NOTE]
+===============
+The version of your staff client will
+need to match the version of your Evergreen server. If you are unsure about the
+version of your Evergreen server, contact your system administrator.
+===============
++
+. Click on the downloaded Evergreen setup file.
+. Click _Next_ to begin installation:
++
+image::media/staff_client_installation_0.png[]
++
+. Click _Next_ to accept
+destination folder.
++
+image::media/staff_client_installation_1.png[]
++
+. Click _Install_.
++
+image::media/staff_client_installation_2.png[]
++
+. A pop-up should appear indicating that Evergreen has been installed.
+Click _Finish_ to complete the installation.
+
+image::media/staff_client_installation_3.png[]
+
+When you login to Evergreen from the workstation for the first time, you will
+also need to <<register_workstation,register your workstation>>.
+
+Installing on Linux
+~~~~~~~~~~~~~~~~~~~
+
+indexterm:[staff client, installation, Linux]
+
+. On the Evergreen *server*, navigate to the `staff_client` directory inside
+ the Evergreen source:
++
+[source, bash]
+--------
+cd /path/to/Evergreen/Open-ILS/xul/staff_client
+--------
++
+. As the *root* user, build release versions of staff clients for both
+ 32-bit and 64-bit Linux systems:
++
+[source, bash]
+--------
+make rigrelease rebuild linux32-updates-client linux64-updates-client
+make install
+--------
++
+This builds and copies two staff client tarballs for Linux to the `updates`
+directory on the Web server.
++
+. As the *root* user, reset the ownership of the Evergreen install directory
+ to the *opensrf* user. For example, if your install directory is `/openils`:
++
+[source, bash]
+--------
+chown -R opensrf:opensrf /openils
+--------
++
+. On your staff client workstation, download the 32-bit or 64-bit version of
+ the staff client from your Web server at
+ http://hostname/updates/manualupdate.html (where _hostname_ represents the
+ hostname of your Web server).
+. On your staff client workstation, create a directory with the name of your
+ staff client and version.
+. Extract the tar files into that directory.
+. Within the directory, click on the `evergreen` file to start the program.
++
+Or, you can run the program from a terminal (command line). For example, if the
+staff client files were extracted to a directory called `evergreen_client` in
+your home directory, you can run it with:
++
+[source, bash]
+--------
+~/evergreen_client/evergreen
+--------
+
+Registering a Workstation
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+anchor:register_workstation[]
+
+
+indexterm:[staff client, registering a workstation]
+
+Before you can connect to Evergreen from your staff client, you will need to
+register your workstation when you try to login.
+
+[NOTE]
+===============
+You will need the permissions to add workstations to your network. If you do
+not have these permissions, ask your system administrator for assistance.
+===============
+
+. When you login for the first time, a red box will appear around your workstation
+information on the right side of the screen.
++
+image::media/staff_client_installation_4.png[]
++
+. Create a unique workstation name or use the default computer name provided.
+. Click _Register_
+. You will now be able to log into the system.
+
+Removing Staff Client Preferences
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+indexterm:[staff client, removing user preferences]
+indexterm:[staff client, removing user settings]
+
+Windows
+^^^^^^^
+
+When you uninstall the Evergreen staff client code from your system, the staff
+client preferences and cached data are not removed from your system. This can
+be a problem if, for example, you have registered your workstation with the
+wrong library; or if you have chosen a display language (locale) that is broken
+and will not let you start up the client again
+
+On Windows, you can uninstall the Evergreen staff client code using the
+Add/Remove Programs menu.
+
+To remove the staff client preferences and cached data entirely on Windows,
+there are two directories that you must delete completely (where _<profile>_
+represents your user profile name):
+
+* *C:\Documents and Settings\<profile>\Application Data\OpenILS*
+* *C:\Documents and Settings\<profile>\Local Settings\Application Data\OpenILS*
+
+You might need to change the preferences in Windows Explorer to display hidden
+files (Tools -> Folder Options… -> View).
+
+Linux
+^^^^^
+
+To remove the staff client preferences and cached data from your user account
+on Linux, there is one directory that you must delete completely:
+
+[source, bash]
+----------
+rm -fr ~/.openils
+----------
+
--- /dev/null
+System Requirements
+-------------------
+
+Server Minimum Requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following are the base requirements setting Evergreen up on a test server:
+
+ * An available desktop, server or virtual image
+ * 4GB RAM, or more if your server also runs a graphical desktop
+ * Linux Operating System (community supports Debian, Ubuntu, or Fedora)
+ * Ports 80 and 443 should be opened in your firewall for TCP connections to allow OPAC and staff client connections to the Evergreen server.
+
+Staff Client Requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Staff terminals connect to the central database using the Evergreen staff client, available for download from The Evergreen download page.
+The staff client must be installed on each staff workstation and requires at minimum:
+
+ * Windows, Mac OS X, or Linux operating system
+ * a reliable high speed Internet connection
+ * 2GB RAM
+ * The staff client uses the TCP protocol on ports 80 and 443 to communicate with the Evergreen server.
+
+*Barcode Scanners*
+
+Evergreen will work with virtually any barcode scanner – if it worked with your legacy system it should work on Evergreen.
+
+*Printers*
+
+Evergreen can use any printer configured for your terminal to print receipts, check-out slips, holds lists, etc. The single exception is spine label printing,
+which is still under development. Evergreen currently formats spine labels for output to a label roll printer. If you do not have a roll printer manual formatting may be required.
--- /dev/null
+TPac Configuration and Customization
+------------------------------------
+
+Template toolkit documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For more general information about template toolkit see: http://template-toolkit.org/docs/index.html[official
+documentation].
+
+The purpose of this chapter is to focus on the
+Evergreen-specific uses of Template Toolkit ('TT') in the OPAC.
+
+TPAC URL
+~~~~~~~~
+
+The URL for the TPAC on a default Evergreen system is
+http://localhost/eg/opac/home (adjust `localhost` to match your hostname or IP
+address, naturally!)
+
+Perl modules used directly by TPAC
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ * `Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm`
+ * `Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm`
+ * `Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm`
+ * `Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm`
+ * `Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm`
+ * `Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm`
+
+Default templates
+~~~~~~~~~~~~~~~~~
+
+The source template files are found in `Open-ILS/src/templates/opac`.
+
+These template files are installed in `/openils/var/templates/opac`.
+
+.NOTE
+You should generally avoid touching the installed default template files,
+unless you are contributing changes that you want Evergreen to adopt as a new
+default. Even then, while you are developing your changes, consider using
+template overrides rather than touching the installed templates until you are
+ready to commit the changes to a branch. See below for information on template
+overrides.
+
+Apache configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The base Evergreen configuration file on Debian-based systems can be found in
+`/etc/apache2/sites-enabled/eg.conf`. This file defines the basic virtual host
+configuration for Evergreen (hostnames and ports), then single-sources the
+bulk of the configuration for each virtual host by including
+`/etc/apache2/eg_vhost.conf`.
+
+TPAC CSS and media files
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The CSS files used by the default TPAC templates are stored in the repo in
+`Open-ILS/web/css/skin/default/opac/` and installed in
+`/openils/var/web/css/skin/default/opac/`.
+
+The media files--mostly PNG images--used by the default TPAC templates are
+stored in the repo in `Open-ILS/web/images/` and installed in
+`/openils/var/web/images/`.
+
+Mapping templates to URLs
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The mapping for templates to URLs is straightforward. Following are a few
+examples, where `<templates>` is a placeholder for one or more directories
+that will be searched for a match:
+
+ * `http://localhost/eg/opac/home` => `/openils/var/<templates>/opac/home.tt2`
+ * `http://localhost/eg/opac/advanced` => `/openils/var/<templates>/opac/advanced.tt2`
+ * `http://localhost/eg/opac/results` => `/openils/var/<templates>/opac/results.tt2`
+
+The template files themselves can process, be wrapped by, or include other
+template files. For example, the `home.tt2` template currently involves a
+number of other template files to generate a single HTML file:
+
+.Example Template Toolkit file: opac/home.tt2
+[source, html]
+------------------------------------------------------------------------------
+[% PROCESS "opac/parts/header.tt2";
+ WRAPPER "opac/parts/base.tt2";
+ INCLUDE "opac/parts/topnav.tt2";
+ ctx.page_title = l("Home") %]
+ <div id="search-wrapper">
+ [% INCLUDE "opac/parts/searchbar.tt2" %]
+ </div>
+ <div id="content-wrapper">
+ <div id="main-content-home">
+ <div class="common-full-pad"></div>
+ [% INCLUDE "opac/parts/homesearch.tt2" %]
+ <div class="common-full-pad"></div>
+ </div>
+ </div>
+[% END %]
+------------------------------------------------------------------------------
+
+We will dissect this example in some more detail later, but the important
+thing to note is that the file references are relative to the top of the
+template directory.
+
+How to override templates
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Overrides for templates go in a directory that parallels the structure of the
+default templates directory. The overrides then get pulled in via the Apache
+configuration.
+
+In the following example, we demonstrate how to create a file that overrides
+the default "Advanced search page" (`advanced.tt2`) by adding a new templates
+directory and editing the new file in that directory.
+
+.Adding an override for the Advanced search page (example)
+[source, bash]
+------------------------------------------------------------------------------
+bash$ mkdir -p /openils/var/templates_custom/opac
+bash$ cp /openils/var/templates/opac/advanced.tt2 \
+ /openils/var/templates_custom/opac/.
+bash$ vim /openils/var/templates_custom/opac/advanced.tt2
+------------------------------------------------------------------------------
+
+We now need to teach Apache about the new templates directory. Open `eg.conf`
+and add the following `<Location /eg>` element to each of the `<VirtualHost>`
+elements in which you want to include the overrides. The default Evergreen
+configuration includes a `VirtualHost` directive for port 80 (HTTP) and another
+one for port 443 (HTTPS); you probably want to edit both, unless you want the
+HTTP user experience to be different from the HTTPS user experience.
+
+.Configuring the custom templates directory in Apache's eg.conf
+[source,xml]
+------------------------------------------------------------------------------
+<VirtualHost *:80>
+ # <snip>
+
+ # - absorb the shared virtual host settings
+ Include eg_vhost.conf
+ <Location /eg>
+ PerlAddVar OILSWebTemplatePath "/openils/var/templates_algoma"
+ </Location>
+
+ # <snip>
+</VirtualHost>
+------------------------------------------------------------------------------
+
+Finally, reload the Apache configuration to pick up the changes:
+
+.Reloading the Apache configuration
+[source,bash]
+------------------------------------------------------------------------------
+bash# /etc/init.d/apache2 reload
+------------------------------------------------------------------------------
+
+You should now be able to see your change at http://localhost/eg/opac/advanced
+
+Defining multiple layers of overrides
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can define multiple layers of overrides, so if you want every library in
+your consortium to have the same basic customizations, and then apply
+library-specific customizations, you can define two template directories for
+each library.
+
+In the following example, we define the `template_CONS` directory as the set of
+customizations to apply to all libraries, and `template_BR#` as the set of
+customizations to apply to library BR1 and BR2.
+
+As the consortial customizations apply to all libraries, we can add the
+extra template directory directly to `eg_vhost.conf`:
+
+.Apache configuration for all libraries (eg_vhost.conf)
+[source,xml]
+------------------------------------------------------------------------------
+# Templates will be loaded from the following paths in reverse order.
+PerlAddVar OILSWebTemplatePath "/openils/var/templates"
+PerlAddVar OILSWebTemplatePath "/openils/var/templates_CONS"
+------------------------------------------------------------------------------
+
+Then we define a virtual host for each library to add the second layer of
+customized templates on a per-library basis. Note that for the sake of brevity
+we only show the configuration for port 80.
+
+.Apache configuration for each virtual host (eg.conf)
+[source,xml]
+------------------------------------------------------------------------------
+<VirtualHost *:80>
+ ServerName br1.concat.ca
+ DocumentRoot /openils/var/web/
+ DirectoryIndex index.html index.xhtml
+ Include eg_vhost.conf
+ <Location /eg>
+ PerlAddVar OILSWebTemplatePath "/openils/var/templates_BR1"
+ </Location>
+</VirtualHost>
+
+<VirtualHost *:80>
+ ServerName br2.concat.ca
+ DocumentRoot /openils/var/web/
+ DirectoryIndex index.html index.xhtml
+ Include eg_vhost.conf
+ <Location /eg>
+ PerlAddVar OILSWebTemplatePath "/openils/var/templates_BR2"
+ </Location>
+</VirtualHost>
+------------------------------------------------------------------------------
+
+Changing some text in the TPAC
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Out of the box, the TPAC includes a number of placeholder text and links. For
+example, there is a set of links cleverly named 'Link 1', 'Link 2', and so on
+in the header and footer of every page in the TPAC. Let's customize that for
+our `templates_BR1` skin.
+
+To begin with, we need to find the page(s) that contain the text in question.
+The simplest way to do that is with the handy utility `ack`, which is much
+like `grep` but with built-in recursion and other tricks. On Debian-based
+systems, the command is `ack-grep` as `ack` conflicts with an existing utility.
+In the following example, we search for files that contain the text "Link 1":
+
+.Searching for text matching "Link 1"
+[source,bash]
+------------------------------------------------------------------------------
+bash$ ack-grep "Link 1" /openils/var/templates/opac
+/openils/var/templates/opac/parts/topnav_links.tt2
+4: <a href="http://example.com">[% l('Link 1') %]</a>
+------------------------------------------------------------------------------
+
+Next, we copy the file into our overrides directory and edit it with `vim`:
+
+.Copying the links file into the overrides directory
+[source,bash]
+------------------------------------------------------------------------------
+bash$ cp /openils/var/templates/opac/parts/topnav_links.tt2 \
+ /openils/var/templates_BR1/opac/parts/topnav_links.tt2
+bash$ vim /openils/var/templates_BR1/opac/parts/topnav_links.tt2
+------------------------------------------------------------------------------
+
+Finally, we edit the link text in `opac/parts/header.tt2`.
+
+.Content of the opac/parts/header.tt2 file
+[source,html]
+------------------------------------------------------------------------------
+<div id="gold-links-holder">
+ <div id="gold-links">
+ <div id="header-links">
+ <a href="http://example.com">[% l('Link 1') %]</a>
+ <a href="http://example.com">[% l('Link 2') %]</a>
+ <a href="http://example.com">[% l('Link 3') %]</a>
+ <a href="http://example.com">[% l('Link 4') %]</a>
+ <a href="http://example.com">[% l('Link 5') %]</a>
+ </div>
+ </div>
+</div>
+------------------------------------------------------------------------------
+
+For the most part, the page looks like regular HTML, but note the `[%_("`
+`")%]` that surrounds the text of each link. The `[% ... %]` signifies a TT
+block, which can contain one or more TT processing instructions. `l(" ... ");`
+is a function that marks text for localization (translation); a separate
+process can subsequently extract localized text as GNU gettext-formatted PO
+files.
+
+.NOTE
+As Evergreen supports multiple languages, any customizations to Evergreen's
+default text must use the localization function. Also, note that the
+localization function supports placeholders such as `[_1]`, `[_2]` in the text;
+these are replaced by the contents of variables passed as extra arguments to
+the `l()` function.
+
+Once we have edited the link and link text to our satisfaction, we can load
+the page in our Web browser and see the live changes immediately (assuming
+we are looking at the BR1 overrides, of course).
+
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+If there is a problem such as a TT syntax error, it generally shows up as a
+an ugly server failure page. If you check the Apache error logs, you will
+probably find some solid clues about the reason for the failure. For example,
+in the following example the error message identifies the file in which the
+problem occurred as well as the relevant line numbers:
+
+.Example error message in Apache error logs
+[source,bash]
+------------------------------------------------------------------------------
+bash# grep "template error" /var/log/apache2/error_log
+[Tue Dec 06 02:12:09 2011] [warn] [client 127.0.0.1] egweb: template error:
+ file error - parse error - opac/parts/record/summary.tt2 line 112-121:
+ unexpected token (!=)\n [% last_cn = 0;\n FOR copy_info IN
+ ctx.copies;\n callnum = copy_info.call_number_label;\n
+------------------------------------------------------------------------------
+
--- /dev/null
+Receipt Template Editor
+-----------------------
+indexterm:[receipt template editor]
+indexterm:[receipt template editor, macros]
+indexterm:[receipt template editor, checkout]
+
+There are many default receipt templates included with the Evergreen staff client. These templates are saved on individual workstations. Customization can be done workstation by workstation or by exporting the templates to import to other workstations.
+
+All receipts in Evergreen follow a basic format of a _Header_, _Line item_ and _Footer_.
+
+The receipt templates follow full W3C html. http://w3schools.com/html/default.asp.
+
+The Receipt Template Editor can be found at: *Admin -> Workstation Administration -> Receipt Template Editor*
+
+The Editor can also be found on the default home page of the staff client.
+
+Receipts come in various types: Bills, checkout, items, holds, transits and Payments.
+
+To edit a Receipt:
+
+. Select *Admin -> Workstation Administration -> Receipt Template Editor*.
+
+. Choose the Receipt in the drop down list.
++
+image::media/receipt-2.png[select checkout]
++
+. Make edits to the Receipt on the right hand side.
++
+image::media/receipt-3.jpg[receipt-3]
++
+. Click out of the section you are editing to see what your changes will look right on the Left hand side.
++
+image::media/receipt-3.jpg[receipt-3]
++
+. Click ''Save Locally'' in the Upper right hand corner.
++
+image::media/receipt-15.jpg[receipt-15]
+
+
+Receipt templates use macros for various pieces of information coming from the Evergreen database. Macros deal with everything from the Library name to the due date of an item. See list <<macros, Receipt Macros for the macros>>. You can also click on MACROS on the screen to see the macros that are available for a given receipt.
+
+IMPORTANT: *Remember:* Not all Macros listed on the pop up screen will work. The listing of macros are drawn from the table that the receipt pulls information from. Some of the tables will not have any data in some of the fields. Example is the %mbts_xact_finish% on the Bills Current Slip, as this is a list of current bills, they would not have a finish date.
+
+Exporting and importing Customized Receipts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you have your receipts set up on one machine you can export your receipts, and then load them on to another machine. Just remember to ''Save Locally'' once you import the receipts on the new machine.
+
+Exporting templates
+^^^^^^^^^^^^^^^^^^^
+As you can only save a template on to the computer you are working on you will need to export the template if you have more than one computer that prints out receipts (i.e., more than one computer on the circulation desk, or another computer in the workroom that you use to checkin items or capture holds with)
+
+. Export.
+. Select the location to save the template to, name the template, and click Save.
+. Click OK.
++
+image::media/receipt-17.jpg[receipt-17]
+
+
+Importing Templates
+^^^^^^^^^^^^^^^^^^^
+
+. Click Import.
++
+image::media/receipt-20.jpg[receipt-20]
++
+. Navigate to and select the template that you want to import. Click Open.
++
+image::media/receipt-21.jpg[receipt-21]
++
+. Click OK.
+. Click Save Locally.
+. Click OK.
++
+image::media/receipt-23.jpg[receipts-23]
+
+Receipt Customizations
+~~~~~~~~~~~~~~~~~~~~~~
+
+Customizing the receipts is fairly simple once you realize what can be placed in each of the sections of the receipts. One thing to remember when customizing receipts to always ''Save Locally''. Checkouts, Hold Slip, Hold Transit Slip are customized below.
+
+TIP: Always remember to ''Save Locally''.
+
+Print Holds Slip with Landscape Layout
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+indexterm:[receipt template editor, holds receipt, layout]
+
+This feature enables you to use Mozilla-specific CSS to print holds with a landscape layout. To use the landscape layout:
+
+. Click *Admin* -> *Workstation Administration* -> *Receipt Template Editor*.
+. Select *hold transit slip* from the *Template Name* drop down menu.
+. Enter <div> before and after the block of text that you wish to rotate.
+. Enter the stylesheet text in the <div> bracket that appears before the block of text that you wish to rotate:
++
+[source, html]
+------------------------
+<div style="moz-transform: rotate(90deg);">
+------------------------
+. When you click out of this box, notice that the text in the *Preview* box on the left side of the screen has rotated 90 degrees.
+. You can further customize the look of the text by adjusting its height and width. The height and width that you specify will be unique to your printer.
++
+For example, you could add the following height and width to your rotated text:
++
+[source, html]
+------------------------
+<div style="moz-transform: rotate(90deg);height: 300px; width: 200px;">
+------------------------
++
+image::media/Print_Holds_Slip1.jpg[Print_Holds_Slip1]
++
+. The holds slip will print with the configured text in a landscape layout:
++
+image::media/Print_Holds_Slip2.jpg[Print_Holds_Slip2]
+
+Checkout
+^^^^^^^^
+This is the receipt that prints when items are checked out to individuals. Item you can customize are adding the library logo, adding information about renewals on the bottom of the receipt. If you notice at the end of the Footer the <br/>.<br/>, the allows an auto cut printer a little extra room so it will not cut the phone number off. The period is needed so the extra lines are added.
+
+Header
+[source,html]
+----------------------------------------------------------------------------------
+<img align="center" src="http://www.library.org/images/logo.jpg"><br/>
+Welcome to %LIBRARY%!<br/>
+You checked out the following items:
+<hr/>
+<ol>
+----------------------------------------------------------------------------------
+Line Item
+[source,html]
+----------------------------------------------------------------------------------
+<li>%title%<br/>
+By: %author%<br/>
+Barcode: %barcode%<br/>
+Due: %due_date%
+----------------------------------------------------------------------------------
+Footer
+[source,html]
+----------------------------------------------------------------------------------
+</ol>
+<hr />
+%SHORTNAME% %TODAY_TRIM%<br/>
+You were helped by %STAFF_FIRSTNAME%<br/>
+<br/>
+<center>If you want to renew your materials please visit<br/>
+www.library.org<br/>
+or call us at ###-###-####</center>
+<br/>
+<br/>
+.<br/>
+----------------------------------------------------------------------------------
+
+Hold_Slip #1
+^^^^^^^^^^^^^
+This is the slip that prints when a hold is fulfilled. Things to customize are the patrons name at the top of the slip, Bold the %hold_for_msg%, among others.
+
+Header
+[source,html]
+----------------------------------------------------------------------------------
+<font size="6"><b>%PATRON_LASTNAME%, %PATRON_FIRSTNAME%</b>
+</font><br/><br/><br/><br/>
+This item needs to be routed to <b>%route_to%</b>:<br/>
+Barcode: %item_barcode%<br/>
+Title: %item_title%<br/>
+<br/>
+<b>%hold_for_msg%</b><br/>
+Barcode: %PATRON_BARCODE%<br/>
+Notify by phone: %notify_by_phone%<br/>
+Notify by email: %notify_by_email%<br/>
+----------------------------------------------------------------------------------
+Line Item
+[source,html]
+----------------------------------------------------------------------------------
+<em>%formatted_note%</em><br/>
+----------------------------------------------------------------------------------
+Footer
+[source,html]
+----------------------------------------------------------------------------------
+Request date: %request_date%<br/>
+<br/>
+Slip Date: %TODAY_D% %TODAY_I%:%TODAY_M%<br/>
+Printed by %STAFF_FIRSTNAME% at %SHORTNAME%<br/>.<br/>
+----------------------------------------------------------------------------------
+
+Hold_Slip #2
+^^^^^^^^^^^^^
+This is the slip that prints when a hold is fulfilled. This slip uses the SUBSTR macro to truncate the Patrons Last name to the first 4 characters and the patron's barcode to the last 5 digits. This slip is designed for libraries that use self-serve holds. So, you will notice a lot of information about the hold is left off of the receipt.
+
+Header
+[source,html]
+----------------------------------------------------------------------------------
+<p style="padding-top:80px; padding-bottom:80px">
+<font size="6"><b>
+%SUBSTR(0,4)%%PATRON_LASTNAME%%SUBSTR_END%
+ %SUBSTR(-5)%%PATRON_BARCODE%%SUBSTR_END%
+</b></font></p>
+</font><br/><br/><br/><br/>
+This item needs to be routed to <b>%route_to%</b>:<br/>
+Barcode: %item_barcode%<br/>
+Title: %item_title%<br/>
+<br/>
+Notify by phone: %notify_by_phone%<br/>
+----------------------------------------------------------------------------------
+Line Item
+[source,html]
+----------------------------------------------------------------------------------
+<em>%formatted_note%</em><br/>
+----------------------------------------------------------------------------------
+Footer
+[source,html]
+----------------------------------------------------------------------------------
+Request date: %request_date%<br/>
+<hr style="border: 1px dotted"/><br/>
+Slip Date: %TODAY_TRIM%<br/>
+Printed by %STAFF_FIRSTNAME% at %SHORTNAME%<br/>.<br/>
+----------------------------------------------------------------------------------
+
+Hold_transit_slip
+^^^^^^^^^^^^^^^^^^
+This is the slip that is printed when an Item is needed at another library for a hold. In this customization, the address of the library is removed, The library's shortname size is increased, and made a little more notable at top, and the patron's phone number and email address is removed from the slip.
+
+Header
+[source,html]
+----------------------------------------------------------------------------------
+<font size="5">Route to %route_to%</font><br/><br/><br/>
+This item needs to be routed to <b>%route_to%</b>:<br/>
+%route_to_org_fullname%<br/><br/>
+Barcode: %item_barcode%<br/>
+Title: %item_title%<br/>
+Author: %item_author%<br><br/>
+%hold_for_msg%<br/>
+Barcode: %PATRON_BARCODE%<br/>
+----------------------------------------------------------------------------------
+Line Item
+[source,html]
+----------------------------------------------------------------------------------
+<em>%formatted_note%</em><br/>
+----------------------------------------------------------------------------------
+Footer
+[source,html]
+----------------------------------------------------------------------------------
+<br/>Request date: %request_date%<br/>
+Slip Date: %TODAY_TRIM%<br/>
+Printed at %SHORTNAME%<br/>
+<br/><br/>.<br/>
+----------------------------------------------------------------------------------
+
+Receipt Templates
+~~~~~~~~~~~~~~~~~
+This is a complete list of all the receipts currently in use in Evergreen.
+
+[horizontal]
+*item_status*::
+type::: items
+description::: Listing of items inputted in to Item Status.
+default format:::
+header:::: The following items have been examined:<hr/><ol>
+line_item:::: <li>%title%<br/>Barcode: %barcode%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/><br/>
+
+*transit_list*::
+type::: transits
+description::: List of items in transit.
+default format:::
+header:::: Transits:<hr/><ol>
+line_item:::: <li>From: %transit_source% To: %transit_dest_lib%<br/>When: %transit_source_send_time%<br />Barcode: %transit_item_barcode% Title: %transit_item_title%<br/>
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/><br/>
+
+*items_out*::
+type::: items
+description::: List of items a patron has checked out.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have the following items:<hr/><ol>
+line_item:::: <li>%title%<br/>Barcode: %barcode% Due: %due_date%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*renew*::
+type::: items
+description::: List of items that have been renewed using the renew item screen
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have renewed the following items::<hr/><ol>
+line_item:::: <li>%title%<br/>Barcode: %barcode% Due: %due_date%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*checkout*::
+type::: items
+description::: List of items currently checked out to the patron during this transaction.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You checked out the following items::<hr/><ol>
+line_item:::: <li>%title%<br/>Barcode: %barcode% Due: %due_date%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*offline_checkout*::
+type::: offline_checkout
+description::: List of items checked out via the Standalone interface. Remember that Standalone interface does not have access to the database.
+default format:::
+header:::: Patron %patron_barcode%<br/>You checked out the following items::<hr/><ol>
+line_item:::: <li>Barcode: %barcode%<br/>Due: %due_date%
+footer:::: </ol><hr />%TODAY_TRIM%<br/><br/>
+
+*checkin*::
+type::: items
+description::: List of items that have just been entered in to the check-in screens.
+default format:::
+header:::: You checked in the following items:<hr/><ol>
+line_item:::: <li>%title%<br/>Barcode: %barcode% Call Number: %call_number%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/><br/>
+
+*bill_payment*::
+type::: payment
+description::: Patron payment receipt
+default format:::
+header::::
+Welcome to %LIBRARY%!<br/>
+A receipt of your transaction:
+<hr/> <table width="100%">
+<tr> <td>Original Balance:</td> <td align="right">$%original_balance%</td> </tr>
+<tr> <td>Payment Method:</td> <td align="right">%payment_type%</td> </tr>
+<tr> <td>Payment Received:</td> <td align="right">$%payment_received%</td> </tr>
+<tr> <td>Payment Applied:</td> <td align="right">$%payment_applied%</td> </tr>
+<tr> <td>Billings Voided:</td> <td align="right">%voided_balance%</td> </tr>
+<tr> <td>Change Given:</td> <td align="right">$%change_given%</td> </tr>
+<tr> <td>New Balance:</td> <td align="right">$%new_balance%</td> </tr> </table>
+<p> Note: %note% </p> <p> Specific bills: <blockquote>
+line_item::::
+Bill #%bill_id% %last_billing_type% Received: $%payment%<br />%barcode% %title%<br /><br />
+footer::::
+</blockquote> </p> <hr />%SHORTNAME% %TODAY_TRIM%<br/> <br/>
+
+*bills_historical*::
+type::: bills
+description::: Listing of bills that have had payments made on them. This is used on the Bill History Transaction screen.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You had the following bills:<hr/><ol>
+line_item:::: <dt><b>Bill #%mbts_id%</b> %title% </dt> <dd>
+<table> <tr valign="top"><td>Date::</td><td>%mbts_xact_start%</td></tr>
+<tr valign="top"><td>Type:</td><td>%xact_type%</td></tr>
+<tr valign="top"><td>Last Billing:</td><td>%last_billing_type%<br/>%last_billing_note%</td></tr>
+<tr valign="top"><td>Total Billed::</td><td>$%total_owed%</td></tr>
+<tr valign="top"><td>Last Payment::</td><td>%last_payment_type%<br/>%last_payment_note%</td></tr>
+<tr valign="top"><td>Total Paid::</td><td>$%total_paid%</td></tr>
+<tr valign="top"><td><b>Balance::</b></td><td><b>$%balance_owed%</b></td></tr> </table><br/>
+footer::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/><br/>
+
+*bills_current*::
+type::: bills
+description::: Listing of current bills for a patron.
+default format:::
+header::::
+Welcome to %LIBRARY%!<br/>
+You have the following bills:<hr/><ol>
+line_item:::: <dt><b>Bill #%mbts_id%</b></dt> <dd>
+<table> <tr valign="top"><td>Date:</td><td>%mbts_xact_start%</td></tr>
+<tr valign="top"><td>Type:</td><td>%xact_type%</td></tr>
+<tr valign="top"><td>Last Billing:</td><td>%last_billing_type%<br/>%last_billing_note%</td></tr>
+<tr valign="top"><td>Total Billed:</td><td>$%total_owed%</td></tr>
+<tr valign="top"><td>Last Payment:</td><td>%last_payment_type%<br/>%last_payment_note%</td></tr>
+<tr valign="top"><td>Total Paid:</td><td>$%total_paid%</td></tr>
+<tr valign="top"><td><b>Balance:</b></td><td><b>$%balance_owed%</b></td></tr> </table><br/>
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/><br/>
+
+*offline_checkin*::
+type::: offline_checkin
+description::: List of item checked in via Standalone interface. Remember that Standalone interface does not have access to the database.
+default format:::
+header:::: You checked in the following items:<hr/><ol>
+line_item:::: <li>Barcode: %barcode%
+footer:::: </ol><hr />%TODAY_TRIM%<br/><br/>
+
+*offline_renew*::
+type::: offline_renew
+description::: List of items renewed via Standalone interface. Remember that Standalone interface does not have access to the database.
+default format:::
+header:::: You renewed the following items:<hr/><ol>
+line_item:::: <li>Barcode: %barcode%
+footer:::: </ol><hr />%TODAY_TRIM%<br/><br/>
+
+*offline_inhouse_use*::
+type::: offline_inhouse_use
+description::: List of item marked in-house use via Standalone interface. Remember that Standalone interface does not have access to the database.
+default format:::
+header:::: You marked the following in-house items used:<hr/><ol>
+line_item:::: <li>Barcode: %barcode%Uses: %count%
+footer:::: </ol><hr />%TODAY_TRIM%<br/><br/>
+
+*in_house_use*::
+type::: items
+description::: List of items inputted in to the In-house use.
+default format:::
+header:::: You marked the following in-house items used:<hr/><ol>
+line_item:::: <li>Barcode: %barcode%Uses: %uses%<br />%alert_message%
+footer:::: </ol><hr />%TODAY_TRIM%<br/><br/>
+
+*holds*::
+type::: holds
+description::: List of items on hold for a patron.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have the following titles on hold:<hr/><ol>
+line_item:::: <li>%title%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*holds_on_bib*::
+type::: holds
+description::: This list is used to print the holds on a title record.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have the following titles on hold:<hr/><ol>
+line_item:::: <li>%title%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*holds_for_patron*::
+description::: This list is used to print the holds on a patron record.
+type::: holds
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have the following titles on hold:<hr/><ol>
+line_item:::: <li>%title%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*holds_shelf*::
+type::: holds
+description::: This list is used to print the holds on the holds shelf.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have the following titles on hold:<hr/><ol>
+line_item:::: <li>%title%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*holds_pull_list*::
+type::: holds
+description::: This list is used to print the holds on the holds pull list.
+default format:::
+header:::: Welcome to %LIBRARY%!<br/>You have the following titles on hold:<hr/><ol>
+line_item:::: <li>%title%
+footer:::: </ol><hr />%SHORTNAME% %TODAY_TRIM%<br/>You were helped by %STAFF_FIRSTNAME%<br/><br/>
+
+*hold_slip*::
+type::: holds
+description::: This is printed when a hold is fulfilled.
+default format:::
+header:::: This item needs to be routed to <b>%route_to%</b>:<br/>Barcode: %item_barcode%<br/>Title: %item_title%<br/><br/>%hold_for_msg%<br/>Barcode: %PATRON_BARCODE%<br/>Notify by phone: %notify_by_phone%<br/>Notified by text: %notify_by_text%<br/>Notified by email: %notify_by_email%<br/>
+line_item:::: %formatted_note%<br/>
+footer:::: <br/>Request date: %request_date%<br/>Slip Date: %TODAY_TRIM%<br/>Printed by %STAFF_FIRSTNAME% at %SHORTNAME%<br/><br/>
+
+*transit_slip*::
+type::: transits
+description::: This is printed when a item goes into transit.
+default format:::
+header::::
+This item needs to be routed to <b>%route_to%</b>:<br/>%route_to_org_fullname%<br/>
+%street1%<br/>%street2%<br/>
+%city_state_zip%<br/><br/>
+Barcode: %item_barcode%<br/>
+Title: %item_title%<br/>
+Author: %item_author%<br><br/>
+line_item:::: (Intentionally left blank)
+footer:::: Slip Date: %TODAY_TRIM%<br/>Printed by %STAFF_FIRSTNAME% at %SHORTNAME%<br/><br/>
+
+*hold_transit_slip*::
+type::: transits
+description::: This is printed when a hold goes in-transit to another library.
+default format:::
+header::::
+This item needs to be routed to <b>%route_to%</b>:<br/>%route_to_org_fullname%<br/>
+%street1%<br/>%street2%<br/>%city_state_zip%<br/><br/>
+Barcode: %item_barcode%<br/>
+Title: %item_title%<br/>
+Author: %item_author%<br><br/>
+%hold_for_msg%<br/>Barcode: %PATRON_BARCODE%<br/>
+Notify by phone: %notify_by_phone%<br/>
+Notified by text: %notify_by_text%<br/>
+Notified by email: %notify_by_email%<br/>
+line_item:::: %formatted_note%<br/>
+footer:::: <br/>Request date: %request_date%<br/>Slip Date: %TODAY_TRIM%<br/>Printed by %STAFF_FIRSTNAME% at %SHORTNAME%<br/><br/>
+
+*holdings_maintenance*::
+type::: items
+description::: This is printed from holding maintenance.
+default format:::
+header::::
+Title: %title%<br/>
+Author: %author%<br/>
+ISBN: %isbn% Edition: %edition% PubDate: %pubdate%<br/>
+TCN: %tcn_value% Record ID: %mvr_doc_id%<br/>
+Creator: %creator% Create Date: %create_date%<br/>
+Editor: %editor% Edit Date: %edit_date%<hr/>
+line_item:::: %prefix% %tree_location% %suffix% %parts% %acp_status%<br/>
+footer:::: <hr />%SHORTNAME% %TODAY_TRIM%<br/><br/>
+
+[[macros]]
+
+Receipt Template Editor Macros
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here is a list of the Receipt Template Macros that are in use on the receipts. There are two types of macros General and type specific. General Macros can be used on any of the receipts. Type specific macros are available depending on the type of the receipt.
+
+General Macros
+^^^^^^^^^^^^^^
+indexterm:[receipt template editor, macros]
+
+[horizontal]
+%LIBRARY%:: Library full name
+%SHORTNAME%:: Library Policy Name
+%STAFF_FIRSTNAME%:: First name of Staff login account
+%STAFF_LASTNAME%:: Last name of Staff login account
+%STAFF_BARCODE%:: Barcode of Staff login account
+%STAFF_PROFILE%:: Profile of Staff login account
+%PATRON_FIRSTNAME%:: First name of Patron
+%PATRON_LASTNAME%:: Last name of Patron
+%PATRON_BARCODE% or %patron_barcode%:: Patron Barcode
+%TODAY%:: Full Date and time in the format: Wed Sep 21 2011 13:20:44 GMT-0400 (Eastern Daylight Time)
+%TODAY_TRIM%:: Date and time in a shorted format: 2011-09-21 13:21
+%TODAY_m%:: Two digit Month: 09
+%TODAY_d%:: Two digit Day: 21
+%TODAY_Y%:: Year: 2011
+%TODAY_H%:: Hour in 24 hour day: 13
+%TODAY_I%:: Hour in 12 hour format: 1
+%TODAY_M%:: Minutes of the Hour: 24
+%TODAY_D%:: date in standard US format: 09/21/11
+%TODAY_F%:: date in International Standard: 2011-09-21
+%-TRIM%:: Trims white space before the macro
+%TRIM-%:: Trims white space after the macro
+%SUBSTR(#)%...%SUBSTR_END%:: Take substring starting at position # to end of string. If # is negative count backwards from end of string.
+%SUBSTR(#,#)%...%SUBSTR_END%:: Same as %SUBSTR(#)%, but limit to second provided number characters after start point. If second number is negative, count backwards instead of forwards.
+
+There are several macros that can carry pre-built contents specific to individual libraries. The contents can be set up in local administration. For details see <<_library_settings_editor, Library Settings>>. Though text can be hard-coded in receipt templates, the pre-built contents will be automatically applied to receipts printed from all workstations without editing each template.
+
+indexterm:[receipt template editor, includes]
+
+* %INCLUDE(notice_text)%
+* %INCLUDE(alert_text)%
+* %INCLUDE(event_text)%
+* %INCLUDE(footer_text)%%
+* %INCLUDE(header_text)%
+
+Additional Macros for various slip types
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*Holds*
+
+[horizontal]
+%ROUTE_TO%:: It should say Hold Shelf if it is a hold being fulfilled
+%item_barcode%:: Item Barcode
+%item_title%:: Item Title
+%hold_for_msg%:: Hold for Message: this gives the patron's Name
+%PATRON_BARCODE%:: Patron's Barcode
+%notify_by_phone%:: Phone number listed in the Hold Database. This may not be the same as what is in the Patron's record, as they can list another number when placing the hold.
+%notify_by_email%:: Email listed in Hold Database. Same as phone number
+%request_date%:: The date that the Request was originally placed.
+%formatted_note%:: Hold Notes (new to 2.1)
+%notify_by_text%:: SMS contact number (new to 2.2)
+
+*Check out*
+
+[horizontal]
+%title%:: Title
+%author%:: Author
+%barcode%:: Item Barcode
+%due_date%:: Due Date: formated by the date field in the library settings editor
+
+*Payment*
+
+[horizontal]
+%original_balance%:: The original balance the patron owes
+%payment_received%:: How much was received from the patron
+%payment_applied%:: How much of the payment was applied
+%payment_type%:: What type of payment was applied: IE Cash
+%voided_balance%:: Any Voided balance
+%change_given%:: How much change was given
+%new_balance%:: The new balance on the account
+%note%:: Any notes on the annotated payment
+%bill_id% or %mbts_id%:: The id for the bill in the bill database
+%payment%:: How much of the payment that was applied was applied to this title
+%title%:: Title that the payment was applied to.
+%last_billing_type%:: The type of bill that was last charged to the patron for this title
+%last_billing_note%:: Notes on the last bill
+%last_payment_type%:: The type of payment that was last used to pay the bill
+%mbts_xact_start%:: The date that the bill was started
+%last_payment_note%:: Notes on last payment
+%xact_type%:: Type of Biil
+%barcode%:: Item barcode
+%title%:: title of item
+
+*Bills*
+
+[horizontal]
+%mbts_id%:: The id for the bill in the bill database
+%title%:: Title that the payment was applied to.
+%last_billing_type%:: The type of bill that was last charged to the patron for this bill
+%last_billing_note%:: Notes on the last bill
+%last_billing_ts%:: The time stamp for the last billing
+%last_payment_type%:: The type of payment that was last used to pay the bill
+%last_payment_note%:: Notes on last payment
+%last_payment_ts%:: The time stamp for the last payment
+%mbts_xact_start%:: The date that the bill was started (currently not working)
+%xact_type%:: Type of Biil
+%title%:: title of item
+
+*Transit*
+
+Transit receipts come into two types, general Transit receipts and Transit slips. Transit receipts are listings of item that are in transits. Transit slips are Slips telling the staff that this item is in transit to another location.
+
+.*General Transits*
+
+[horizontal]
+%transit_item_author%:: Item author
+%transit_item_barcode%:: Barcode of item in transit
+%transit_item_callnumber%:: Call number of item in transit
+%transit_item_title%:: Title of Item intransit
+%transit_dest_lib%:: Destination Library
+%transit_source_send_time%:: Time item was sent intransit
+%transit_source%:: Library that placed the item intransit.
+
+
+.*Transit Slip*
+
+[horizontal]
+%route_to%:: Library Policy Name that the item is in transit to
+%route_to_org_fullname%:: Library Full Name that the item is in transit to
+%street1%:: Library Street address Line 1 that the item is in transit to.
+%street2%:: Library Street address Line 2 that the item is in transit to.
+%city_state_zip%:: City, State, Zip of Library the Item is in transit to.
+%item_barcode%:: Item barcode
+%item_title%:: Item title
+%item_author%:: Item Author
+%hold_for_msg%:: Hold for Message: this gives the patron's name
+%PATRON_BARCODE%:: Patron's Barcode
+%notify_by_phone%:: Phone number listed in the Hold Database. This may not be the same as what is in the Patron's record, as they can list another number when placing the hold.
+%notify_by_email%:: Email listed in Hold Database. Same as phone number
+%notify_by_text%:: SMS contact number (new to 2.2)
+%request_date%:: Date that the Request was originally placed