Bumping version numbers, adding Upgrade Script and Changelog
authorJason Boyer <JBoyer@equinoxOLI.org>
Fri, 20 May 2022 20:16:13 +0000 (16:16 -0400)
committerJason Boyer <JBoyer@equinoxOLI.org>
Fri, 20 May 2022 20:16:13 +0000 (16:16 -0400)
Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
ChangeLog
Open-ILS/src/perlmods/lib/OpenILS/Application.pm
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/version-upgrade/3.7.2-3.7.3-upgrade-db.sql [new file with mode: 0644]
Open-ILS/xul/staff_client/chrome/content/main/about.html
Open-ILS/xul/staff_client/defaults/preferences/prefs.js
Open-ILS/xul/staff_client/windowssetup.nsi
README [changed from symlink to file mode: 0644]
configure.ac

index 1f72b2c..cf74fd3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-Evergreen doesn't keep a GNU-style ChangeLog except in release tarballs.
-Those seeking a change log are encouraged to run 'git log -v', or read
-it online at: http://git.evergreen-ils.org/?p=Evergreen.git;a=log
+commit 647c0f45ab6b8b2cbd55226fb92345a8e19f2879
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Fri May 20 09:03:48 2022 -0400
+
+    Update Server Upgrade Doc
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+16     16      docs/modules/installation/pages/server_upgrade.adoc
+
+commit e79e34035a17cf2d72c57e3b2a99b24f6fba5b6e
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Fri May 20 08:58:31 2022 -0400
+
+    bumping Perl version string for 3.7.3
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+1      1       Open-ILS/src/perlmods/lib/OpenILS.pm
+
+commit f86068866fb2778e0074d2504ae356c16064940e
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Fri May 20 08:55:32 2022 -0400
+
+    Translation updates - po files
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+4      4       build/i18n/po/actor/ar-JO.po
+4      4       build/i18n/po/actor/cs-CZ.po
+4      4       build/i18n/po/actor/de-DE.po
+4      4       build/i18n/po/actor/en-GB.po
+4      4       build/i18n/po/actor/es-ES.po
+4      4       build/i18n/po/actor/hy-AM.po
+619    319     build/i18n/po/bootstrap-opac/cs-CZ.po
+614    310     build/i18n/po/bootstrap-opac/en-CA.po
+1889   1435    build/i18n/po/bootstrap-opac/es-ES.po
+991    642     build/i18n/po/bootstrap-opac/fr-CA.po
+7      5       build/i18n/po/cat.properties/en-CA.po
+31     22      build/i18n/po/circ.properties/en-CA.po
+3753   3266    build/i18n/po/db.seed/ar-JO.po
+3823   3280    build/i18n/po/db.seed/cs-CZ.po
+3651   3214    build/i18n/po/db.seed/de-DE.po
+3684   3238    build/i18n/po/db.seed/en-CA.po
+3658   3221    build/i18n/po/db.seed/en-GB.po
+3758   3271    build/i18n/po/db.seed/es-ES.po
+3671   3234    build/i18n/po/db.seed/fi-FI.po
+3659   3222    build/i18n/po/db.seed/fr-CA.po
+3646   3209    build/i18n/po/db.seed/he-IL.po
+3646   3209    build/i18n/po/db.seed/hu-HU.po
+3767   3280    build/i18n/po/db.seed/hy-AM.po
+3652   3215    build/i18n/po/db.seed/oc-FR.po
+3662   3225    build/i18n/po/db.seed/pt-BR.po
+3657   3220    build/i18n/po/db.seed/ru-RU.po
+3646   3209    build/i18n/po/db.seed/sv-SE.po
+3647   3210    build/i18n/po/db.seed/tr-TR.po
+3571   3210    build/i18n/po/fm_IDL.dtd/ar-JO.po
+3584   3220    build/i18n/po/fm_IDL.dtd/cs-CZ.po
+3525   3182    build/i18n/po/fm_IDL.dtd/de-DE.po
+3569   3208    build/i18n/po/fm_IDL.dtd/en-CA.po
+3568   3207    build/i18n/po/fm_IDL.dtd/en-GB.po
+3571   3210    build/i18n/po/fm_IDL.dtd/es-ES.po
+3571   3210    build/i18n/po/fm_IDL.dtd/fi-FI.po
+3520   3177    build/i18n/po/fm_IDL.dtd/fr-CA.po
+3519   3176    build/i18n/po/fm_IDL.dtd/he-IL.po
+3519   3176    build/i18n/po/fm_IDL.dtd/hu-HU.po
+3574   3213    build/i18n/po/fm_IDL.dtd/hy-AM.po
+3519   3176    build/i18n/po/fm_IDL.dtd/oc-FR.po
+3562   3204    build/i18n/po/fm_IDL.dtd/pt-BR.po
+3561   3203    build/i18n/po/fm_IDL.dtd/ru-RU.po
+3519   3176    build/i18n/po/fm_IDL.dtd/sv-SE.po
+3519   3176    build/i18n/po/fm_IDL.dtd/tr-TR.po
+274    257     build/i18n/po/ils_events.xml/ar-JO.po
+278    259     build/i18n/po/ils_events.xml/cs-CZ.po
+271    257     build/i18n/po/ils_events.xml/de-DE.po
+275    258     build/i18n/po/ils_events.xml/en-CA.po
+281    262     build/i18n/po/ils_events.xml/en-GB.po
+274    257     build/i18n/po/ils_events.xml/es-ES.po
+274    257     build/i18n/po/ils_events.xml/fi-FI.po
+275    258     build/i18n/po/ils_events.xml/fr-CA.po
+271    257     build/i18n/po/ils_events.xml/he-IL.po
+271    257     build/i18n/po/ils_events.xml/hu-HU.po
+274    257     build/i18n/po/ils_events.xml/hy-AM.po
+271    257     build/i18n/po/ils_events.xml/oc-FR.po
+275    258     build/i18n/po/ils_events.xml/pt-BR.po
+274    257     build/i18n/po/ils_events.xml/ru-RU.po
+271    257     build/i18n/po/ils_events.xml/sv-SE.po
+271    257     build/i18n/po/ils_events.xml/tr-TR.po
+26     18      build/i18n/po/kpac/ar-JO.po
+27     19      build/i18n/po/kpac/cs-CZ.po
+26     18      build/i18n/po/kpac/de-DE.po
+31     23      build/i18n/po/kpac/en-GB.po
+26     18      build/i18n/po/kpac/es-ES.po
+26     18      build/i18n/po/kpac/hy-AM.po
+5      5       build/i18n/po/lang.dtd/en-CA.po
+16     12      build/i18n/po/multiclass_search_help.html/en-GB.po
+23     19      build/i18n/po/patron.properties/en-CA.po
+5      5       build/i18n/po/register.js/en-CA.po
+13     13      build/i18n/po/selfcheck.js/en-CA.po
+439    274     build/i18n/po/tpac/ar-JO.po
+450    282     build/i18n/po/tpac/cs-CZ.po
+424    267     build/i18n/po/tpac/de-DE.po
+424    270     build/i18n/po/tpac/en-CA.po
+440    275     build/i18n/po/tpac/en-GB.po
+442    277     build/i18n/po/tpac/es-ES.po
+441    276     build/i18n/po/tpac/fi-FI.po
+565    400     build/i18n/po/tpac/fr-CA.po
+424    267     build/i18n/po/tpac/he-IL.po
+424    267     build/i18n/po/tpac/hu-HU.po
+440    275     build/i18n/po/tpac/hy-AM.po
+424    267     build/i18n/po/tpac/oc-FR.po
+424    270     build/i18n/po/tpac/pt-BR.po
+424    267     build/i18n/po/tpac/ru-RU.po
+424    267     build/i18n/po/tpac/sv-SE.po
+424    267     build/i18n/po/tpac/tr-TR.po
+634    0       build/i18n/po/vandelay/en-CA.po
+890    600     build/i18n/po/webstaff/ar-JO.po
+1177   861     build/i18n/po/webstaff/cs-CZ.po
+816    591     build/i18n/po/webstaff/de-DE.po
+822    595     build/i18n/po/webstaff/en-CA.po
+842    593     build/i18n/po/webstaff/en-GB.po
+890    600     build/i18n/po/webstaff/es-ES.po
+847    595     build/i18n/po/webstaff/hy-AM.po
+816    591     build/i18n/po/webstaff/ru-RU.po
+ create mode 100644 build/i18n/po/vandelay/en-CA.po
+
+commit 9ff76946eb7d1c5cd05b84cb169b43beda65f5cb
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Fri May 20 15:54:51 2022 -0400
+
+    Update 3.7 Point Release Notes
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+4      4       docs/RELEASE_NOTES_3_7.adoc
+
+commit a3bc6094a84cb6cbf8d31379812e8f4512b71d8c
+Author: Andrea Buntz Neiman <abneiman@equinoxinitiative.org>
+Date:   Fri May 20 14:46:55 2022 -0400
+
+    Docs: 3.7.3 Release Notes
+    
+    Signed-off-by: Andrea Buntz Neiman <abneiman@equinoxinitiative.org>
+
+159    0       docs/RELEASE_NOTES_3_7.adoc
+
+commit 997407f8d89b0bc9951cf8009d0263ad6a561e14
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Fri May 20 08:39:14 2022 -0400
+
+    Translation updates - newpot
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+531    507     build/i18n/po/bootstrap-opac/bootstrap-opac.pot
+1      1       build/i18n/po/conify/conify.pot
+5      9       build/i18n/po/fm_IDL.dtd/fm_IDL.dtd.pot
+14     14      build/i18n/po/kpac/kpac.pot
+441    441     build/i18n/po/tpac/tpac.pot
+2      2       build/i18n/po/urlverify/urlverify.pot
+121    121     build/i18n/po/webstaff/webstaff.pot
+
+commit 5105bfe1306276229b56c8207ab66e9cc6a37d18
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Thu May 19 17:25:52 2022 -0400
+
+    LP#1946531: (follow-up) show progress bar when adding users to bucket
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+6      3       Open-ILS/web/js/ui/default/staff/circ/patron/bucket/app.js
+
+commit e3e0673e3d3e4495f1ea6c70f6eefdc1ec9e8628
+Author: Jeff Davis <jeff.davis@bc.libraries.coop>
+Date:   Wed May 11 15:55:21 2022 -0700
+
+    LP#1946531: use batch method to add users to bucket via User Buckets UI
+    
+    Signed-off-by: Jeff Davis <jeff.davis@bc.libraries.coop>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+20     19      Open-ILS/web/js/ui/default/staff/circ/patron/bucket/app.js
+
+commit cc8c8b549bc306873c76acf2ada14fe7ed56a51e
+Author: Kyle Huckins <khuckins@catalyte.io>
+Date:   Wed Dec 15 17:43:42 2021 +0000
+
+    lp1950507 Providers Admin Screenreader form fix
+    
+    - Move Search and Reset Form buttons to bottom of form when expanded.
+    
+    Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
+    Signed-off-by: Tiffany Little <tlittle@georgialibraries.org>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+8      2       Open-ILS/src/eg2/src/app/staff/acq/provider/acq-provider-search-form.component.html
+
+commit 80f4dede70e311720da4318501edc315271f5a1c
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Thu May 19 14:12:20 2022 -0400
+
+    LP#1968082: (follow-up) show progress bar when adding/removing items from bucket
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+12     4       Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js
+
+commit 9491523be07d5d4836131ad2da8ce211ec1bdc6e
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Thu May 19 13:52:14 2022 -0400
+
+    LP#1968082: (follow-up) tidy up whitespace
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+22     24      Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js
+
+commit 7bc64a213a2defa573a043c2c597e3777d1bf961
+Author: Jessica Woolford <jwoolford@biblio.org>
+Date:   Thu Apr 7 15:15:55 2022 -0400
+
+    LP#1968082: Use the batch API call to add and remove items from item buckets.
+    
+    In particular, when adding/removing items while on the item
+    bucket interface itself.
+    
+    Signed-off-by: Jessica Woolford <jwoolford@biblio.org>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+42     34      Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js
+
+commit 3c34ec4196293575838954e31bf538a9f21b44e1
+Author: Bill Erickson <berickxx@gmail.com>
+Date:   Thu Jun 3 11:09:25 2021 -0400
+
+    LP1930740 EDI order writer attribute check repair
+    
+    Repairs mistaken references to $self->{compiled}->{edi_attr}...  The
+    hash key we need is {edi_attrs}.
+    
+    This issue prevented these attribute types from getting applied:
+    
+    LINEITEM_IDENT_VENDOR_NUMBER
+    COPY_SPEC_CODES
+    INCLUDE_EMPTY_LI_NOTE
+    
+    Signed-off-by: Bill Erickson <berickxx@gmail.com>
+    Signed-off-by: Jessica Woolford <jwoolford@biblio.org>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+3      3       Open-ILS/src/perlmods/lib/OpenILS/Utils/EDIWriter.pm
+
+commit 0647d3bdc9c7945bdda4e80735247df631d382b3
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Tue Apr 26 17:33:18 2022 -0400
+
+    LP#1970486: fix SuperCat crash on serial units with stat cats
+    
+    This patch fixes a bug where retrieving a title via SuperCat (in
+    particular, with holdings XML) can crash of the title has a serial
+    unit (i.e., barcoded serial item) attached that also has a statistical
+    category.
+    
+    To test
+    -------
+    [1] Create a title with a barcoded serial item.
+    [2] Attempt to fetch the title via SuperCat:
+    
+    https://EGSERVER/opac/extras/supercat/retrieve/marcxml-full/record/BIBID
+    
+    [3] Note that an internal server error is returned.
+    [4] Apply the patch and repeat step 2. This time, an XML
+        document should be returned that includes the serial item
+        and its stat cat.
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+1      0       Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+
+commit 59a3000be00e3c7392efd9a907ba26cc6fa7eede
+Author: Garry Collum <gcollum@gmail.com>
+Date:   Thu Apr 15 15:50:55 2021 -0400
+
+    LP1907863 Bootstrap Opac: My Lists formatting
+    
+    This patch moves the buttons for each list row underneath the title and descriptions fields.
+    It makes the create list form collapsible using a button.
+    If there are lists, the create form is collapsed.
+    The create form is expanded on load, if the user selects move bucket to new list, or add rec to new list from a menu or button from another page.
+    The "Move contents of basket to this list?" in the creation form now defaults to 'yes' if an option to move a basket to a new list is chosen from a menu.
+    It adds localization functions to the button texts and removes a dangling </div> in anon-list.tt2
+    It moves the create form from a <table> design and uses Bootstrap elements instead.
+    
+    To Test.
+    
+    1. After applying the patch view the list page and notice that the form is expanded.
+    2. Create a list.  The form is now collapse.
+    3. Perform a search and add some of the titles to a basket.
+    4. From one of the result rows drop-down the Add to My List menu and select 'Add to New List'.
+       The form is expanded and the "Move contents of basket to this list" should be 'yes'.
+    5. From the basket screen or from the lists screen click on the 'Add to New List' button.  The results should be the same as step 4.
+    6. After creating a few lists, notice that the buttons for each list are now displayed under the list title and description and
+       each row is distinguished by a bottom border.
+    
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Ruth Frasur <rfrasur@library.in.gov>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+110    114     Open-ILS/src/templates-bootstrap/opac/myopac/lists.tt2
+6      7       Open-ILS/src/templates-bootstrap/opac/parts/anon_list.tt2
+1      1       Open-ILS/src/templates-bootstrap/opac/parts/bookbag_actions.tt2
+
+commit 6c89e2ffe9f9ac4efe3f51a59af35c1cdc731a1b
+Author: Dan Briem <dbriem@wlsmail.org>
+Date:   Thu Mar 17 16:38:10 2022 -0400
+
+    LP#1965317 Barcode Completion on Traditional Cat Staff Holds
+    
+    This allows the completed barcode to populate in the barcode
+    input when the hold group interface isn't rendered.
+    
+    Signed-off-by: Dan Briem <dbriem@wlsmail.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+1      1       Open-ILS/web/js/ui/default/opac/staff.js
+
+commit 74662562d5f436588f3887d57f3b87e3779b44c2
+Author: Jane Sandberg <js7389@princeton.edu>
+Date:   Thu Apr 7 15:40:47 2022 -0700
+
+    Stamp upgrade script for MADS update
+    
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+1      1       Open-ILS/src/sql/Pg/002.schema.config.sql
+1      1       Open-ILS/src/sql/Pg/upgrade/{XXXX.data.MADS21-xsl.sql => 1325.data.MADS21-xsl.sql}
+ rename Open-ILS/src/sql/Pg/upgrade/{XXXX.data.MADS21-xsl.sql => 1325.data.MADS21-xsl.sql} (99%)
+
+commit afe551c8cec1d43cde4c6ce189388a420b1c5dff
+Author: Jane Sandberg <sandbej@linnbenton.edu>
+Date:   Tue Jan 5 13:27:05 2021 -0800
+
+    LP1800871: small correction to upgrade script
+    
+    Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+2      2       Open-ILS/src/sql/Pg/upgrade/XXXX.data.MADS21-xsl.sql
+
+commit 2e80011b2ff838f17709b60686c2f4b5898ad862
+Author: Josh Stompro <stompro@stompro.org>
+Date:   Thu Feb 28 08:39:54 2019 -0600
+
+    LP#1800871 - MARC21slim2MADS 2.15 update
+    
+    This update fixes an error when trying to process a 755 tag in
+    and authority record that has a source set.
+    
+    See the discussion on the listserv at:
+    https://georgialibraries.markmail.org/thread/rmwcxkwjzv2qczmu
+    
+    To test, try to import the sample authority record provided
+    by Linda Jansova (https://markmail.org/thread/2ay3j4wg7fecymhz)
+    in evergreen, and see the log files for the import errors.
+    
+    It is also possible to test from the command line.
+    
+    In /openils/var/xsl, copy the example autority marc xml file to
+    that directory, name it americ.xml, then run the command
+    xsltproc ./MARC21slim2MADS.xsl ./americ.xml
+    
+    This will error out.
+    
+    After patch has been applied, try importing the sample authority
+    record and see that it imports successfully.
+    
+    Signed-off-by: Josh Stompro <stompro@stompro.org>
+    Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+2      1       Open-ILS/src/sql/Pg/955.data.MADS21-xsl.sql
+1631   0       Open-ILS/src/sql/Pg/upgrade/XXXX.data.MADS21-xsl.sql
+3      2       Open-ILS/xsl/MARC21slim2MADS.xsl
+ create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.data.MADS21-xsl.sql
+
+commit 20774cdf0dcce81cc944d3185a9fb1edf0df8830
+Author: Garry Collum <gcollum@gmail.com>
+Date:   Thu Sep 23 14:31:24 2021 -0400
+
+    LP#1942240 Insufficient color contrast in boostrap forms
+    
+    Overrides the bootstrap form-control border color. Also changes the
+    border_standard color in colors.tt2 which is used for the border
+    around some form elements.
+    
+    After this patch is applied the color ratio is 3.54:1
+    
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+5      1       Open-ILS/src/templates-bootstrap/opac/css/style.css.tt2
+1      1       Open-ILS/src/templates-bootstrap/opac/parts/css/colors.tt2
+
+commit 38504ee71419d93b5016799198a4566228012461
+Author: blake <blake@mobiusconsortium.org>
+Date:   Mon Sep 20 12:32:26 2021 -0500
+
+    LP1944205 Advanced Authority Documentation
+    
+    Added a new document authorities_advanced.adoc
+    
+    Integrated to the nav
+    
+    Signed-off-by: blake <blake@mobiusconsortium.org>
+    Signed-off-by: Lynn Floyd <alynn2671@gmail.com>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+1      0       docs/modules/cataloging/nav.adoc
+397    0       docs/modules/cataloging/pages/authorities_advanced.adoc
+ create mode 100644 docs/modules/cataloging/pages/authorities_advanced.adoc
+
+commit a9e3431fd21221f93791104bb376b5250b1209c2
+Author: Jason Stephenson <jason@sigio.com>
+Date:   Fri Feb 11 09:44:55 2022 -0500
+
+    LP1959904: Fix Angular Profile Select Component
+    
+    The Angular profile select component has a bug when permission group
+    tree display entries are used.  It will loop forever if the grp and
+    parent have the same value in permission.grp_tree_display_entry
+    because it is comparing permission group tree entries to permission
+    group tree display entries in the groups filter of the grpLabel
+    function.
+    
+    This patch adds a ternary operator to compare display entries to
+    display entries and group tree entries to group tree entries in a
+    manner identical to how the parent value is determined a few lines
+    above.
+    
+    See the bug description for more information:
+    
+        https://bugs.launchpad.net/evergreen/+bug/1959904
+    
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: John Amundson <jamundson@cwmars.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+1      1       Open-ILS/src/eg2/src/app/staff/share/patron/profile-select.component.ts
+
+commit 93915e867613c49fc9dc0071c04b8094eb8fa7ca
+Author: Bill Erickson <berickxx@gmail.com>
+Date:   Wed Mar 16 14:22:13 2022 -0400
+
+    LP1950826 Return error result on contact invalidation
+    
+    If penalty creation fails, return the error/event response to the caller
+    instead of the editor's last event.
+    
+    Signed-off-by: Bill Erickson <berickxx@gmail.com>
+    Signed-off-by: Christine Burns <christine.burns@bc.libraries.coop>
+
+4      1       Open-ILS/src/perlmods/lib/OpenILS/Utils/BadContact.pm
+
+commit c502f686ab18da72522a806b340dbb81df2aff0f
+Author: Jason Etheridge <jason@EquinoxOLI.org>
+Date:   Mon Nov 15 17:30:17 2021 -0500
+
+    LP1950826 fix invalidate email action
+    
+    and other invalidate contact actions
+    
+    Signed-off-by: Jason Etheridge <jason@EquinoxOLI.org>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Bill Erickson <berickxx@gmail.com>
+
+8      3       Open-ILS/src/perlmods/lib/OpenILS/Utils/BadContact.pm
+
+commit df24ff42034d87cc6c0a109b613487bd231665dd
+Author: Kyle Huckins <khuckins@catalyte.io>
+Date:   Sun Mar 13 00:27:16 2022 +0000
+
+    lp1913340 - List All Courses in OPAC
+    
+    - Removed handling preventing an empty query from providing results
+    - Strip * from query to ensure expected behavior
+    
+    Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
+    Signed-off-by: Christine Burns <christine.burns@bc.libraries.coop>
+    Signed-off-by: Jane Sandberg <js7389@princeton.edu>
+
+3      2       Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Course.pm
+
+commit 58fcafc2970fd5a1d793ecea3a97ce88f95c1306
+Author: Chris Sharp <csharp@georgialibraries.org>
+Date:   Wed Dec 15 08:49:28 2021 -0500
+
+    LP#1954923: Fix current date issue in Boostrap OPAC Circ History CSV export
+    
+    Signed-off-by: Chris Sharp <csharp@georgialibraries.org>
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+1      1       Open-ILS/src/templates-bootstrap/opac/myopac/circ_history/export.tt2
+
+commit ec32f4c330c4a3067a5276a38987a366ff606631
+Author: Garry Collum <gcollum@gmail.com>
+Date:   Thu Jan 13 15:02:34 2022 -0500
+
+    LP1920039-Bootstrap Opac: More Details button doesn't change on use.
+    
+    The 'More Details' button in a bib record in the Bootstrap Opac should change
+    to say 'Less Details' when pressed.  This patch fixes that behavior.
+    
+    To Test.
+    1. Go to a bib record in the boostrap opac.
+    2. Press "More Details"
+    3. Notice the button still displays "More Details"
+    4. Apply the patch and repeat.
+    5. The button should now toggle between "More Details" and "Less Details"
+    
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: John Amundson <jamundson@cwmars.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+
+9      6       Open-ILS/src/templates-bootstrap/opac/parts/record/summary.tt2
+
+commit 9b8597a1886e20b51ea9a7ec660e754b695c3b95
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Thu Sep 23 15:49:16 2021 -0400
+
+    LP1930747: Add MARC_NAMESPACE to Const.pm
+    
+    Now that we have 3 separate $MARC_NAMESPACE definitions it's time
+    to just move it into Const.pm and call it done.
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+
+2      3       Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm
+2      3       Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AuthCommon.pm
+5      6       Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/BibCommon.pm
+5      0       Open-ILS/src/perlmods/lib/OpenILS/Const.pm
+
+commit 6301bfdac77da0404fa7e7f31f7fb1895ba47f84
+Author: Jason Boyer <JBoyer@equinoxinitiative.org>
+Date:   Thu Oct 15 13:50:18 2020 -0400
+
+    LP1900005: Don't require a specific 'opensrf' user
+    
+    There's no technical reason to require a specific user beyond our
+    instructions stating that it's the default. One thing that we should
+    do is not allow our network services to be run as root.
+    Additionally, autogen.sh is excluded from running as root because while
+    that would work, it may then have to *always* be run by root or
+    require you to change the file owner between runs.
+    
+    NOTE: We check for the user by id rather than name, as there's no rule
+    saying user 0 must be called "root" on Linux.
+    
+    NOTE: This also cleans up and unifies the the coding style and removes
+    some dead code in autogen.sh.
+    
+    To test:
+    Pre-patch:
+    Use oils_ctl.sh to start SIP or z3950 as opensrf, Success.
+    Use oils_ctl.sh to start SIP or z3950 as yourself, Failure.
+    Use oils_ctl.sh to start SIP or z3950 as root, Failure.
+    Run autogen.sh as opensrf, Success.
+    Run autogen.sh as yourself, Failure.
+    Run autogen.sh as root, Failure.
+    
+    Post patch:
+    Use oils_ctl.sh to start SIP or z3950 as opensrf, Success.
+    Use oils_ctl.sh to start SIP or z3950 as your normal user, Success.
+    Use oils_ctl.sh to start SIP or z3950 as root, Failure.
+    Run autogen.sh as opensrf, Success.
+    Run autogen.sh as yourself, potential Success - IF you're able to write to the correct directory / files.
+    Run autogen.sh as root, Failure.
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxinitiative.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+2      2       Open-ILS/examples/oils_ctl.sh
+82     49      Open-ILS/src/extras/autogen.sh
+
+commit eb99c4a5bf0e3d1ee05d8f85aa123037b83ad2f7
+Author: Dan Briem <dbriem@wlsmail.org>
+Date:   Wed Mar 16 16:45:37 2022 -0400
+
+    LP#1746800 Exclude empty records on filtered staff searches
+    
+    Excludes empty bibs on staff searches when filtering on location
+    or location group or when using the availability modifier.
+    
+    Signed-off-by: Dan Briem <dbriem@wlsmail.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+1      1       Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
+
+commit 007d4fe599c435e862ec1a858547967c424ca095
+Author: Terran McCanna <tmccanna@georgialibraries.org>
+Date:   Thu Mar 24 14:48:14 2022 -0400
+
+    LP1909681 Open hold grid links in new tab (for 3.7)
+    
+    Followup to lp1909681_open_hold_grid_links_in_new_tabs which
+    resolved the same issue on 3.8 and 3.9.
+    
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+2      2       Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.html
+
+commit 65e2870540b1a388649122becadddf66b3e6d174
+Author: Garry Collum <gcollum@gmail.com>
+Date:   Thu Feb 3 17:57:45 2022 -0500
+
+    LP#1959405: hold status not looking for shelf delay status
+    
+    This patch fixes the blank status display in the opac by treating that
+    status as a 'Waiting for Copy' status.  This commit covers both the TPAC
+    and the Bootstrap OPAC.
+    
+    To Test:
+    As stated by Erica in LP1959405
+    1. Administration->Local Administration->Library Settins Editor
+    set Hold Shelf Status Delay to 1 minute.
+    2. Place a hold for a patron
+    3. Capture the hold.
+       The opac will change from "Waiting for Copy" to a blank column.
+    4. Allow the delay interval to expire
+       The opac will change from a blank status to "Available"
+    
+    5. Apply the patch
+    6. Repeat 2-3.
+       The opac will continue to display "Waiting for Copy"
+    7. Allow the delay interval to expire
+       The opac will change from "Waiting for Copy" to "Available"
+    
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+2      2       Open-ILS/src/templates-bootstrap/opac/parts/hold_status.tt2
+2      2       Open-ILS/src/templates/opac/parts/hold_status.tt2
+
+commit 209f99883dd8f43082b61a603e908a88bb9618b7
+Author: Michele Morgan <mmorgan@noblenet.org>
+Date:   Tue Mar 2 11:46:42 2021 -0500
+
+    LP1907123 Angular Catalog View Holds missing columns
+    
+    Teaches the t_holds.tt2 TPAC file to save columns with the same names as
+    the Angular Catalog.
+    
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Elaine Hardy <ehardy@georgialibraries.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+134    134     Open-ILS/src/templates/staff/cat/catalog/t_holds.tt2
+
+commit 3ae18863abe7ac7490e599df24d7c9f2e78b5a4e
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Fri Feb 11 10:45:51 2022 -0500
+
+    LP#1939338: fix IDL mistake that could prevent admin of carousels
+    
+    This patch fixes a typo found in the IDL definition of the
+    classes for bib, call number, item, and user buckets. One effect
+    of the typo is that the admin interface for carousels could not
+    flesh out the record buckets unless the staff user was either
+    a global administrator or was the one who had created the carousel
+    and bucket originally.
+    
+    This patch likely fixes other cases where one would expect to be
+    able to access buckets created by another user.
+    
+    This patch is effectively a subset of a patch in the Simple Reporter
+    branch (bug 1945836 and working repository commit 36369719067) that
+    addresses several more errors in the IDL. However, I'm submitting this one
+    now in the hopes of resolving a long-standing bug with carousels sooner
+    rather than later.
+    
+    To test
+    -------
+    [1] As a local admin, create a carousel definition.
+    [2] As a different local admin at the same OU, open the carousels
+        admin interface. Note that attempting to retrieve carousel defs
+        created in step 1 will result in a console error and the interface
+        not being completely rendered.
+    [3] Apply the patch and repeat step 2. This time, the carousel definitions
+        should all display.
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Andrea Buntz Neiman <abneiman@equinoxOLI.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+16     16      Open-ILS/examples/fm_IDL.xml
+
+commit 385c7af5f4f9f46f2beed8a1b60912750ca8517f
+Author: Tiffany Little <tlittle@georgialibraries.org>
+Date:   Fri Jun 18 14:33:50 2021 -0400
+
+    LP1928003 Protect real copies from auto-deletion by cancelling acq line items
+    
+    Signed-off-by: Tiffany Little <tlittle@georgialibraries.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+1      1       Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
+
+commit ea6ebb9333c0f246c7443ce6242c7bebadcf03a3
+Author: Garry Collum <gcollum@gmail.com>
+Date:   Sun Jan 23 21:05:16 2022 -0500
+
+    LP1010494 - More Details button is not translatable.
+    
+    Surrounds the text in the More Details and Less Details button in the
+    bootstrap opac bib record screen and changes 'Less Details' to
+    'Fewer Details'.
+    
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+3      3       Open-ILS/src/templates-bootstrap/opac/parts/record/summary.tt2
+
+commit f32e39bd76f85938c76869f9ee8a27736790af1c
+Author: Lynn Floyd <alynn2671@gmail.com>
+Date:   Thu Dec 30 15:56:29 2021 -0500
+
+    Added Author to Pending view in Item Buckets
+    
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+2      1       Open-ILS/src/templates/staff/cat/bucket/copy/t_pending.tt2
+
+commit 6e752c8d8cd1818b0eac51df59ac2c8850e20116
+Author: Lynn Floyd <alynn2671@gmail.com>
+Date:   Thu Dec 30 12:22:17 2021 -0500
+
+    Add Author field to Item buckets.
+    
+    Signed-off-by: Lynn Floyd <alynn2671@gmail.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+2      0       Open-ILS/src/templates/staff/cat/bucket/copy/t_view.tt2
+
+commit f06a162b27ba3e0859ae18f74fadace3d6dbaae5
+Author: Jason Stephenson <jason@sigio.com>
+Date:   Wed Mar 16 13:29:09 2022 -0400
+
+    LP1965161: Sort Monograph Parts in Holds Metadata
+    
+    When placing a hold in the Angular Staff Catalog, parts are not sorted
+    in the proper order.  This patch corrects the sort order.
+    
+    To verify the bug:
+    
+     1. Find a record with parts in your catalog.
+     2. Place a hold on a specific part using the Angular Staff Catalog.
+     3. Notice that the entries int he parts drop down are likely not
+        sorted in the correct order. (If they are you lucked out and
+        should try again with a different record.)
+    
+    To verify the fix after applying the patch and re-installing
+    Evergreen, repeat the above steps.  The parts should display in the
+    proper sort order by label.
+    
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Bill Erickson <berickxx@gmail.com>
+
+5      1       Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
+
+commit 179c78b3f443465e27d0668ad25cd5af3f5c0ed1
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Tue Nov 9 18:22:07 2021 -0500
+
+    LP#1950394: isolate attribute extraction of metarecord
+    
+    This patch ensures that calling the Template Toolkit block
+    get_marc_attrs() on the metarecord's lead record's MARCXML
+    does not interfere with attributes already parsed from the
+    current bib's MARCXML on the record summary page in the Bootstrap
+    OPAC.
+    
+    This fixes an issue where electronic resource links could fail to
+    be displayed under the following conditions:
+    
+    - the MARC record has an 856 field with ind1 = 4 and ind2 = 0 or 1
+      and is NOT a located URI
+    - the bib is part of a metarecord set with at least one other member
+    - the master record in the metarecord set does not have 856 fields
+    
+    To test
+    -------
+    [1] Create a setup where two bibs are in the same metarecord set, one
+        with 856 fields and one without. Arrange that the one without
+        856 fields is the lead record in the metarecord.
+    [2] View the one that has 856 fields in the Bootstrap OPAC's record
+        summary page. Note that the electronic resource links do not
+        appear.
+    [3] Apply the patch and repeat step 2. This time, the links should
+        appear.
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+
+4      0       Open-ILS/src/templates-bootstrap/opac/parts/record/summary.tt2
+
+commit d2fd2441a841b1fa1d29bc4f55ebefc0f89f126a
+Author: Dan Briem <dbriem@wlsmail.org>
+Date:   Sat Nov 20 15:14:36 2021 -0500
+
+    LP#1939426 Traditional Catalog Holds: Patron Info Not Populating
+    
+    When no hold groups exist, its interface isn't present. When
+    placing volume holds, the advanced link isn't present.
+    
+    This checks that those elements exist before accessing their
+    attributes and adds a missing name attribute to the Bootstrap
+    catalog to display the email address.
+    
+    Signed-off-by: Dan Briem <dbriem@wlsmail.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+
+1      1       Open-ILS/src/templates-bootstrap/opac/parts/place_hold.tt2
+12     7       Open-ILS/web/js/ui/default/opac/staff.js
+
+commit 0b3dddad68d056a0c867055942cc1df090ed0913
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Fri Mar 11 09:03:02 2022 -0500
+
+    LP1964019: Change span tag to div to work around a Chrome bug
+    
+    For some reason the span tag wrapping the contents of the Holdable? column
+    began to cause problems with Chrome 99 on Windows. Changing the spans to divs
+    works everywhere without turning off tooltips.
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+3      3       Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.html
+
+commit 6440259b9354ba517ab700190e73c9b79b81b830
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Wed Jan 26 12:20:40 2022 -0500
+
+    Revising 'Using the Public Access Catalog' page
+    
+    Updating screenshots and information in this doc to match Bootstrap.  Some areas need updating still.
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/opac/assets/images/opac/advanced_search_ex.jpg
+-      -       docs/modules/opac/assets/images/opac/advanced_search_filters.jpg
+-      -       docs/modules/opac/assets/images/opac/back_to_results.jpg
+-      -       docs/modules/opac/assets/images/opac/branch_search.jpg
+-      -       docs/modules/opac/assets/images/opac/did_you_mean_no_results.jpg
+-      -       docs/modules/opac/assets/images/opac/email_records_screen.jpg
+-      -       docs/modules/opac/assets/images/opac/highlighting.jpg
+-      -       docs/modules/opac/assets/images/opac/more_details_record.jpg
+-      -       docs/modules/opac/assets/images/opac/permalink.jpg
+-      -       docs/modules/opac/assets/images/opac/placing_holds.jpg
+-      -       docs/modules/opac/assets/images/opac/print_email_records.jpg
+-      -       docs/modules/opac/assets/images/opac/print_records_screen.jpg
+-      -       docs/modules/opac/assets/images/opac/record_details.jpg
+-      -       docs/modules/opac/assets/images/opac/search_facets.JPG
+-      -       docs/modules/opac/assets/images/opac/search_results.jpg
+-      -       docs/modules/opac/assets/images/opac/search_results_quantity.JPG
+-      -       docs/modules/opac/assets/images/opac/viewing_record.jpg
+45     56      docs/modules/opac/pages/using_the_public_access_catalog.adoc
+ create mode 100644 docs/modules/opac/assets/images/opac/advanced_search_ex.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/advanced_search_filters.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/back_to_results.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/branch_search.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/did_you_mean_no_results.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/email_records_screen.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/highlighting.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/more_details_record.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/permalink.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/placing_holds.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/print_email_records.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/print_records_screen.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/record_details.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/search_facets.JPG
+ create mode 100644 docs/modules/opac/assets/images/opac/search_results.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac/search_results_quantity.JPG
+ create mode 100644 docs/modules/opac/assets/images/opac/viewing_record.jpg
+
+commit 54544786f2d46e964fac032a969f2404dee1b95d
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Tue Mar 1 07:55:16 2022 -0500
+
+    Update Test for LP1722827 After LP1482757
+    
+    The 4th part of the old test is incorrect as not deleting these is
+    the point of 1482757. Test has been updated to reflect that.
+    
+    Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
+
+3      3       Open-ILS/src/sql/Pg/t/lp1722827_trim_spaces_from_located_uris.pg
+
+commit 4551f3b913c5d8567535c30d4449dd277179976f
+Author: Michele Morgan <mmorgan@noblenet.org>
+Date:   Fri Feb 25 16:30:12 2022 -0500
+
+    LP#1482757: stamp upgrade script
+    
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+1      1       Open-ILS/src/sql/Pg/002.schema.config.sql
+2      0       Open-ILS/src/sql/Pg/upgrade/{XXXX.function.biblio.extract_located_uris.sql => 1311.function.biblio.extract_located_uris.sql}
+ rename Open-ILS/src/sql/Pg/upgrade/{XXXX.function.biblio.extract_located_uris.sql => 1311.function.biblio.extract_located_uris.sql} (99%)
+
+commit 160690af7091d38db88eecdfb9df2cbf8092ca88
+Author: Jason Stephenson <jason@sigio.com>
+Date:   Thu Sep 24 12:31:23 2020 -0400
+
+    LP#1482757: Speed Up the Delete of Orphaned URIs in upgrade script
+    
+    Modify the code that deletes orphaned asset.uri table entries in the
+    upgrade script to use IN logic on the subquery, because IN is much
+    faster than NOT IN.  Also take into account the link between
+    serial.item and asset.uri so that we don't accidentally delete URIs
+    used by serial items.
+    
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Jessica Woolford <jwoolford@biblio.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+9      3       Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+
+commit 6d621d264fab6aa3e49ecad1a11eb1858400810f
+Author: Michele Morgan <mmorgan@noblenet.org>
+Date:   Wed Jul 29 16:40:06 2020 -0400
+
+    LP#1482757: Delete URIs and call numbers when all 856 fields are removed
+    
+    This patch assures that URIs and call numbers are deleted as appropriate
+    when all 856 fields are removed from the MARC.
+    
+    Also provides for tracking editor and edit_date when call numbers are
+    deleted.
+    
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+9      5       Open-ILS/src/sql/Pg/030.schema.metabib.sql
+10     6       Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+
+commit 452665b7ad155f673acc786a278db141c6b9510c
+Author: Michele Morgan <mmorgan@noblenet.org>
+Date:   Fri Apr 24 13:03:23 2020 -0400
+
+    LP#1482757: Amend upgrade script to remove existing orphaned URIs
+    
+    Remove orphaned URIs from the database that have accumulated from past
+    additions, updates and deletions of records with located URIs.
+    
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+8      0       Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+
+commit 75535fd1ce953180f1d260d06e0032053c86d5bc
+Author: Michele Morgan <mmorgan@noblenet.org>
+Date:   Fri Apr 24 12:43:39 2020 -0400
+
+    LP#1482757: Remove 'orphaned_uri_list' and 'NOT cn.deleted' criteria
+    
+    Per Dan Wells' suggestions.
+    
+    1) One possible "crack" I see for data to fall through is the dead map
+    selector. The "AND cn.label = '##URI##' AND NOT cn.deleted" seems overly
+    restrictive. Now, I realize we *shouldn't* have mappings to deleted or
+    non-##URI## call numbers, but it isn't impossible, and I don't think we'd
+    have harm in leaving those restrictions out. If a map isn't used, let's
+    get rid of it regardless, I think.
+    
+    2) (side note) orphaned_uri_list doesn't seems to be used any more, so
+    should be removed.
+    
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+1      2       Open-ILS/src/sql/Pg/030.schema.metabib.sql
+1      2       Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+
+commit 68359b62f2facc1dc853369ba20a14b75bb6c100
+Author: Mike Rylander <mrylander@gmail.com>
+Date:   Fri May 19 15:33:03 2017 -0400
+
+    LP#1482757: Be sure to remove all orphaned URI
+    
+    As reported by Michele Morgan, URIs can be orphaned in some cases, such
+    as when a location drops one of several 856 entries.  This commit tracks
+    objects at the mapping level, to identify disused URIs even where the
+    call number level is not changed.
+    
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+25     19      Open-ILS/src/sql/Pg/030.schema.metabib.sql
+26     20      Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+
+commit 4dfa5ff6681358958fa609d2729ab099dab96e68
+Author: Mike Rylander <mrylander@gmail.com>
+Date:   Fri Aug 5 08:56:05 2016 -0400
+
+    LP#1482757: More careful Located URI remapping
+    
+    Instead of recreating all Located URI mappings, we will add any new
+    ones and remember all those (existing and new) that are in use. Any
+    existing maps that we don't see in this record, and whose URI is only
+    used once previously and therefore about to be orphaned, we remove.
+    
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+33     8       Open-ILS/src/sql/Pg/030.schema.metabib.sql
+140    0       Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+ create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.function.biblio.extract_located_uris.sql
+
+commit 594687ef2c4562ea3e79c17376c1785cf9a84262
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Thu Feb 17 09:55:10 2022 -0500
+
+    Update to Batch Search page
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/opac/assets/images/opac_basket/add_to_basket.jpg
+-      -       docs/modules/opac/assets/images/opac_basket/basket_icon.jpg
+-      -       docs/modules/opac/assets/images/opac_basket/drop_down_actions.jpg
+-      -       docs/modules/opac/assets/images/opac_basket/select_checkboxes.jpg
+-      -       docs/modules/opac/assets/images/opac_basket/view_basket.jpg
+1      1       docs/modules/opac/nav.adoc
+78     0       docs/modules/opac/pages/baskets.adoc
+0      108     docs/modules/opac/pages/batch_actions_from_search.adoc
+ create mode 100644 docs/modules/opac/assets/images/opac_basket/add_to_basket.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac_basket/basket_icon.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac_basket/drop_down_actions.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac_basket/select_checkboxes.jpg
+ create mode 100644 docs/modules/opac/assets/images/opac_basket/view_basket.jpg
+ create mode 100644 docs/modules/opac/pages/baskets.adoc
+ delete mode 100644 docs/modules/opac/pages/batch_actions_from_search.adoc
+
+commit 8c1e4bfb580b74d83b397d892b8a7c844e5d6c76
+Author: Jeff Godin <jgodin@tadl.org>
+Date:   Fri Jan 28 17:54:38 2022 -0500
+
+    Avoid fleshing standing penalty org unit children
+    
+    When fleshing the org unit on standing penalties, exclude child org
+    units. We don't need them, and they can cause issues when your
+    standing penalty has a Depth of "Everywhere": you end up with a full
+    copy of the org unit tree, and you will include this when editing
+    and saving the user.
+    
+    Signed-off-by: Jeff Godin <jgodin@tadl.org>
+    Signed-off-by: Chris Sharp <csharp@georgialibraries.org>
+
+4      1       Open-ILS/web/js/ui/default/staff/services/patron_search.js
+
+commit a4e6ed0f70e296dada640a3361312160b6770a1e
+Author: Terran McCanna <tmccanna@georgialibraries.org>
+Date:   Mon Jun 21 12:55:57 2021 -0400
+
+    LP1927990 Bootstrap OPAC: Patron messages lose line breaks
+    
+    Fixes problem where messages added to the Patron Message Center
+    lose their line breaks in the Bootstrap OPAC and makes them
+    difficult to read.
+    
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+1      1       Open-ILS/src/templates-bootstrap/opac/myopac/messages/single_message.tt2
+
+commit bc51765f250e371b5b434ebbb341eece0033912f
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Mon Nov 1 12:36:31 2021 -0400
+
+    LP#1949389: reduce number of PCRUD requests by subscription manager
+    
+    This patch changes how the AngularJS subscription manager fetches
+    serial item templates. In particular, rather than issuing a PCRUD
+    request for every org unit in the system, it fetches them in one
+    fell swoop. This fixes an issue where loading the subscription manager
+    in a large Evergreen consortium could lead to so many requests that
+    it drives PCRUD into backlog mode, resulting in higher request
+    latency across the board.
+    
+    To test
+    -------
+    [1] Apply the patch.
+    [2] Verify that the subscription manager lets you set the receiving
+        template for each distribution and that the drop-down's contents
+        changes if the distribution library is changed.
+    [3] Verify that the Apply Binding Template action works and that
+        the binding template drop-down(s) include the relevant copy templates.
+    
+    Note that if a binding template has been set already, the current
+    binding template is _not_ displayed as the selected value in the drop-down.
+    This is existing behavior that this patch does not aim to fix.
+    
+    Sponsored-by: BC Libraries Cooperative
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Jeff Davis <jdavis@sitka.bclibraries.ca>
+
+7      8       Open-ILS/web/js/ui/default/staff/serials/directives/subscription_manager.js
+34     4       Open-ILS/web/js/ui/default/staff/serials/services/core.js
+
+commit 35286d4359dd21f6fe874f857d0df0d8399b02f8
+Author: Steven Callender <stevecallender@esilibrary.com>
+Date:   Mon Oct 4 13:20:56 2021 -0400
+
+    LP#1946019: copyloc.js change to clear locations on new branch select.
+    
+    Signed-off-by: Steven Callender <stevecallender@esilibrary.com>
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+1      0       Open-ILS/web/js/ui/default/opac/copyloc.js
+
+commit 6cd54975990d20304657ca9e2d22583036146b6d
+Author: Garry Collum <gcollum@gmail.com>
+Date:   Wed Dec 29 14:29:41 2021 -0500
+
+    LP1955927_Barcode_search_fails_in_patron_search_modal
+    
+    Fixes the barcode search in the patron search modal in the holds screen.
+    
+    To test:
+    1. Navigate to the 'place a hold' screen in a bib record and open
+    the patron search modal.
+    2. Enter a patron barcode.
+    3. The search for the patron fails.
+    4. Apply the patch and repeat.
+    
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+
+1      1       Open-ILS/src/eg2/src/app/staff/share/patron/search.component.html
+
+commit bda143573b8ac7ff4aaecddfe1fb1110f91d2bbd
+Author: Terran McCanna <tmccanna@georgialibraries.org>
+Date:   Thu Jan 13 17:10:32 2022 -0500
+
+    LP1957840 Typo fix in mcrp class in fm_IDL.xml
+    
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+    Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
+
+1      1       Open-ILS/examples/fm_IDL.xml
+
+commit 60029bc2b5ba4b35a48b8b41351918356ae8d1db
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Fri Jan 7 18:50:04 2022 -0500
+
+    LP#1951021: account for change in OverDrive checkout response
+    
+    The OverDrive circulation API soon will stop providing a direct
+    download link in favor of displaying a separate fulfillment page
+    (either as an iframe or a redirect). This patch implements this
+    change with the redirect option.
+    
+    Additional information on the API change can be found at
+    
+    http://developer.overdrive.com/overdrive-api-notices/01-sep-2021-coming-soon-changes-to-overdrive-checkouts-api
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Jeff Davis <jdavis@sitka.bclibraries.ca>
+    Signed-off-by: Garry Collum <gcollum@gmail.com>
+
+6      2       Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI.pm
+31     3       Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI/OverDrive.pm
+4      1       Open-ILS/src/perlmods/lib/OpenILS/Utils/HTTPClient.pm
+8      1       Open-ILS/web/js/ui/default/opac/ebook_api/loggedin.js
+
+commit 6febd96f44049fbb574bce2efb92d641c8b55e25
+Author: Lynn Floyd <alynn2671@gmail.com>
+Date:   Mon Sep 6 12:13:13 2021 -0400
+
+    Adding videos from Conferences
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+3      0       docs/modules/circulation/pages/basic_holds.adoc
+8      0       docs/modules/reports/pages/introduction.adoc
+2      0       docs/modules/shared/pages/how_to_contribute_docs.adoc
+
+commit c364e0da0a998ec1fb8ee53c13c873917927efac
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Wed Feb 2 11:54:44 2022 -0500
+
+    Docs: Updating Opac Lists doc
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/opac/assets/images/lists_opac/add_to_basket.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/add_to_list_basket.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/basket_checkbox.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/call_number.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/home_list_link.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/list_notes.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/list_options.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/list_preferences.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/move_selected_to_list.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/my_account_list_options.jpg
+-      -       docs/modules/opac/assets/images/lists_opac/search_results_list_button.jpg
+37     17      docs/modules/opac/pages/my_lists.adoc
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/add_to_basket.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/add_to_list_basket.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/basket_checkbox.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/call_number.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/home_list_link.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/list_notes.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/list_options.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/list_preferences.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/move_selected_to_list.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/my_account_list_options.jpg
+ create mode 100644 docs/modules/opac/assets/images/lists_opac/search_results_list_button.jpg
+
+commit fe3f6dbd0f3a37ccc8573bd20d32312ecb4d9a31
+Author: Jane Sandberg <sandbergja@gmail.com>
+Date:   Tue Jan 25 09:50:47 2022 -0800
+
+    Docs: use asciidoc ordered list rather than adding numbers manually
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+23     38      docs/modules/cataloging/pages/overlay_record_3950_import.adoc
+
+commit 25161711beca3ed6a083e94214b4599ccb8a3f8e
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Wed Nov 10 14:37:40 2021 -0500
+
+    Docs: updating z39.50 overlay doc and images
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/cataloging/assets/images/overlay/mark_local_overlay.jpg
+-      -       docs/modules/cataloging/assets/images/overlay/overlay.jpg
+-      -       docs/modules/cataloging/assets/images/overlay/overlay_confirmation.jpg
+-      -       docs/modules/cataloging/assets/images/overlay/search.png
+-      -       docs/modules/cataloging/assets/images/overlay/view_marc.jpg
+14     19      docs/modules/cataloging/pages/overlay_record_3950_import.adoc
+ create mode 100644 docs/modules/cataloging/assets/images/overlay/mark_local_overlay.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/overlay/overlay.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/overlay/overlay_confirmation.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/overlay/search.png
+ create mode 100644 docs/modules/cataloging/assets/images/overlay/view_marc.jpg
+
+commit ed50ac40338cbe755ec3f74ba33b8de48ed170bd
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Mon Jan 24 14:04:16 2022 -0500
+
+    Docs: Update barcode_completion_grid.jpg
+    
+    Updated barcode grid screenshot; other one was too blurry
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/admin/assets/images/barcode_completion/barcode_completion_grid.jpg
+
+commit 3bb007277374dce161e1338e356f1b68188acbf7
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Fri Jul 30 10:15:46 2021 -0400
+
+    Docs: Update basic_holds.adoc
+    
+    removing Print full pull list alternative reference
+    
+    https://bugs.launchpad.net/evergreen/+bug/1775402
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+0      2       docs/modules/circulation/pages/basic_holds.adoc
+
+commit 96c793974e62503fa9088bec04722b90a8511756
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Fri Jul 30 10:14:01 2021 -0400
+
+    Docs: Update basic_holds.adoc to include updated screenshot
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/circulation/assets/images/media/holds-managing-16.png
+-      -       docs/modules/circulation/assets/images/media/queue_positions.jpg
+2      2       docs/modules/circulation/pages/basic_holds.adoc
+ delete mode 100644 docs/modules/circulation/assets/images/media/holds-managing-16.png
+ create mode 100644 docs/modules/circulation/assets/images/media/queue_positions.jpg
+
+commit 6e32ee20e85d2e379283e70b5fbe72a53ee7d52d
+Author: Jane Sandberg <sandbergja@gmail.com>
+Date:   Fri Jan 14 15:58:02 2022 -0800
+
+    Docs: add a chapter about the course materials module
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+1      0       docs/antora.yml
+4      0       docs/modules/course_materials/_attributes.adoc
+3      0       docs/modules/course_materials/nav.adoc
+2      0       docs/modules/course_materials/pages/_attributes.adoc
+74     0       docs/modules/course_materials/pages/administration.adoc
+4      0       docs/modules/course_materials/pages/introduction.adoc
+66     0       docs/modules/course_materials/pages/materials.adoc
+ create mode 100644 docs/modules/course_materials/_attributes.adoc
+ create mode 100644 docs/modules/course_materials/nav.adoc
+ create mode 100644 docs/modules/course_materials/pages/_attributes.adoc
+ create mode 100644 docs/modules/course_materials/pages/administration.adoc
+ create mode 100644 docs/modules/course_materials/pages/introduction.adoc
+ create mode 100644 docs/modules/course_materials/pages/materials.adoc
+
+commit a9716efeed659a63ed4993261741760ed9790315
+Author: Jane Sandberg <sandbergja@gmail.com>
+Date:   Tue Dec 14 13:02:15 2021 -0800
+
+    LP 1942645: stamp upgrade script
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+1      1       Open-ILS/src/sql/Pg/002.schema.config.sql
+1      1       Open-ILS/src/sql/Pg/upgrade/{XXXX.schema.update_course_module_term_constraints.sql => 1309.schema.update_course_module_term_constraints.sql}
+ rename Open-ILS/src/sql/Pg/upgrade/{XXXX.schema.update_course_module_term_constraints.sql => 1309.schema.update_course_module_term_constraints.sql} (74%)
+
+commit 90833952b2e590564c52c55232825059b00fd11b
+Author: malexander <malexander@catalyte.io>
+Date:   Wed Dec 8 19:12:23 2021 +0000
+
+    lp-1942645 term name uniqueness
+    
+    dropped name uniqueness between orgs, added constraint to owning lib and name
+    
+    Includes syntax corrections from Martha Driscoll -- thank you, Martha!
+    
+    Signed-off-by: malexander <malexander@catalyte.io>
+    Signed-off-by: Beth Willis <willis@noblenet.org>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+3      2       Open-ILS/src/sql/Pg/040.schema.asset.sql
+11     0       Open-ILS/src/sql/Pg/upgrade/XXXX.schema.update_course_module_term_constraints.sql
+ create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.schema.update_course_module_term_constraints.sql
+
+commit 560ad20dcb7a2d156a3901573773c729b70726dc
+Author: Jason Stephenson <jason@sigio.com>
+Date:   Mon Feb 10 11:09:37 2020 -0500
+
+    Lp 1862652: pingest.pl reingest record attributes fix
+    
+    Use the rdeleted parameter when reingesting record attributes in
+    pingest.pl support script so that passing argument values to the
+    --attr option makes sense.
+    
+    Prior to this patch, arguments of the --attr option would be ignored,
+    and all record attribute fields were reingested for all records,
+    deleted and not deleted alike.
+    
+    With this patch, the arguments of the --attr option are respected for
+    not deleted records.  Deleted records still have all attributes
+    reingested.
+    
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+1      1       Open-ILS/src/support-scripts/pingest.pl
+
+commit 52a3dd19b4115f800fd862177ec855a471e6a827
+Author: Bill Erickson <berickxx@gmail.com>
+Date:   Thu Jul 8 10:19:43 2021 -0400
+
+    LP1933275 Staff catalog holdings view shows correct counts
+    
+    teaches the Holdings view to determine the number of copies and call
+    numbers attached to each org unit based on the full data set (via new
+    API) instead of copies in hand, since we may only have copies in hand
+    for a subset of child org units.
+    
+    Signed-off-by: Bill Erickson <berickxx@gmail.com>
+    Signed-off-by: Mary Llewellyn <mllewell@biblio.org>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+32     24      Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
+72     0       Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm
+
+commit de798db2fd4ae9bd112ef6e3bfbbb47d64c646cc
+Author: Jane Sandberg <sandbergja@gmail.com>
+Date:   Wed Dec 1 16:08:52 2021 -0800
+
+    Docs: remove outdated screenshots
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/admin/assets/images/media/lsa-barcode_completion_admin.png
+-      -       docs/modules/admin/assets/images/media/lsa-barcode_completion_fields.png
+ delete mode 100644 docs/modules/admin/assets/images/media/lsa-barcode_completion_admin.png
+ delete mode 100644 docs/modules/admin/assets/images/media/lsa-barcode_completion_fields.png
+
+commit 054d2c2402b679121d40e4d493c77146c72b62d7
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Thu Nov 18 08:57:26 2021 -0500
+
+    Docs: update lsa-barcode-completion
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/admin/assets/images/barcode_completion/barcode_completion_grid.jpg
+-      -       docs/modules/admin/assets/images/barcode_completion/barcode_record_editor.jpg
+2      2       docs/modules/admin/pages/lsa-barcode_completion.adoc
+ create mode 100644 docs/modules/admin/assets/images/barcode_completion/barcode_completion_grid.jpg
+ create mode 100644 docs/modules/admin/assets/images/barcode_completion/barcode_record_editor.jpg
+
+commit 7fed99cb0ef2a57b15067e352e6ba9ab76e423ba
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Thu Nov 11 11:21:11 2021 -0500
+
+    LP#1949910: serialize deleting items from item bucket
+    
+    This patch serializes the fetching and fleshing of items to delete
+    when the delete-from-item-bucket action is invoked, thereby
+    avoiding possible drone starvation from open-ils.search. It
+    also throws up the progress dialog for good measure while
+    the deletion occurs.
+    
+    To test
+    -------
+    [1] Set up an item bucket with 25-50 items.
+    [2] From the item bucket intervace, invoke the action to delete
+        all of the items.
+    [3] Note that the open-ils.search.asset.copy.fleshed2.retrieve calls,
+        one for each item, are all made simultaneously. Assuming stock
+        max_children settings, this will cause open-ils.search to log
+        that some requests are hitting the backlog.
+    [4] Apply the patch and refresh the item bucket page, then repeat
+        step 2 (it doesn't matter for this purpose that the items have
+        already been deleted). This time, the open-ils.search API calls
+        are made serially and a progress bar is displayed while the
+        deletion takes place. Verify that no requests hit the backlog.
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+    Signed-off-by: Jeff Davis <jdavis@sitka.bclibraries.ca>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+12     8       Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js
+
+commit c4582addfea354c297622f1008a7a9ab15ff91cb
+Author: Jason Boyer <JBoyer@equinoxOLI.org>
+Date:   Thu Nov 18 08:52:09 2021 -0500
+
+    Forward Port 3.6.3 Upgrade Script
+
+105    0       Open-ILS/src/sql/Pg/version-upgrade/3.6.2-3.6.3-upgrade-db.sql
+ create mode 100644 Open-ILS/src/sql/Pg/version-upgrade/3.6.2-3.6.3-upgrade-db.sql
+
+commit 6287faaa0a51a7b9a4e35ea1c4896253f834d500
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Wed Nov 17 13:40:16 2021 -0500
+
+    docs: updating batch_importing_MARC.adoc
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/import_item_attribute_def.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/import_record.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/marc_tag_and_subfield.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/match_set_quality.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/new_record_match.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/operator.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/record_attribute.jpg
+-      -       docs/modules/cataloging/assets/images/batch_importing_MARC/replace_node.jpg
+58     64      docs/modules/cataloging/pages/batch_importing_MARC.adoc
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/import_item_attribute_def.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/import_record.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/marc_tag_and_subfield.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/match_set_quality.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/new_record_match.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/operator.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/record_attribute.jpg
+ create mode 100644 docs/modules/cataloging/assets/images/batch_importing_MARC/replace_node.jpg
+
+commit 69b220019728ebb254ff778de05424467798a65a
+Author: Kyle Huckins <khuckins@catalyte.io>
+Date:   Wed Jul 31 16:42:35 2019 +0000
+
+    Docs: lp1739277 Release Notes for Org Selector Styling
+    
+    - Add release notes for new Org Selector Styling functionality.
+    
+    Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
+    
+     Changes to be committed:
+            new file:   docs/RELEASE_NOTES_NEXT/Client/org-select-styling.adoc
+    
+    Signed-off-by: Jennifer Bruch <jbruch@sparkpa.org>
+    Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
+
+4      0       docs/RELEASE_NOTES_NEXT/Client/org-select-styling.adoc
+ create mode 100644 docs/RELEASE_NOTES_NEXT/Client/org-select-styling.adoc
+
+commit 5aef704200d7c6cbfaddc56e3b0c5d44f7dd2a6d
+Author: Kyle Huckins <khuckins@catalyte.io>
+Date:   Tue Jul 30 19:00:14 2019 +0000
+
+    lp1739277 OrgSelect Class Callback Holdings Implementation
+    
+    - Implement OrgSelectClassCallback in Angular Catalog Holdings UI
+    
+    Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
+    
+     Changes to be committed:
+            modified:   Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html
+            modified:   Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
+    
+    Signed-off-by: Jennifer Bruch <jbruch@sparkpa.org>
+    Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
+
+4      2       Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html
+21     0       Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
+
+commit 1b97e2f633d912d3c3eec29e86d309b960d3ad47
+Author: Bill Erickson <berickxx@gmail.com>
+Date:   Tue Jul 30 12:12:12 2019 -0400
+
+    LP1739277 Angular org selector style callback
+    
+    Allow the caller of an <eg-org-select> to pass a function which is
+    called against each org unit in the list to determine what CSS class(es)
+    should be applied to the org unit label in the list.
+    
+    Includes sandbox example.
+    
+    Signed-off-by: Bill Erickson <berickxx@gmail.com>
+    Signed-off-by: Jennifer Bruch <jbruch@sparkpa.org>
+    Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
+
+1      1       Open-ILS/src/eg2/src/app/share/org-select/org-select.component.html
+8      1       Open-ILS/src/eg2/src/app/share/org-select/org-select.component.ts
+6      0       Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
+6      1       Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
+
+commit 72a75c6e6a1560732a817cef6052646e542f3756
+Author: Jennifer Pringle <jennifer.pringle@bc.libraries.coop>
+Date:   Thu Oct 7 11:46:13 2021 -0700
+
+    Docs: Adding latency test and disable sounds to workstation admin.
+    
+    Signed-off-by: Jennifer Pringle <jennifer.pringle@bc.libraries.coop>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/admin/assets/images/workstation/latency-test.png
+34     0       docs/modules/admin/pages/latency.adoc
+1      0       docs/modules/admin/pages/workstation_admin.adoc
+ create mode 100644 docs/modules/admin/assets/images/workstation/latency-test.png
+ create mode 100644 docs/modules/admin/pages/latency.adoc
+
+commit b6e43c82c359c86b1144210698444e473de1216e
+Author: Lynn Floyd <alynn2671@gmail.com>
+Date:   Fri Jun 4 15:41:31 2021 -0400
+
+    Docs: Transit List
+    
+    Documentation on Transit List.
+    
+    Signed-off-by: Lynn Floyd <alynn2671@gmail.com>
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+-      -       docs/modules/local_admin/assets/images/transit_list/transit_list_from.png
+-      -       docs/modules/local_admin/assets/images/transit_list/transit_list_to.png
+1      0       docs/modules/local_admin/nav.adoc
+35     0       docs/modules/local_admin/pages/transit_list.adoc
+ create mode 100644 docs/modules/local_admin/assets/images/transit_list/transit_list_from.png
+ create mode 100644 docs/modules/local_admin/assets/images/transit_list/transit_list_to.png
+ create mode 100644 docs/modules/local_admin/pages/transit_list.adoc
+
+commit 06198b7bec47aebca66524ac243404c3df7e77d1
+Author: gmontimantis <86423994+gmontimantis@users.noreply.github.com>
+Date:   Mon Jun 28 12:22:57 2021 -0400
+
+    Docs: Update receipt_template_editor.adoc
+    
+    Fixes https://bugs.launchpad.net/evergreen/+bug/1929592
+    
+    Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
+
+3      1       docs/modules/admin/pages/receipt_template_editor.adoc
+
+commit 767bfeeb7fbc8f73f595a189895db34372d420ad
+Author: Terran McCanna <tmccanna@georgialibraries.org>
+Date:   Tue Sep 21 16:48:50 2021 -0400
+
+    LP1766726 Clarify Field Hints on Print Templates
+    
+    Adds 'patron.' to beginning of patron field hints in Checkout and Items Out
+    templates to make it easier for users to understand.
+    
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Jennifer Weston <jennifer.weston@equinoxOLI.org>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+18     18      Open-ILS/src/templates/staff/share/print_templates/t_checkout.tt2
+13     13      Open-ILS/src/templates/staff/share/print_templates/t_items_out.tt2
+
+commit 137f42f13f6dd0aa6813a077d81bd975529d6047
+Author: Mike Risher <mrisher@catalyte.io>
+Date:   Wed May 20 23:27:20 2020 +0000
+
+    LP#1819233 improve AngularJS eg-basic-combo-box filtering
+    
+    Adjust the eg-basic-combo-box so that it doesn’t give console errors
+    when typing characters such as [. Fix the bug that causes it to
+    sometimes show no results when there are valid results that match.
+    
+    To test
+    -------
+    [1] Apply the patch, then create a new report template, add a
+        display field, then open the Change Transform modal.
+    [2] Verify that the selection box will accept characters like '['
+        as input without browser console noise, that the filtering
+        is case-insensitive, and that filtering continues to work
+        after clicking on the selector.
+    [3] Instances of this combo box can also be found in the AngularJS
+        volume/copy editor.
+    
+    Signed-off-by: Mike Risher <mrisher@catalyte.io>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+13     3       Open-ILS/web/js/ui/default/staff/services/ui.js
+
+commit ba8e057a2797860268b6a962133fb2120c9a1c5b
+Author: Steven Callender <stevecallender@esilibrary.com>
+Date:   Fri Dec 4 09:59:25 2020 -0500
+
+    LP1906842 PLACE_UNFILLABLE_HOLD permission not working if no titles exist
+    
+    This fix will correct an issue where the screen just keeps looping to
+    the override screen when trying to place a hold that has no titles
+    available for it.
+    
+    Patch courtesy of Mike Rylander.
+    
+    Signed-off-by: Steven Callender <stevecallender@esilibrary.com>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+1      1       Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
+
+commit a9821ca3b6b4fa508fc11e97740459b23c970641
+Author: Jeff Davis <jeff.davis@bc.libraries.coop>
+Date:   Thu Jun 6 14:30:34 2019 -0700
+
+    LP#1830089: close transaction and update copy status on payment or adjust to zero
+    
+    When you make a payment that sets the balance owed to zero, Evergreen
+    closes the transaction and sets the item status to Lost & Paid (if
+    appropriate).  Adjust to Zero should do the same thing, but hitherto it
+    would not update the item status.  This commit refactors some code to
+    ensure that Evergreen gives the same result whether you make a payment
+    or adjust to zero.
+    
+    Signed-off-by: Jeff Davis <jeff.davis@bc.libraries.coop>
+    Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+54     0       Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm
+10     56      Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm
+
+commit b04ecabb9346b113d37809a31a7ee39e9111421c
+Author: Galen Charlton <gmc@equinoxOLI.org>
+Date:   Fri Nov 5 12:07:52 2021 -0400
+
+    LP#1947173: stamp schema update
+    
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+1      1       Open-ILS/src/sql/Pg/002.schema.config.sql
+1      1       Open-ILS/src/sql/Pg/upgrade/{XXXX.schema.symspell-speed-ingest.sql => 1306.schema.symspell-speed-ingest.sql}
+ rename Open-ILS/src/sql/Pg/upgrade/{XXXX.schema.symspell-speed-ingest.sql => 1306.schema.symspell-speed-ingest.sql} (99%)
+
+commit ca64d81c00fd2ec98e2b81d9bad17cab245c903e
+Author: Mike Rylander <mrylander@gmail.com>
+Date:   Wed Oct 20 16:22:37 2021 -0400
+
+    LP#1947173: Clean up bad cataloging pot hole
+    
+    If a MARC record has effectively empty fields (all space or punctuation)
+    then it's possible to stumble over a NULL text array when parsing
+    content for the symspell dictionary.  This commit checks for that
+    condition and returns early to avoid the problem.
+    
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+3      0       Open-ILS/src/sql/Pg/300.schema.staged_search.sql
+3      0       Open-ILS/src/sql/Pg/upgrade/XXXX.schema.symspell-speed-ingest.sql
+
+commit 1ed9223c2d63ef9dd4a142c42386c1cb729ad599
+Author: Mike Rylander <mrylander@gmail.com>
+Date:   Thu Oct 14 09:57:24 2021 -0400
+
+    LP#1947173: Speed up the symspell part of ingest
+    
+    For certain data, and certain data set sizes, merging the suggestion
+    arrays used by the symspell algorithm is noticably expensive.  This is
+    the case for suggestion arrays containing many thousands of entries.
+    These suggestion sets are not only slow, but generally not useful.  We
+    avoid the creation of such overly long suggestion sets using several
+    word filters that take advantage of our knowledge of the incoming data
+    to optimize for what is useful in a bibliographic context.  The
+    mechanisms employed by this patch are:
+    
+    - Omit suggestions whose length is longer than the max prefix key length
+      when the prefix key length is less than or equal to the maximum prefix
+      key length minus the maximum edit distance.
+    - Omit words that contain a run of 5 or more digits. This will drop most
+      identifiers from the dictionary while still allowing suggestions to
+      happen for year values.
+    - Omit empty keys from the dictionary.  This should have been the case
+      already but is now enforced directly.
+    - Add a small speedup to evergreen.text_array_merge_unique() by making
+      it assume that arrays passed to it do not have null values, which we
+      intentionally avoid, and against which we protect in other ways in the
+      commit.
+    
+    Besides improving reingest speed, the patches will also make the
+    search.symspell_dictionary table significantly smaller.
+    
+    Signed-off-by: Mike Rylander <mrylander@gmail.com>
+    Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
+
+18     4       Open-ILS/src/sql/Pg/300.schema.staged_search.sql
+420    0       Open-ILS/src/sql/Pg/upgrade/XXXX.schema.symspell-speed-ingest.sql
+6      1       Open-ILS/src/support-scripts/symspell-sideload.pl
+ create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.schema.symspell-speed-ingest.sql
+
+commit f2081ba7fcf2b8c228ded32129b002accb70017d
+Author: Jason Stephenson <jason@sigio.com>
+Date:   Fri Oct 29 11:17:36 2021 -0400
+
+    Forward-port 3.7.2 version upgrade script
+    
+    Signed-off-by: Jason Stephenson <jason@sigio.com>
+
+781    0       Open-ILS/src/sql/Pg/version-upgrade/3.7.1-3.7.2-upgrade-db.sql
+ create mode 100644 Open-ILS/src/sql/Pg/version-upgrade/3.7.1-3.7.2-upgrade-db.sql
index d750216..dc44774 100644 (file)
@@ -7,7 +7,7 @@ use OpenILS::Utils::Fieldmapper;
 sub ils_version {
     # version format is "x-y-z", for example "2-0-0" for Evergreen 2.0.0
     # For branches, format is "x-y"
-    return "HEAD";
+    return "3-7-3";
 }
 
 __PACKAGE__->register_method(
index 8198950..b992aeb 100644 (file)
@@ -93,6 +93,7 @@ CREATE TRIGGER no_overlapping_deps
     FOR EACH ROW EXECUTE PROCEDURE evergreen.array_overlap_check ('deprecates');
 
 INSERT INTO config.upgrade_log (version, applied_to) VALUES ('1325', :eg_version); -- stompro/sandbergja/JBoyer
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('3.7.3', :eg_version);
 
 CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/version-upgrade/3.7.2-3.7.3-upgrade-db.sql b/Open-ILS/src/sql/Pg/version-upgrade/3.7.2-3.7.3-upgrade-db.sql
new file mode 100644 (file)
index 0000000..614b614
--- /dev/null
@@ -0,0 +1,2231 @@
+--Upgrade Script for 3.7.2 to 3.7.3
+\set eg_version '''3.7.3'''
+BEGIN;
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('3.7.3', :eg_version);
+
+SELECT evergreen.upgrade_deps_block_check('1306', :eg_version);
+
+-- We don't pass this function arrays with nulls, so we save 5% not testing for that
+CREATE OR REPLACE FUNCTION evergreen.text_array_merge_unique (
+    TEXT[], TEXT[]
+) RETURNS TEXT[] AS $F$
+    SELECT NULLIF(ARRAY(
+        SELECT * FROM UNNEST($1) x
+            UNION
+        SELECT * FROM UNNEST($2) y
+    ),'{}');
+$F$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION search.symspell_build_raw_entry (
+    raw_input       TEXT,
+    source_class    TEXT,
+    no_limit        BOOL DEFAULT FALSE,
+    prefix_length   INT DEFAULT 6,
+    maxED           INT DEFAULT 3
+) RETURNS SETOF search.symspell_dictionary AS $F$
+DECLARE
+    key         TEXT;
+    del_key     TEXT;
+    key_list    TEXT[];
+    entry       search.symspell_dictionary%ROWTYPE;
+BEGIN
+    key := raw_input;
+
+    IF NOT no_limit AND CHARACTER_LENGTH(raw_input) > prefix_length THEN
+        key := SUBSTRING(key FROM 1 FOR prefix_length);
+        key_list := ARRAY[raw_input, key];
+    ELSE
+        key_list := ARRAY[key];
+    END IF;
+
+    FOREACH del_key IN ARRAY key_list LOOP
+        -- skip empty keys
+        CONTINUE WHEN del_key IS NULL OR CHARACTER_LENGTH(del_key) = 0;
+
+        entry.prefix_key := del_key;
+
+        entry.keyword_count := 0;
+        entry.title_count := 0;
+        entry.author_count := 0;
+        entry.subject_count := 0;
+        entry.series_count := 0;
+        entry.identifier_count := 0;
+
+        entry.keyword_suggestions := '{}';
+        entry.title_suggestions := '{}';
+        entry.author_suggestions := '{}';
+        entry.subject_suggestions := '{}';
+        entry.series_suggestions := '{}';
+        entry.identifier_suggestions := '{}';
+
+        IF source_class = 'keyword' THEN entry.keyword_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'title' THEN entry.title_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'author' THEN entry.author_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'subject' THEN entry.subject_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'series' THEN entry.series_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'identifier' THEN entry.identifier_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'keyword' THEN entry.keyword_suggestions := ARRAY[raw_input]; END IF;
+
+        IF del_key = raw_input THEN
+            IF source_class = 'keyword' THEN entry.keyword_count := 1; END IF;
+            IF source_class = 'title' THEN entry.title_count := 1; END IF;
+            IF source_class = 'author' THEN entry.author_count := 1; END IF;
+            IF source_class = 'subject' THEN entry.subject_count := 1; END IF;
+            IF source_class = 'series' THEN entry.series_count := 1; END IF;
+            IF source_class = 'identifier' THEN entry.identifier_count := 1; END IF;
+        END IF;
+
+        RETURN NEXT entry;
+    END LOOP;
+
+    FOR del_key IN SELECT x FROM UNNEST(search.symspell_generate_edits(key, 1, maxED)) x LOOP
+
+        -- skip empty keys
+        CONTINUE WHEN del_key IS NULL OR CHARACTER_LENGTH(del_key) = 0;
+        -- skip suggestions that are already too long for the prefix key
+        CONTINUE WHEN CHARACTER_LENGTH(del_key) <= (prefix_length - maxED) AND CHARACTER_LENGTH(raw_input) > prefix_length;
+
+        entry.keyword_suggestions := '{}';
+        entry.title_suggestions := '{}';
+        entry.author_suggestions := '{}';
+        entry.subject_suggestions := '{}';
+        entry.series_suggestions := '{}';
+        entry.identifier_suggestions := '{}';
+
+        IF source_class = 'keyword' THEN entry.keyword_count := 0; END IF;
+        IF source_class = 'title' THEN entry.title_count := 0; END IF;
+        IF source_class = 'author' THEN entry.author_count := 0; END IF;
+        IF source_class = 'subject' THEN entry.subject_count := 0; END IF;
+        IF source_class = 'series' THEN entry.series_count := 0; END IF;
+        IF source_class = 'identifier' THEN entry.identifier_count := 0; END IF;
+
+        entry.prefix_key := del_key;
+
+        IF source_class = 'keyword' THEN entry.keyword_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'title' THEN entry.title_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'author' THEN entry.author_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'subject' THEN entry.subject_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'series' THEN entry.series_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'identifier' THEN entry.identifier_suggestions := ARRAY[raw_input]; END IF;
+        IF source_class = 'keyword' THEN entry.keyword_suggestions := ARRAY[raw_input]; END IF;
+
+        RETURN NEXT entry;
+    END LOOP;
+
+END;
+$F$ LANGUAGE PLPGSQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION search.symspell_build_entries (
+    full_input      TEXT,
+    source_class    TEXT,
+    old_input       TEXT DEFAULT NULL,
+    include_phrases BOOL DEFAULT FALSE
+) RETURNS SETOF search.symspell_dictionary AS $F$
+DECLARE
+    prefix_length   INT;
+    maxED           INT;
+    word_list   TEXT[];
+    input       TEXT;
+    word        TEXT;
+    entry       search.symspell_dictionary;
+BEGIN
+    IF full_input IS NOT NULL THEN
+        SELECT value::INT INTO prefix_length FROM config.internal_flag WHERE name = 'symspell.prefix_length' AND enabled;
+        prefix_length := COALESCE(prefix_length, 6);
+
+        SELECT value::INT INTO maxED FROM config.internal_flag WHERE name = 'symspell.max_edit_distance' AND enabled;
+        maxED := COALESCE(maxED, 3);
+
+        input := evergreen.lowercase(full_input);
+        word_list := ARRAY_AGG(x) FROM search.symspell_parse_words_distinct(input) x;
+        IF word_list IS NULL THEN
+            RETURN;
+        END IF;
+    
+        IF CARDINALITY(word_list) > 1 AND include_phrases THEN
+            RETURN QUERY SELECT * FROM search.symspell_build_raw_entry(input, source_class, TRUE, prefix_length, maxED);
+        END IF;
+
+        FOREACH word IN ARRAY word_list LOOP
+            -- Skip words that have runs of 5 or more digits (I'm looking at you, ISxNs)
+            CONTINUE WHEN CHARACTER_LENGTH(word) > 4 AND word ~ '\d{5,}';
+            RETURN QUERY SELECT * FROM search.symspell_build_raw_entry(word, source_class, FALSE, prefix_length, maxED);
+        END LOOP;
+    END IF;
+
+    IF old_input IS NOT NULL THEN
+        input := evergreen.lowercase(old_input);
+
+        FOR word IN SELECT x FROM search.symspell_parse_words_distinct(input) x LOOP
+            -- similarly skip words that have 5 or more digits here to
+            -- avoid adding erroneous prefix deletion entries to the dictionary
+            CONTINUE WHEN CHARACTER_LENGTH(word) > 4 AND word ~ '\d{5,}';
+            entry.prefix_key := word;
+
+            entry.keyword_count := 0;
+            entry.title_count := 0;
+            entry.author_count := 0;
+            entry.subject_count := 0;
+            entry.series_count := 0;
+            entry.identifier_count := 0;
+
+            entry.keyword_suggestions := '{}';
+            entry.title_suggestions := '{}';
+            entry.author_suggestions := '{}';
+            entry.subject_suggestions := '{}';
+            entry.series_suggestions := '{}';
+            entry.identifier_suggestions := '{}';
+
+            IF source_class = 'keyword' THEN entry.keyword_count := -1; END IF;
+            IF source_class = 'title' THEN entry.title_count := -1; END IF;
+            IF source_class = 'author' THEN entry.author_count := -1; END IF;
+            IF source_class = 'subject' THEN entry.subject_count := -1; END IF;
+            IF source_class = 'series' THEN entry.series_count := -1; END IF;
+            IF source_class = 'identifier' THEN entry.identifier_count := -1; END IF;
+
+            RETURN NEXT entry;
+        END LOOP;
+    END IF;
+END;
+$F$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION search.symspell_build_and_merge_entries (
+    full_input      TEXT,
+    source_class    TEXT,
+    old_input       TEXT DEFAULT NULL,
+    include_phrases BOOL DEFAULT FALSE
+) RETURNS SETOF search.symspell_dictionary AS $F$
+DECLARE
+    new_entry       RECORD;
+    conflict_entry  RECORD;
+BEGIN
+
+    IF full_input = old_input THEN -- neither NULL, and are the same
+        RETURN;
+    END IF;
+
+    FOR new_entry IN EXECUTE $q$
+        SELECT  count,
+                prefix_key,
+                s AS suggestions
+          FROM  (SELECT prefix_key,
+                        ARRAY_AGG(DISTINCT $q$ || source_class || $q$_suggestions[1]) s,
+                        SUM($q$ || source_class || $q$_count) count
+                  FROM  search.symspell_build_entries($1, $2, $3, $4)
+                  GROUP BY 1) x
+        $q$ USING full_input, source_class, old_input, include_phrases
+    LOOP
+        EXECUTE $q$
+            SELECT  prefix_key,
+                    $q$ || source_class || $q$_suggestions suggestions,
+                    $q$ || source_class || $q$_count count
+              FROM  search.symspell_dictionary
+              WHERE prefix_key = $1 $q$
+            INTO conflict_entry
+            USING new_entry.prefix_key;
+
+        IF new_entry.count <> 0 THEN -- Real word, and count changed
+            IF conflict_entry.prefix_key IS NOT NULL THEN -- we'll be updating
+                IF conflict_entry.count > 0 THEN -- it's a real word
+                    RETURN QUERY EXECUTE $q$
+                        UPDATE  search.symspell_dictionary
+                           SET  $q$ || source_class || $q$_count = $2
+                          WHERE prefix_key = $1
+                          RETURNING * $q$
+                        USING new_entry.prefix_key, GREATEST(0, new_entry.count + conflict_entry.count);
+                ELSE -- it was a prefix key or delete-emptied word before
+                    IF conflict_entry.suggestions @> new_entry.suggestions THEN -- already have all suggestions here...
+                        RETURN QUERY EXECUTE $q$
+                            UPDATE  search.symspell_dictionary
+                               SET  $q$ || source_class || $q$_count = $2
+                              WHERE prefix_key = $1
+                              RETURNING * $q$
+                            USING new_entry.prefix_key, GREATEST(0, new_entry.count);
+                    ELSE -- new suggestion!
+                        RETURN QUERY EXECUTE $q$
+                            UPDATE  search.symspell_dictionary
+                               SET  $q$ || source_class || $q$_count = $2,
+                                    $q$ || source_class || $q$_suggestions = $3
+                              WHERE prefix_key = $1
+                              RETURNING * $q$
+                            USING new_entry.prefix_key, GREATEST(0, new_entry.count), evergreen.text_array_merge_unique(conflict_entry.suggestions,new_entry.suggestions);
+                    END IF;
+                END IF;
+            ELSE
+                -- We keep the on-conflict clause just in case...
+                RETURN QUERY EXECUTE $q$
+                    INSERT INTO search.symspell_dictionary AS d (
+                        $q$ || source_class || $q$_count,
+                        prefix_key,
+                        $q$ || source_class || $q$_suggestions
+                    ) VALUES ( $1, $2, $3 ) ON CONFLICT (prefix_key) DO
+                        UPDATE SET  $q$ || source_class || $q$_count = d.$q$ || source_class || $q$_count + EXCLUDED.$q$ || source_class || $q$_count,
+                                    $q$ || source_class || $q$_suggestions = evergreen.text_array_merge_unique(d.$q$ || source_class || $q$_suggestions, EXCLUDED.$q$ || source_class || $q$_suggestions)
+                        RETURNING * $q$
+                    USING new_entry.count, new_entry.prefix_key, new_entry.suggestions;
+            END IF;
+        ELSE -- key only, or no change
+            IF conflict_entry.prefix_key IS NOT NULL THEN -- we'll be updating
+                IF NOT conflict_entry.suggestions @> new_entry.suggestions THEN -- There are new suggestions
+                    RETURN QUERY EXECUTE $q$
+                        UPDATE  search.symspell_dictionary
+                           SET  $q$ || source_class || $q$_suggestions = $2
+                          WHERE prefix_key = $1
+                          RETURNING * $q$
+                        USING new_entry.prefix_key, evergreen.text_array_merge_unique(conflict_entry.suggestions,new_entry.suggestions);
+                END IF;
+            ELSE
+                RETURN QUERY EXECUTE $q$
+                    INSERT INTO search.symspell_dictionary AS d (
+                        $q$ || source_class || $q$_count,
+                        prefix_key,
+                        $q$ || source_class || $q$_suggestions
+                    ) VALUES ( $1, $2, $3 ) ON CONFLICT (prefix_key) DO -- key exists, suggestions may be added due to this entry
+                        UPDATE SET  $q$ || source_class || $q$_suggestions = evergreen.text_array_merge_unique(d.$q$ || source_class || $q$_suggestions, EXCLUDED.$q$ || source_class || $q$_suggestions)
+                    RETURNING * $q$
+                    USING new_entry.count, new_entry.prefix_key, new_entry.suggestions;
+            END IF;
+        END IF;
+    END LOOP;
+END;
+$F$ LANGUAGE PLPGSQL;
+
+
+\qecho ''
+\qecho 'The following should be run at the end of the upgrade before any'
+\qecho 'reingest occurs.  Because new triggers are installed already,'
+\qecho 'updates to indexed strings will cause zero-count dictionary entries'
+\qecho 'to be recorded which will require updating every row again (or'
+\qecho 'starting from scratch) so best to do this before other batch'
+\qecho 'changes.  A later reingest that does not significantly change'
+\qecho 'indexed strings will /not/ cause table bloat here, and will be'
+\qecho 'as fast as normal.  A copy of the SQL in a ready-to-use, non-escaped'
+\qecho 'form is available inside a comment at the end of this upgrade sub-'
+\qecho 'script so you do not need to copy this comment from the psql ouptut.'
+\qecho ''
+\qecho '\\a'
+\qecho '\\t'
+\qecho ''
+\qecho '\\o title'
+\qecho 'select value from metabib.title_field_entry where source in (select id from biblio.record_entry where not deleted);'
+\qecho '\\o author'
+\qecho 'select value from metabib.author_field_entry where source in (select id from biblio.record_entry where not deleted);'
+\qecho '\\o subject'
+\qecho 'select value from metabib.subject_field_entry where source in (select id from biblio.record_entry where not deleted);'
+\qecho '\\o series'
+\qecho 'select value from metabib.series_field_entry where source in (select id from biblio.record_entry where not deleted);'
+\qecho '\\o identifier'
+\qecho 'select value from metabib.identifier_field_entry where source in (select id from biblio.record_entry where not deleted);'
+\qecho '\\o keyword'
+\qecho 'select value from metabib.keyword_field_entry where source in (select id from biblio.record_entry where not deleted);'
+\qecho ''
+\qecho '\\o'
+\qecho '\\a'
+\qecho '\\t'
+\qecho ''
+\qecho '// Then, at the command line:'
+\qecho ''
+\qecho '$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl title > title.sql'
+\qecho '$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl author > author.sql'
+\qecho '$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl subject > subject.sql'
+\qecho '$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl series > series.sql'
+\qecho '$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl identifier > identifier.sql'
+\qecho '$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl keyword > keyword.sql'
+\qecho ''
+\qecho '// And, back in psql'
+\qecho ''
+\qecho 'ALTER TABLE search.symspell_dictionary SET UNLOGGED;'
+\qecho 'TRUNCATE search.symspell_dictionary;'
+\qecho ''
+\qecho '\\i identifier.sql'
+\qecho '\\i author.sql'
+\qecho '\\i title.sql'
+\qecho '\\i subject.sql'
+\qecho '\\i series.sql'
+\qecho '\\i keyword.sql'
+\qecho ''
+\qecho 'CLUSTER search.symspell_dictionary USING symspell_dictionary_pkey;'
+\qecho 'REINDEX TABLE search.symspell_dictionary;'
+\qecho 'ALTER TABLE search.symspell_dictionary SET LOGGED;'
+\qecho 'VACUUM ANALYZE search.symspell_dictionary;'
+\qecho ''
+\qecho 'DROP TABLE search.symspell_dictionary_partial_title;'
+\qecho 'DROP TABLE search.symspell_dictionary_partial_author;'
+\qecho 'DROP TABLE search.symspell_dictionary_partial_subject;'
+\qecho 'DROP TABLE search.symspell_dictionary_partial_series;'
+\qecho 'DROP TABLE search.symspell_dictionary_partial_identifier;'
+\qecho 'DROP TABLE search.symspell_dictionary_partial_keyword;'
+
+/* To run by hand:
+
+\a
+\t
+
+\o title
+select value from metabib.title_field_entry where source in (select id from biblio.record_entry where not deleted);
+
+\o author
+select value from metabib.author_field_entry where source in (select id from biblio.record_entry where not deleted);
+
+\o subject
+select value from metabib.subject_field_entry where source in (select id from biblio.record_entry where not deleted);
+
+\o series
+select value from metabib.series_field_entry where source in (select id from biblio.record_entry where not deleted);
+
+\o identifier
+select value from metabib.identifier_field_entry where source in (select id from biblio.record_entry where not deleted);
+
+\o keyword
+select value from metabib.keyword_field_entry where source in (select id from biblio.record_entry where not deleted);
+
+\o
+\a
+\t
+
+// Then, at the command line:
+
+$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl title > title.sql
+$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl author > author.sql
+$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl subject > subject.sql
+$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl series > series.sql
+$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl identifier > identifier.sql
+$ ~/EG-src-path/Open-ILS/src/support-scripts/symspell-sideload.pl keyword > keyword.sql
+
+// To the extent your hardware allows, the above commands can be run in 
+// in parallel, in different shells.  Each will use a full CPU, and RAM
+// may be a limiting resource, so keep an eye on that with `top`.
+
+
+// And, back in psql
+
+ALTER TABLE search.symspell_dictionary SET UNLOGGED;
+TRUNCATE search.symspell_dictionary;
+
+\i identifier.sql
+\i author.sql
+\i title.sql
+\i subject.sql
+\i series.sql
+\i keyword.sql
+
+CLUSTER search.symspell_dictionary USING symspell_dictionary_pkey;
+REINDEX TABLE search.symspell_dictionary;
+ALTER TABLE search.symspell_dictionary SET LOGGED;
+VACUUM ANALYZE search.symspell_dictionary;
+
+DROP TABLE search.symspell_dictionary_partial_title;
+DROP TABLE search.symspell_dictionary_partial_author;
+DROP TABLE search.symspell_dictionary_partial_subject;
+DROP TABLE search.symspell_dictionary_partial_series;
+DROP TABLE search.symspell_dictionary_partial_identifier;
+DROP TABLE search.symspell_dictionary_partial_keyword;
+
+*/
+
+
+SELECT evergreen.upgrade_deps_block_check('1309', :eg_version);
+
+ALTER TABLE asset.course_module_term
+        DROP CONSTRAINT course_module_term_name_key;
+
+ALTER TABLE asset.course_module_term
+        ADD CONSTRAINT cmt_once_per_owning_lib UNIQUE (owning_lib, name);
+
+
+SELECT evergreen.upgrade_deps_block_check('1311', :eg_version);
+
+CREATE OR REPLACE FUNCTION biblio.extract_located_uris( bib_id BIGINT, marcxml TEXT, editor_id INT ) RETURNS VOID AS $func$
+DECLARE
+    uris            TEXT[];
+    uri_xml         TEXT;
+    uri_label       TEXT;
+    uri_href        TEXT;
+    uri_use         TEXT;
+    uri_owner_list  TEXT[];
+    uri_owner       TEXT;
+    uri_owner_id    INT;
+    uri_id          INT;
+    uri_cn_id       INT;
+    uri_map_id      INT;
+    current_uri     INT;
+    current_map     INT;
+    uri_map_count   INT;
+    current_uri_map_list    INT[];
+    current_map_owner_list  INT[];
+
+BEGIN
+
+    uris := oils_xpath('//*[@tag="856" and (@ind1="4" or @ind1="1") and (@ind2="0" or @ind2="1")]',marcxml);
+    IF ARRAY_UPPER(uris,1) > 0 THEN
+        FOR i IN 1 .. ARRAY_UPPER(uris, 1) LOOP
+            -- First we pull info out of the 856
+            uri_xml     := uris[i];
+
+            uri_href    := (oils_xpath('//*[@code="u"]/text()',uri_xml))[1];
+            uri_label   := (oils_xpath('//*[@code="y"]/text()|//*[@code="3"]/text()',uri_xml))[1];
+            uri_use     := (oils_xpath('//*[@code="z"]/text()|//*[@code="2"]/text()|//*[@code="n"]/text()',uri_xml))[1];
+
+            IF uri_label IS NULL THEN
+                uri_label := uri_href;
+            END IF;
+            CONTINUE WHEN uri_href IS NULL;
+
+            -- Get the distinct list of libraries wanting to use 
+            SELECT  ARRAY_AGG(
+                        DISTINCT REGEXP_REPLACE(
+                            x,
+                            $re$^.*?\((\w+)\).*$$re$,
+                            E'\\1'
+                        )
+                    ) INTO uri_owner_list
+              FROM  UNNEST(
+                        oils_xpath(
+                            '//*[@code="9"]/text()|//*[@code="w"]/text()|//*[@code="n"]/text()',
+                            uri_xml
+                        )
+                    )x;
+
+            IF ARRAY_UPPER(uri_owner_list,1) > 0 THEN
+
+                -- look for a matching uri
+                IF uri_use IS NULL THEN
+                    SELECT id INTO uri_id
+                        FROM asset.uri
+                        WHERE label = uri_label AND href = uri_href AND use_restriction IS NULL AND active
+                        ORDER BY id LIMIT 1;
+                    IF NOT FOUND THEN -- create one
+                        INSERT INTO asset.uri (label, href, use_restriction) VALUES (uri_label, uri_href, uri_use);
+                        SELECT id INTO uri_id
+                            FROM asset.uri
+                            WHERE label = uri_label AND href = uri_href AND use_restriction IS NULL AND active;
+                    END IF;
+                ELSE
+                    SELECT id INTO uri_id
+                        FROM asset.uri
+                        WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active
+                        ORDER BY id LIMIT 1;
+                    IF NOT FOUND THEN -- create one
+                        INSERT INTO asset.uri (label, href, use_restriction) VALUES (uri_label, uri_href, uri_use);
+                        SELECT id INTO uri_id
+                            FROM asset.uri
+                            WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active;
+                    END IF;
+                END IF;
+
+                FOR j IN 1 .. ARRAY_UPPER(uri_owner_list, 1) LOOP
+                    uri_owner := uri_owner_list[j];
+
+                    SELECT id INTO uri_owner_id FROM actor.org_unit WHERE shortname = BTRIM(REPLACE(uri_owner,chr(160),''));
+                    CONTINUE WHEN NOT FOUND;
+
+                    -- we need a call number to link through
+                    SELECT id INTO uri_cn_id FROM asset.call_number WHERE owning_lib = uri_owner_id AND record = bib_id AND label = '##URI##' AND NOT deleted;
+                    IF NOT FOUND THEN
+                        INSERT INTO asset.call_number (owning_lib, record, create_date, edit_date, creator, editor, label)
+                            VALUES (uri_owner_id, bib_id, 'now', 'now', editor_id, editor_id, '##URI##');
+                        SELECT id INTO uri_cn_id FROM asset.call_number WHERE owning_lib = uri_owner_id AND record = bib_id AND label = '##URI##' AND NOT deleted;
+                    END IF;
+
+                    -- now, link them if they're not already
+                    SELECT id INTO uri_map_id FROM asset.uri_call_number_map WHERE call_number = uri_cn_id AND uri = uri_id;
+                    IF NOT FOUND THEN
+                        INSERT INTO asset.uri_call_number_map (call_number, uri) VALUES (uri_cn_id, uri_id);
+                        SELECT id INTO uri_map_id FROM asset.uri_call_number_map WHERE call_number = uri_cn_id AND uri = uri_id;
+                    END IF;
+
+                    current_uri_map_list := current_uri_map_list || uri_map_id;
+                    current_map_owner_list := current_map_owner_list || uri_cn_id;
+
+                END LOOP;
+
+            END IF;
+
+        END LOOP;
+    END IF;
+
+    -- Clear any orphaned URIs, URI mappings and call
+    -- numbers for this bib that weren't mapped above.
+    FOR current_map IN
+        SELECT  m.id
+          FROM  asset.uri_call_number_map m
+                LEFT JOIN asset.call_number cn ON (cn.id = m.call_number)
+          WHERE cn.record = bib_id
+                AND cn.label = '##URI##'
+                AND (NOT (m.id = ANY (current_uri_map_list))
+                     OR current_uri_map_list is NULL)
+    LOOP
+        SELECT uri INTO current_uri FROM asset.uri_call_number_map WHERE id = current_map;
+        DELETE FROM asset.uri_call_number_map WHERE id = current_map;
+
+        SELECT COUNT(*) INTO uri_map_count FROM asset.uri_call_number_map WHERE uri = current_uri;
+        IF uri_map_count = 0 THEN
+            DELETE FROM asset.uri WHERE id = current_uri;
+        END IF;
+    END LOOP;
+
+    UPDATE asset.call_number
+    SET deleted = TRUE, edit_date = now(), editor = editor_id
+    WHERE id IN (
+        SELECT  id
+          FROM  asset.call_number
+          WHERE record = bib_id
+                AND label = '##URI##'
+                AND NOT deleted
+                AND (NOT (id = ANY (current_map_owner_list))
+                     OR current_map_owner_list is NULL)
+    );
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- Remove existing orphaned URIs from the database.
+DELETE FROM asset.uri
+WHERE id IN
+(
+SELECT uri.id
+FROM asset.uri
+LEFT JOIN asset.uri_call_number_map
+ON uri_call_number_map.uri = uri.id
+LEFT JOIN serial.item
+ON item.uri = uri.id
+WHERE uri_call_number_map IS NULL
+AND item IS NULL
+);
+
+
+
+SELECT evergreen.upgrade_deps_block_check('1325', :eg_version);
+
+UPDATE config.xml_transform SET xslt=$XSLT$<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:mads="http://www.loc.gov/mads/v2"
+       xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:marc="http://www.loc.gov/MARC21/slim"
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="marc">
+       <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
+       <xsl:strip-space elements="*"/>
+
+       <xsl:variable name="ascii">
+               <xsl:text> !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~</xsl:text>
+       </xsl:variable>
+
+       <xsl:variable name="latin1">
+               <xsl:text> ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ</xsl:text>
+       </xsl:variable>
+       <!-- Characters that usually don't need to be escaped -->
+       <xsl:variable name="safe">
+               <xsl:text>!'()*-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~</xsl:text>
+       </xsl:variable>
+
+       <xsl:variable name="hex">0123456789ABCDEF</xsl:variable>
+
+
+       <xsl:template name="datafield">
+               <xsl:param name="tag"/>
+               <xsl:param name="ind1">
+                       <xsl:text> </xsl:text>
+               </xsl:param>
+               <xsl:param name="ind2">
+                       <xsl:text> </xsl:text>
+               </xsl:param>
+               <xsl:param name="subfields"/>
+               <xsl:element name="marc:datafield">
+                       <xsl:attribute name="tag">
+                               <xsl:value-of select="$tag"/>
+                       </xsl:attribute>
+                       <xsl:attribute name="ind1">
+                               <xsl:value-of select="$ind1"/>
+                       </xsl:attribute>
+                       <xsl:attribute name="ind2">
+                               <xsl:value-of select="$ind2"/>
+                       </xsl:attribute>
+                       <xsl:copy-of select="$subfields"/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template name="subfieldSelect">
+               <xsl:param name="codes">abcdefghijklmnopqrstuvwxyz</xsl:param>
+               <xsl:param name="delimeter">
+                       <xsl:text> </xsl:text>
+               </xsl:param>
+               <xsl:variable name="str">
+                       <xsl:for-each select="marc:subfield">
+                               <xsl:if test="contains($codes, @code)">
+                                       <xsl:value-of select="text()"/>
+                                       <xsl:value-of select="$delimeter"/>
+                               </xsl:if>
+                       </xsl:for-each>
+               </xsl:variable>
+               <xsl:value-of select="substring($str,1,string-length($str)-string-length($delimeter))"/>
+       </xsl:template>
+
+       <xsl:template name="buildSpaces">
+               <xsl:param name="spaces"/>
+               <xsl:param name="char">
+                       <xsl:text> </xsl:text>
+               </xsl:param>
+               <xsl:if test="$spaces>0">
+                       <xsl:value-of select="$char"/>
+                       <xsl:call-template name="buildSpaces">
+                               <xsl:with-param name="spaces" select="$spaces - 1"/>
+                               <xsl:with-param name="char" select="$char"/>
+                       </xsl:call-template>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="chopPunctuation">
+               <xsl:param name="chopString"/>
+               <xsl:param name="punctuation">
+                       <xsl:text>.:,;/ </xsl:text>
+               </xsl:param>
+               <xsl:variable name="length" select="string-length($chopString)"/>
+               <xsl:choose>
+                       <xsl:when test="$length=0"/>
+                       <xsl:when test="contains($punctuation, substring($chopString,$length,1))">
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>
+                                       <xsl:with-param name="punctuation" select="$punctuation"/>
+                               </xsl:call-template>
+                       </xsl:when>
+                       <xsl:when test="not($chopString)"/>
+                       <xsl:otherwise>
+                               <xsl:value-of select="$chopString"/>
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+
+       <xsl:template name="chopPunctuationFront">
+               <xsl:param name="chopString"/>
+               <xsl:variable name="length" select="string-length($chopString)"/>
+               <xsl:choose>
+                       <xsl:when test="$length=0"/>
+                       <xsl:when test="contains('.:,;/[ ', substring($chopString,1,1))">
+                               <xsl:call-template name="chopPunctuationFront">
+                                       <xsl:with-param name="chopString" select="substring($chopString,2,$length - 1)"
+                                       />
+                               </xsl:call-template>
+                       </xsl:when>
+                       <xsl:when test="not($chopString)"/>
+                       <xsl:otherwise>
+                               <xsl:value-of select="$chopString"/>
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+
+       <xsl:template name="chopPunctuationBack">
+               <xsl:param name="chopString"/>
+               <xsl:param name="punctuation">
+                       <xsl:text>.:,;/] </xsl:text>
+               </xsl:param>
+               <xsl:variable name="length" select="string-length($chopString)"/>
+               <xsl:choose>
+                       <xsl:when test="$length=0"/>
+                       <xsl:when test="contains($punctuation, substring($chopString,$length,1))">
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>
+                                       <xsl:with-param name="punctuation" select="$punctuation"/>
+                               </xsl:call-template>
+                       </xsl:when>
+                       <xsl:when test="not($chopString)"/>
+                       <xsl:otherwise>
+                               <xsl:value-of select="$chopString"/>
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+
+       <!-- nate added 12/14/2007 for lccn.loc.gov: url encode ampersand, etc. -->
+       <xsl:template name="url-encode">
+
+               <xsl:param name="str"/>
+
+               <xsl:if test="$str">
+                       <xsl:variable name="first-char" select="substring($str,1,1)"/>
+                       <xsl:choose>
+                               <xsl:when test="contains($safe,$first-char)">
+                                       <xsl:value-of select="$first-char"/>
+                               </xsl:when>
+                               <xsl:otherwise>
+                                       <xsl:variable name="codepoint">
+                                               <xsl:choose>
+                                                       <xsl:when test="contains($ascii,$first-char)">
+                                                               <xsl:value-of
+                                                                       select="string-length(substring-before($ascii,$first-char)) + 32"
+                                                               />
+                                                       </xsl:when>
+                                                       <xsl:when test="contains($latin1,$first-char)">
+                                                               <xsl:value-of
+                                                                       select="string-length(substring-before($latin1,$first-char)) + 160"/>
+                                                               <!-- was 160 -->
+                                                       </xsl:when>
+                                                       <xsl:otherwise>
+                                                               <xsl:message terminate="no">Warning: string contains a character
+                                                                       that is out of range! Substituting "?".</xsl:message>
+                                                               <xsl:text>63</xsl:text>
+                                                       </xsl:otherwise>
+                                               </xsl:choose>
+                                       </xsl:variable>
+                                       <xsl:variable name="hex-digit1"
+                                               select="substring($hex,floor($codepoint div 16) + 1,1)"/>
+                                       <xsl:variable name="hex-digit2" select="substring($hex,$codepoint mod 16 + 1,1)"/>
+                                       <!-- <xsl:value-of select="concat('%',$hex-digit2)"/> -->
+                                       <xsl:value-of select="concat('%',$hex-digit1,$hex-digit2)"/>
+                               </xsl:otherwise>
+                       </xsl:choose>
+                       <xsl:if test="string-length($str) &gt; 1">
+                               <xsl:call-template name="url-encode">
+                                       <xsl:with-param name="str" select="substring($str,2)"/>
+                               </xsl:call-template>
+                       </xsl:if>
+               </xsl:if>
+       </xsl:template>
+
+
+<!--
+2.15  reversed genre and setAuthority template order under relatedTypeAttribute                       tmee 11/13/2018
+2.14    Fixed bug in mads:geographic attributes syntax                                      ws   05/04/2016            
+2.13   fixed repeating <geographic>                                                                                                            tmee 01/31/2014
+2.12   added $2 authority for <classification>                                                                                         tmee 09/18/2012
+2.11   added delimiters between <classification> subfields                                                                     tmee 09/18/2012
+2.10   fixed type="other" and type="otherType" for mads:related                                                        tmee 09/16/2011
+2.09   fixed professionTerm and genreTerm empty tag error                                                                      tmee 09/16/2011
+2.08   fixed marc:subfield @code='i' matching error                                                                            tmee 09/16/2011
+2.07   fixed 555 duplication error                                                                                                                     tmee 08/10/2011 
+2.06   fixed topic subfield error                                                                                                                      tmee 08/10/2011 
+2.05   fixed title subfield error                                                                                                                      tmee 06/20/2011 
+2.04   fixed geographicSubdivision mapping for authority element                                                       tmee 06/16/2011
+2.03   added classification for 053, 055, 060, 065, 070, 080, 082, 083, 086, 087                       tmee 06/03/2011         
+2.02   added descriptionStandard for 008/10                                                                                            tmee 04/27/2011
+2.01   added extensions for 046, 336, 370, 374, 375, 376                                                                       tmee 04/08/2011
+2.00   redefined imported MODS elements in version 1.0 to MADS elements in version 2.0         tmee 02/08/2011
+1.08   added 372 subfields $a $s $t for <fieldOfActivity>                                                                      tmee 06/24/2010
+1.07   removed role/roleTerm 100, 110, 111, 400, 410, 411, 500, 510, 511, 700, 710, 711        tmee 06/24/2010
+1.06   added strip-space                                                                                                                                       tmee 06/24/2010
+1.05   added subfield $a for 130, 430, 530                                                                                                     tmee 06/21/2010
+1.04   fixed 550 z omission                                                                                                                            ntra 08/11/2008
+1.03   removed duplication of 550 $a text                                                                                                      tmee 11/01/2006
+1.02   fixed namespace references between mads and mods                                                                        ntra 10/06/2006
+1.01   revised                                                                                                                                                         rgue/jrad 11/29/05
+1.00   adapted from MARC21Slim2MODS3.xsl                                                                                                       ntra 07/06/05
+-->
+
+       <!-- authority attribute defaults to 'naf' if not set using this authority parameter, for <authority> descriptors: name, titleInfo, geographic -->
+       <xsl:param name="authority"/>
+       <xsl:variable name="auth">
+               <xsl:choose>
+                       <xsl:when test="$authority">
+                               <xsl:value-of select="$authority"/>
+                       </xsl:when>
+                       <xsl:otherwise>naf</xsl:otherwise>
+               </xsl:choose>
+       </xsl:variable>
+       <xsl:variable name="controlField008" select="marc:controlfield[@tag='008']"/>
+       <xsl:variable name="controlField008-06"
+               select="substring(descendant-or-self::marc:controlfield[@tag=008],7,1)"/>
+       <xsl:variable name="controlField008-11"
+               select="substring(descendant-or-self::marc:controlfield[@tag=008],12,1)"/>
+       <xsl:variable name="controlField008-14"
+               select="substring(descendant-or-self::marc:controlfield[@tag=008],15,1)"/>
+       <xsl:template match="/">
+               <xsl:choose>
+                       <xsl:when test="descendant-or-self::marc:collection">
+                               <mads:madsCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                                       xsi:schemaLocation="http://www.loc.gov/mads/v2 http://www.loc.gov/standards/mads/v2/mads-2-0.xsd">
+                                       <xsl:for-each select="descendant-or-self::marc:collection/marc:record">
+                                               <mads:mads version="2.0">
+                                                       <xsl:call-template name="marcRecord"/>
+                                               </mads:mads>
+                                       </xsl:for-each>
+                               </mads:madsCollection>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <mads:mads version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                                       xsi:schemaLocation="http://www.loc.gov/mads/v2 http://www.loc.gov/standards/mads/mads-2-0.xsd">
+                                       <xsl:for-each select="descendant-or-self::marc:record">
+                                               <xsl:call-template name="marcRecord"/>
+                                       </xsl:for-each>
+                               </mads:mads>
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+
+       <xsl:template name="marcRecord">
+               <mads:authority>
+                       <!-- 2.04 -->
+                       <xsl:choose>
+                               <xsl:when test="$controlField008-06='d'">
+                                       <xsl:attribute name="geographicSubdivision">
+                                               <xsl:text>direct</xsl:text>
+                                       </xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="$controlField008-06='i'">
+                                       <xsl:attribute name="geographicSubdivision">
+                                               <xsl:text>indirect</xsl:text>
+                                       </xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="$controlField008-06='n'">
+                                       <xsl:attribute name="geographicSubdivision">
+                                               <xsl:text>not applicable</xsl:text>
+                                       </xsl:attribute>
+                               </xsl:when>
+                       </xsl:choose>
+                       
+                       <xsl:apply-templates select="marc:datafield[100 &lt;= @tag  and @tag &lt; 200]"/>               
+               </mads:authority>
+
+               <!-- related -->
+               <xsl:apply-templates
+                       select="marc:datafield[500 &lt;= @tag and @tag &lt;= 585]|marc:datafield[700 &lt;= @tag and @tag &lt;= 785]"/>
+
+               <!-- variant -->
+               <xsl:apply-templates select="marc:datafield[400 &lt;= @tag and @tag &lt;= 485]"/>
+
+               <!-- notes -->
+               <xsl:apply-templates select="marc:datafield[667 &lt;= @tag and @tag &lt;= 688]"/>
+
+               <!-- url -->
+               <xsl:apply-templates select="marc:datafield[@tag=856]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=010]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=024]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=372]"/>
+               
+               <!-- classification -->
+               <xsl:apply-templates select="marc:datafield[@tag=053]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=055]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=060]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=065]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=070]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=080]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=082]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=083]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=086]"/>
+               <xsl:apply-templates select="marc:datafield[@tag=087]"/>
+
+               <!-- affiliation-->
+               <xsl:for-each select="marc:datafield[@tag=373]">
+                       <mads:affiliation>
+                               <mads:position>
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                               </mads:position>
+                               <mads:dateValid point="start">
+                                       <xsl:value-of select="marc:subfield[@code='s']"/>
+                               </mads:dateValid>
+                               <mads:dateValid point="end">
+                                       <xsl:value-of select="marc:subfield[@code='t']"/>
+                               </mads:dateValid>
+                       </mads:affiliation>
+               </xsl:for-each>
+               <xsl:for-each select="marc:datafield[@tag=371]">
+                       <mads:affiliation>
+                               <mads:address>
+                                       <mads:street>
+                                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                                       </mads:street>
+                                       <mads:city>
+                                               <xsl:value-of select="marc:subfield[@code='b']"/>
+                                       </mads:city>
+                                       <mads:state>
+                                               <xsl:value-of select="marc:subfield[@code='c']"/>
+                                       </mads:state>
+                                       <mads:country>
+                                               <xsl:value-of select="marc:subfield[@code='d']"/>
+                                       </mads:country>
+                                       <mads:postcode>
+                                               <xsl:value-of select="marc:subfield[@code='e']"/>
+                                       </mads:postcode>
+                               </mads:address>
+                               <mads:email>
+                                       <xsl:value-of select="marc:subfield[@code='m']"/>
+                               </mads:email>
+                       </mads:affiliation>
+               </xsl:for-each>
+
+               <!-- extension-->
+               <xsl:for-each select="marc:datafield[@tag=336]">
+                       <mads:extension>
+                               <mads:contentType>
+                                       <mads:contentType type="text">
+                                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                                       </mads:contentType>
+                                       <mads:contentType type="code">
+                                               <xsl:value-of select="marc:subfield[@code='b']"/>
+                                       </mads:contentType>
+                               </mads:contentType>
+                       </mads:extension>
+               </xsl:for-each>
+
+               <xsl:for-each select="marc:datafield[@tag=374]">
+                       <mads:extension>
+                               <mads:profession>
+                                       <xsl:choose>
+                                               <xsl:when test="marc:subfield[@code='a']">
+                                                       <mads:professionTerm>
+                                                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                                                       </mads:professionTerm>
+                                               </xsl:when>
+                                               <xsl:when test="marc:subfield[@code='s']">
+                                                       <mads:dateValid point="start">
+                                                               <xsl:value-of select="marc:subfield[@code='s']"/>
+                                                       </mads:dateValid>
+                                               </xsl:when>
+                                               <xsl:when test="marc:subfield[@code='t']">
+                                                       <mads:dateValid point="end">
+                                                               <xsl:value-of select="marc:subfield[@code='t']"/>
+                                                       </mads:dateValid>
+                                               </xsl:when>
+                                       </xsl:choose>
+                               </mads:profession>
+                       </mads:extension>
+               </xsl:for-each>
+               
+               <xsl:for-each select="marc:datafield[@tag=375]">
+                       <mads:extension>
+                               <mads:gender>
+                                       <xsl:choose>
+                                               <xsl:when test="marc:subfield[@code='a']">
+                                                       <mads:genderTerm>
+                                                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                                                       </mads:genderTerm>
+                                               </xsl:when>
+                                               <xsl:when test="marc:subfield[@code='s']">
+                                                       <mads:dateValid point="start">
+                                                               <xsl:value-of select="marc:subfield[@code='s']"/>
+                                                       </mads:dateValid>
+                                               </xsl:when>
+                                               <xsl:when test="marc:subfield[@code='t']">
+                                                       <mads:dateValid point="end">
+                                                               <xsl:value-of select="marc:subfield[@code='t']"/>
+                                                       </mads:dateValid>
+                                               </xsl:when>
+                                       </xsl:choose>
+                               </mads:gender>
+                       </mads:extension>
+               </xsl:for-each>
+
+               <xsl:for-each select="marc:datafield[@tag=376]">
+                       <mads:extension>
+                               <mads:familyInformation>
+                                       <mads:typeOfFamily>
+                                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                                       </mads:typeOfFamily>
+                                       <mads:nameOfProminentMember>
+                                               <xsl:value-of select="marc:subfield[@code='b']"/>
+                                       </mads:nameOfProminentMember>
+                                       <mads:hereditaryTitle>
+                                               <xsl:value-of select="marc:subfield[@code='c']"/>
+                                       </mads:hereditaryTitle>
+                                       <mads:dateValid point="start">
+                                               <xsl:value-of select="marc:subfield[@code='s']"/>
+                                       </mads:dateValid>
+                                       <mads:dateValid point="end">
+                                               <xsl:value-of select="marc:subfield[@code='t']"/>
+                                       </mads:dateValid>
+                               </mads:familyInformation>
+                       </mads:extension>
+               </xsl:for-each>
+
+               <mads:recordInfo>
+                       <mads:recordOrigin>Converted from MARCXML to MADS version 2.0 (Revision 2.13)</mads:recordOrigin>
+                       <!-- <xsl:apply-templates select="marc:datafield[@tag=024]"/> -->
+
+                       <xsl:apply-templates select="marc:datafield[@tag=040]/marc:subfield[@code='a']"/>
+                       <xsl:apply-templates select="marc:controlfield[@tag=005]"/>
+                       <xsl:apply-templates select="marc:controlfield[@tag=001]"/>
+                       <xsl:apply-templates select="marc:datafield[@tag=040]/marc:subfield[@code='b']"/>
+                       <xsl:apply-templates select="marc:datafield[@tag=040]/marc:subfield[@code='e']"/>
+                       <xsl:for-each select="marc:controlfield[@tag=008]">
+                               <xsl:if test="substring(.,11,1)='a'">
+                                       <mads:descriptionStandard>
+                                               <xsl:text>earlier rules</xsl:text>
+                                       </mads:descriptionStandard>
+                               </xsl:if>
+                               <xsl:if test="substring(.,11,1)='b'">
+                                       <mads:descriptionStandard>
+                                               <xsl:text>aacr1</xsl:text>
+                                       </mads:descriptionStandard>
+                               </xsl:if>
+                               <xsl:if test="substring(.,11,1)='c'">
+                                       <mads:descriptionStandard>
+                                               <xsl:text>aacr2</xsl:text>
+                                       </mads:descriptionStandard>
+                               </xsl:if>
+                               <xsl:if test="substring(.,11,1)='d'">
+                                       <mads:descriptionStandard>
+                                               <xsl:text>aacr2 compatible</xsl:text>
+                                       </mads:descriptionStandard>
+                               </xsl:if>
+                               <xsl:if test="substring(.,11,1)='z'">
+                                       <mads:descriptionStandard>
+                                               <xsl:text>other rules</xsl:text>
+                                       </mads:descriptionStandard>
+                               </xsl:if>
+                       </xsl:for-each>
+               </mads:recordInfo>
+       </xsl:template>
+
+       <!-- start of secondary templates -->
+
+       <!-- ======== xlink ======== -->
+
+       <!-- <xsl:template name="uri"> 
+    <xsl:for-each select="marc:subfield[@code='0']">
+      <xsl:attribute name="xlink:href">
+       <xsl:value-of select="."/>
+      </xsl:attribute>
+    </xsl:for-each>
+     </xsl:template> 
+   -->
+       <xsl:template match="marc:subfield[@code='i']">
+               <xsl:attribute name="otherType">
+                       <xsl:value-of select="."/>
+               </xsl:attribute>
+       </xsl:template>
+
+       <!-- No role/roleTerm mapped in MADS 06/24/2010
+       <xsl:template name="role">
+               <xsl:for-each select="marc:subfield[@code='e']">
+                       <mads:role>
+                               <mads:roleTerm type="text">
+                                       <xsl:value-of select="."/>
+                               </mads:roleTerm>
+                       </mads:role>
+               </xsl:for-each>
+       </xsl:template>
+-->
+
+       <xsl:template name="part">
+               <xsl:variable name="partNumber">
+                       <xsl:call-template name="specialSubfieldSelect">
+                               <xsl:with-param name="axis">n</xsl:with-param>
+                               <xsl:with-param name="anyCodes">n</xsl:with-param>
+                               <xsl:with-param name="afterCodes">fghkdlmor</xsl:with-param>
+                       </xsl:call-template>
+               </xsl:variable>
+               <xsl:variable name="partName">
+                       <xsl:call-template name="specialSubfieldSelect">
+                               <xsl:with-param name="axis">p</xsl:with-param>
+                               <xsl:with-param name="anyCodes">p</xsl:with-param>
+                               <xsl:with-param name="afterCodes">fghkdlmor</xsl:with-param>
+                       </xsl:call-template>
+               </xsl:variable>
+               <xsl:if test="string-length(normalize-space($partNumber))">
+                       <mads:partNumber>
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString" select="$partNumber"/>
+                               </xsl:call-template>
+                       </mads:partNumber>
+               </xsl:if>
+               <xsl:if test="string-length(normalize-space($partName))">
+                       <mads:partName>
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString" select="$partName"/>
+                               </xsl:call-template>
+                       </mads:partName>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="nameABCDN">
+               <xsl:for-each select="marc:subfield[@code='a']">
+                       <mads:namePart>
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString" select="."/>
+                               </xsl:call-template>
+                       </mads:namePart>
+               </xsl:for-each>
+               <xsl:for-each select="marc:subfield[@code='b']">
+                       <mads:namePart>
+                               <xsl:value-of select="."/>
+                       </mads:namePart>
+               </xsl:for-each>
+               <xsl:if
+                       test="marc:subfield[@code='c'] or marc:subfield[@code='d'] or marc:subfield[@code='n']">
+                       <mads:namePart>
+                               <xsl:call-template name="subfieldSelect">
+                                       <xsl:with-param name="codes">cdn</xsl:with-param>
+                               </xsl:call-template>
+                       </mads:namePart>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="nameABCDQ">
+               <mads:namePart>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">aq</xsl:with-param>
+                                       </xsl:call-template>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:namePart>
+               <xsl:call-template name="termsOfAddress"/>
+               <xsl:call-template name="nameDate"/>
+       </xsl:template>
+
+       <xsl:template name="nameACDENQ">
+               <mads:namePart>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">acdenq</xsl:with-param>
+                       </xsl:call-template>
+               </mads:namePart>
+       </xsl:template>
+
+       <xsl:template name="nameDate">
+               <xsl:for-each select="marc:subfield[@code='d']">
+                       <mads:namePart type="date">
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString" select="."/>
+                               </xsl:call-template>
+                       </mads:namePart>
+               </xsl:for-each>
+       </xsl:template>
+
+       <xsl:template name="specialSubfieldSelect">
+               <xsl:param name="anyCodes"/>
+               <xsl:param name="axis"/>
+               <xsl:param name="beforeCodes"/>
+               <xsl:param name="afterCodes"/>
+               <xsl:variable name="str">
+                       <xsl:for-each select="marc:subfield">
+                               <xsl:if
+                                       test="contains($anyCodes, @code) or (contains($beforeCodes,@code) and following-sibling::marc:subfield[@code=$axis]) or (contains($afterCodes,@code) and preceding-sibling::marc:subfield[@code=$axis])">
+                                       <xsl:value-of select="text()"/>
+                                       <xsl:text> </xsl:text>
+                               </xsl:if>
+                       </xsl:for-each>
+               </xsl:variable>
+               <xsl:value-of select="substring($str,1,string-length($str)-1)"/>
+       </xsl:template>
+
+       <xsl:template name="termsOfAddress">
+               <xsl:if test="marc:subfield[@code='b' or @code='c']">
+                       <mads:namePart type="termsOfAddress">
+                               <xsl:call-template name="chopPunctuation">
+                                       <xsl:with-param name="chopString">
+                                               <xsl:call-template name="subfieldSelect">
+                                                       <xsl:with-param name="codes">bc</xsl:with-param>
+                                               </xsl:call-template>
+                                       </xsl:with-param>
+                               </xsl:call-template>
+                       </mads:namePart>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="displayLabel">
+               <xsl:if test="marc:subfield[@code='z']">
+                       <xsl:attribute name="displayLabel">
+                               <xsl:value-of select="marc:subfield[@code='z']"/>
+                       </xsl:attribute>
+               </xsl:if>
+               <xsl:if test="marc:subfield[@code='3']">
+                       <xsl:attribute name="displayLabel">
+                               <xsl:value-of select="marc:subfield[@code='3']"/>
+                       </xsl:attribute>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="isInvalid">
+               <xsl:if test="@code='z'">
+                       <xsl:attribute name="invalid">yes</xsl:attribute>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="sub2Attribute">
+               <!-- 024 -->
+               <xsl:if test="../marc:subfield[@code='2']">
+                       <xsl:attribute name="type">
+                               <xsl:value-of select="../marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template match="marc:controlfield[@tag=001]">
+               <mads:recordIdentifier>
+                       <xsl:if test="../marc:controlfield[@tag=003]">
+                               <xsl:attribute name="source">
+                                       <xsl:value-of select="../marc:controlfield[@tag=003]"/>
+                               </xsl:attribute>
+                       </xsl:if>
+                       <xsl:value-of select="."/>
+               </mads:recordIdentifier>
+       </xsl:template>
+
+       <xsl:template match="marc:controlfield[@tag=005]">
+               <mads:recordChangeDate encoding="iso8601">
+                       <xsl:value-of select="."/>
+               </mads:recordChangeDate>
+       </xsl:template>
+
+       <xsl:template match="marc:controlfield[@tag=008]">
+               <mads:recordCreationDate encoding="marc">
+                       <xsl:value-of select="substring(.,1,6)"/>
+               </mads:recordCreationDate>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=010]">
+               <xsl:for-each select="marc:subfield">
+                       <mads:identifier type="lccn">
+                               <xsl:call-template name="isInvalid"/>
+                               <xsl:value-of select="."/>
+                       </mads:identifier>
+               </xsl:for-each>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=024]">
+               <xsl:for-each select="marc:subfield[not(@code=2)]">
+                       <mads:identifier>
+                               <xsl:call-template name="isInvalid"/>
+                               <xsl:call-template name="sub2Attribute"/>
+                               <xsl:value-of select="."/>
+                       </mads:identifier>
+               </xsl:for-each>
+       </xsl:template>
+
+       <!-- ========== 372 ========== -->
+       <xsl:template match="marc:datafield[@tag=372]">
+               <mads:fieldOfActivity>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">a</xsl:with-param>
+                       </xsl:call-template>
+                       <xsl:text>-</xsl:text>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">st</xsl:with-param>
+                       </xsl:call-template>
+               </mads:fieldOfActivity>
+       </xsl:template>
+
+
+       <!-- ========== 040 ========== -->
+       <xsl:template match="marc:datafield[@tag=040]/marc:subfield[@code='a']">
+               <mads:recordContentSource authority="marcorg">
+                       <xsl:value-of select="."/>
+               </mads:recordContentSource>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=040]/marc:subfield[@code='b']">
+               <mads:languageOfCataloging>
+                       <mads:languageTerm authority="iso639-2b" type="code">
+                               <xsl:value-of select="."/>
+                       </mads:languageTerm>
+               </mads:languageOfCataloging>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=040]/marc:subfield[@code='e']">
+               <mads:descriptionStandard>
+                       <xsl:value-of select="."/>
+               </mads:descriptionStandard>
+       </xsl:template>
+       
+       <!-- ========== classification 2.03 ========== -->
+       
+       <xsl:template match="marc:datafield[@tag=053]">
+               <mads:classification>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       
+       <xsl:template match="marc:datafield[@tag=055]">
+               <mads:classification>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       
+       <xsl:template match="marc:datafield[@tag=060]">
+               <mads:classification>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=065]">
+               <mads:classification>
+                       <xsl:attribute name="authority">
+                               <xsl:value-of select="marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=070]">
+               <mads:classification>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=080]">
+               <mads:classification>
+                       <xsl:attribute name="authority">
+                               <xsl:value-of select="marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=082]">
+               <mads:classification>
+                       <xsl:attribute name="authority">
+                               <xsl:value-of select="marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=083]">
+               <mads:classification>
+                       <xsl:attribute name="authority">
+                               <xsl:value-of select="marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=086]">
+               <mads:classification>
+                       <xsl:attribute name="authority">
+                               <xsl:value-of select="marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=087]">
+               <mads:classification>
+                       <xsl:attribute name="authority">
+                               <xsl:value-of select="marc:subfield[@code='2']"/>
+                       </xsl:attribute>
+                       <xsl:call-template name="subfieldSelect">
+                               <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
+                               <xsl:with-param name="delimeter">-</xsl:with-param>
+                       </xsl:call-template>
+               </mads:classification>
+       </xsl:template>
+       
+
+       <!-- ========== names  ========== -->
+       <xsl:template match="marc:datafield[@tag=100]">
+               <mads:name type="personal">
+                       <xsl:call-template name="setAuthority"/>
+                       <xsl:call-template name="nameABCDQ"/>
+               </mads:name>
+               <xsl:apply-templates select="*[marc:subfield[not(contains('abcdeq',@code))]]"/>
+               <xsl:call-template name="title"/>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=110]">
+               <mads:name type="corporate">
+                       <xsl:call-template name="setAuthority"/>
+                       <xsl:call-template name="nameABCDN"/>
+               </mads:name>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=111]">
+               <mads:name type="conference">
+                       <xsl:call-template name="setAuthority"/>
+                       <xsl:call-template name="nameACDENQ"/>
+               </mads:name>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=400]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <mads:name type="personal">
+                               <xsl:call-template name="nameABCDQ"/>
+                       </mads:name>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+                       <xsl:call-template name="title"/>
+               </mads:variant>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=410]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <mads:name type="corporate">
+                               <xsl:call-template name="nameABCDN"/>
+                       </mads:name>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:variant>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=411]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <mads:name type="conference">
+                               <xsl:call-template name="nameACDENQ"/>
+                       </mads:name>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:variant>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=500]|marc:datafield[@tag=700]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <!-- <xsl:call-template name="uri"/> -->
+                       <mads:name type="personal">
+                               <xsl:call-template name="setAuthority"/>
+                               <xsl:call-template name="nameABCDQ"/>
+                       </mads:name>
+                       <xsl:call-template name="title"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=510]|marc:datafield[@tag=710]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <!-- <xsl:call-template name="uri"/> -->
+                       <mads:name type="corporate">
+                               <xsl:call-template name="setAuthority"/>
+                               <xsl:call-template name="nameABCDN"/>
+                       </mads:name>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=511]|marc:datafield[@tag=711]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <!-- <xsl:call-template name="uri"/> -->
+                       <mads:name type="conference">
+                               <xsl:call-template name="setAuthority"/>
+                               <xsl:call-template name="nameACDENQ"/>
+                       </mads:name>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+
+       <!-- ========== titles  ========== -->
+       <xsl:template match="marc:datafield[@tag=130]">
+               <xsl:call-template name="uniform-title"/>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=430]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <xsl:call-template name="uniform-title"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:variant>
+       </xsl:template>
+
+       <xsl:template match="marc:datafield[@tag=530]|marc:datafield[@tag=730]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:call-template name="uniform-title"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+
+       <xsl:template name="title">
+               <xsl:variable name="hasTitle">
+                       <xsl:for-each select="marc:subfield">
+                               <xsl:if test="(contains('tfghklmors',@code) )">
+                                       <xsl:value-of select="@code"/>
+                               </xsl:if>
+                       </xsl:for-each>
+               </xsl:variable>
+               <xsl:if test="string-length($hasTitle) &gt; 0 ">
+                       <mads:titleInfo>
+                               <xsl:call-template name="setAuthority"/>
+                               <mads:title>
+                                       <xsl:variable name="str">
+                                               <xsl:for-each select="marc:subfield">
+                                                       <xsl:if test="(contains('atfghklmors',@code) )">
+                                                               <xsl:value-of select="text()"/>
+                                                               <xsl:text> </xsl:text>
+                                                       </xsl:if>
+                                               </xsl:for-each>
+                                       </xsl:variable>
+                                       <xsl:call-template name="chopPunctuation">
+                                               <xsl:with-param name="chopString">
+                                                       <xsl:value-of select="substring($str,1,string-length($str)-1)"/>
+                                               </xsl:with-param>
+                                       </xsl:call-template>
+                               </mads:title>
+                               <xsl:call-template name="part"/>
+                               <!-- <xsl:call-template name="uri"/> -->
+                       </mads:titleInfo>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template name="uniform-title">
+               <xsl:variable name="hasTitle">
+                       <xsl:for-each select="marc:subfield">
+                               <xsl:if test="(contains('atfghklmors',@code) )">
+                                       <xsl:value-of select="@code"/>
+                               </xsl:if>
+                       </xsl:for-each>
+               </xsl:variable>
+               <xsl:if test="string-length($hasTitle) &gt; 0 ">
+                       <mads:titleInfo>
+                               <xsl:call-template name="setAuthority"/>
+                               <mads:title>
+                                       <xsl:variable name="str">
+                                               <xsl:for-each select="marc:subfield">
+                                                       <xsl:if test="(contains('adfghklmors',@code) )">
+                                                               <xsl:value-of select="text()"/>
+                                                               <xsl:text> </xsl:text>
+                                                       </xsl:if>
+                                               </xsl:for-each>
+                                       </xsl:variable>
+                                       <xsl:call-template name="chopPunctuation">
+                                               <xsl:with-param name="chopString">
+                                                       <xsl:value-of select="substring($str,1,string-length($str)-1)"/>
+                                               </xsl:with-param>
+                                       </xsl:call-template>
+                               </mads:title>
+                               <xsl:call-template name="part"/>
+                               <!-- <xsl:call-template name="uri"/> -->
+                       </mads:titleInfo>
+               </xsl:if>
+       </xsl:template>
+
+
+       <!-- ========== topics  ========== -->
+       <xsl:template match="marc:subfield[@code='x']">
+               <mads:topic>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:value-of select="."/>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:topic>
+       </xsl:template>
+       
+       <!-- 2.06 fix -->
+       <xsl:template
+               match="marc:datafield[@tag=150][marc:subfield[@code='a' or @code='b']]|marc:datafield[@tag=180][marc:subfield[@code='x']]">
+               <xsl:call-template name="topic"/>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=450][marc:subfield[@code='a' or @code='b']]|marc:datafield[@tag=480][marc:subfield[@code='x']]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <xsl:call-template name="topic"/>
+               </mads:variant>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=550 or @tag=750][marc:subfield[@code='a' or @code='b']]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <!-- <xsl:call-template name="uri"/> -->
+                       <xsl:call-template name="topic"/>
+                       <xsl:apply-templates select="marc:subfield[@code='z']"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template name="topic">
+               <mads:topic>
+                       <xsl:call-template name="setAuthority"/>
+                       <!-- tmee2006 dedupe 550a
+                       <xsl:if test="@tag=550 or @tag=750">
+                               <xsl:call-template name="subfieldSelect">
+                                       <xsl:with-param name="codes">ab</xsl:with-param>
+                               </xsl:call-template>
+                       </xsl:if>       
+                       -->
+                       <xsl:choose>
+                               <xsl:when test="@tag=180 or @tag=480 or @tag=580 or @tag=780">
+                                       <xsl:call-template name="chopPunctuation">
+                                               <xsl:with-param name="chopString">
+                                                       <xsl:apply-templates select="marc:subfield[@code='x']"/>
+                                               </xsl:with-param>
+                                       </xsl:call-template>
+                               </xsl:when>
+                       </xsl:choose>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:choose>
+                                               <xsl:when test="@tag=180 or @tag=480 or @tag=580 or @tag=780">
+                                                       <xsl:apply-templates select="marc:subfield[@code='x']"/>
+                                               </xsl:when>
+                                               <xsl:otherwise>
+                                                       <xsl:call-template name="subfieldSelect">
+                                                               <xsl:with-param name="codes">ab</xsl:with-param>
+                                                       </xsl:call-template>
+                                               </xsl:otherwise>
+                                       </xsl:choose>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:topic>
+       </xsl:template>
+
+       <!-- ========= temporals  ========== -->
+       <xsl:template match="marc:subfield[@code='y']">
+               <mads:temporal>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:value-of select="."/>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:temporal>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=148][marc:subfield[@code='a']]|marc:datafield[@tag=182 ][marc:subfield[@code='y']]">
+               <xsl:call-template name="temporal"/>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=448][marc:subfield[@code='a']]|marc:datafield[@tag=482][marc:subfield[@code='y']]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <xsl:call-template name="temporal"/>
+               </mads:variant>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=548 or @tag=748][marc:subfield[@code='a']]|marc:datafield[@tag=582 or @tag=782][marc:subfield[@code='y']]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <!-- <xsl:call-template name="uri"/> -->
+                       <xsl:call-template name="temporal"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template name="temporal">
+               <mads:temporal>
+                       <xsl:call-template name="setAuthority"/>
+                       <xsl:if test="@tag=548 or @tag=748">
+                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                       </xsl:if>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:choose>
+                                               <xsl:when test="@tag=182 or @tag=482 or @tag=582 or @tag=782">
+                                                       <xsl:apply-templates select="marc:subfield[@code='y']"/>
+                                               </xsl:when>
+                                               <xsl:otherwise>
+                                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                                               </xsl:otherwise>
+                                       </xsl:choose>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:temporal>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+
+       <!-- ========== genre  ========== -->
+       <xsl:template match="marc:subfield[@code='v']">
+               <mads:genre>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:value-of select="."/>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:genre>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=155][marc:subfield[@code='a']]|marc:datafield[@tag=185][marc:subfield[@code='v']]">
+               <xsl:call-template name="genre"/>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=455][marc:subfield[@code='a']]|marc:datafield[@tag=485 ][marc:subfield[@code='v']]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <xsl:call-template name="genre"/>
+               </mads:variant>
+       </xsl:template>
+       <!--
+       <xsl:template match="marc:datafield[@tag=555]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:call-template name="uri"/>
+                       <xsl:call-template name="genre"/>
+               </mads:related>
+       </xsl:template>
+       -->
+       <xsl:template
+               match="marc:datafield[@tag=555 or @tag=755][marc:subfield[@code='a']]|marc:datafield[@tag=585][marc:subfield[@code='v']]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:call-template name="genre"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template name="genre">
+               <mads:genre>
+                       <xsl:if test="@tag=555">
+                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                       </xsl:if>
+                       <xsl:call-template name="setAuthority"/>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:choose>
+                                               <!-- 2.07 fix -->
+                                               <xsl:when test="@tag='555'"/>
+                                               <xsl:when test="@tag=185 or @tag=485 or @tag=585">
+                                                       <xsl:apply-templates select="marc:subfield[@code='v']"/>
+                                               </xsl:when>
+                                               <xsl:otherwise>
+                                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                                               </xsl:otherwise>
+                                       </xsl:choose>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:genre>
+               <xsl:apply-templates/>
+       </xsl:template>
+
+       <!-- ========= geographic  ========== -->
+       <xsl:template match="marc:subfield[@code='z']">
+               <mads:geographic>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:value-of select="."/>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:geographic>
+       </xsl:template>
+       <xsl:template name="geographic">
+               <mads:geographic>
+                       <!-- 2.14 -->
+                       <xsl:call-template name="setAuthority"/>
+                       <!-- 2.13 -->
+                       <xsl:if test="@tag=151 or @tag=551">
+                               <xsl:value-of select="marc:subfield[@code='a']"/>
+                       </xsl:if>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                               <xsl:if test="@tag=181 or @tag=481 or @tag=581">
+                                                               <xsl:apply-templates select="marc:subfield[@code='z']"/>
+                                               </xsl:if>
+                                               <!-- 2.13
+                                                       <xsl:choose>
+                                               <xsl:when test="@tag=181 or @tag=481 or @tag=581">
+                                                       <xsl:apply-templates select="marc:subfield[@code='z']"/>
+                                               </xsl:when>
+                                       
+                                               <xsl:otherwise>
+                                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                                               </xsl:otherwise>
+                                               </xsl:choose>
+                                               -->
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:geographic>
+               <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=151][marc:subfield[@code='a']]|marc:datafield[@tag=181][marc:subfield[@code='z']]">
+               <xsl:call-template name="geographic"/>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=451][marc:subfield[@code='a']]|marc:datafield[@tag=481][marc:subfield[@code='z']]">
+               <mads:variant>
+                       <xsl:call-template name="variantTypeAttribute"/>
+                       <xsl:call-template name="geographic"/>
+               </mads:variant>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=551]|marc:datafield[@tag=581][marc:subfield[@code='z']]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <!-- <xsl:call-template name="uri"/> -->
+                       <xsl:call-template name="geographic"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=580]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template
+               match="marc:datafield[@tag=751][marc:subfield[@code='z']]|marc:datafield[@tag=781][marc:subfield[@code='z']]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:call-template name="geographic"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=755]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:call-template name="setAuthority"/>
+                       <xsl:call-template name="genre"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=780]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+       <xsl:template match="marc:datafield[@tag=785]">
+               <mads:related>
+                       <xsl:call-template name="relatedTypeAttribute"/>
+                       <xsl:apply-templates select="marc:subfield[@code!='i']"/>
+               </mads:related>
+       </xsl:template>
+
+       <!-- ========== notes  ========== -->
+       <xsl:template match="marc:datafield[667 &lt;= @tag and @tag &lt;= 688]">
+               <mads:note>
+                       <xsl:choose>
+                               <xsl:when test="@tag=667">
+                                       <xsl:attribute name="type">nonpublic</xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="@tag=670">
+                                       <xsl:attribute name="type">source</xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="@tag=675">
+                                       <xsl:attribute name="type">notFound</xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="@tag=678">
+                                       <xsl:attribute name="type">history</xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="@tag=681">
+                                       <xsl:attribute name="type">subject example</xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="@tag=682">
+                                       <xsl:attribute name="type">deleted heading information</xsl:attribute>
+                               </xsl:when>
+                               <xsl:when test="@tag=688">
+                                       <xsl:attribute name="type">application history</xsl:attribute>
+                               </xsl:when>
+                       </xsl:choose>
+                       <xsl:call-template name="chopPunctuation">
+                               <xsl:with-param name="chopString">
+                                       <xsl:choose>
+                                               <xsl:when test="@tag=667 or @tag=675">
+                                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                                               </xsl:when>
+                                               <xsl:when test="@tag=670 or @tag=678">
+                                                       <xsl:call-template name="subfieldSelect">
+                                                               <xsl:with-param name="codes">ab</xsl:with-param>
+                                                       </xsl:call-template>
+                                               </xsl:when>
+                                               <xsl:when test="680 &lt;= @tag and @tag &lt;=688">
+                                                       <xsl:call-template name="subfieldSelect">
+                                                               <xsl:with-param name="codes">ai</xsl:with-param>
+                                                       </xsl:call-template>
+                                               </xsl:when>
+                                       </xsl:choose>
+                               </xsl:with-param>
+                       </xsl:call-template>
+               </mads:note>
+       </xsl:template>
+
+       <!-- ========== url  ========== -->
+       <xsl:template match="marc:datafield[@tag=856][marc:subfield[@code='u']]">
+               <mads:url>
+                       <xsl:if test="marc:subfield[@code='z' or @code='3']">
+                               <xsl:attribute name="displayLabel">
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">z3</xsl:with-param>
+                                       </xsl:call-template>
+                               </xsl:attribute>
+                       </xsl:if>
+                       <xsl:value-of select="marc:subfield[@code='u']"/>
+               </mads:url>
+       </xsl:template>
+
+       <xsl:template name="relatedTypeAttribute">
+               <xsl:choose>
+                       <xsl:when
+                               test="@tag=500 or @tag=510 or @tag=511 or @tag=548 or @tag=550 or @tag=551 or @tag=555 or @tag=580 or @tag=581 or @tag=582 or @tag=585">
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='a'">
+                                       <xsl:attribute name="type">earlier</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='b'">
+                                       <xsl:attribute name="type">later</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='t'">
+                                       <xsl:attribute name="type">parentOrg</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='g'">
+                                       <xsl:attribute name="type">broader</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='h'">
+                                       <xsl:attribute name="type">narrower</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='r'">
+                                       <xsl:attribute name="type">other</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="contains('fin|', substring(marc:subfield[@code='w'],1,1))">
+                                       <xsl:attribute name="type">other</xsl:attribute>
+                               </xsl:if>
+                       </xsl:when>
+                       <xsl:when test="@tag=530 or @tag=730">
+                               <xsl:attribute name="type">other</xsl:attribute>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <!-- 7xx -->
+                               <xsl:attribute name="type">equivalent</xsl:attribute>
+                       </xsl:otherwise>
+               </xsl:choose>
+               <xsl:apply-templates select="marc:subfield[@code='i']"/>
+       </xsl:template>
+       
+
+
+       <xsl:template name="variantTypeAttribute">
+               <xsl:choose>
+                       <xsl:when
+                               test="@tag=400 or @tag=410 or @tag=411 or @tag=451 or @tag=455 or @tag=480 or @tag=481 or @tag=482 or @tag=485">
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='d'">
+                                       <xsl:attribute name="type">acronym</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="substring(marc:subfield[@code='w'],1,1)='n'">
+                                       <xsl:attribute name="type">other</xsl:attribute>
+                               </xsl:if>
+                               <xsl:if test="contains('fit', substring(marc:subfield[@code='w'],1,1))">
+                                       <xsl:attribute name="type">other</xsl:attribute>
+                               </xsl:if>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <!-- 430  -->
+                               <xsl:attribute name="type">other</xsl:attribute>
+                       </xsl:otherwise>
+               </xsl:choose>
+               <xsl:apply-templates select="marc:subfield[@code='i']"/>
+       </xsl:template>
+
+       <xsl:template name="setAuthority">
+               <xsl:choose>
+                       <!-- can be called from the datafield or subfield level, so "..//@tag" means
+                       the tag can be at the subfield's parent level or at the datafields own level -->
+
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=100 and (@ind1=0 or @ind1=1) and $controlField008-11='a' and $controlField008-14='a'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>naf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=100 and (@ind1=0 or @ind1=1) and $controlField008-11='a' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lcsh</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=100 and (@ind1=0 or @ind1=1) and $controlField008-11='k'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lacnaf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=100 and @ind1=3 and $controlField008-11='a' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lcsh</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=100 and @ind1=3 and $controlField008-11='k' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">cash</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='a' and $controlField008-14='a'">
+                               <xsl:attribute name="authority">naf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='a' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">lcsh</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='k' and $controlField008-14='a'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lacnaf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='k' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>cash</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='b'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lcshcl</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=100 or ancestor-or-self::marc:datafield/@tag=110 or ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130 or ancestor-or-self::marc:datafield/@tag=151) and $controlField008-11='c'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>nlmnaf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=100 or ancestor-or-self::marc:datafield/@tag=110 or ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130 or ancestor-or-self::marc:datafield/@tag=151) and $controlField008-11='d'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>nalnaf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='r'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>aat</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='s'">
+                               <xsl:attribute name="authority">sears</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='v'">
+                               <xsl:attribute name="authority">rvm</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='z'">
+                               <xsl:attribute name="authority">
+                                       <xsl:value-of
+                                               select="../marc:datafield[ancestor-or-self::marc:datafield/@tag=040]/marc:subfield[@code='f']"
+                                       />
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130) and $controlField008-11='a' and $controlField008-14='a'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>naf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130) and $controlField008-11='a' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lcsh</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130) and $controlField008-11='k' ">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lacnaf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='a' ">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lcsh</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='a' ">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>lcsh</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='c' ">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>mesh</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='d' ">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>nal</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='k' ">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>cash</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='a' and $controlField008-14='a'">
+                               <xsl:attribute name="authority">
+                                       <xsl:text>naf</xsl:text>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='a' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">lcsh</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='k' and $controlField008-14='a'">
+                               <xsl:attribute name="authority">lacnaf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='k' and $controlField008-14='b'">
+                               <xsl:attribute name="authority">cash</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(..//ancestor-or-self::marc:datafield/@tag=180 or ..//ancestor-or-self::marc:datafield/@tag=181 or ..//ancestor-or-self::marc:datafield/@tag=182 or ..//ancestor-or-self::marc:datafield/@tag=185) and $controlField008-11='a'">
+                               <xsl:attribute name="authority">lcsh</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=700 and (@ind1='0' or @ind1='1') and @ind2='0'">
+                               <xsl:attribute name="authority">naf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="ancestor-or-self::marc:datafield/@tag=700 and (@ind1='0' or @ind1='1') and @ind2='5'">
+                               <xsl:attribute name="authority">lacnaf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when test="ancestor-or-self::marc:datafield/@tag=700 and @ind1='3' and @ind2='0'">
+                               <xsl:attribute name="authority">lcsh</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when test="ancestor-or-self::marc:datafield/@tag=700 and @ind1='3' and @ind2='5'">
+                               <xsl:attribute name="authority">cash</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(700 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 755 ) and @ind2='1'">
+                               <xsl:attribute name="authority">lcshcl</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=700 or ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='2'">
+                               <xsl:attribute name="authority">nlmnaf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=700 or ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='3'">
+                               <xsl:attribute name="authority">nalnaf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(700 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 755 ) and @ind2='6'">
+                               <xsl:attribute name="authority">rvm</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(700 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 755 ) and @ind2='7'">
+                               <xsl:attribute name="authority">
+                                       <xsl:value-of select="marc:subfield[@code='2']"/>
+                               </xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='5'">
+                               <xsl:attribute name="authority">lacnaf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='0'">
+                               <xsl:attribute name="authority">naf</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='0'">
+                               <xsl:attribute name="authority">lcsh</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='2'">
+                               <xsl:attribute name="authority">mesh</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='3'">
+                               <xsl:attribute name="authority">nal</xsl:attribute>
+                       </xsl:when>
+                       <xsl:when
+                               test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='5'">
+                               <xsl:attribute name="authority">cash</xsl:attribute>
+                       </xsl:when>
+               </xsl:choose>
+       </xsl:template>
+       <xsl:template match="*"/>
+</xsl:stylesheet>$XSLT$ WHERE name = 'mads21';
+
+COMMIT;
+
+-- Update auditor tables to catch changes to source tables.
+--   Can be removed/skipped if there were no schema changes.
+SELECT auditor.update_auditors();
index b2b87b6..de5fdf6 100644 (file)
@@ -1,7 +1,7 @@
 <html><head><script></script></head><body onload="var x = document.getElementById('version'); var version ='/xul/server/'.split(/\//)[2]; if (version == 'server') { version = 'versionless debug build'; } x.appendChild(document.createTextNode(version));">
 <h1 style="text-decoration: underline">Evergreen</h1>
 <p>Target Server ID: <span id="version"></span></p>
-<p>$HeadURL$</p>
+<p>http://git.evergreen-ils.org/?p=Evergreen.git;a=shortlog;h=refs/heads/tags/rel_3_7_3</p>
 <h2>What is Evergreen?</h2>
 <blockquote>
 <p>
index 0613a13..c4c9ae4 100644 (file)
@@ -11,7 +11,7 @@ pref("toolkit.singletonWindowType", "eg_main");
 pref("open-ils.enable_join_tabs", true);
 
 // We'll use this one to help brand some build information into the client, and rely on subversion keywords
-pref("open-ils.repository.headURL","$HeadURL$");
+pref("open-ils.repository.headURL","http://git.evergreen-ils.org/?p=Evergreen.git;a=shortlog;h=refs/heads/tags/rel_3_7_3");
 pref("open-ils.repository.author","$Author$");
 pref("open-ils.repository.revision","$Revision$");
 pref("open-ils.repository.date","$Date$");
index a954357..fe5c988 100644 (file)
@@ -3,7 +3,7 @@
 ; HM NIS Edit Wizard helper defines
 ; Old versions of makensis don't like this, moved to Makefile
 ;!define /file PRODUCT_VERSION "client/VERSION"
-!define PRODUCT_TAG "Master"
+!define PRODUCT_TAG "3.7"
 !define PRODUCT_INSTALL_TAG "${PRODUCT_TAG}"
 !define UI_IMAGESET "beta"
 ;!define UI_IMAGESET "release"
diff --git a/README b/README
deleted file mode 120000 (symlink)
index 1486a8d6764f2981a61f67869b6c4a2bee76df52..0000000000000000000000000000000000000000
--- a/README
+++ /dev/null
@@ -1 +0,0 @@
-docs/modules/installation/pages/server_installation.adoc
\ No newline at end of file
diff --git a/README b/README
new file mode 100644 (file)
index 0000000000000000000000000000000000000000..694dc0663d92880967de108b5d3862403d1184de
--- /dev/null
+++ b/README
@@ -0,0 +1,662 @@
+= Installing the Evergreen server =
+:toc:
+
+== 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 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**: The minimum supported version is 9.6.
+  * **Linux**: Evergreen has been tested on 
+    Debian Buster (10), 
+    Debian Stretch (9), 
+    Debian Jessie (8),
+    Ubuntu Focal Fossa (20.04),
+    and Ubuntu Bionic Beaver (18.04).
+    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 or Ubuntu websites.
+  * **OpenSRF**: The minimum supported version of OpenSRF is 3.2.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 (3.2.0 or later).
+   You can download OpenSRF releases from http://evergreen-ils.org/opensrf-downloads/
++
+2. Issue the following commands as the *root* Linux account to install
+   prerequisites using the `Makefile.install` prerequisite installer,
+   substituting `debian-buster`,`debian-stretch`,`debian-jessie`,`ubuntu-focal`,
+   or `ubuntu-bionic` for <osname> below:
++
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install <osname>
+------------------------------------------------------------------------------
++
+[[optional_developer_additions]]
+3. OPTIONAL: Developer additions
++
+To perform certain developer tasks from a Git source code checkout, 
+including the testing of the Angular web client components,
+additional packages may be required.  As the *root* Linux account:
++
+ * To install packages needed for retrieving and managing web dependencies,
+   use the <osname>-developer Makefile.install target.  Currently, 
+   this is only needed for building and installing the web
+   staff client.
++
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install <osname>-developer
+------------------------------------------------------------------------------
++
+ * To install packages required for building Evergreen translations, use
+   the <osname>-translator Makefile.install target.
++
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install <osname>-translator
+------------------------------------------------------------------------------
++
+ * 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
+------------------------------------------------------------------------------
+
+== Extra steps for web staff client ==
+
+[NOTE]
+Skip this entire section if you are using an official release tarball downloaded
+from http://evergreen-ils.org/downloads. Otherwise, ensure you have installed the
+xref:#optional_developer_additions[optional developer additions] before proceeding.
+
+[[install_files_for_web_staff_client]]
+=== Install AngularJS files for web 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 JS dependencies
+------------------------------------------------------------------------------
++
+3. Run the build script.
++
+[source,sh]
+------------------------------------------------------------------------------
+# build, concat+minify
+npm run build-prod
+------------------------------------------------------------------------------
++
+4. OPTIONAL: Test web client code if the <osname>-developer packages were installed.
+   CHROME_BIN should be set to the path to chrome or chromimum, e.g.,
+   `/usr/bin/chromium`:
++
+[source,sh]
+------------------------------------------------------------------------------
+CHROME_BIN=/path/to/chrome npm run test
+------------------------------------------------------------------------------
+
+[[install_files_for_angular_web_staff_client]]
+=== Install Angular files for web staff client ===
+
+1. Building, Testing, Minification: The remaining steps all take place within
+   the Angular staff root:
++
+[source,sh]
+------------------------------------------------------------------------------
+cd $EVERGREEN_ROOT/Open-ILS/src/eg2/
+------------------------------------------------------------------------------
++
+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 JS dependencies
+------------------------------------------------------------------------------
++
+3. Run the build script.
++
+[source,sh]
+------------------------------------------------------------------------------
+# build and run tests
+ng build --prod
+------------------------------------------------------------------------------
++
+4. OPTIONAL: Test eg2 web client code if the <osname>-developer packages were installed:
+   CHROME_BIN should be set to the path to chrome or chromimum, e.g.,
+   `/usr/bin/chromium`:
++
+[source,sh]
+------------------------------------------------------------------------------
+CHROME_BIN=/path/to/chrome npm run test
+------------------------------------------------------------------------------
+
+[[install_opac_deps]]
+=== Install OPAC skin dependencies ===
+
+1. The following steps take place within the OPAC dependencies root:
++
+[source,sh]
+------------------------------------------------------------------------------
+cd $EVERGREEN_ROOT/Open-ILS/web/opac/deps
+------------------------------------------------------------------------------
++
+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 JS and CSS dependencies
+------------------------------------------------------------------------------
++
+Note that there is no build step.
+
+== 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 and copy
+   example configuration files to `/openils/conf`.
++
+[source, bash]
+------------------------------------------------------------------------------
+make install
+------------------------------------------------------------------------------
+
+== 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
+------------------------------------------------------------------------------
+
+== Run ldconfig ==
+
+On Ubuntu 18.04 / 20.04 or Debian Stretch / Buster, run the following command as the root user:
+
+[source, bash]
+------------------------------------------------------------------------------
+ldconfig
+------------------------------------------------------------------------------
+
+== 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 to configure your Web server for 
+the Evergreen catalog, web staff client, Web services, and administration
+interfaces. Issue the following commands as the *root* Linux account:
++
+[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_24/eg_startup      /etc/apache2/
+# Now set up SSL
+mkdir /etc/apache2/ssl
+cd /etc/apache2/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
+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):
+     * Replace `Require host 10.0.0.0/8` with `Require all granted`
+. Change the user for the Apache server.
+  * As the *root* Linux account, edit
+    `/etc/apache2/envvars`.  Change `export APACHE_RUN_USER=www-data` to 
+    `export APACHE_RUN_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.
+  * Edit `/etc/apache2/apache2.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 catalog to the web:
++
+.`/etc/apache2/mods-available/mpm_prefork.conf`
+[source,bash]
+------------------------------------------------------------------------------
+<IfModule mpm_prefork_module>
+   StartServers            15
+   MinSpareServers          5
+   MaxSpareServers         15
+   MaxRequestWorkers       75
+   MaxConnectionsPerChild 500
+</IfModule>
+------------------------------------------------------------------------------
++
+. As the *root* user, enable the mpm_prefork module:
++
+[source,bash]
+------------------------------------------------------------------------------
+a2dismod mpm_event
+a2enmod mpm_prefork
+------------------------------------------------------------------------------
++
+. As the *root* Linux account, enable the Evergreen site:
++
+[source,bash]
+------------------------------------------------------------------------------
+a2dissite 000-default  # OPTIONAL: disable the default site (the "It Works" page)
+a2ensite eg.conf
+------------------------------------------------------------------------------
++
+. 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:
+
+  * xref:admin:apache_rewrite_tricks.adoc#apache_rewrite_tricks[Apache Rewrite Tricks]
+  * xref:admin:apache_access_handler.adoc#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 xref:#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 running action triggers, see
+xref:admin:actiontriggers_process.adoc#processing_action_triggers[Notifications / Action Triggers].
+
+[[creating_the_evergreen_database]]
+== 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:
+
+. 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. This will install PostgreSQL 9.6,
+the minimum supported version.
+
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-buster
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-stretch
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-jessie
+make -f Open-ILS/src/extras/Makefile.install postgres-server-ubuntu-bionic
+make -f Open-ILS/src/extras/Makefile.install postgres-server-ubuntu-focal
+------------------------------------------------------------------------------
+
+To install PostgreSQL version 10, use the following command for your operating
+system:
+
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-buster-10
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-stretch-10
+make -f Open-ILS/src/extras/Makefile.install postgres-server-debian-jessie-10
+make -f Open-ILS/src/extras/Makefile.install postgres-server-ubuntu-bionic-10
+make -f Open-ILS/src/extras/Makefile.install postgres-server-ubuntu-focal-10
+------------------------------------------------------------------------------
+
+For a standalone PostgreSQL server, install the following Perl modules for your
+distribution as the *root* Linux account:
+
+.(Debian and Ubuntu) 
+No extra modules required for these distributions.
+
+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.
+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.6 and later ====
+
+To create the database instance on a remote database server running PostgreSQL
+9.6 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 web staff
+   client and catalog 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 web 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.
index f7da014..4592f29 100644 (file)
@@ -20,7 +20,7 @@
 
 export PATH=${PATH}:/usr/sbin
 AC_PREREQ(2.61)
-AC_INIT(Open-ILS, trunk, open-ils-dev@list.georgialibraries.org)
+AC_INIT(Open-ILS, 3.7.3, open-ils-dev@list.georgialibraries.org)
 AC_CONFIG_SRCDIR([configure.ac])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE